{"id":99,"date":"2017-12-11T21:06:14","date_gmt":"2017-12-11T21:06:14","guid":{"rendered":"http:\/\/eipsoftware.com\/musings\/?p=99"},"modified":"2018-02-01T16:42:43","modified_gmt":"2018-02-01T16:42:43","slug":"webgl-hello-world","status":"publish","type":"post","link":"https:\/\/eipsoftware.com\/musings\/webgl-hello-world\/","title":{"rendered":"WebGL &#8211; Hello World"},"content":{"rendered":"<p>WebGL is really a fascinating topic to me. Being able to utilize the power of a local machine&#8217;s GPU via the web browser is a very novel concept.<\/p>\n<p>If one was to ask back in 1996 would you be able to render Open GL code in a web browser via\u00a0 GPU, even the most tech savvy may have replied, &#8220;Open GL? GPU? what are those things, you speak about?&#8221;<\/p>\n<h4>WebGL Hello World<\/h4>\n<p><!--more--><\/p>\n<p>In the posting below I will show the equivalent of writing a Hello World example that is used to teach many other programming languages.\u00a0 The code is written in JavaScript and should run on newer browsers.<\/p>\n<p>The code will draw 1 triangle and fill the triangle with gradients.\u00a0 The JavaScript may not be the worlds most exciting but neither are the Hello World examples.\u00a0 However it will lay the foundation for showing what is possible and future postings will show some more details.<\/p>\n<p>Link to a working example.\u00a0\u00a0<a href=\"https:\/\/eipsoftware.com\/musings\/webgl\/glt\/gradient_triangle.html\">gradient triangle<\/a><\/p>\n<p>There is\u00a0 a lot more lines of code than a typical Hello World program; but no one ever said drawing a gradient triangle would be easy.<\/p>\n<h4>Code for Gradient Triangle<\/h4>\n<pre class=\"theme:github width-set:true width-mode:1 width:700 lang:js decode:true\">\/\/js draw a triangle via webGL\r\n\r\n\/\/vertex shader\r\nvar vertexShaderText =\r\n\t\t\t\t\t[\r\n\t\t\t\t\t'precision mediump float;'\r\n\t\t\t\t\t,''\r\n\t\t\t\t\t,'attribute vec2 vertPosition;'\r\n\t\t\t\t\t,'attribute vec3 vertColor;'\r\n\t\t\t\t\t,'varying vec3 fragColor;'\r\n\t\t\t\t\t,'void main()'\r\n\t\t\t\t\t,'{'\r\n\t\t\t\t\t,' fragColor = vertColor;'\r\n\t\t\t\t\t,' gl_Position = vec4(vertPosition, 0.0, 1.0);'\r\n\t\t\t\t\t,'}'\r\n\t\t\t\t\t].join('\\n');\r\n\r\n\/\/fragment shader\r\nvar fragmentShaderText =\r\n[\r\n\t'precision mediump float;'\r\n\t,''\r\n\t,'varying vec3 fragColor;'\r\n\t,'void main()'\r\n\t,'{'\r\n\t,' gl_FragColor = vec4(fragColor ,1.0);'\r\n\t,'}'\r\n].join('\\n');\r\n\r\nvar InitDemo = function()\r\n{\r\n\tconsole.log(\"this is working\");\r\n\tvar canvas = document.getElementById('blank_surface');\r\n\tvar gl = canvas.getContext(\"webgl\");\r\n\t\r\n\tif (!gl)\r\n\t{\r\n\t\tconsole.log(\"using experimental webgl\");\r\n\t\tgl = canvas.getContext(\"experimental-webgl\");\r\n\t}\r\n\tif(!gl)\r\n\t{\r\n\t\talert(\"Your Browser doesn't have webGL support\");\r\n\t}\r\n\t\r\n\t\/\/adjust the width \/ height of canvas\r\n\t\/\/canvas.width = window.innerWidth;\r\n\t\/\/canvas.width = window.innerHeight;\r\n\t\/\/reset the viewport since adjusted the canvas size\r\n\t\/\/gl.viewport(0, 0, window.innerWidth, window.innerHeight);\r\n\t\r\n\t\/\/setting color in format of RGB Alpha\r\n\tgl.clearColor(0.75,0.85,0.8,1.0);\r\n\t\/\/argument of what buffer to render too\r\n\tgl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);\r\n\t\r\n\t\/\/ open the shaders\r\n\tvar vertexShader = gl.createShader(gl.VERTEX_SHADER);\r\n\tvar fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);\r\n\t\r\n\t\/\/set shader source\r\n\tgl.shaderSource(vertexShader, vertexShaderText);\r\n\tgl.shaderSource(fragmentShader, fragmentShaderText);\r\n\t\r\n\t\/\/compile the shaders\r\n\tgl.compileShader(vertexShader);\r\n\t\/\/to check if compiled correctly\r\n\tif(!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))\r\n\t{\r\n\t\tconsole.error(\"ERROR in compile: vertex shader\"\r\n\t\t\t\t\t  ,gl.getShaderInfoLog(vertexShader));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t\r\n\tgl.compileShader(fragmentShader);\r\n\t\tif(!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))\r\n\t{\r\n\t\tconsole.error(\"ERROR in compile: fragment shader\"\r\n\t\t\t\t\t  ,gl.getShaderInfoLog(fragmentShader));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t\/\/create an opengl program\r\n\tvar program = gl.createProgram();\r\n\tgl.attachShader(program, vertexShader);\r\n\tgl.attachShader(program, fragmentShader);\r\n\t\r\n\t\/\/link gl program\r\n\tgl.linkProgram(program);\r\n\t\/\/check for errors while linking\r\n\tif(!gl.getProgramParameter(program, gl.LINK_STATUS))\r\n\t{\r\n\t\tconsole.error(\"ERROR linking program\"\r\n\t\t\t\t\t  , gl.getProgramInfoLog(program));\r\n\t\treturn;\r\n\t}\r\n\t\/\/validate the program -- only in debug, not production code\r\n\tgl.validateProgram(program);\r\n\tif(!gl.getProgramParameter(program, gl.VALIDATE_STATUS))\r\n\t{\r\n\t\tconsole.error(\"ERROR validating program\"\r\n\t\t\t\t\t  ,gl.getProgramInfoLog(program));\r\n\t\treturn;\r\n\t}\r\n\t\r\n\t\/\/ create buffer\r\n\t\/\/ x coord, y coord, RGB\r\n\tvar triangleVertices =\r\n\t[\t0.0\t ,0.5\t,1.0 ,1.0 ,0.0\r\n\t\t,-0.5,-0.5\t,0.7 ,0.0 ,1.0\r\n\t\t,0.5 ,-0.5\t,0.1 ,1.0 ,0.6\r\n\t];\r\n\t\r\n\tvar triangleVertexBufferObject = gl.createBuffer();\r\n\tgl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexBufferObject);\r\n\t\/\/cast array to float 32\r\n\tgl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW);\r\n\t\r\n\tvar positionAttribLocation = gl.getAttribLocation(program, 'vertPosition');\r\n\tvar colorAttribLocation = gl.getAttribLocation(program, 'vertColor');\r\n\t\/\/layout of the attribute\r\n\tgl.vertexAttribPointer(\r\n\t\t\t\t\t\t\tpositionAttribLocation\t\t\/\/attribute location\r\n\t\t\t\t\t\t\t,2\t\t\t\t\t\t\t\/\/number of elements per attribute\r\n\t\t\t\t\t\t\t,gl.FLOAT \t\t\t\t\t\/\/32 bit float\r\n\t\t\t\t\t\t\t,gl.FALSE\t\t\t\t\t\/\/\r\n\t\t\t\t\t\t\t,5 * Float32Array.BYTES_PER_ELEMENT \/\/size of an individual vertex\r\n\t\t\t\t\t\t\t,0 \/\/offset from the beginning of a single vertex to this attribute\r\n\t\t\t\t\t\t\t);\r\n\t\r\n\tgl.vertexAttribPointer(\r\n\t\t\t\t\t\t\tcolorAttribLocation\t\t\t\/\/attribute location\r\n\t\t\t\t\t\t\t,3\t\t\t\t\t\t\t\/\/number of elements per attribute\r\n\t\t\t\t\t\t\t,gl.FLOAT \t\t\t\t\t\/\/32 bit float\r\n\t\t\t\t\t\t\t,gl.FALSE\t\t\t\t\t\/\/\r\n\t\t\t\t\t\t\t,5 * Float32Array.BYTES_PER_ELEMENT \/\/size of an individual vertex\r\n\t\t\t\t\t\t\t,2 * Float32Array.BYTES_PER_ELEMENT \/\/offset from the beginning of a single vertex to this attribute\r\n\t\t\t\t\t\t\t);\r\n\t\r\n\tgl.enableVertexAttribArray(positionAttribLocation);\r\n\tgl.enableVertexAttribArray(colorAttribLocation);\r\n\t\/\/main render loop\r\n\tgl.useProgram(program);\r\n\t\/\/buffer actively bound\r\n\t\/\/what to draw, how many to skip, and how many vertices to draw\r\n\tgl.drawArrays(gl.TRIANGLES, 0, 3);\t\r\n\t\r\n};<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>WebGL is really a fascinating topic to me. Being able to utilize the power of a local machine&#8217;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\u00a0 GPU, even the most tech [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[4,10,11],"tags":[19,20,21,22],"series":[],"class_list":["post-99","post","type-post","status-publish","format-standard","hentry","category-code","category-javascript","category-webgl","tag-webgl","tag-hello-world","tag-triangle","tag-gradient"],"_links":{"self":[{"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/posts\/99","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/comments?post=99"}],"version-history":[{"count":4,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/posts\/99\/revisions"}],"predecessor-version":[{"id":141,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/posts\/99\/revisions\/141"}],"wp:attachment":[{"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/media?parent=99"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/categories?post=99"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/tags?post=99"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/eipsoftware.com\/musings\/wp-json\/wp\/v2\/series?post=99"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}