GameDev

How to Optimize Graphics in Games

How to Optimize Graphics in Games

Learn: The Profession of Game Designer from Scratch to PRO

Learn more

In 2021, programmer Vasif Abdullayev discussed the importance of graphics optimization in video games from a developer's perspective during the From Zero to Game online session on the Azerbaijani portal Gamepons. He explained in detail what optimization is, how exactly developers improve graphics in games, why it is necessary, and what effort such processes require. Graphics optimization is a key aspect of game development, contributing to increased performance and a better user experience.

Skillbox Media's Gamedev editorial team presents the key points of this report. It examines important aspects of the development of the gaming industry, innovations in game design, and current trends influencing video game creation. The report offers an in-depth analysis of current changes in game development and highlights the significance of these factors for the future of the industry.

More than five years of experience in developing mobile and desktop games, both in indie teams and large studios. His specialization includes gameplay programming, CG shader creation, and multiplayer development using Unity and Unreal Engine. He currently works in collaboration with the Turkish studio Coconut Game, which allows him to apply his skills to the creation of innovative gaming projects.

What is Optimization?

Code or software optimization is an important process aimed at improving the performance of individual program components and reducing resource consumption. In the context of game optimization, resources include the graphics processing unit (GPU), central processing unit (CPU), smartphone battery, RAM, and other hardware components. Effective optimization can ensure smoother gameplay, improve visuals, and extend the battery life of devices. This is especially true in resource-constrained environments such as mobile platforms, where each optimization can significantly improve the user experience.

There are two main categories of optimization in game development. The first category includes performance optimization, which is aimed at improving the game's speed and reducing the load on hardware resources. This may include optimizing code, graphics, and physics to ensure a smooth gameplay experience even on devices with limited capabilities.

The second category is user experience optimization, which focuses on creating a convenient and intuitive interface, improving controls, and increasing player engagement. This may include testing on various devices and collecting user feedback to make necessary changes.

These two optimization categories are interconnected and play a key role in creating a successful game, ensuring not only technical stability but also a high-quality player experience.

  • Code optimization, which mostly affects the CPU, is performed by programmers responsible for gameplay, UI, combat, and other important elements of the game;
  • Graphics optimization is a more complex process that involves both processors. Game graphics programmers and technical artists are responsible for this type of optimization.

Why optimize graphics in games

  • A developer is always interested in their game selling well. But not every player can boast of having modern hardware. According to Steam statistics, as of March 2023, the share of systems with a NVIDIA GeForce GTX 1060 video card was 7.85% of the total number of builds (for comparison: the leader NVIDIA GeForce RTX 3060 has 10.67%). A project with modern, but unoptimized graphics will slow down significantly on a system with a relatively weak video card or will not launch at all. This means that not everyone will be able to play the game. Thus, optimization increases audience reach.
  • Each platform - consoles, portable devices, smartphones, tablets - has its own hardware. If a developer plans a multiplatform release, the game must run perfectly on all specified devices. Therefore, it must be optimized.
  • Finally, optimized graphics are the key to smooth gameplay without frame drops, even if the scene contains many detailed objects.

Examples of highly optimized games include projects that provide stable performance and smooth gameplay across various devices. Such games include both indie titles and large AAA titles. Successful optimization allows players to enjoy high-quality graphics and responsive controls, regardless of the specifications of their computers or consoles. Well-optimized games not only attract more users but also create a positive image for their developers. Examples of such games demonstrate the importance of considering technical aspects when creating game content.

  • Metal Gear Solid 5: The Phantom Pain, a stealth action game with an open world and dynamic lighting, runs at 60 frames per second on PS4 and Xbox One, while the image quality on PS3 and Xbox 360, where the game is also available, is no worse (albeit the frame rate on these platforms is lower).
  • Marvel’s Spider-Man, a game with smooth gameplay and a detailed open world, is available on both PS4 and the PC port.
Screenshot: game Metal Gear Solid 5: The Phantom Pain / Konami Digital Entertainment
Screenshot: Marvel's Spider-Man Remastered / Insomniac Games

Graphics optimization in games depends not only on the skill level of programmers and the capabilities of the technologies used, but also on the interaction between programmers working with game engines and 2D/3D artists. The effective work of these specialists can significantly improve the performance and visual quality of graphics, which in turn affects the overall gaming experience. Synergy between programming and artistic design plays a key role in the creation of graphically rich and optimized game projects.

