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.

Revisions

  1. davidsharp created this gist May 8, 2024.
    147 changes: 147 additions & 0 deletions shader-progress.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,147 @@
    <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>