Creating a User Interface for Blend4Web (Part 1)

  • Tutorial
Sometimes I find myself a pioneer opening new pages using Blend4Web. This is a young engine, with an energetic development team, rich features and many not-so-well-documented features. Something I draw from the source code of a large number of demos, I pull developers on all kinds of issues, and most often I use the “scientific poke” method. In this article I want to share my experience in creating a user interface for an application. And what's important, with Blend4Web and HTML5 you can make a pretty decent game GUI.



In the game, when the boats fly, successfully shooting hordes of meteorites and their own kind, I want to see a little more on the screen, that is, to get any information about the gameplay. These are all kinds of text messages about missions or earned points, “life strips”, etc. All these elements can be created in two ways: using the HTML / CSS functions and through Blender / JavaScript.

In December 2015, the next release of Blend4Web was released with a curious feature. Talking about Viewport Alignment- This is nothing more than a tool for automatically aligning user interface elements with the camera. It seems nothing surprising, but you need to know that traditionally the layout of the GUI for the Blend4Web application is performed using HTML / CSS. Personally, this approach seems inconvenient to me and I prefer to do everything in Blender itself. It used to be difficult, because the interface “crawled” when changing the resolution or aspect ratio of the screen. Now it is possible to abandon the troubles with HTML and create a GUI directly in the Blender scene.

Static elements


From the point of view of Blend4Web, the GUI element is no different from any object in the scene, except that it is attached to the active camera. All magic is done in Blender itself.

GUI elements are traditionally considered two-dimensional, but in the case of Blend4Web they are always three-dimensional objects. True, they can look different. The easiest option is to create a Plane with a stretched texture.

There is a convenient plugin called “Import Images as Planes”, which is standard on Blender. Its purpose is to create a plane with an already finished texture. It really speeds up the process, because it’s enough to select the desired picture and it appears on the scene. But I do not recommend using this plugin for the GUI for one simple reason - not optimal. It is advisable to store all drawn interface elements on the same texture, i.e. create the so-called atlas.

You can draw an interface in anything, but it’s important to fit everything on a texture with the same aspect ratio as a multiple of 4, for example, 512x512, 1024x1024. And do not get carried away in size. Too small a texture is bad, too large is not very. So, the maximum size should be limited to a resolution of 2048x2048, although for me this is a lot. In general, it’s good practice to display pixel-by-pixel interface elements without any scaling. But in our case, this is unrealistic, because each element is an ordinary three-dimensional object.

So it turns out that the creation of the interface is performed by standard Blender tools. Consider the basic steps:

  • Create a Plane primitive ( ADD | Mesh menu ). First, switch to Camera view. When you add Plane to the scene, pay attention to the auxiliary panel on the left with the parameters of the created primitive. There is an Align To View option . If you activate it, then Plane will turn “face” to the camera.
  • Set UV coordinates. This is more convenient when the UV Editing window layout is on. Select your plane, press the Tab key to enter edit mode and U -> Unwrap to set the coordinates. Just open the desired texture in the next window. Now, using the standard methods of moving and scaling Blender (hot keys G and S), place the vertices of UV around the desired picture.




  • Create material and customize texture. In principle, this action is no different from the usual work with materials in Blender. Take a look at the picture below. I highlighted the key options for setting the texture and material with transparency. Shadeless is also included here . This is useful if you want your material to not react to light sources.




So, in the scene there is a plane with a texture rotated towards the camera. It’s time to consider the Viewport Alignment tool (do not forget that the options of the Blend4Web engine will become visible only after choosing a render with the same name).

Viewport Alignment allows you to “attach” the selected object to the borders or corners of the active camera. By doing this in Blender, you will be sure that the interface elements remain in place regardless of screen resolution.

First you need to create a parent-child relationship between your plane and the camera itself. Highlight Plane and then Camera with the Shift key pressed . From the Object -> Parent menu, select Object. If everything is done correctly, then when you move the camera, the plane will obediently slide after it.

And only now will the Viewport Alignment options in the Object panel become available.



Turn on Viewport Alignment and select the side you want to snap from the menu. If you now try to export the scene and view the result in a browser, then most likely you will get an amazing result. The object “sticks” to the selected location, but it will not look at all as expected.

The panel has a Fit to Camera button . Using it, you can place the object in accordance with the selected snap and distance parameters (option Distance) Therefore, by clicking on it, you finally move the item to the right place. There is another nuance that for some reason is not explained in the official documentation.

The fact is that the binding is performed depending on the center of the object. And for proper installation, it must be shifted in the right direction. The figure below shows the center of the element, which is pressed to the upper right corner.

To shift the center, go to edit mode ( Tab key ). Place the 3D cursor in the right place (by clicking the left mouse button) and select the menu item Object -> Transform -> Origin to 3D Cursor.



In such a simple way, you can create any interface elements that are attached to the camera and automatically change their location when changing the screen resolution

By the way, even though I called this part of the lesson “Static Elements”, nothing prevents you from creating any animations for GUI elements. All this is done in standard ways for Blender.

Dynamic elements


Do you think I'm going to start talking about cool animation effects? No, I’ll leave this fertile ground to other authors, and I’ll move on to this topic ...

In the game very often we need all kinds of indicators: life, protection, heating of weapons, etc. Their visual appearance depends on the current action. The hero is rich in “life” - a long strip, loses the “life” and the strip decreases.

The simplest thing that comes to mind is to create an object animation, for example, with a change in scale. But you also need to consider the convenience of working with such an animation, because the size of the indicator must correspond to some digital value. Therefore, the most advantageous is a change in geometry, the so-called vertex animation. Moreover, it is enough to create two forms: initial and final. And the transitions between them from the code.