Graphics APIs

Graphics optimization begins with understanding how graphics APIs work. These interfaces play a key role for developers, allowing them to efficiently display images on the screen. Graphics APIs are also critical for real-time rendering, ensuring high performance and graphics quality. Proper use of these interfaces can significantly improve visual effects and reduce system load, which is especially important for games and interactive applications.

Graphics APIs play a key role in the development of modern applications and games, providing developers with tools for creating high-quality graphics and visual effects. Among the most popular graphics APIs is OpenGL, which is widely used for developing cross-platform applications. DirectX, specifically Direct3D, is the standard for game development on the Windows and Xbox platforms, offering a rich set of features for working with 3D graphics. Vulkan is a modern low-level graphics API that provides more efficient resource use and better performance, especially on multi-core processors. Metal, developed by Apple, optimizes graphics performance on iOS and macOS devices. These graphics APIs enable realistic visual effects and deliver high performance, making them indispensable in modern apps and games.

  • PC — Vulkan, DirectX 11/12, OpenGL, Metal.
  • Mobile platforms — Vulkan, OpenGL, Metal.
  • Consoles — DirectX, PSGL, GNM.

Each graphics API has a unique code syntax, shader programming language, and level of compatibility with various devices. The list provided shows that some interfaces provide cross-platform support. The main function of these APIs is to display an image on the screen using rasterization or ray tracing methods in real time. Modern game engines are able to support several graphics APIs simultaneously, which allows developers to choose the most suitable tool for their projects and optimize performance.

Vulkan and DirectX 12 belong to the category of modern graphics interfaces. The term "modern" often implies simplification of processes, but in practice this is not always the case. For example, the code to render a simple triangle in Vulkan can take around 1000 lines, while in OpenGL it takes less than 100 lines. This demonstrates that modern graphics APIs offer lower-level access to hardware resources, allowing developers to optimize performance, but require more complexity in the code.

Rendering a simple triangle in OpenGL Frame: Gamepons / YouTube

This type of API It doesn't hide data in functions, giving developers the ability to optimize performance, especially in terms of CPU usage. This makes it a more effective tool for creating high-performance applications.

Note

This note contains important information that you should take into account. It may relate to various aspects, such as terms of use, product or service features, and recommendations for proper use. Please read the provided details carefully to avoid misunderstandings and ensure effective use of the presented materials. Remember that following these recommendations will help you achieve the best results.

For a detailed study of the benefits of the Vulkan API, we recommend checking the specification on the official NVIDIA website. This information will help you understand how Vulkan optimizes graphics performance and provides developers with modern tools for creating high-quality games and applications.

In the presented Vulkan code, you can see many commands known as drawcalls. These commands communicate data about textures, vertex buffers, geometry clipping, shaders, and other important elements to the CPU. Understanding how drawcalls work is crucial for optimizing the performance of graphics applications, as they play a key role in the rendering process. Effective use of drawcalls can significantly improve the speed and quality of rendering in graphics-intensive games and applications.

Drawcalls in code Frame: Gamepons / YouTube

A shader is a specialized program responsible for rendering and defining The visual characteristics of the surface of objects in a scene. It controls texture mapping, bump mapping, and interactions with light sources, including absorption, scattering, reflection, and refraction. Shaders work closely with graphics processors and are typically written in HLSL or GLSL. However, most developers don't write shader code manually, but configure them through engine interfaces. For example, in Unreal Engine, you can use a visual editor to create shaders using nodes, which simplifies the process of their development and configuration.

Visual Shader Programming in Unreal Engine 5 Image: Unreal Engine 5

The Nuances of Working with Game Engines

There are many game engines, each with its own advantages and disadvantages. Each engine has a unique architecture and approach to graphics processing. When choosing a technology, it is important to consider factors such as budget, target platform, game genre, and gameplay features. The right choice of game engine can significantly impact the quality of the final product and its success in the market.

When optimizing game scenes, it is necessary to take into account their unique characteristics. For example, rendering a dense forest and simulating a large number of people require different technical approaches. Programmers working on graphics in games must have access to the game engine's source code. This allows them to understand how to optimally implement various operations within the chosen technology. Without this access, game optimization becomes a significant challenge.

