Day 2 - ⚡️ Quick - Backface vs Occlusion Culling

Article / 01 May 2026

Backface Culling vs Occlusion Culling — What's the Difference?

Front-/Backface culling is done at the hardware level; the GPU determines the winding order of a triangle (clockwise vs. counter-clockwise relative to the camera). If it's back-facing, the triangle is discarded before the pixel shader runs.

There are cases where you'll need to disable it, for example two-sided materials like foliage cards, thin fabric, or leaves need both faces to be visible, and transparent geometry such as glass often requires interior faces to render correctly, so the volume reads right. Fast, cheap, and on by default for opaque geometry.

Occlusion culling happens at a higher level, before draw calls are even submitted. It determines whether an object is hidden behind something else; if it is, the engine won't queue the draw call at all. This works well for opaque assets.

Alpha-tested and alpha-blended materials are trickier: because they don't fully write to the depth buffer, they can't reliably act as occluders themselves. Some engines handle the occlusion pass automatically with tools like Umbra, or through built-in Software Occlusion Culling like UE. But you can also manually help the engine by creating custom occluder meshes, which is what tomorrow's post covers.

Key difference: backface culling happens at the triangle level and removes back-facing triangles. Occlusion culling happens at the object/draw call level and skips rendering hidden assets entirely.

© 2026 Stefan Groenewoud — All views are my own, not those of my employer.

Day 1 - 🔬 Deep dive - Shadow Proxies

Article / 30 April 2026

Shadow LODs were a manual optimization technique for reducing shadow rendering cost. With modern rendering tech like Nanite and Micromesh, they're largely obsolete, but not entirely.

Back in the day

When I just entered the industry I only played around with Visual LODs, which was already challenging enough at times if you had to manually generate them. Any normal, UV or vertex inconsistencies were quite noticeable, and not all studios used automated tools. So for some of the games that I worked on, we manually reduced meshes inside Maya, and then did manual tweaks to polish. Nowadays, we have fancy tools like Simplygon or default to using Nanite-like techniques.

The Old Problem

First, we had offline baking processes that would take care of the heavy lifting. In preparation for that, you needed UVs on your mesh, and then generate a secondary UV set that was a complete unique layout for lightmap generation. Problem: every time an asset changed or if you updated the Time of Day, you had to rebake the level; slow and tedious as you can imagine! The industry responded on two fronts: light probes (storing irradiance as spherical harmonics coefficients) let dynamic objects receive indirect lighting without triggering a full rebake, and the shift to deferred rendering separated the geometry and lighting passes, enabling more dynamic lights without a proportional performance cost.

The more complex and dense assets became, as games increased in scale (more open world games), and the more dynamic worlds have to become, the harder it is to solely rely on the visual LOD also affecting the shadow maps and/or shadow cascades. The shadow depth pass has to evaluate every triangle in a mesh — or worse, every pixel for alpha cutouts, and that cost adds up fast. The solution was a shadow proxy: strip away the visual shader entirely and substitute a separate, ultra-simplified mesh used only for shadow casting, while the full-detail mesh handles visible rendering.

Great example from CryEngine where they demonstrate the reduction from 10k triangles to just 1k triangles. Visually the difference is barely noticeable to the naked eye but performance-wise it will have an impact.

You don't need normal or albedo information in a shadow proxy shader. If you require displacement or alpha-testing for your visual shader, you'll want to integrate those into your shadow proxy shader too, for parity. From an organizational and performance point of view, you want to separate your opaque vs. alpha-tested materials, keeping the number of alpha-tested triangles/pixels to a minimum and not drawing them for the entire mesh if you don't have to.

For visual LODs you can swap out different simplified meshes at predefined draw distance thresholds; the same can be done for shadow proxies. Having a reduced shadow proxy at far distances will also help reduce load on shadow memory. Note: the visual mesh threshold doesn't need to match the shadow proxy threshold. For example, a shadow proxy can draw at a maximum distance of 200 metres while the last visual LOD draws at 500 metres. Shadows at just a few pixels may not be noticeable, but the visual representation still is.

To sum up:

  • Use a custom proxy mesh that only writes to the shadow cascades
  • Assign a dedicated shadow proxy shader; strip any information that isn't needed in this stage of the pipeline
  • Set custom draw distances independent of your visual LOD thresholds

Limitations

The statement "no longer necessary with Nanite" is the right instinct, but it's only fully true for opaque Nanite geometry. Foliage and Characters still remain challenged by custom shadow proxies.
Shadow Physics Asset still useful for Characters. While Foliage needs an alpha-tested fallback option.

