All the introductory tutorials to WebGL I could find use utility libraries in efforts to make the hello-world examples easier to understand. I find this has the opposite effect, because my desire is to understand the WebGL interface itself, not abstracted away by a utility library. (It’s even more frustrating when the live examples accompanying the tutorial use minified JavaScript. What gives?) So here’s a simple Hello World in vanilla WebGL with no dependencies and linear control flow.
Last active
February 26, 2023 06:42
-
-
Save mbostock/5440492 to your computer and use it in GitHub Desktop.
Hello WebGL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <meta charset="utf-8"> | |
| <canvas width="960" height="500"></canvas> | |
| <script id="fragment-shader" type="x-shader/x-fragment"> | |
| void main(void) { | |
| gl_FragColor = vec4(0, 1, 0, 1); | |
| } | |
| </script> | |
| <script id="vertex-shader" type="x-shader/x-vertex"> | |
| attribute vec2 a_position; | |
| uniform mat3 u_matrix; | |
| void main(void) { | |
| gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1); | |
| } | |
| </script> | |
| <script> | |
| var canvas = document.querySelector("canvas"), | |
| width = +canvas.getAttribute("width"), | |
| height = +canvas.getAttribute("height"), | |
| context = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); | |
| var fragmentShader = context.createShader(context.FRAGMENT_SHADER); | |
| context.shaderSource(fragmentShader, document.querySelector("#fragment-shader").textContent); | |
| context.compileShader(fragmentShader); | |
| if (!context.getShaderParameter(fragmentShader, context.COMPILE_STATUS)) throw new Error(context.getShaderInfoLog(fragmentShader)); | |
| var vertexShader = context.createShader(context.VERTEX_SHADER); | |
| context.shaderSource(vertexShader, document.querySelector("#vertex-shader").textContent); | |
| context.compileShader(vertexShader); | |
| if (!context.getShaderParameter(vertexShader, context.COMPILE_STATUS)) throw new Error(context.getShaderInfoLog(vertexShader)); | |
| var program = context.createProgram(); | |
| context.attachShader(program, fragmentShader); | |
| context.attachShader(program, vertexShader); | |
| context.linkProgram(program); | |
| if (!context.getProgramParameter(program, context.LINK_STATUS)) throw new Error(context.getProgramInfoLog(program)); | |
| context.useProgram(program); | |
| var vertexBuffer = context.createBuffer(); | |
| context.bindBuffer(context.ARRAY_BUFFER, vertexBuffer); | |
| context.bufferData(context.ARRAY_BUFFER, new Float32Array([0, 0, width, 0, width, height, 0, height]), context.STATIC_DRAW); | |
| var positionAttribute = context.getAttribLocation(program, "a_position"); | |
| context.enableVertexAttribArray(positionAttribute); | |
| context.vertexAttribPointer(positionAttribute, 2, context.FLOAT, false, 0, 0); | |
| var matrixUniform = context.getUniformLocation(program, "u_matrix"); | |
| context.uniformMatrix3fv(matrixUniform, false, [2 / width, 0, 0, 0, -2 / height, 0, -1, 1, 1]); | |
| context.drawArrays(context.TRIANGLE_FAN, 0, 4); | |
| </script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
🙏