There is no perfect game engine. Even well-known projects like Unreal Engine 5 require optimization for various reasons. Firstly, even the most advanced technologies may not take into account all the specific features of a specific project, which can lead to reduced performance. Secondly, optimization is necessary to ensure compatibility across multiple platforms and devices. Furthermore, each game has its own unique requirements, which may require additional tweaks and improvements. Therefore, it is important for developers to always remember about optimization in order to achieve the best results and provide a high-quality gaming experience for users.

  • Many people still play on weak hardware.
  • Innovative Nanite technology with the ability to render millions of polygons does not work on small objects like plants.
  • Ray tracing or various lighting scenarios can negatively affect performance.

Reading is an important part of personal growth and development. It opens new horizons, helps expand your horizons, and deepen your knowledge. Regularly reading books, articles, and scientific research helps improve critical thinking and analytical skills. Furthermore, reading different genres of literature enriches your vocabulary and improves writing skills. To get the most out of reading, it's worth choosing a variety of topics and styles. This will help not only in your professional career but also in your everyday life. Read to learn, develop, and gain new ideas and inspiration.

The Best Game Engines for Game Development: 4 Freemium Options – From Unity to Unreal Engine.

When choosing an engine for game development, it's important to consider many factors, such as functionality, resource availability, and the developer community. Among the best freemium engines, Unity and Unreal Engine stand out, offering powerful tools for creating both 2D and 3D games. Known for its ease of learning and extensive mobile development capabilities, Unity is ideal for beginner developers. Unreal Engine, on the other hand, offers high-quality graphics and a powerful visual editor, making it an excellent choice for creating complex projects. Godot and CryEngine are also worth considering, offering their own unique capabilities and features for developers. Choosing the right game engine depends on your needs and goals, but these options are among the best on the market.

How Rendering Works

Rendering, or the process of drawing images, is performed using the computing power of the central processing unit (CPU). As a result, the player sees a sequence of frames or animations of 3D objects on the screen, taking into account their position, textures, lighting, and other characteristics. There are two main types of rendering: single-threaded and multi-threaded. In single-threaded rendering, calculations are performed sequentially, while multi-threaded rendering uses multiple CPU cores for simultaneous processing, which allows for more efficient load balancing and accelerates the image creation process. Multithreaded rendering significantly improves performance and visual quality, which is especially important in modern games and graphics-intensive applications.

CPU performance during renderingSource: Vasif Abdullaeva / Gamepons. Infographics: Maya Malgina for Skillbox Media

There are two main methods of rendering on a GPU: ray tracing and rasterization of 3D models. Rasterization is the more popular approach in computer graphics, so we'll look at it in more detail. This method converts 3D objects into 2D images, efficiently using the hardware capabilities of GPUs. Rasterization allows for high performance when rendering complex scenes, making it the preferred choice for most gaming and graphics applications.

Game scenes are formed from 3D objects, which in turn consist of primitives such as points, lines, and triangles, sometimes including squares. The program responsible for rasterization is tasked with converting these source primitives into fragments that represent the pixels of the final image. Rasterization is a key step in the rendering process, as it enables the visualization of 3D objects on the screen, turning mathematical models into graphical elements visible to the user.

General principle of rasterizationSource: Vasif Abdullaeva / Gamepons. Infographics: Maya Malgina for Skillbox Media

The diagram above shows the main stages of the process. Each stage plays a key role in achieving the final result. The initial stage involves planning and preparation, which provides the foundation for further actions. The next stage is associated with the implementation of the plan, where it is important to consider all details and potential risks. The final stage involves analyzing the results and drawing conclusions, which allows for improving future projects. Understanding these stages helps optimize the process and achieve goals more effectively.

  • Input Assembler - reads primitive data (points, lines, and triangles) from populated buffers and assembles the data into primitives that will be used in subsequent stages. Also at this stage, system-generated values ​​are attached to improve shader efficiency.
  • Vertex Shader Stage — processing individual vertices by the shader to produce a transformed attribute.
  • Tessellation Stage — transforming the geometry and forming a set of small objects (triangles, points, and lines).
  • Geometry Shader Stage — processing entire primitives: triangles, lines, points, and their adjacent vertices.
  • Rasterizer Stage — trimming primitives that are not in the representation and preparing them for the next pixel shader stage. Vector data (shapes or primitives) are converted into a pixel-based bitmap to render 3D graphics in real time.
  • Pixel Shader Stage – ingests interpolated primitive data and generates per-pixel data (such as color data). Advanced features such as per-pixel lighting and post-processing are available at this stage.
  • Output Merger Stage – Output data (pixel shader values, depth, and tile set information) is combined with the render target content, depth buffers, and tile set to produce the final result.

