📜 ⬆️ ⬇️

Optimizing assets for WebGL correctly

So often it happens that optimization techniques that work well for regular desktop or mobile graphics do not always give the desired effect in the case of WebGL. In this article, I collected (or rather translated into Russian and set out in a text form our presentation with Verge3Day) those methods of increasing productivity that are well recommended for creating interactive web applications.



Geometry / Meshes


The correct geometry is the key to the performance of any three-dimensional application. To get smooth shading and fast rendering, you need to keep the polygonal mesh as even as possible. At the very beginning of the work, you should decide on the level of detail of your scene and stick to it when modeling.


')
When modeling wrinkles, it is better to use shading groups, rather than adding more polygons.



When working with a cylindrical model, try to reduce the number of polygons closer to the center.



Do not overload the model with additional details that the user will not see anyway. As shown in the figure below, the edge highlighted in orange determines the level of detail for the entire model, so you can use it as a guide.



Normal maps


A common way to optimize WebGL performance is to reduce the number of polygons by creating normal maps.



However, normal maps can create visible artifacts due to the limited accuracy of the 8-bit image. Possible solutions to this problem are shown in the picture below, but they are rather difficult to implement: using an image with higher accuracy will lead to an increase in the size of the downloadable file, while the second approach is rather laborious and does not guarantee a net result. The third approach sometimes works in the case of rough surfaces. In this case, we recommend adding noise to your materials to reduce potential artifacts.



Based on our experience, we concluded that the best solution for glossy objects is to use geometry of medium complexity with smooth vertex groups, and without using any normal map.



Finally, here are some cases where you can use a normal map, and not a very detailed mesh:




Texturing


Here is a typical set of textures used in modern PBR lighting models (and not only).



As you can see, most of them are black and white. Therefore, you can combine black and white textures in RGBA channels of one image (up to 4 cards in total per image).



If you only have one b / w texture, you can combine it with any existing RGB texture, wrapping it in an alpha channel. Finally, if you don't have an image to merge, you can convert your black and white image to jpeg format with 95% compression and gray mode enabled.



Another way to reduce the size of the texture is to optimize the UV sweep. The smaller your scan, the more efficient your image will be using texture space. This allows you to have more lightweight images without losing quality.



Vertex colors


Using vertex colors instead of images is an effective way to speed up the loading and improve the overall performance of your WebGL applications. The only drawback is that you have to add a few extra edges to your model in order to separate the colors of the same vertices.



You can also use vertex colors to determine roughness, metallicity or mirror surfaces, or any other parameters. Below you can see an example of such a material in which only the colors of the vertices are used.



Number of shaders


It is very important that there are fewer different materials / shaders on your scene. Compiling shaders in WebGL leads to long loading, which is especially noticeable in Windows. In addition, if you have fewer shaders, the engine will spend less time switching between them during rendering, thereby improving performance.

If you have similar materials that differ only in textures, you can use only one material and load / change its textures at runtime. To do this, you can use JavaScript or use the visual logic editor available in some WebGL frameworks. This not only optimizes the number of shaders, but also reduces the number of images that are loaded when the application starts.



Here is an example of such optimization. All four varieties of the same tire are represented by the same material, and are customized by replacing textures.



To reduce the number of shaders, you can combine 2 or more simple materials into one more complex. This method is especially effective if you plan to switch between these materials (for example, create a configurator application), and not just switch, but also animate the transition from one material to another smoothly and beautifully.



Draw calls


In addition, there is another important aspect - the number of Draw-calls (they are draw calls and draw calls). This roughly corresponds to the number of individual objects if only one material is assigned to each object, while objects with several materials require even more calls to render them.

Therefore, you should strive to merge grids whenever possible, and use fewer unique materials to reduce the number of draw calls and improve performance.



If you have an animated object, you can still connect its parts and use the bones for animation, which is sometimes more convenient for animating individual objects.



HDR lighting


This helps to significantly improve performance if you illuminate your scene only with an HDR image, without using any light sources. An HDR file can weigh less than 1 MB.



Shadows


Use dynamic shadows only when they help to present your object in the best possible way. The image below shows the dynamic shadows from our Industrial Robot demo. Since the model itself rotates in this application, and not the camera, the shadows cannot hide any part of the object from the user and perfectly emphasize the shape of the robot. On the other hand, the same shadows in the Scooter demo will obscure many details of the model.



From here we conclude: if your object does not move in the application, you can bake shadow maps and ambient occlusion and assign them to the plane below the object. Such a solution will be more productive and look better than when using dynamic shadows.



That's all. If you have any other tips that can help with WebGL performance, write in the comments.

Source: https://habr.com/ru/post/456526/


All Articles