How It Worked in Unreal Engine & Proprietary

UE3 / UE4 / Others:

You could assign a simplified static mesh exclusively for shadow casting in a few ways:

  • A dedicated low-poly mesh component with rendering disabled and shadow casting enabled, using a convex hull or box mesh casting the shadow instead of the real geometry
  • For alpha-heavy assets (foliage, fences, chains), this eliminated the expensive per-pixel shadow depth evaluation on alpha cutout materials
  • Per-LOD shadow control: disable shadow casting on lower LODs entirely, or force a simpler shadow representation per LOD level

UE5 / Nanite:

Nanite handles shadow depth passes through its own rasterizer with automatic LOD, which largely removes the need to hand-author shadow proxies for high-poly opaque meshes.

However, Nanite doesn't fully support alpha masked geometry. Alpha-heavy assets still fall back to traditional shadow rendering, which means the proxy technique remains relevant for:

  • Foliage with alpha cutouts
  • Fences, railings, chains, cables
  • Any non-Nanite mesh in a Nanite pipeline

Practical Takeaway

If your project uses Nanite for hero assets, shadow LODs are off your plate for those. But keep the proxy approach in your toolkit for anything with alpha transparency or anything outside the Nanite pipeline. A box mesh shadow proxy on a dense foliage card cluster is still a meaningful win.

© 2026 Stefan Groenewoud — All views are my own, not those of my employer.

Day 0 - 💬 Announcement post - why I'm doing this, what to expect

Article / 29 April 2026

I'm Back — And This Time I'm Actually Going to Post

It's been a while since I've written anything here. Longer than I'd like to admit.

Coming back to the blog is partly an exercise in figuring out where I want to go next in my career: what areas of tech-art I still want to explore, what I've learned that's worth sharing, and honestly, what I still don't fully understand yet. Writing has always been a good way for me to work that out.

The other reason is simpler: my old approach wasn't working. Some of my posts took several evenings to get through: writing, rewriting, proofreading, trying to make everything perfect before hitting publish. It was too slow and too draining to keep up. I'd rather post something good every day than something perfect every six months.

So this is an experiment. For the next 60 working days, I'm going to post something every weekday. The posts will vary: deep dives, quick breakdowns, behind-the-process writeups, opinions, experiments. Some will be long. Some will be short. Not all of them will be great, and that's fine.

If it gains traction, great. If not, I'll still have sharpened my writing, figured out which formats actually suit me, and gotten a lot of ideas out of my head and into the world.

Let's see how it goes.

© 2026 Stefan Groenewoud — All views are my own, not those of my employer.


Refining Performant Levels of Detail (LOD)

General / 25 May 2025

Welcome back to the second part of our discussion on Level of Detail meshes! This blog post will be slightly shorter as it primarily builds upon the concepts introduced in the first post. In the first draft, we focused on calculating the LOD based on the diameter of an object. However, since the player in a game would see the mesh from various angles, it’s crucial to consider all viewpoints, not just one. 

Additionally, as someone pointed out in the comment section, this process assumes absolute values. To ensure your values are positive, simply wrap an Abs() function around them.

For instance, if we encounter assets from different angles, such as full frontal, full side view, or full top view, depending on their positioning and rotation by the artist, we shouldn’t only use one angle (the diagonal) for calculation. By taking into account all angles, we can give thin or flat objects a more realistic chance of being accurately measured. We collect all these values and calculate the mean as the input value. 

In hindsight, it might be better to use the maximum of all angles. If the difference between the smallest and largest number is too large, the LODs will fade out too quickly.

In an ideal setup, if the assets are placed and scaled, whether it’s larger or smaller, or if the field of view is wide or small, the game engine should compensate for these factors accordingly.


pseudo code


diagonal = ∛(0.075² + 0.157² + 0.167²) = 0.387m
front = ∛(0.075² + 0.157²)  = 0.312m
side = ∛(0.157² + 0.167²)  = 0.375m
top = ∛(0.075² + 0.167²)  = 0.322m


mean = ((diagonal + front + side + top) / 4)  = 0.349m


CalculateDistance(inSize=mean, inScreenSpacePercentage=100, inFovDegrees=45.0, inVerticalResolution=1080):
   ratio = inVerticalResolution / 1080 # compensate for 4k or FullHD screens
   # distance to see the asset, top to bottom
   distance_to_object = (inSize * 0.5) / (tan(inFovDegrees * 0.5))
   distance_by_screensize = distance_to_object * 100 / inScreenSpacePercentage
   max_distance = distance_by_screensize * ratio
   return max_distance


Horizon Forbidden West: Automated Asset Conversion And Updating

General / 06 March 2025

This postmortem analysis delves into my approach to swiftly converting a substantial amount of assets. Picture this scenario: when transitioning from Horizon Zero Dawn, the initial game, to its sequel, Horizon Forbidden West, we encountered the task of updating the game’s asset-art (props and environment-art models) to reflect the latest technological advancements and ensure compliance with the technical specifications. Moreover, we had to replace the assigned shaders with novel ones specifically designed for Horizon Forbidden West. The sequel would leverage existing assets while introducing new ones. Consequently, some of these scripts and pipelines were reusable. Given the sheer number of assets we wanted to display on screen, we prioritized optimizing their setup to stay within the memory budgets while maintaining the visual fidelity of the first game, supporting an approximately 7-year-old platform (PS4) and the (at the time) newly released PS5.

Step-by-step

  • Asset Management: Collected, tagged, and tracked over 5000 assets in a local database, highlighting the importance of testing and validating changes.
  • Texture Optimization: Optimized textures by discarding unnecessary maps, converting PSDs to PNGs, and ensuring consistency in materials like rock and stone.
  • Conversion Process: Utilized the Substance Automation Toolkit API and a shared Python library for texture conversion, ensuring PBR compliance and compatibility with the engine.
  • Maya: Executed Maya batch script, providing information and updating shaders, and relinking textures.
  • Export: Exported assets to the engine and linked to a test level for evaluation purposes.
  • Evaluating: Evaluated GPU performance, export/conversion issues, and internal tools/settings in-game.

I initiated the process by collecting all assets that required updating through a script. This step allowed me to assess the scope of the undertaking. I tagged and tracked each asset in my local database (a JSON file) with the appropriate process, the Maya file associated with that asset, all the textures linked to the asset, and some other data that I can’t quite remember right now.

Side note:

However, it’s important to mention that this approach wasn’t entirely foolproof and a one-size-fits-all solution. With over 5,000 files touched, all of which were linked to levels, sets, cinematics, or prefabs, the process became even more fragile and complicated, particularly during production when everyone was striving to complete the game. Coordinating the initiative poses a challenge, emphasizing the significance of allocating sufficient time for testing and validating the changes. To address this, it’s crucial to split the changes into smaller check-ins.

Let’s continue!

While updating the files, I took the liberty of optimizing content whenever possible. I discarded any Specular maps that weren’t necessary for dielectrics or any other unnecessary maps. Determining the need for dedicated Specular channels could be challenging, especially since not everything was authored using PBR techniques. Relying solely on Python libraries and image processing wasn’t always sufficient. Additionally, I converted all PSDs to PNGs to significantly enhance Perforce syncing times, image processing, and DDS exporting times.

In addition to texture optimization, we also had to identify assets that required recoloring treatment. For instance, if an asset contained rock or stone materials, we wanted to ensure that it (visually and color-wise) matched the other rocks by applying the same coloring treatment. In most cases, I was able to quickly generate a mask for other assets through a manual process. I could either extract it from the PSD layers, bake out the UV layout and use that, or simply mask in Photoshop and have that linked during the Substance file generation process.

Conversion

To begin the texture conversion process, I utilized the Substance Automation Toolkit API. Certain aspects of this process were defined in a shared Python library that I had written for it. This library is explained in more detail in another blog post titled “Texturing for Rocks.” This shared graph would clamp the Color values to be more PBR compliant, clamp the Roughness ranges due to the engine shading model, and run the AO through a Curve node to compensate for some manually authored AO that was too dark.

Why the Substance Automation Toolkit? Creating a new file using the API is a straightforward process. It’s easy to replicate, and we can open the Substance file in Designer and export it if necessary. Batch exporting is also an option if any changes are made to the shared Substance graph.

Maya

The next step was to update the textures linked in the engine and reexport the DDS’s. This was accomplished using the internally created library, which resulted in a relatively fast process.

Initially, I attempted to use a headless Maya version, but this approach did not work because the viewport renderer did not initialize the shaders and shader-defined information required for evaluation and update. As a slower alternative, I opted to run regular Maya in a batch process. In this process, I provided Maya with a list of information per Maya scene and updated the shaders. Upon loading, I retained the old variables in memory, updated the shader, and then updated the variables accordingly, compensating for any differences, such as variable names or ratios, like tiling for detail maps. Finally, I relinked the textures to the shader once more, ensuring they were correctly associated with the mesh.

From there, the assets were exported to the engine. Unfortunately, I cannot provide further details due to the proprietary nature of the engine.

Once the assets were exported, I was able to link them to my test level, enabling me to evaluate the performance (GPU) in-game and assess any issues that may have arisen during export or the conversion process. Before checking in, I conducted a quick test process to ensure everything was working as expected. I used our internal tools and double-checked if none of the previously set settings or draw distances were broken. The further into development you are, the more vital this becomes.

Conclusion

The way I present the steps in my explanation is also how the process functioned in Python. Evaluating images using PIL was the quickest step, while Maya posed the most significant challenge. Re-exporting assets from Maya was the slowest and most prone to crashes. Multiprocessing consumed so much memory that I experienced several blue screens. It was a valuable learning experience, as I learned how to automate certain steps and refine the Python code to be more compatible in different scenarios rather than a one-time use solution. However, it became apparent that full automation for this process was too risky due to the many odd cases and asset setups that had to be validated by eye. 

The ideations and iterations that emerged from these processes, served and continue to serve as the foundation for more automated and/or procedurally driven processes.

A special thanks to Chris Thompson for proofreading and to Guerrilla for allowing me to publish and share this information.

Writing technical documentation for production readiness

General / 03 February 2025

In this blog post, I’ll share my thoughts and expertise on the under appreciated yet crucial process of writing documentation within the industry. I’m referring to the broader implications of outsourcing assets and texturing pipelines, excluding the financial aspects since they’re not my area of expertise. This topic likely extends far beyond the scope of a single blog post, and I may delve deeper into it over time.

Objective of Documentation

Clear documentation is essential for internal teams, new members (including partners and outsourcing vendors), and project management. It serves as a comprehensive reference for project information and workflow, eliminating misunderstandings and inefficiencies that save time and money. No one wants a tool or system set up by someone who left the company without proper documentation, leaving them uncertain about its limitations, setup, and potential improvements.

The key to its success lies in regular updates. This ensures that outdated or obsolete information doesn’t accumulate, potentially leading to code rot. Documentation should be detailed enough to explain the main process but concise enough to be easily accessible when needed, such as onboarding a new developer or updating it.

Analysis

  • Ambiguity regarding the documentation’s intended purpose
  • Inconsistent terminology causes confusion
  • Repetitive information encourages skimming rather than thorough reading
  • Information scattered across various locations 
  • Is it sufficiently clear to non-native English speakers (depending on your team and your vendors)?

Iteration

The following points will undergo a continuous process of iteration and evaluation in collaboration with your collaborators and team members. The ever-changing landscape of tools, workflows, and tech needs us to keep adapting and improving our development process.

  • Thoroughly review all the documentation, following each documented step-by-step to ensure its accuracy and identify any missing information.
  • Conduct buddy checks to verify that everything makes sense from multiple perspectives.
  • Organize the content based on its complexity, considering that not all artists need or would be comfortable exploring more complex topics.
  • The information is available, but it is currently separated from the fundamental concepts.
  • Evaluate any workflow issues, blockers, or missing features in shared content, such as shaders or textures/material library.
  • Understand your target audience: Are you writing the documentation for a developer who is expected to have basic knowledge of a tool, software, or engine, or are you writing it for someone who has never used it before?

Lessons Learned

If I were to start fresh, I would improve the approach by adding more clear images, callouts, or even videos to reduce confusion, which is especially helpful for visual learners. Before starting the project, I would suggest creating a layout and showing a proof-of-concept for the potential setup. Furthermore, collaborating with different departments will help us delegate and coordinate specific documentation tasks.

Example

Texturing & Materials (Main Category)

---> Basic Workflow (Subcategory)

    -> Simple Material Blend Workflow

        -> Bespoke Texturing Workflow

    -> Advanced Workflow

        -> Height Blend Workflow

Conclusion

Be open to rewriting, re-editing, and redoing a substantial portion of the initially written documentation. Don’t be overly attached to what’s been written. With a well-designed revisioning system, you can always undo any changes or unintended problems. View this as an opportunity to reflect on your personal growth and improvements throughout the process.

Horizon Forbidden West: Batch Baking, Texturing, and Exporting Rocks

General / 22 January 2025

One of the most significant initiatives I’ve had the pleasure to be involved in during the development of Horizon Forbidden West was automating the rock asset baking pipeline. This process involved setting up a semi-automated (rock) texturing process, writing a Substance Python library (built on the Substance Automation Toolkit), and more.

Why was this approach significant?

  1. The game would feature a multitude of unique rocks, and all these rocks would need to be treated equally to ensure visual consistency.
  2. Any texturing (Substance) changes could be easily reapplied by batch reprocessing the Substance files only.
  3. There’s only one shared setting to bake all the rocks for visual and data consistency.
  4. My ‘database’ (read: JSON file) successfully tracked all texture resolutions, including those for baking and the in-game target resolution.

Database

The automated process aims to streamline the environment artist’s workflow. They only need to define parameters for naming textures in a small database, JSON file, specifying which component should be packed onto a single sheet, using a custom cage mesh, and setting the target resolution for in-game use. The tool will automatically adjust other parameters during the first run.

Context

In this context, a “set” or “component set” refers to a collection of multiple assets that need to be combined onto a single texture sheet. For instance, during the initial setup of the automated system, an artist would have to bake three rocks as individual assets. They would then have to manually merge all the mesh data to reduce the amount of draw calls and achieve the desired target texel density. However, through the automated pipeline, I was able to merge all their bakes together and apply the Substance graph to the final result. The only requirement from the Environment artist was to perform proper UV mapping beforehand and ensure a well-organized layout.

For each rock asset, we had to bake out various data, including Normals, Ambient Occlusion, Curvature, World Space Normals, UV mask, World Space Direction, and two others. If these were baked at a high resolution of 4k, it would significantly impact the performance of Substance. To address this, I combined all the mesh bakes for each type of rock into a single call. For instance, four different rocks would have their own AO maps, which I merged into a single sheet (automatically). That combined result would be exported as PNGs and integrated into the Substance graph for texturing.

With this automated setup and tracking of assets, we could easily rebake, retexture, and reexport all the rocks if needed. This wasn’t often required, as the environment team did an exceptional job of providing high-quality bakes. However, having the option to verify all in-game content ensures that it’s always up-to-date, and is a great feature.

Texturing

For the rocks, we utilized a shared Substance graph to input all the baked mesh data. This enabled us to generate breakups and variations on a per-asset basis. For generic rock details, we employed tri-planar projections that were appropriately scaled to their real-world scale. For instance, cliffs had a larger repeating rate compared to pebbles. We also incorporated other types of variation and breakups, such as occlusion and curvature, in conjunction with cloud or Perlin noise. However, the process is more intricate and detailed than I can fully explain here.

Most of the assets’ uniqueness stems from the World-Data that is hand-painted by the artists and designers or generated offline. In combination with the addition of shader features like Medium and High Frequency detail maps, even this is defined by parameters such as the asset’s location in the world.


CLI

I had developed a command-line interface (CLI) in Python that allows artists to easily drop and drag their low-poly mesh onto a .batch file. This file offers a couple of options:

  1. Transferring high-poly to low-poly data for single assets
  2. Transferring high-poly to low-poly data for all assets within the set
  3. Only reprocessing the texturing pipeline
  4. Exporting the assets into the game
  5. Performing all of the above options

Problems and solutions

  1. Transferring detailed information from high-poly to low-poly models using the Substance API was a bit of a challenge. Certain assets were too complex and caused memory issues because of the way I had set up the queue. After testing and iterating, I re-examined my threading setup. Upon further exploration of the Substance API, I realized that I could load in the meshes once and bake out all maps simultaneously, rather than doing it individually. This change eliminated the need to load the high and low poly meshes into memory for each thread(!). Looking back, it seems obvious, but it was all part of the learning process, adaptation, and continuous improvement as a technical artist.
  2. Writing the internal Substance Python functions was a bit of a challenge. Learning a new API while simultaneously writing a tool that is somewhat production-ready is not an easy task, but it’s a valuable experience! You get direct input from your end-users, and being able to troubleshoot with your team at someone’s desk together is a valuable asset. In addition to writing the internal Substance functions, it was also used to batch process and texture other assets, such as the face textures in Horizon Forbidden West.
  3. None of the pipelines were finalized yet. The Substance graph for the rocks was still in its early stages of development, but that’s part of the iterative process and trusting the workflow we envisioned.

Next Steps

I began developing a graphical user interface (GUI) around the tool to manage rock bakes and provide artists with the flexibility to set custom parameters. However, this endeavor required a solid foundation of code and a well-defined roadmap outlining the necessary features, based on the feedback I had collected from the team.

Scaling up the process to ensure visual consistency across all assets by using the same bake settings would streamline our workflow. Currently, we manually send out bake settings to our partners, which can lead to errors. This tool would eliminate these potential errors, making the process more efficient.

A special thanks to Chris Thompson for proofreading and to Guerrilla for allowing me to publish and share this information.

Calculating Performant Levels of Detail (LOD)

General / 15 January 2025

For some time now, I’ve been exploring how to establish the most efficient method for rendering meshes on the screen. Instead of solely relying on mesh density, I’m aiming to determine the draw distance using a more scientific approach, considering the mesh’s size on the screen.