Note: Keep text clear and descriptive. Ensure it meets SEO guidelines by including keywords and phrases that will improve search engine visibility. Avoid redundancy and focus on providing valuable information to the reader.

Rasterization stages may vary depending on the GPU architecture. For a more detailed examination of all stages of the rasterization process in the context of Direct3D, we recommend consulting the official Microsoft documentation. This will help you better understand how to optimize graphics performance and improve the visual quality of your applications.

Now that we understand how GPUs and CPUs process graphics, it's worth considering optimization aspects. Graphics optimization plays a key role in improving system performance and enhancing the user experience. Proper optimization techniques can significantly reduce CPU load, improve image quality, and ensure smoother application performance. It's important to explore various optimization approaches, including using efficient algorithms, resource optimization, and tweaking visualization settings. These measures will not only help speed up graphics processing but also ensure higher performance in games and graphics applications.

Profiling

Performance optimization is a key aspect of development, and one of the most effective tools for this is profilers. These tools allow you to analyze elements that may degrade performance in specific scenes. Profilers provide detailed information about the operation of low-level API modules, which helps developers identify bottlenecks and optimize code. Unlike traditional methods, such tools measure performance in milliseconds (ms), which allows for a more accurate assessment of system efficiency and the necessary improvements. Proper use of profilers can significantly improve the overall performance of an application and enhance the user experience.

Graphics profiling can be performed both within engines (for example, Unreal Insights for Unreal Engine and Unity Profiler for Unity) and using third-party tools. Popular profiling utilities include RenderDoc, NVIDIA Nsight, Radeon GPU Profiler, and Pix. These tools help developers optimize the performance of graphics applications by identifying bottlenecks and providing a smoother gaming experience.

An example of NVIDIA Nsight in action. Frame: Gamepons / YouTube

There are several key aspects to consider when working with the profiler. First, it's important to properly configure profiling parameters to obtain accurate data on your app's performance. Second, you should analyze the profiling results to identify bottlenecks and potential issues in your code. Careful examination of this data will help optimize your app and improve its performance. Furthermore, regular use of the profiler allows you to track performance changes as you make code changes, helping to maintain high quality standards. It's also important to ensure the profiler's compatibility with the technologies you're using to avoid potential errors and inaccuracies in your analysis.

  • The profiler must be run on the target platform—you shouldn't optimize a mobile game on a PC.
  • Profile a finished build, not a project: game engine editors use a lot of resources.
  • Try profiling the game under different conditions, as the CPU and GPU clock speeds depend on the device's temperature and battery level. Overclocking utilities, such as NVIDIA's GPU Boost or AMD's PowerTune, can help with this.

Forward Rendering is the standard rendering method used in most graphics engines. This approach involves obtaining geometry data, projecting it, and dividing it into vertices. The vertices are then converted into geometry and then segmented into fragments, or pixels. These pixels are then rendered and sent to the screen. During the rendering process, lighting in the scene is calculated separately for each vertex and fragment, taking into account the number of light sources. This method provides high visual quality, but may be less effective with a large number of light sources, which should be considered when choosing a rendering method for specific tasks.

Deferred Rendering is a process in which all the geometric information in the scene is first drawn. Fragment shaders, which are responsible for lighting, are then applied to the resulting image. The final step is displaying the finished image on the screen. This approach allows for efficient processing of complex scenes with multiple light sources, minimizing resource costs and improving overall graphics system performance.

Deferred rendering is often thought of as a method related to deferred shading/lighting. It's a modification that optimizes G-buffer usage, especially when there are multiple light sources in a scene. This approach significantly reduces memory requirements and improves performance, making it particularly relevant for modern games and graphics applications. Using deferred rendering allows for more efficient processing of lighting and shadows, which in turn leads to the creation of more realistic and detailed visual effects.

Comparison of processes during forward and deferred rendering Source: Vasif Abdullaeva / Gamepons. Infographics: Maya Malgina for Skillbox Media

