WebGL is really a fascinating topic to me. Being able to utilize the power of a local machine’s GPU via the web browser is a very novel concept.
If one was to ask back in 1996 would you be able to render Open GL code in a web browser via GPU, even the most tech savvy may have replied, “Open GL? GPU? what are those things, you speak about?”
WebGL Hello World
In the posting below I will show the equivalent of writing a Hello World example that is used to teach many other programming languages. The code is written in JavaScript and should run on newer browsers.
The code will draw 1 triangle and fill the triangle with gradients. The JavaScript may not be the worlds most exciting but neither are the Hello World examples. However it will lay the foundation for showing what is possible and future postings will show some more details.
Link to a working example. gradient triangle
There is a lot more lines of code than a typical Hello World program; but no one ever said drawing a gradient triangle would be easy.
Code for Gradient Triangle
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 |
//js draw a triangle via webGL //vertex shader var vertexShaderText = [ 'precision mediump float;' ,'' ,'attribute vec2 vertPosition;' ,'attribute vec3 vertColor;' ,'varying vec3 fragColor;' ,'void main()' ,'{' ,' fragColor = vertColor;' ,' gl_Position = vec4(vertPosition, 0.0, 1.0);' ,'}' ].join('\n'); //fragment shader var fragmentShaderText = [ 'precision mediump float;' ,'' ,'varying vec3 fragColor;' ,'void main()' ,'{' ,' gl_FragColor = vec4(fragColor ,1.0);' ,'}' ].join('\n'); var InitDemo = function() { console.log("this is working"); var canvas = document.getElementById('blank_surface'); var gl = canvas.getContext("webgl"); if (!gl) { console.log("using experimental webgl"); gl = canvas.getContext("experimental-webgl"); } if(!gl) { alert("Your Browser doesn't have webGL support"); } //adjust the width / height of canvas //canvas.width = window.innerWidth; //canvas.width = window.innerHeight; //reset the viewport since adjusted the canvas size //gl.viewport(0, 0, window.innerWidth, window.innerHeight); //setting color in format of RGB Alpha gl.clearColor(0.75,0.85,0.8,1.0); //argument of what buffer to render too gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // open the shaders var vertexShader = gl.createShader(gl.VERTEX_SHADER); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); //set shader source gl.shaderSource(vertexShader, vertexShaderText); gl.shaderSource(fragmentShader, fragmentShaderText); //compile the shaders gl.compileShader(vertexShader); //to check if compiled correctly if(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { console.error("ERROR in compile: vertex shader" ,gl.getShaderInfoLog(vertexShader)); return; } gl.compileShader(fragmentShader); if(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { console.error("ERROR in compile: fragment shader" ,gl.getShaderInfoLog(fragmentShader)); return; } //create an opengl program var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); //link gl program gl.linkProgram(program); //check for errors while linking if(!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.error("ERROR linking program" , gl.getProgramInfoLog(program)); return; } //validate the program -- only in debug, not production code gl.validateProgram(program); if(!gl.getProgramParameter(program, gl.VALIDATE_STATUS)) { console.error("ERROR validating program" ,gl.getProgramInfoLog(program)); return; } // create buffer // x coord, y coord, RGB var triangleVertices = [ 0.0 ,0.5 ,1.0 ,1.0 ,0.0 ,-0.5,-0.5 ,0.7 ,0.0 ,1.0 ,0.5 ,-0.5 ,0.1 ,1.0 ,0.6 ]; var triangleVertexBufferObject = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject); //cast array to float 32 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW); var positionAttribLocation = gl.getAttribLocation(program, 'vertPosition'); var colorAttribLocation = gl.getAttribLocation(program, 'vertColor'); //layout of the attribute gl.vertexAttribPointer( positionAttribLocation //attribute location ,2 //number of elements per attribute ,gl.FLOAT //32 bit float ,gl.FALSE // ,5 * Float32Array.BYTES_PER_ELEMENT //size of an individual vertex ,0 //offset from the beginning of a single vertex to this attribute ); gl.vertexAttribPointer( colorAttribLocation //attribute location ,3 //number of elements per attribute ,gl.FLOAT //32 bit float ,gl.FALSE // ,5 * Float32Array.BYTES_PER_ELEMENT //size of an individual vertex ,2 * Float32Array.BYTES_PER_ELEMENT //offset from the beginning of a single vertex to this attribute ); gl.enableVertexAttribArray(positionAttribLocation); gl.enableVertexAttribArray(colorAttribLocation); //main render loop gl.useProgram(program); //buffer actively bound //what to draw, how many to skip, and how many vertices to draw gl.drawArrays(gl.TRIANGLES, 0, 3); }; |
Leave a Reply