Hello WebGL source code

Previous: Quick tour of the demo.

Setting up the Shaders

This is followed by the shader setup, which uses GLScene helpers too, f.i. the fragment shader is created and compiled with

fragmentShader := TGLFragmentShader.Create(rc);
if not fragmentShader.Compile(#"
   precision mediump float;
   varying vec4 vColor;
   void main(void) {
      gl_FragColor = vColor;
   }") then
   raise Exception.Create(fragmentShader.InfoLog);

The vertex shader is created & compiled similarly, then both are linked into a shader program:

shaderProgram := TGLShaderProgram.Create(rc);
if not shaderProgram.Link(vertexShader, fragmentShader) then
   raise Exception.Create(shaderProgram.InfoLog);

Note that the shader program automatically builds a cache of uniforms and locations, and you can also use the AttribInfo[] and UniformInfo[] properties to enumerate attributes and uniforms.

Finally the Render loop is where you can see the vector & matrix helpers at work.
Since OpenGL ES 2.0 doesn’t include matrix stacks, you have to do them on your side, but this is easily achieved with a dynamic array’s Push() & Pop() pseudo-methods.

const
   cSpeed = 24*3600;
var
   projMat, mvMat : Matrix4;
   mvStack : array of Matrix4;
begin
   gl.ViewportSet(0, 0, canvas.Handle.width, canvas.Handle.height);

   gl.clear(gl.COLOR_BUFFER_BIT);

   shaderProgram.Use;

   projMat := Matrix4.CreatePerspective(45, canvas.width/canvas.height, 0.1, 100);
   mvMat := Matrix4.Identity;

   shaderProgram.SetUniform('uPMatrix', projMat);

   gl.enableVertexAttribArray(vertexPosAttrib);

   mvMat := mvMat.Translate([-1.5, 0, -7]);
   mvStack.Push(mvMat);

   mvMat := mvMat.RotateY(Frac(Now)*cSpeed);
   shaderProgram.SetUniform('uMVMatrix', mvMat);

   triangleBuffer.VertexAttribPointer(vertexPosAttrib, 3, false, 0, 0);
   gl.drawArrays(gl.TRIANGLES, 0, 3);

   mvMat := mvStack.Pop;

   mvMat := mvMat.Translate([3.0, 0, 0]).RotateX(Frac(Now)*cSpeed);
   shaderProgram.SetUniform('uMVMatrix', mvMat);

   squareBuffer.VertexAttribPointer(vertexPosAttrib, 3, false, 0, 0);
   gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);

The last bit I didn’t mention is the requestAnimationFrame shim, which is used to keep things rotating/animating, and which should at some point become part of the VJL or RTL.

So that’s about it for the walk-through!