Algorithm for creating shape animation (see the figure below):
  • Give the object an initial shape.
  • Go to the Object Data panel and set the base key (in the screenshot it is called Basis).
  • Add a new key (key 1) and set the Value to one.
  • Go to edit mode and give the object a final shape.
  • Open the Object panel and enable the Export Shape Keys option.




If everything is done correctly, then when changing the value of Value, the geometry of the object will change.

This is where the magic lies. The Blend4Web API allows you to control the Value parameter from the code. Its values ​​vary from 0 to 1, so it’s easy to write the adaptation function of any digital data as applied to the status bar animation.

A small example:

...
var m_scene = b4w.require("scenes");
var m_geom = b4w.require("geometry");
…
//ищем в сцене объект с именем "Object Name"
var obj = m_scene.get_object_by_name("Object Name");
//устанавливаем значение Value ключа Key 1, как 0.5 (50%)
m_geom.set_shape_key_value(obj , "Key 1", 0.5);
...


Text output


These are all kinds of messages, points earned and everything like that, which allows the player to receive returns from the game process.

At first glance, Blend4Web has nothing to display text information on the screen, not in the form of pictures or 3D, but in plain text itself. To be honest, at first I was baffled when I tried to implement a simple Print Score. There were no native functions in the API. But there is an excellent mechanism for working with HTML5 Canvas. And with its help, miracles can be done with the text.

Working with HTML5 outline in the official documentation of the engine is considered extremely sparingly. Some important points are simply not taken into account. Hereinafter I will try to talk about them.

So, the basis of the canvas in the world of Blend4Web is any surface of a three-dimensional object. This means that you can display text or other information on the canvas (for example, video), and then work with this object as you wish. It offers great opportunities for the coolest effects. After all, a 3D model with a canvas is no different from any other three-dimensional object - rotate, scale, apply animation and physics. Here is an example of working with canvas , which the developers themselves cite.

In my game, I used a simple rectangular plane attached to the corner of the screen to display Score. You don’t need to apply any special settings to the canvas object. The material is the most ordinary, but a special texture is used.

Preparing an object surface for HTML5 Canvas output:
  • Create a UV scan for the plane where the canvas is supposed to be drawn. Be careful and start placing your UV mesh from the top of the texture. For some reason, I initially placed UV at the bottom of the texture and lost a lot of time trying to figure out why there is no rendering.




  • Add a new texture of type None to the texture slot of the material. Give her a normal name.
  • In the texture options, set the Source Type to Canvas.

In principle, everything. We pass to the code.

In the examples on the Blend4Web site, there is a ready-made piece of code that displays text literally on the canvas. It was him who I used in my project. I bring with some changes and additions.

…
var m_tex = b4w.require("textures");
var m_scene = b4w.require("scenes");
...
// параметры печати текста
    var text = ["Hello”, “World!"];
    var MARGIN_LEFT = 250;
    var LINE_SPACING = 10;
    var MARGIN_TOP = 120;
// поиск объекта-носителя канвы
    var obj = m_scene.get_object_by_name("Object");
// поиск текстуры по имени
    var ctx_image = m_tex.get_canvas_ctx(obj, "tex_id");
    var font = ctx_image.font.split("px");
    var font_height = parseInt(font[0]);
//HTML5 Canvas функции и переменные
    ctx_image.fillStyle = "rgba(255,230,0,255)";
    ctx_image.clearRect(0,0,512,512);    
    ctx_image.font = "120px Arial";
    ctx_image.textAlign = "start";
//вывод текста
    for (var i = 0; i < text.length; i++)
        ctx_image.fillText(text[i], MARGIN_LEFT, Math.round(LINE_SPACING * font_height * i + MARGIN_TOP));
// обновление канвы
    m_tex.update_canvas_ctx(obj, "tex_id");


There is nothing complicated in this code and it is hardworking to display letter by letter. The most interesting thing is the parameters of the HTML5 Canvas itself. Truly wide opportunities open up here. Consider some of them.

Magic HTML5 Canvas


You can use not only system fonts, but also downloadable ones. To do this, add the following description to the CSS file:

@font-face {
    font-family: MyFont;
    src: url(fonts/MyFont.ttf);
}


In this case, the font initialization string will look like this:

ctx_image.font = "120px MyFont";


The font color in RGBA format is set by the line:

    ctx_image.fillStyle = "rgba(255,230,0,255)";


You can change the alignment of the text inside the canvas. For example, in the center:

ctx_image.textAlign = "center";


There are some effects with shadows:

    ctx_image.shadowOffsetX = 5;
    ctx_image.shadowOffsetY = 5;
    ctx_image.shadowBlur = 10;
    ctx_image.shadowColor = "rgba(255, 132, 0, 1)";


In the end, having played around a bit with the capabilities of HTML5 Canvas, I got the required output from Score.



So, the traditional conclusions. The Viewport Alignment tool solves all the problems of positioning elements. Integration with HTML5 Canvas allows you to easily display information with wide possibilities for creating text effects. 3D + Canvas is generally a unique feature for creating unusual three-dimensional menus, windows and more complex elements.

And here is a fly in the ointment (where would it be without it) - there is not enough tool for conveniently setting the output of information to HTML5 Canvas. With any change in the parameters of the canvas, you have to export the project to check the result. This, of course, takes a lot of time for such experiments. But in general, there were no special problems in creating a custom UI for the Blend4Web application.

Also popular now: