There is a very nice introduction to OpenGL on the web, written by Joey de Vries. It has a number of tutorials, an offline course book (containing the online tutorials) and a site where the used code can be found. You find the course at

It starts with the basics of OpenGL (Part 1 of the book) and ends with more advanced topics. Some of the final chapters are on PBR (Physics Based Rendering, Part 6 of the book). The code is written in C++. The main purpose of this project is to rewrite the code in javascript. The emphasis will be on programs in Part6. This and the following pages form together the documentation of the project.

The javascript interface of WebGL2 will be used for the OpenGL calls. WebGL2 is supported by the Chrome browser and all tests are done with Chrome only. The latest version of the Microsoft Edge also supports WebGl2. On the mozilla site the availability of the WebGL2 interface on other browsers is documented. In many cases Internet Explorer and Safari browsers will have limited support. Also in many cases this problem can be circumvented by using WebGl1 and using extensions. An option is to use WebGL1.1, ( WebGl with extensions, see:; one of the included extensions is OES_vertex_array_object and with that extension the programs of Part1 can stay the same (not tested, but see notes below)).

Not all code will be translated, only the C++ code of most of Part 1 and Part 6 will be completely rewritten in javascript, but only a selection of the other Parts After Part 1 the way to transform the code will be clear. The translation of Part 6 proves that also more complicated subjects can be treated in javascript and the version of GLSL we use.

There are two extras: one, a loader of gltf meshes and materials is given (in Part 3 and Part 6) and second, a program for the creation of 3D text is presented in Part 7. After Part 7 there is a Part Final where some of the code of Part1 - Part7 is restructured. Only the code in this Part Final is written with the MIT licence.

  1. The tools
  2. The project structure
  3. The translation of code
  4. Part 1 programs (Ends with class Camera)
  5. Part 2 programs
  6. Part 3 programs (Assimp library is replaced with Gltf)
  7. Part 4 programs
  8. Part 5 programs
  9. Part 6 programs (Physics Based Rendering and IBL)
  10. Part 7 programs (Treatment of Text)
  11. Part Final programs (restructuring the code)


A next project might be on subjects found in project Filament with anisotropy, cloth, transparency, camera model and post processing.

And another book on OpenGL programming is found in these tutorials

There is a checklist for good webgl programs, see best practices.

Babylon is a javascript engine with camera's scenes etc. It has a nice page about compressed textures on GPU harware on different hardware (windows, apple, samsung phone): compressed textures.

We did look at the webgl-v1.1.js mentioned before, using the program of Chapter 10 on camera's. We introduced a definition of an interface WebGL1_1RenderingContext with an methods for vertexarrays and the following code:

 * D3Q: used in DrawContext
export enum ContextTypes {

 * D3Q: a context that contains another context.
 * After creating, use only this context:
 *      use getWebGL2_0() to get a WebGl2 context
 *      use getwebGL1_1() to get a WebGL1.1 context
 * getWebGL2_0() will raise an error when contextType WebGl1.1 is in use.
export class DrawContext {

    contextType: ContextTypes;
    gl2_0: WebGL2RenderingContext = null;
    gl1: any = null;
     * D3Q: creates DrawContext
     * @param typeNeeded 
     * @param context for webgl types a canvas object
    constructor(typeNeeded: ContextTypes, context: object) {
        this.contextType = typeNeeded;

        switch (typeNeeded) {
            case ContextTypes.webgl1_1: {
                this.gl1 = (context as HTMLCanvasElement).getContext('webgl');
                if (!this.gl1) {
                    throw "WebGL 1 needed";
                let ext =
                    (this.gl1)._OES_vertex_array_object = this.gl1.getExtension('OES_vertex_array_object');
                this.gl1.VERTEX_ARRAY_BINDING = ext.VERTEX_ARRAY_BINDING;
                if (!ext) throw "Extension vertex array needed";

                //append functions for webgl1.1
                this.gl1.createVertexArray = function () {
                    return this._OES_vertex_array_object.createVertexArrayOES(...arguments);
                this.gl1.deleteVertexArray = function (vertexArray: WebGLVertexArrayObject) {
                this.gl1.isVertexArray = function (vertexArray: WebGLVertexArrayObject): boolean {
                    return this._OES_vertex_array_object.isVertexArrayOES(...arguments);
                this.gl1.bindVertexArray = function (array: WebGLVertexArrayObject): void {
            case ContextTypes.webgl2_0: {
                this.gl2_0 = (context as HTMLCanvasElement).getContext('webgl2');
                if (!this.gl2_0) {
                    throw "WebGL 2 needed";

    getWebGl2_0(): WebGL2RenderingContext {
        if (this.contextType == ContextTypes.webgl1_1) throw "WebGl1.1 in use";
        return this.gl2_0;

    getWebGl1_1(): WebGL1_1RenderingContext {
        if (this.contextType == ContextTypes.webgl2_0) return this.gl2_0;
        return this.gl1 as WebGL1_1RenderingContext;

The result was that on a Samsung Android vs. 4 with Chrome it did not work at all and on Androis vs. 7 the result was poor. On the computer it looks fine. To change a program to version 1.1 one also has to change the GLSL programs and take care of limitations such as that textures height and width have to be powers of 2. Our conclusion was: stick to WebGL2.

date: 22 sept 2020. version: 1.00.
code found at:
©Drikus Kleefsman