<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>01_simple-shape</title> <style> .test { background-color: gray; } canvas { background-color: gray; width: 100%; height: 100%; display: block; } </style> </head> <body> <!-- Simple example of shader source code (WebGL Fundamentals) --> <script id="vertex-simple-shader" type="x-shader/x-vertex"> attribute vec2 a_position; uniform vec2 u_resolution; void main() { // Convert pixel coordinates to a float randing from 0.0 -> 1.0 vec2 zeroToOne = a_position / u_resolution; // Convert from 0->1 to 0->2 vec2 zeroToTwo = zeroToOne * 2.0; // Convert from 0->2 to -1.0->1.0 vec2 clipSpace = zeroToTwo - 1.0; gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1); } </script> <script id="fragment-simple-shader" type="x-shader/x-vertex"> precision mediump float; uniform vec4 u_color; void main() { gl_FragColor = u_color; } </script> <!-- HTML document --> <p class="test">This is test HTML with some CSS. Logging with JS...<br>The following block is an OpenGL canvas</p> <canvas id="canvas"></canvas> <!-- WebGL --> <script> function main() { // // Boilerplate OpenGL helper functions function createShader(gl, type, source) { let shader = gl.createShader(type); gl.shaderSource(shader, source); gl.compileShader(shader); let success = gl.getShaderParameter(shader, gl.COMPILE_STATUS); if (success) { return shader; } console.log(gl.getShaderInfoLog(shader)); gl.deleteShader(shader); } function createProgram(gl, vertexShader, fragmentShader) { // Add check to automatically compile shaders if Strings are provided // + Strings should be equal to HTML script id attribute value for vertex and fragment shaders if (typeof vertexShader == 'string') { let vertexShaderSource = document.querySelector(vertexShader).text; vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource); } if (typeof fragmentShader == 'string') { let fragmentShaderSource = document.querySelector(fragmentShader).text; fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource); } let program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); let success = gl.getProgramParameter(program, gl.LINK_STATUS); if (success) { return program; } console.log(gl.getProgramInfoLog(program)); gl.deleteProgram(program); } let canvas = document.querySelector("#canvas"); let gl = canvas.getContext('webgl'); if (!gl) { console.log("ERROR: Unable to get OpenGL context"); return; } else { console.log("Created OpenGL context on HTML canvas") } // Creating shader program and compiling shader source code let program = createProgram(gl, "#vertex-simple-shader", "#fragment-simple-shader"); // look up where the vertex data needs to go. let positionAttributeLocation = gl.getAttribLocation(program, "a_position"); // look up uniform locations let resolutionUniformLocation = gl.getUniformLocation(program, "u_resolution"); let colorUniformLocation = gl.getUniformLocation(program, "u_color"); // Create a buffer to put three 2d clip space points in let positionBuffer = gl.createBuffer(); // Bind it to ARRAY_BUFFER (think of it as ARRAY_BUFFER = positionBuffer) gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // Canvas setup // Resize canvas to match client size const width = canvas.clientWidth; const height = canvas.clientHeight; canvas.width = width; canvas.height = height; gl.viewport(0, 0, gl.canvas.width, gl.canvas.height); // Clear the canvas gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); // Tell OpenGL to use our shader program gl.useProgram(program); // Enable attribute; Bind gl.ARRAY_BUFFER for use with this attribute gl.enableVertexAttribArray(positionAttributeLocation); gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer); // Tell the attribute how to get data out of positionBuffer (ARRAY_BUFFER) let size = 2; // 2 components per iteration (X and Y value for each vertex position) let type = gl.FLOAT; // Each X and Y value is a 32bit float let normalize = false; // don't normalize the data let stride = 0; // 0 = move forward size * sizeof(type) each iteration to get the next position let offset = 0; // start at the beginning of the buffer gl.vertexAttribPointer(positionAttributeLocation, size, type, normalize, stride, offset); // Initialize geometry data for a 2D triangle with 3 vertices let triangle = new Float32Array([ 350, 100, 500, 300, 200, 300, ]); // Write geometry data to positions array buffer gl.bufferData(gl.ARRAY_BUFFER, triangle, gl.STATIC_DRAW); // Set a random color gl.uniform4f(colorUniformLocation, Math.random(), Math.random(), Math.random(), 1); // set the resolution gl.uniform2f(resolutionUniformLocation, gl.canvas.width, gl.canvas.height); // Draw the triangle with 0 offset and 3 total vertices gl.drawArrays(gl.TRIANGLES, 0, 3); } main(); </script> </body> </html>