Skip to content

Instantly share code, notes, and snippets.

@davidsharp
Created May 8, 2024 13:55
Show Gist options
  • Save davidsharp/f67d673a05cc4a5efdf66609644d0f33 to your computer and use it in GitHub Desktop.
Save davidsharp/f67d673a05cc4a5efdf66609644d0f33 to your computer and use it in GitHub Desktop.
pinched a webgl shader example and playing with shaders for use as a progress bar
<body bgcolor=black>
<canvas id='canvas1' width='1024' height='720'>
</canvas>
<button onclick="progress=Math.max(0.0,progress-0.1)">&lt;</button>
<button onclick="progress=Math.min(1.0,progress+0.1)">&gt;</button>
</body>
<script id="vs" type="x-shader/x-vertex">
attribute vec3 aPosition;
varying vec3 vPosition;
void main() {
gl_Position = vec4(aPosition, 1.0);
vPosition = aPosition;
}
</script>
<script id="fs" type="x-shader/x-fragment">
precision mediump float;
uniform float uTime;
varying vec3 vPosition;
uniform float progress;
vec3 played = vec3(0.5,0.5,1.0);
void main() {
vec3 color = ((progress*2.0)-1.0)>vPosition.x?played:vec3(1.0,1.0,1.0);
gl_FragColor = vec4(color, 1.0);
}
</script>
<script>
var progress = 0.5;
/**
* Function that pulls out text content from a DOM element
* @param id - ID of the DOM element
* @returns {string}
*/
function getStringFromDOMElement(id) {
var node = document.getElementById(id);
// Recurse and get all text in the node
var recurseThroughDOMNode = function recurseThroughDOMNode(childNode, textContext) {
if (childNode) {
if (childNode.nodeType === 3) {
textContext += childNode.textContent;
}
return recurseThroughDOMNode(childNode.nextSibling, textContext);
} else {
return textContext;
}
};
return recurseThroughDOMNode(node.firstChild, '');
}
/**
* Create and attach a shader to gl program
* @param gl
* @param program
* @param type
* @param src
*/
function addshader(gl, program, type, src) {
var shader = gl.createShader(type);
gl.shaderSource(shader, src);
gl.compileShader(shader);
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
throw "Cannot compile shader:\n\n" + gl.getShaderInfoLog(shader);
}
gl.attachShader(program, shader);
}
/**
* Function that creates and links the gl program with the
* application's vertex and fragment shader.
* @param gl
* @param vertexShader
* @param fragmentShader
*/
function gl_init(gl, vertexShader, fragmentShader) {
var program = gl.createProgram();
var buffer = gl.createBuffer();
addshader(gl, program, gl.VERTEX_SHADER, vertexShader);
addshader(gl, program, gl.FRAGMENT_SHADER, fragmentShader);
gl.linkProgram(program);
if (! gl.getProgramParameter(program, gl.LINK_STATUS))
throw "Could not link the shader program!";
gl.useProgram(program);
// Create a square as a strip of two triangles.
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(
gl.ARRAY_BUFFER,
new Float32Array([
-1,1,
0,1,
1,0,
-1,-1,
0,1,
-1,0]),
gl.STATIC_DRAW
);
gl.aPosition = gl.getAttribLocation(program, "aPosition");
gl.enableVertexAttribArray(gl.aPosition);
gl.vertexAttribPointer(gl.aPosition, 3, gl.FLOAT, false, 0, 0);
gl.uTime = gl.getUniformLocation(program, "uTime");
gl.progress = gl.getUniformLocation(program,"progress");
}
/**
* This function is called once per frame.
* @param gl
*/
function gl_update(gl) {
gl.uniform1f(gl.progress, progress);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
// Start the next frame
requestAnimFrame(function() { gl_update(gl); });
}
function start_gl(canvas_id, vertexShader, fragmentShader) {
// Make sure the browser supports WebGL.
try {
var canvas = document.getElementById(canvas_id);
var gl = canvas.getContext("experimental-webgl");
} catch (e) {
throw "Sorry, your browser does not support WebGL.";
}
// Initialize gl. Then start the frame loop.
gl_init(gl, vertexShader, fragmentShader);
gl_update(gl);
}
// A browser-independent way to call a function after 1/60 second.
requestAnimFrame = (function() {
return requestAnimationFrame
|| webkitRequestAnimationFrame
|| mozRequestAnimationFrame
|| oRequestAnimationFrame
|| msRequestAnimationFrame
|| function(callback) {
setTimeout(callback, 1000 / 60);
}; })();
start_gl("canvas1", getStringFromDOMElement('vs'), getStringFromDOMElement('fs'));
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment