Hi, Im Tony Albrecht, one of the engineers Render Strike Team is a new beginning in League of Legends. This should improve the rendering engine of the game, and we cant wait to get to work. I will briefly talk about how the engine works now.
For me its a great excuse to walk through the stages of the graphics pipeline in order to make the team understand what we have to work. Ill tell you how League of Legends builds and displays a single frame in the game (remember, on powerful computers, this happens over 100 times per second). The discussion will include technical details, but I hope will be affordable even for those who have no experience in rendering. To begin with — a couple of words about the graphics available to us libraries.
League of Legends should work effectively on many platforms. For example, Windows XP is now the fourth most popular OS among our players (after Windows 7, 8 and 10). Every month, Windows XP users are involved in more than 10 million matches, and to preserve backward compatibility, we must support DirectX 9 and only use their chips. We use a broadly similar set of functions of OpenGL 1.5 on computers with OS X, but that will soon change.
In most of the computers have a CPU (Central processing unit) and GPU (graphics processor). The CPU is responsible for logic and computation of the game, while the graphics he gets from the triangles (triangles) and textures and displays them on the screen as pixels. Pixel shaders (pixel shaders) is a small program on the GPU, allowing us to affect the rendering. For example, you can change how textures are applied to the triangles, or to cause the GPU to perform calculations for each Texel of the texture.
Thus, it is possible to apply the texture to the triangle, or impose on him a variety of textures, or run more complex processes, like bump mapping (bump mapping), lighting, reflections or realistic skin Shader. All visible objects are drawn in the framebuffer and displayed on the screen when rendering is complete. Consider the example. Here is a picture of Garena, showing all 6336 triangles on the frame — monolithic model without textures.
It was created by our artists and exported to a format that can read and animate the engine League of Legends. You may notice a non-planar shading. This limitation of the application used for the study of rendering. The image of the model without textures not only boring, but also obscure.
It does not convey the fact of Garena, which we all know. To revive the character, the right texture. Garena textures are on the disk as a DDS or TGA file that looks like a frame from a horror movie. But if you correctly apply them to the model, we get this image:
Its already something similar. A Shader that renders our mesh with skinning (skinned meshes), not only impose a texture on the model, but well talk to you later. These are the basics, but League of Legends needs to render not only the champion model and textures.
Consider a phased rendering the whole following scene. Before otrisovany scenes we must prepare the fog of war and shadow (mist and shadow — sounds ominous). The CPU stores the fog of war in the form of a grid (grid) 128 by 128, which massturbate to a square texture of 512 by 512. After we dissolve this texture and use it to darken the appropriate areas and zones on the minimap.
The shade is an essential part of 3D scene, without them it would seem that the objects hang in the air. The shadow should be rendered relative to the light source, to make it seem that they cast a minion or champion. The distance from the light source to the object casting a shadow is taken into account for each pixel in the RGB components and the alpha component set to zero.
The first image below is the elevation eld of shadows (shadow height field) besieged towers, minions and Champions in RGB. On the second — only the alpha component. Textures were cropped to the details of the shadows and was visible. The minions at the bottom, and the tower and Champions at the top.
Finally, we blur the shadow, smoothing their boundaries (the display of which was recently optimized to improve frame rate). The result is a texture that can be applied to static geometry to create the shadow effect. Preparing the fog of war, and the texture of the shadows, we begin to draw the remainder of the scene in the frame.
First and foremost this is a static geometry (static geometry), that is, objects without animation. It combines the fog of war and information about shadows with your primary texture. The result is this image: Pay attention to the shadow minions and the fog of war, climb onto the border of the stage.
On the map Summoners rift (The Summoners Rift) for static geometry are not rendered dynamic shadows. The main light source is not moving, so the shadows of static meshes (static meshes) “baked” on their textures. So artists can better control the appearance of the card, and improves performance (because you do not need to render shadows from static meshes). Shadows can only drop minions, towers and Champions.
The relief and shadow is already possible to overlay objects. In the first place — minions, Champions and towers — that is, those that should realistically move and have stiff joints (bending joints). Each animated mesh (animated mesh) contains a skeleton (a framework of hierarchically arranged bones) and the mesh of triangles (mesh of triangles), such as the image above of Garena. Each vertex is associated with the bones (one to four), the movement of which vertices move in the manner of the leather — hence the name “skinning”.
Our artists create meshes and animations for all objects and export them in a format that is uploaded to League of Legends early in the game. All bones of the mesh model Garena demonstrated in the images above. Left his bones with the names.
To the right of the top (blue cubes) and the yellow line showing bind them to the bones that control their position. In addition to rendering of meshes with skinning in the HR buffer shaders meshes rendered their scaled depth in another buffer, which we use later for contours. And the skinning Shader calculates the Fresnel effect (Fresnel) and the emitted light, calculate the reflection and change the lighting for fog of war.
Polygon selection is the default for meshes with skinning, and makes their outlines more clearly. It helps to separate them from the background, especially in areas with low contrast. The first of the images at the bottom of the selection circuits is disabled, the second enabled.
The contours are obtained using the scaled depth of the previous stage to apply the Sobel filter (Sobel filter) that extracts boundaries that we will render each mesh individually. If the GPU cant render to multiple objects at once, apply the fallback method using the stencil buffer. Shadow grass — part of the texture of the earth, they are not rendered dynamically.
Now add the grass: Tufts of grass — also mesh with skinning. So we can animate them when they are crossed by characters or the wind blows in Summoners rift (Summoners Rift).
After the grass is being rendered water — semi-sheer mesh with lightly animated textures waves. After you have added the water lilies, the ripples of the stones and the shore, insects. The animation of these objects gives life to the scene. To emphasize the effects of water (which is not particularly conspicuous), I removed the geometry under water, but kept the transparency.
It highlights the effects to us it was easier to study them. In the following image, the highlighted frame of the entire ripple. You can see the effects of the water on the banks of the river, around the rocks and Lily pads.
Animated and normal rendering the water looks like this: After the grass and water are added the decals — simple flat geometry with a texture overlapping on the ground, like a indicator of range of the guns of the tower in the image below. Some of the contours become thicker when the mouse is over the object or the inclusion of specific conditions, like the tower in the picture below.
They are created in the same way as conventional circuits, but use a stronger blur to make them thicker. Also, these contours stand out above the rest because are created at a later stage of the rendering and may block some effects. Next is one of the most important stages. Particles.
I wrote an article about them earlier. Each spell, increasing the effect is a particle system that you want to animate and update. This particular scene is not as dynamic as, say, battle 5 on 5, but still a lot of particles. Show only particles (generally removing the background), we will see the following:
If you show the triangles particles (without textures), we will see purple geometry: And look particles during normal rendering.
Now, when the main part of the scene is drawn, it is necessary to “Polish”. For this we first make a pass with anti-aliasing (AA) is the smoothed border and make the image “cleaner”. On a static image, this effect is not very noticeable, but it helps to reduce the effect of flickering pixels, which occurs when you move a high-contrast borders around the screen. In League of Legends we use the fast algorithm for smoothing Fast Approximate Anti-Aliasing.
The picture on the left minion without smoothing and to the right is smoothed using FXAA. Note how the softened border. Upon completion of FXAA we carry out gamma correction by adjusting brightness of the scene. Recently, to optimize the screen after the death of the character we added to this process the reduction of the saturation of the screen.
Now, when the champion dies, no need to replace all the visible shaders on meshes bleached option. At this stage of the game are rendered indicators. Health bars, indicators of the damage, and the rest of the text on the screen. Also displayed is not included in the post-process full screen effects, for example, the effect of damage on the image below.
Finally, the rendered user interface. Text, icons and objects are superimposed on top of everything else as a separate texture. In this scene about a thousand of triangles are used for the interface, approximately 300 mini-card and 700 for everything else.
The entire scene contains about 200 thousand triangles, about 90 thousand of them are used only for particles. Over 625 of draw calls (draw calls) render 28 million pixels. For comfortable game it should happen as quickly as possible. You can achieve more than 60 frames per second, if all the stages are passed in less than 16.66 milliseconds.
What we have described is from the side of the GPU. The CPU during this time, cheat all the game logic, handles the command user input, collision, particles, animation, and delivers the commands to the GPU. If the frame rate you have is 300, so all this happens in less than 3.3 milliseconds.
Now you know what difficulties connected the render single frame League of Legends. But this is only part of the output. On the screen you see is the result of hundreds of thousands of function calls to the rendering engine — it is constantly changing and evolving to meet the demands of the time. In the codebase of the game there are different forms of rendering to support new and old hardware.
Cards work differently. Summoners rift (Summoners Rift) renders a little differently than the Howling abyss (Howling Abyss) or forest of the Damned (Twisted Treeline). Some parts of the rendering engine remained from the previous versions League, others did not reach their potential. Team Render Strike Team needs to rework the code so the rendering was performed through the same interface.
If we can handle it — players will not notice the difference (except perhaps performance improvements in some moments). But after completion we will be able to make changes to all game modes simultaneously.