Level of Detail (LOD) is a crucial technique for optimizing graphics performance. It involves replacing a more expensive mesh with a cheaper one as the distance from the camera increases. Ideally, you want to see a high-resolution mesh up close, but as an asset becomes smaller on the screen, optimizing the mesh becomes more important. When executed correctly, you won’t notice any visual difference, and it’s also more cost-effective to render, creating a win-win situation.

Would it be practical to create an infinite number of LODs? Not really. 
They require additional storage space on disc, which can be a concern. Additionally, loading them into memory puts more strain on the CPU and GPU. It’s a delicate balance to keep in mind. Furthermore, at a certain point, the mesh becomes too small to be rendered on screen effectively, so it’s best to set the maximum asset draw distance at that threshold.

There are several methods to determine the maximum LOD distance. One method calculates the distance in units like centimeters or meters. The other option is based on screen size, which is more adaptable as it considers platform and render resolution. For instance, rendering for HD versus 4K displays depends on render resolution for detail visibility, while physical distance remains constant.

This approach ignores any mesh-related costs, such as pre-optimized triangles with maximum area triangulation or the initial mesh cost.

However, this method is not foolproof. Factors like mesh silhouette changes and unmatched normals per level of detail (LOD) can noticeably affect lighting between meshes.

The method outlined here is based on unit distance measured in meters and can be implemented in your Engine’s API or in Maya. I begin with the highest visual mesh level of detail (LOD), which is L0, and calculate the diagonal of the asset to provide a rough estimate of its size, although there are exceptions, such as more rectangular assets, where this method may not be entirely accurate. Nevertheless, I do this because the draw distance needs to be effective from various visible angles.

Here’s an example of asset sizes (in percentage terms) that can be displayed on a screen.

To determine the maximum draw distance, we input the diagonal and the target size on screen (in percentage). For the L0, I set the display size to 90%; you could say 100%, but that would trigger the L1 if the asset is visible from top to bottom of your screen, which is extremely close. The 90% provides some breathing room.

The L0 is always set at 0 meters since it’s the closest to the camera. However, we want to switch to the L1 mesh at a specific distance, and that’s where the ‘maximum draw distance value’ comes into play. This value determines the distance at which we transition to a lower LOD. We continue this process until we reach the lowest LOD in the set.

A bounding box that encapsulates the dimensions (height, width, and depth) is required for our calculations. 

Using trigonometry, I can calculate the distance of the asset to the camera at a given percentage by utilizing the diameter.

pseudo code

diagonal = ∛(0.075² + 0.157² + 0.167²) = 0.387m

CalculateDistance(inSize=diagonal, inScreenSpacePercentage=100, inFovDegrees=45.0, inVerticalResolution=1080):
   ratio = inVerticalResolution / 1080 # compensate for 4k or FullHD screens

   # distance to see the asset, top to bottom
   distance_to_object = (inSize * 0.5) / (tan(inFovDegrees * 0.5))
   distance_by_screensize = distance_to_object * 100 / inScreenSpacePercentage
   max_distance = distance_by_screensize * ratio
   
   return max_distance


What about the other LODs, you might ask? 

With appropriate reductions, I aim for a 50% triangle reduction with each LOD step. Therefore, if I multiply the calculated distance times two, it mostly works. However, there are always odd cases when the poly count is already too low, which can break the silhouette or the normals, and this approach won’t hold up completely.

You might be wondering why you should bother learning how to calculate it yourself when Simplygon or Unreal can do it for you?
In my opinion, you should be aware of the following points:

  • Understanding the underlying principles allows you to troubleshoot issues when automated tools don’t produce the desired results.
  • By knowing how to calculate it yourself, you can tailor the process to fit specific project requirements, which might not be fully supported by generic tools.
  • Relying on your own skills ensures you’re not limited by the availability, cost, or licensing of specific tools like Simplygon.

To estimate the draw distance based on the cost of the GPU, you can calculate the distance using the shortest edge lengths of the asset. This means you collect all the edge lengths of the LOD mesh, calculate the average length, and then adjust the distance based on the target platform’s requirements. For instance, if the average length of an asset at a 5-meter distance is 1 centimeter, the mesh is likely too dense, and you’d need to reduce the distance to avoid it becoming a bottleneck.

Are there any flaws? I’m sure there are. But please feel free to comment and discuss or provide your feedback.

Tips on Landing a Job as Technical Artist

General / 06 October 2023

Introduction

