JSFiddle - React, Tailwind, and code Playground
by soulwire
HTML
<!-- physics -->
<script id="physics-vert" type="x-shader">
attribute vec2 aVertexPos;
void main() {
gl_Position = vec4( aVertexPos, 1, 1 );
}
</script>
<script id="physics-frag" type="x-shader">
precision mediump float;
uniform sampler2D uParticleData;
uniform vec2 uViewport;
uniform float uTime;
void main() {
vec4 particle = texture2D( uParticleData, gl_FragCoord.xy / uViewport );
particle.x += sin( uTime ) * 0.005;
particle.y += cos( uTime ) * 0.006;
gl_FragColor = particle;
}
</script>
<!-- render -->
<script id="render-vert" type="x-shader">
uniform sampler2D uParticleData;
attribute vec2 aParticleUV;
void main() {
vec4 particle = texture2D( uParticleData, aParticleUV );
gl_Position = particle;
}
</script>
<script id="render-frag" type="x-shader">
precision mediump float;
void main() {
gl_FragColor = vec4(0,1,0.5,1);
}
</script>
<!-- debug -->
<script id="debug-vert" type="x-shader">
attribute vec2 aVertexPos;
varying vec2 vTexCoord;
void main() {
vTexCoord = ( aVertexPos + 1.0 ) / 2.0; // map from xy to uv
gl_Position = vec4( aVertexPos, 1, 1 );
}
</script>
<script id="debug-frag" type="x-shader">
precision mediump float;
uniform vec2 uViewport;
uniform sampler2D uTexture;
varying vec2 vTexCoord;
void main() {
gl_FragColor = vec4( texture2D( uTexture, vTexCoord ) );
//gl_FragColor = vec4( gl_FragCoord.xy / uViewport, 1, 1 );
}
</script>
<canvas id="canvas" width="200" height="200"></canvas>
CSS
html, body {
background: #f2f2f2;
}
canvas {
border: 1px solid #ccc;
background: #fff;
}
JavaScript
/*
"changing the bound program invalidates your previously enabled arrays anyway"
http://stackoverflow.com/questions/9146748/switch-shader-program-in-webgl
*/
// utilities
function createShader( src, type ) {
var shader = gl.createShader( type );
gl.shaderSource( shader, src );
gl.compileShader( shader );
if ( !gl.getShaderParameter( shader, gl.COMPILE_STATUS ) ) throw gl.getShaderInfoLog( shader );
return shader;
}
function createProgram( vSrc, fSrc ) {
var vs = createShader( vSrc, gl.VERTEX_SHADER );
var fs = createShader( fSrc, gl.FRAGMENT_SHADER );
var program = gl.createProgram();
gl.attachShader( program, vs );
gl.attachShader( program, fs );
gl.linkProgram( program );
if ( !gl.getProgramParameter( program, gl.LINK_STATUS ) ) throw gl.getProgramInfoLog( program );
return program;
}
function getShader( id ) {
return document.getElementById( id ).textContent;
}
function screenQuad() {
/* 2___3
|\ |
| \|
0---1 */
var buffer = gl.createBuffer();
var vertices = [ -1, -1, 1, -1, -1, 1, 1, 1 ];
gl.bindBuffer( gl.ARRAY_BUFFER, buffer );
gl.bufferData( gl.ARRAY_BUFFER, new Float32Array( vertices ), gl.STATIC_DRAW );
buffer.numItems = 4;
buffer.itemSize = 2;
return buffer;
}
// settings
var PARTICLE_COUNT = 16;
var PARTICLE_COUNT_SQRT = Math.sqrt( PARTICLE_COUNT );
// get context
var canvas = document.getElementById( 'canvas' );
var gl = canvas.getContext( 'experimental-webgl' );
gl.getExtension( 'OES_texture_float' );
// create programs
var physicsProg = createProgram( getShader( 'physics-vert' ), getShader( 'physics-frag' ) );
var renderProg = createProgram( getShader( 'render-vert' ), getShader( 'render-frag' ) );
var debugProg = createProgram( getShader( 'debug-vert' ), getShader( 'debug-frag' ) );
// store attribute / uniform locations
physicsProg.uParticleData = gl.getUniformLocation( physicsProg, 'uParticleData'...