It's important to consider the rendering method when optimizing graphics. Consider a situation where a scene contains 100 objects, each containing approximately 1,000 vertices. This results in a total of 100,000 polygons, which the graphics card can handle without any issues. However, when these polygons reach the fragment shader stage, scene lighting calculations begin. With the traditional approach, lighting is calculated separately for each segment, which can lead to delays in image output. Optimizing rendering methods reduces the load on the CPU and graphics card, improving overall performance and graphics quality. Efficient techniques such as batching, shadow maps, and simplified shaders can significantly reduce processing time and improve the visual experience.

When working with complex scenes that use dynamic lighting or multiple light sources, it is recommended to consider deferred rendering. This approach calculates lighting for each pixel only once, significantly improving performance. For example, in Unreal Engine 5, deferred rendering is enabled by default. However, its drawbacks, such as incompatibility with some platforms, should also be considered. Therefore, the choice of rendering method for optimization depends on the specific goals of the developer and the specific features of the game engine, requiring careful analysis and a balanced approach.

In game scenes containing many static objects, it is important to effectively manage out-of-view geometry. This can be achieved using geometry culling methods both within the game engine itself and through dynamic systems based on the GPU. Optimizing object rendering improves game performance and reduces the load on the graphics card, ultimately resulting in smoother gameplay and a better user experience. Using such technologies is an important aspect of modern game development.

When setting clipping, it's important to consider the minimum occluder size. Occluders are objects that hide geometry behind them. For example, if the occluder value is set to 5 meters, this means that all objects greater than 5 meters in height or width will not be rendered behind the occluder, significantly saving rendering time. The occluder size should be carefully considered based on the game's design requirements to ensure optimal performance and visual quality. Properly setting up occluders is a key aspect in game development, contributing to efficient resource usage and improving user experience.

Occluder settings in the Unity engine Image: Unity

When clipping dynamic meshes, it is recommended Use object pooling. This allows for the reuse of entities, significantly reducing the cost of creating and destroying objects. This approach not only optimizes performance but also reduces system load, which is especially important in complex gaming or graphics applications. The object pool helps manage memory efficiently and speeds up processes related to processing dynamic meshes.

An illustration explaining how the object pool works. The developer sets a certain number of bullets for the player to shoot into the pool. Each time the player fires a shot, the bullet disappears and returns to the pool for reuse. This approach reduces CPU load. Source: Mike Geig / Twitter. Infographic: Maya Malgina for Skillbox Media.

The player will not be able to see small objects in detail at a significant distance. Therefore, it is important to adjust the culling distance in game engines depending on the size of the models. In Unity, this setting is made using code that allows you to control the visibility of objects at different distances. In Unreal Engine, a similar function is performed by the Cull Distance Volumes tool, which helps optimize performance and improve visual effects by controlling which objects are displayed on-screen depending on their distance from the camera. Properly setting these parameters contributes to a higher-quality gaming experience.

Physically-based animations and visual effects can significantly load the processor. However, less resource-intensive alternatives exist. One such technology is vertex animation, known as Vertex Animation Texture. This method uses only textures and shaders, which allows you to redistribute the load on the video card. This significantly improves performance and allows you to create high-quality visual effects without undue load on the CPU. Using Vertex Animation Texture is becoming especially relevant in modern games and applications where resource optimization is important.

Avoid tessellation and geometry shader steps, as they require significant time. If relief accentuation is necessary, consider alternative methods. For example, use normal textures to create depth without increasing the polygon count. You can also use height and light maps to achieve realistic rendering. These approaches will help optimize performance while maintaining visual quality.

  • Consider texturing using a parallax map as an alternative.
  • Reduce tessellation based on camera distance.

It is recommended to avoid excessive use of branching (if) constructs in shader code. Graphics processing units (GPUs) process parallel code more efficiently, which can significantly improve rendering performance. Optimizing shader code with an emphasis on parallelism ensures smoother and faster operation of graphics applications.

Reducing the number of shader input parameters is an important aspect of optimization. Keep only those parameters that can be modified at runtime to improve performance. When developing for mobile devices, use the lowest possible shader precision, which will also help reduce the load on resources. Remember to monitor shader usage to avoid potential performance issues and ensure efficient use of graphics resources.

Game Designer Profession from Scratch to PRO

A game designer creates the structure of a game. They think through the idea, rules, gameplay, and decide what emotions the plot will evoke in players. You'll master game design principles from scratch and learn how to work with popular engines like Unity and Unreal Engine. You'll learn how to retain player interest and monetize your games. And we will help you start a career in the gaming industry.

Find out more