As a child, I developed an interest in games, despite being limited to playing older games due to my outdated PC. This sparked my curiosity and I began exploring the world of gaming. I came across a book for modding and level design in Half-Life 2 which gave me insight of pursuing a career in this field. I made the decision to enroll in a game art course where I could further develop my skills and explore potential career paths.

I began my professional journey in the videogames industry as a 3D environment artist, initially focusing on texturing and shaders. As I progressed in my professional career, I learned the importance of understanding shaders, which sparked my interest in learning to code. This curiosity led me to explore the technical aspects of game development and delve into the world of technical art.

My passion for game development extends beyond a specific role or area of expertise. I have a broad interest in all aspects of game development, which has driven me to continuously expand my knowledge and skills. I am always eager to learn and understand how different processes work and I actively seek opportunities to deepen my understanding in areas where I may have knowledge gaps.

One of the key factors that has contributed to my success as a technical artist is my willingness to help others and make their lives easier. I strive to find ways to improve workflows, streamline processes and implement tools or techniques that enhance efficiency. By staying updated with the latest developments in technology, I can identify opportunities for innovation and contribute forward-thinking ideas to make development smoother, faster and more organized.

Securing my current position at Bend Studio (and my previous position at Guerrilla) involved a combination of factors. Apart from honing my technical art skills, I actively engaged in networking events, conferences and workshops. These platforms allowed me to connect with industry professionals and showcase my work, which in turn opened doors to new opportunities. Additionally, I maintained a portfolio that demonstrated my growth as an artist and effectively communicated my abilities to potential employers.

I think, my success as an artist in the game industry can be attributed to my continuous learning mindset, my dedication to technical art and my commitment to improving processes and assisting others. By staying curious, adaptable and proactive, I think, aspiring game artists can increase their chances of breaking into the industry and building successful careers.

Secrets of Success

For environment artists, it is essential to focus on developing traditional art skills such as composition, color theory and scale. These skills contribute to creating visually appealing and cohesive environments. Additionally, gaining a solid understanding of the technical workflows involved in environment creation, such as high-to-low poly modeling and baking and texturing assets is crucial. Building complete environments from start to finish helps getting familiarized with the entire process, even if in some studios, specific tasks may be assigned. It is important to comprehend how all the different parts work together and the significance of each component.

On the other hand, for technical artists, having a comprehensive understanding of various aspects is vital. This includes not only 3D-modeling and texturing assets but also importing them into the game engine. Learning to program small tasks or writing scripts is invaluable for automating repetitive processes and streamlining workflows. Basic programming knowledge in popular languages like Python or C can empower technical artists to accomplish a wide range of tasks, provided the engine or tools support it.

Regardless of the specific artistic discipline, it is beneficial for game industry artists to develop a deep understanding of the backend workings of their chosen game engine. This knowledge helps artists make informed decisions and optimize their work to achieve the desired visual and technical results.

Staying Up to Date

To stay up-to-date with the latest techniques and technologies in game art, I use a variety of strategies. One of my go-to resources is ArtStation, which offers a wealth of tutorials on its marketplace and it’s Learning section (with a subscription). These tutorials provide valuable insights into artists' workflows and processes, allowing me to gain inspiration and grow as an artist. Learning from the experiences and techniques of other artists is an effective way to improve our own skills.

Another valuable platform for staying informed is YouTube. There are numerous channels dedicated to game art that provide in-depth videos, tutorials and discussions. Additionally, in recent years, the Game Developers Conference (GDC) has made many of its sessions freely available on YouTube, featuring industry professionals sharing their expertise and insights.

For high-quality tutorials that are curated by professionals, Gumroad and Gnomon are excellent resources to consider. These platforms offer tutorials and courses that meet a certain quality standard, ensuring that you're learning from reputable sources.

Apart from these specific resources, I highly recommend actively participating in the game art community. Joining forums, engaging in discussions on social media platforms and attending industry events or conferences can provide valuable networking opportunities and expose you to the latest trends and advancements in the field. Connecting with other artists, sharing knowledge and seeking feedback can greatly contribute to your growth and relevance as a game artist.

Lastly, it's essential to keep an eye on industry publications, blogs and websites that focus on game art. These sources often publish articles, interviews and case studies that delve into the latest techniques, technologies and industry insights.

By leveraging these strategies and resources, aspiring game artists can stay informed, continuously improve their skills and remain relevant in the rapidly evolving field of game art.

Creating an Effective Portfolio

Creating a strong portfolio is crucial for aspiring game artists who want to impress game studios and secure a job in the industry. For technical artists, including completed tools in your portfolio is essential. It's better to have a simple but functional tool than a cluttered one that doesn't work properly. Be prepared to explain the purpose and functionality of your tools or scripts and demonstrate them effectively. The ability to showcase your problem-solving approach and the reasoning behind your design choices is important.

Demonstrate your growth in skill set. Showcasing your progression over time is valuable. Highlight new techniques, software proficiency, or artistic styles you have learned and implemented. This demonstrates your adaptability and dedication to continuous improvement.

Focus on quality over quantity. Curate your portfolio to showcase your best work. It's better to have a smaller selection of high-quality pieces than a large collection of mediocre ones. Pay attention to detail and ensure that your work is polished and professional.

Provide clear and concise documentation for your projects. This includes descriptions, breakdowns and explanations of your process. Effective documentation helps reviewers understand your work and the thought process behind it. Although it may be time-consuming, investing in thorough documentation is worthwhile in the long run. As time passes, it becomes easy to forget the specific details of your project, so it would be unfortunate if you couldn't demonstrate them anymore. Additionally, consider writing a reflection report to evaluate both the successes and challenges you encountered during the project.

Using Social Media

Personally, I have found the landscape of visibility for artists to have changed significantly over the years. While platforms like Polycount.com were popular in the past, I have found that being active on ArtStation, Twitter, LinkedIn and participating in select Discord channels has been most effective for me.

ArtStation is a dedicated platform for artists, allowing you to showcase your work and connect with other professionals in the industry. It offers a built-in audience that appreciates and understands the artistry behind game development. Twitter, on the other hand, provides a broader reach and allows you to engage with a wider gaming community, including developers, enthusiasts and potential employers. LinkedIn is useful for establishing a professional presence and connecting with industry professionals and recruiters.

Regularly share your artwork, progress and insights into your creative process. Engage with the community by following and interacting with other artists and game developers. Actively participate in discussions, share valuable resources and provide constructive feedback to others. Building a positive and supportive presence can help you gain visibility and establish meaningful connections.

Job Search Websites

To find job listings for game studios, it is advisable to check the websites of game developers as they are usually the most up-to-date source maintained by the recruitment teams. Additionally, websites like 80.LV and Artstation showcase numerous open positions in the industry. Another valuable resource is GameDev Discord channels, where you can connect with others to discover available opportunities and directly communicate with developers. It's worth noting that positions may become available through these channels before being officially posted online. 

Furthermore, consider sending out open applications to game studios to explore potential opportunities. By utilizing these websites and resources, staying proactive and maintaining a professional network within the game industry, you can increase your chances of finding job opportunities.


Advice

Breaking into the game industry and building a successful career as a game artist requires dedication, continuous learning and a few key principles that have helped me succeed. 

It is important to prioritize the development of a strong foundation in traditional art skills like drawing, composition, color theory, sculpting and/or anatomy. These skills will be fundamental to your artistic abilities and will play a crucial role in creating visually impressive game assets. Plus, they can be valuable when presenting and showcasing your ideas and pitches.

If you aspire to work for a specific game company and want to increase your chances, I would advise to research their current and past projects. Focus on creating a project that aligns with their game type or art style. By doing so, you can demonstrate your skills and abilities in a way that directly relates to the work the company is involved in. This not only helps you grow as an artist but also showcases to potential future employers that you are capable of handling the specific requirements of their ongoing projects.

The game industry is constantly evolving and it's crucial to stay up-to-date with the latest techniques, tools and technologies. Invest time in learning new software, studying industry trends and exploring different art styles. Attend workshops, conferences and the before mentioned online courses to expand your knowledge.

Actively seek feedback from fellow artists, mentors and industry professionals. Constructive criticism helps you grow and improve your work. Be open to feedback, iterate on your designs and constantly strive for excellence.

Embrace adaptability and problem-solving skills to overcome obstacles and find creative solutions. And accept the iterative nature of game development and be open to exploring different approaches to achieve the desired results.

Generating stone walls in Houdini

Work In Progress / 15 June 2022

For a personal project I was trying to figure out an approach to upres my blockout mesh to high-res rocks (while learning Houdini). This process was rather heavy and didn't give me the desired result and control I needed. 

However the first iteration gave me inspiration and gave me this idea to paint a mask in Photoshop of the texture layout, convert the mask to geometry and use it as a base input for Zbrush and refine the detail. During the conversion process I'd still 'roughen' some edges and do local Transformations (rotational and depth offsetting) to get rid of the 2D converted feel.

This idea can be scaled up for larger productions where you can generate large amounts of variations, set parameters per rock or wall type, amount of wear, etc. I have worked on this over a month, did a few tweaks and finally decided to pick up my project again and show the progress.