Skip to content

Instantly share code, notes, and snippets.

@mathdoodle
Last active July 13, 2020 18:26
Show Gist options
  • Save mathdoodle/5ba9c354028f0d28856f to your computer and use it in GitHub Desktop.
Save mathdoodle/5ba9c354028f0d28856f to your computer and use it in GitHub Desktop.
WebGL 008 Painting Directly with the GPU

Painting Directly with the GPU

<!doctype html>
<html>
<head>
<style>
/* STYLE-MARKER */
</style>
<script id='shader-vs' type='x-shader/x-vertex'>
attribute vec3 aVertexPosition;
varying vec2 position;
void main(void) {
position = vec2(aVertexPosition);
gl_Position = vec4(position, 0.0, 1.0);
}
</script>
<script id='shader-fs' type='x-shader/x-fragment'>
varying highp vec2 position;
void main(void) {
highp float distance = length(position);
highp float step = floor(distance * 10.0) * 0.1;
highp float component = max(0.0, 1.0 - step);
gl_FragColor = vec4(0.5 * component, 0.5 * component, component, 1.0);
}
</script>
<!-- SCRIPTS-MARKER -->
<script>
// CODE-MARKER
</script>
</head>
<body>
<canvas id='doodle-canvas' width='400' height='400'>
Your browser does not support the HTML5 canvas element.
</canvas>
</body>
</html>
{
"uuid": "9db997dc-9401-409d-b3cb-8c072c072352",
"description": "WebGL 008 Painting Directly with the GPU",
"dependencies": {
"DomReady": "1.0.0"
},
"operatorOverloading": false,
"name": "webgl-008-painting-directly-with-the-gpu",
"version": "0.1.0"
}
DomReady.ready(main);
function main() {
var canvas = <HTMLCanvasElement>document.getElementById('doodle-canvas');
var gl: WebGLRenderingContext = initWebGL(canvas);
var vs_source = (document.getElementById('shader-vs') as HTMLScriptElement).innerText;
var fs_source = (document.getElementById('shader-fs') as HTMLScriptElement).innerText;
var program = makeProgram(gl, vs_source, fs_source);
gl.useProgram(program);
var size = 2.0;
var vertices: number[] = [
0.0, 0.0, 0.0, // 0 center
-size/2, -size/2, 0.0, // 1 lower left
+size/2, -size/2, 0.0, // 2 lower right
+size/2, +size/2, 0.0, // 3 upper right
-size/2, +size/2, 0.0 // 4 upper left
];
var vbo = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var indices = [0,1,2,0,2,3,0,3,4,0,4,1];
var ibo = gl.createBuffer();
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, ibo);
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(indices), gl.STREAM_DRAW);
gl.clearColor(0.5, 0.5, 0.6, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.viewport(0, 0, canvas.width, canvas.height);
var aVertexPosition = gl.getAttribLocation(program, 'aVertexPosition');
gl.enableVertexAttribArray(aVertexPosition);
gl.vertexAttribPointer(aVertexPosition, 3, gl.FLOAT, false, 0, 0);
gl.drawElements(gl.TRIANGLES, indices.length, gl.UNSIGNED_SHORT, 0);
}
function initWebGL(canvas: HTMLCanvasElement): WebGLRenderingContext {
var context: WebGLRenderingContext = null;
try {
// Try to grab the standard context. If it fails, fallback to experimental.
context = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
}
catch(e) {
}
if (context) {
return context;
}
else {
throw new Error("Unable to initialize WebGL. Your browser may not support it.");
}
}
/**
* Creates a WebGLProgram with compiled and linked shaders.
*/
function makeProgram(gl: WebGLRenderingContext, vertexShader: string, fragmentShader: string): WebGLProgram {
// TODO: Proper cleanup if we throw an error at any point.
var vs = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vs, vertexShader);
gl.compileShader(vs);
if (!gl.getShaderParameter(vs, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(vs));
}
var fs = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fs, fragmentShader);
gl.compileShader(fs);
if (!gl.getShaderParameter(fs, gl.COMPILE_STATUS)) {
throw new Error(gl.getShaderInfoLog(fs));
}
var program = gl.createProgram();
gl.attachShader(program, vs);
gl.attachShader(program, fs);
gl.linkProgram(program);
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
throw new Error(gl.getProgramInfoLog(program));
}
return program;
}
body { background-color: white; }
canvas {
background-color: black;
position: absolute;
left: 500px;
top: 100px;
}
{
"allowJs": true,
"checkJs": true,
"declaration": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"jsx": "react",
"module": "system",
"noImplicitAny": true,
"noImplicitReturns": true,
"noImplicitThis": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"preserveConstEnums": true,
"removeComments": false,
"skipLibCheck": true,
"sourceMap": true,
"strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"target": "es5",
"traceResolution": true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment