Wt-WebGL Lessons

De Vicomwiki

This document explains how to implement the WebGL (JavaScript) lessons (http://learningwebgl.com) using Wt. Wt is a c++ based API to develop web applications that allows to generate dynamic Web pages that redefines the source-code during the execution of the page, according to certain events. In the next chapters, the different lessons (from lesson 1 to 16) are implemented and explained.

This document assumes that the reader has knowledge about all the lessons, hence it will only focus on the implementation details over Wt.

Contenido

[ocultar]

Wt-WebGL Lesson 1

Webgllesson1.png

Program the lesson

All Wt applications must begin by running the application. Therefore, the main function must contain the call to WRun( int argc, char **argv, Wt::ApplicationCreator createApplication) included in #include<Wt/WApplication>. In this case, the function that creates the application is createApplication(), therefore the main function is defined as:

int main(int argc, char **argv) {

    return WRun(argc, argv, &createApplication);

}

The class WebGLDemo, holds the application itself. It is an inherited class from a Wpplication. Therefore, createApplication() calls the creation for a new application:

WApplication *createApplication(const WEnvironment& env) {

    return new WebGLDemo(env);

}

In the class WebGLDemo, the title and initial text to be displayed in the web page are defined.

setTitle("Demo");

root()->addWidget(new WText("Wt/WebGL Lesson 1: A Triangle and a Square"));

A WBreak() is added, in order to separate the text from the other parts of the document vertically.

root()->addWidget(new WBreak());

A container widget is created to hold the WebGL application. The container is resized and is forced to be placed vertically between the other components of the webpage (i.e., nothing will be placed in both sides of the container).

    glContainer_ = new WContainerWidget(root());
glContainer_->resize(500, 500);
glContainer_->setInline(false);

Then, the method updateShaders() is called in order to link the container widget with the WebGL widget DrawGLWidget. The widget is created and resized.

void WebGLDemo::updateShaders() {

    delete drawGLWidget_; drawGLWidget_ = new DrawGLWidget(glContainer_);
    drawGLWidget_->resize(500, 500);
    …

Since all WebGL applications need to haver user-defined shaders, then the shaders are set to the widget, using string variables to hold them (vertShad,fragShad), and finally an alternative content is set, in the case the browser does not support WebGL:

    …
drawGLWidget_->setShaders(vertShad,fragShad);
drawGLWidget_->setAlternativeContent(new WImage("nowebgl.png"));
}

Finally, to finish the structure of the Web page, some text lines are displayed

    root()->addWidget(new WBreak()); 
    root()->addWidget(new WText("This demo has been developed by Vicomtech-IK4 Research Center"));

    root()->addWidget(new WBreak()); 
    root()->addWidget(new WText("Based on the learningwebgl.com lessons.")); root()->addWidget(new WBreak()); root()->addWidget(new WText("www.vicomtech.es"));

Inside the WebGL widget (DrawGLWidget) the functions and structure described in the WebGL lesson 1 (http://learningwebgl.com/blog/?p=28) are implemented. The main difference between a Wt implementation and a Javascript implementation, is that the code that is being written will not be the final source code of the web page. It will be an intermediate code that will specifically write the javascript source code that will be sent and compiled in the client. As a result, acquisition of data is not performed in real time, and therefore statements like Shader vertexShader = createShader(VERTEX_SHADER); will not return a shader object but a string that holds the name of the javascript variable that really holds the shader object.

Another difference, is that the general commands to produce a WebGL-enabled application must be divided in three different functions. initializeGL(), paintGL() and updateGL().

initializeGL() is a function that is meant to contain the parameters to initialize programs, buffers, textures and so on, this is, the code that should only be performed once in the program. For that reason, we perform the shader initialization as well as the buffer initialization in that function. Due to the fact that in c++ the types of the data are important to determine the behavior of the function (i.e., the kind of data that should be “printed out” in the javascript source-code), there are type-specific calls to the buffer creation. In this case, since the buffers are created with an array of floats, the function that prints out the data is bufferDatafv(...), in which “fv” stands for Float Vector.

paintGL() is a function that is meant to contain the code to perform the explicit draw calls, and that will be called again when a scene “refresh” is needed, i.e., when a mouse event or a keyboard event, or animation is performed, when . This is, calls to set uniform values, set attribute pointers and perform the different draw commands such as drawElements(...) or drawArrays(...). In this case, the functions that set the different uniforms and the functions that perform the draw calls are set in this function.

updateGL() is a function that is meant only when it is needed to do changes to the data that was created in the initializeGL(), this is, when a texture should be reloaded, modified or created, when buffers need to change internal data because of level of detail change in the scene and so on. In this case, there is no need to modify parameters, therefore this function is not needed.

For any further detail on the implementation, please refer to http://learningwebgl.com/blog/?p=28

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added when the executable file will be run.:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 2

Webgllesson2.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 1. The differences between this code and the one in Wt-WebGL Lesson 1 are only referred to what is documented in http://learningwebgl.com/blog/?p=134 In this lesson there is not Wt- specific difference with Wt-WebGL Lesson 1.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 3 Server-side animation

Webgllesson3.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 2. javascript source code to generate de example is docuemented in in http://learningwebgl.com/blog/?p=239. This example shows how to implement a simple animation procedure, varying at each frame the model view matrices of each object.

In this case, the implementation of the example was made using a server-side variation of the matrices, i.e. a timer is set up in the server, in order to produce the continous data exange with the client in orfer to produce the animation. The server computes the new matrices, and sends them to the client whith a new paint function that contains the new matrices. In a further example, it will be shown how to implement them using a client-side modification of the matrices, in order to avoid the data transfer bandwidth consumption and speed up (make more smooth) the animation.


Different from the Wt-WebGL Lesson 2, relies in the fact that in the constructor of the WebGLDemo class, a timer is set up using the following code:

//Set up the Timer in order to animate the scene.
timer = new WTimer(drawGLWidget_);
timer->setInterval(25);
timer->start();
timer->timeout().connect(this,&WebGLDemo::animate);

this is used to set up the timer with a 25 ms interval, and at its timeout, the function WebGLDemo::animate() is executed

In that function a request for an Ajax call (a comunication protocol in qhich portions of code can be trasfered between server and client), in which the paint function is re-written is made. As a result the DrawGLWidget object updates the matrix values during the execution of the server-side paintGL() function and then sends the resulting function to the client.

In order to modify the matrices, the following line of code is added to the Paint function

mvMatrix.rotate(angle,0,1,0);
angle+=1.0;

This will change the value of the global float value "angle" to create at each iteration a new matrix to represent the data.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080



Wt-WebGL Lesson 3 Client-side animation

Webgllesson3.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 2. javascript source code to generate de example is docuemented in in http://learningwebgl.com/blog/?p=239. This example shows how to implement a simple animation procedure, varying at each frame the model view matrices of each object.

In this case, the implementation of the example was made using a client-side variation of the matrices, i.e. a javascript "requestAnimationFrame" was programmed in which the matrix modifications were performed, and the paint function was called.

In this case, different from the server-side animation procedure, only javascript code is needed to perform the animation. For that reason in DrawGLWidget, new functions are defined:

void DrawGLWidget::setJavaScript(){ 

    std::stringstream sss;

    sss<<1;
   clientSideFcn_.setJavaScript("function WTVicomGLAnim(){if (myTickValue=-"+sss.str()+"){}"+"if (!window.requestAnimationFrame) {" +
                                "window.requestAnimationFrame = (function() {" +
                                "return window.requestAnimationFrame ||" +
                                "		 window.webkitRequestAnimationFrame ||" +
                                "		 window.mozRequestAnimationFrame ||" +
                                "		 window.oRequestAnimationFrame ||" +
                                "		 function(/* function FrameRequestCallback */ callback, /* DOMElement Element */ element) {"+
                                "		   window.setTimeout(callback, 1000/60);" +
                                "		 };" +
                                "})();}" + 
                                " var obj = " + "(function(){" +
                                "var r = " + jsRef() + ";"+
                                "var o = r ? jQuery.data(r,'obj') : null;" +
                                "return o ? o : {ctx: null};" +
                                "})()" +"; var ctx=obj.ctx; "+WT_CLASS ".glMatrix.mat4.rotate(" +
                                trRotMatrix.jsRef()+",0.01,[0.0,1.0,0.0],"+trRotMatrix.jsRef()+");" +
                                +WT_CLASS ".glMatrix.mat4.rotate(" +
                                sqRotMatrix.jsRef()+",0.005,[1.0,0.0,0.0],"+sqRotMatrix.jsRef()+");" +
                                "  obj.paintGL();" +
                                "  window.requestAnimationFrame(WTVicomGLAnim);"+
                                "}/**Vicomtech_Client_Side_Code*/");

}

In this function a JSlot clientSideFcn_ is defined in order hold the Javascript function. In the function, the javascript variables (javascriptMatrix4x4 trRotMatrix and javascriptMatrix4x4 trRotMatrix) to which each model is related to in the client's paint function is related to, are modified to produce simple rotations. The JSlot is created in order to relate the client event of a button click to the execution of what is inside the slot (the continous call function). However if a event-independent animation wants to be set up, the function 'doJavaScript("javascript string code")' can be used in order to print the code directly in the webpage source code. It's important to notice, that since that call will not call the function itself, but it will "paste" in the web page the string added, the additio of the execution of the function is mandatory, i.e add the following line to the string inside doJavaScript:

doJavaScript(string + "WtVicomGLAnim();");

In order to relate the JSlot with the button, in Lesson3.cpp, inside the WebGLDemo constructor, the following lines are added:

WPushButton *buttonAlert= new WPushButton("start Anim 1", root());
buttonAlert->clicked().connect(drawGLWidget_->clientSideFcn_);

Here, a new button is added, and the click event on it is related to execute the client-side JSlot.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080



Wt-WebGL Lesson 4

Webgllesson4.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 3 Server-side animation. The differences between this code and the one in Wt-WebGL Lesson 3 Server-side animation are only referred to what is documented in http://learningwebgl.com/blog/?p=370. no Wt-specific code is added or modified, therefore it wont be documented.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 5

Webgllesson5.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 3 server-side animation. The JavaScript source code to generate the example is documented in http://learningwebgl.com/blog/?p=507. This example shows how to implement a simple texture over a simple object.

In order to implement a texture into an object two important procedures must be followed:

  • In the costructor of DrawGLWidget, a function to preload each image is required. Therefore, the following line must be added with the address of the image:
texture2 = createTextureAndLoad("./vicomLogoSm.png");


  • In the creation of the images, texture2, which has preloaded the image, is set to load the textures, as the input parameter, this is:
void DrawGLWidget::initTextures(){
    texture = createTexture(); //ok
    bindTexture(TEXTURE_2D,texture); // ok Really works!!!!!!!!!!!!!!!!!!
    pixelStorei(UNPACK_FLIP_Y_WEBGL,true);// Works
    texImage2D(TEXTURE_2D,0,RGBA,RGBA,UNSIGNED_BYTE,texture2); // Works
    texParameteri(TEXTURE_2D,TEXTURE_MAG_FILTER,NEAREST);
    texParameteri(TEXTURE_2D,TEXTURE_MIN_FILTER,NEAREST);
}

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 6

Webgllesson6.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 5. The javascript source code to generate de example is docuemented in http://learningwebgl.com/blog/?p=571. This example shows how to implement keyboard events. Since the animation in this example is programed server-side, the events and results of the events are analyzed server-side. There, the parameters for the animation are changed, varying the animation display.

In the WebGLDemo constructor, an event listener to the keyboard events is added in order to be lounched each time a keyboard event occurs. I the event occurs, a function that determines the pressed key and performs the specific animation event is run.

this->globalKeyWentDown().connect(this,&WebGLDemo::eventKeyWentDown);

According to the pressed key, a different parameter change is performed.

void WebGLDemo::eventKeyWentDown(const WKeyEvent& event)
{
    int e = event.keyCode();

    if (e == ('f'- 32) ) {// change if "f" is pressed.
        drawGLWidget_->changeTextureFilters();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }else if (e ==  34 ) {// change if "avpag" is pressed.
        drawGLWidget_->decrementZDepth();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }else if (e ==  33 ) {// change if "repag" is pressed.
        drawGLWidget_->incrementZDepth();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }else if (e ==  38 ) {// change if "up" is pressed.
        drawGLWidget_->incrementRotX();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }else if (e ==  40 ) {// change if "down" is pressed.
        drawGLWidget_->decrementRotX();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }else if (e ==  39 ) {// change if "right" is pressed.
        drawGLWidget_->incrementRotY();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }else if (e ==  37 ) {// change if "left" is pressed.
        drawGLWidget_->decrementRotY();
        drawGLWidget_->repaintGL(DrawGLWidget::PAINT_GL);
    }
}

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 7

Webgllesson7.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 6. The differences between this code and the one in Wt-WebGL Lesson 6 are only referred to what is documented in http://learningwebgl.com/blog/?p=684 . No Wt specific new code was added in order to perform this lesson.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 8

Webgllesson8.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 7. The differences between this code and the one in Wt-WebGL Lesson 7 are only referred to what is documented in http://learningwebgl.com/blog/?p=859 . No Wt specific new code was added in order to perform this lesson.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 9

Webgllesson9.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 8. The differences between this code and the one in Wt-WebGL Lesson 8 are only referred to what is documented in http://learningwebgl.com/blog/?p=1008 . There are not Wt-specific differences with the previous lessons.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 10

Webgllesson10.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 9. The differences between this code and the one in Wt-WebGL Lesson 9 are only referred to what is documented in http://learningwebgl.com/blog/?p=1067 . There are not Wt-specific differences with the previous lessons.

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 11

Webgllesson11.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 10. The javascript source code of this example can be found in http://learningwebgl.com/blog/?p=1253 . This example shows how to implement a simple client-side mouse interaction with the scene.

The implementation relies to perform the computation using client-side variables, instead of a continuous communication with the server. This is possible if using the Wt client-side matrix javaScriptMatrix4x4. Also, Wt has already implemented mouse handler functions to interact with he user with zoom, rotation and displacement along the

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 12

Webgllesson12.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 11. The differences between this code and the one in Wt-WebGL Lesson 11 are only referred to what is documented in http://learningwebgl.com/blog/?p=1359 .

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 13

Webgllesson13.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 12. The differences between this code and the one in Wt-WebGL Lesson 12 are only referred to what is documented in http://learningwebgl.com/blog/?p=1523 .

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080


Wt-WebGL Lesson 14

Webgllesson14.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 13. The differences between this code and the one in Wt-WebGL Lesson 13 are only referred to what is documented in http://learningwebgl.com/blog/?p=1658 .

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080

Wt-WebGL Lesson 15

Webgllesson15.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 14. The differences between this code and the one in Wt-WebGL Lesson 14 are only referred to what is documented in http://learningwebgl.com/blog/?p=1778 .

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080

Wt-WebGL Lesson 16

Webgllesson16.png

Program the lesson:

In order to initialize the Wt application and to have a basic idea on how to create a basic WebGL application please refer to the Wt-WebGL Lesson 15. The differences between this code and the one in Wt-WebGL Lesson 15 are only referred to what is documented in http://learningwebgl.com/blog/?p=1786 .

Run the Lesson:

To run the application, if you are using an http connector, the following parameters must be added:

--docroot . --http-address 0.0.0.0 --http-port 8080

With this, the application will run in the following address in your WebGL enabled browser:

http://127.0.0.1:8080