top of page

Shader Optimization

These are some techniques I learned from classes at Gnomon taught by Anton Napierala, Ben Cloward's Shading series, book The Unity Shaders Bible by Fabrizio Espindola.
The principles of shader optimization
Move math to a cheaper stage
Move to Vertex Shader
Move to the CPU
Reduce Math Calculations
Simplify equations
Don't calculate redundantly
Don't over normalize
Pixel Clip
Optimizing Texture Sampling
Sample fewer texture
Make textures smaller
Compress textures
Reduce texture filtering
These are the 3 categories of shader optimization. Let's first get into the first one, move math to a cheaper stage. We need to understand the basics of the graphics pipeline to know which part of the computer you need to move the operation to in order for it to be cheaper.
Graphics Pipeline - Transforming 3D data to our 2D monitor screen
CPU
3D software
Send vertex data to GPU
GPU
Vertex Processor
Cheap
Convert the vertices to screen projection space
Primitive Assembly
connect vertices into triangles
Rasterizer
converts triangles into pixels
Pixel Processor
Expensive
Calculate colors of pixels
Optimize by pushing some operations that are in the Pixel Shader to the Vertex Shader
Output image
Unreal - How to know which operation is in the vertex or pixel shader?
image.png
Find ways to lower the Pixel Shader's instructions count will make the shader chaper*
*This is a preliminary measurment of cost, to find the most accurate performance measure, you must package the build and test it in a performance software like PIX*
image.png
If doing things like UV scrolling, moving vertices, using VertexInterpolator node will push the operation from Pixel to Vertex shader so we don't have to move every pixel
Knowing the cost of each node in the shader graph and chose to use cheaper ones if possible
Use Saturate instead of Clamp when clamping between 0-1
Use Add / Mulitply instead of Divide / Subtract / Power
image.png
Use Swizzle instead of CustomRotator to rotate texture 90 degrees
image.png
Use custom node setup instead of BlendAngleCorrectedNormals to blend normal maps
image.png
Using shaders to optimize rendering
 > Computing reflections and refraction in the shader
It can be cheaper to map our environment reflection texture onto our object manually rather than having to calculate the light reflections in-engine.
LatLong Projections
Projecting HDRI map into our object to resemble its reflection.
image.png
Cube Map
Projecting our game environment into a map to be used for reflection
image.png
image.png
To make a cube map, render 6 images of our environment using 90 FOV camera and square aspect ratio, then compose them into one map using photoshop.
The basic LatLong projection setup. The LogLatToUV node could be replaced with :
image.png
image.png
Use reflection vector as UV of our cube map
Manually transforming U and V of the refelction vector is cheaper 
image.png
Projection result
image.png
Projection result
> Using cube map for room interior mapping
This method is used to fake 3 dimentional depth. It is common to use it to map room interior to be seen only from the outside without having to model the room.
image.png
source : 80lvl article about Spiderman game
image.png
source : Polycount
source : 80lvl article about Spiderman game
image.png
image.png
Optimizing Texture Sampling
This method is all about reducing the size of our texture before being sampled into our shader.
Factors that control texture size
- Resoloution 

- Number of channels
- Compression type
image.png
credit : Ben Cloward
We can conclude that :
- Dropping texture resolution 1 step will reduce the size 4 times
- Using 4k texture is very expensive
- Uncompressed textures need to be low resolution
- Using an alpha channel doubles the cost
image.png
Make sure to turn off Alpha if unused.
Use DXT1 compression for roughness, AO, Specular
Remove unnessecery channels
Terrain/foliage : Normal map Z direction could be opted out and computed manually, pack other masks in that channel, compression type will make normal lose a bit of quality but won't suffer quality loss since terrain will mostly be covered by other assests.
image.png
Channel packing
You should always pack the roughness texture into the Alpha channel of base color to avoid loading another entire texture.
Pack black and white mask textures into R / G / B channels of one single texture.
Texture array
image.png
Denim
Felt
Leather
Combine multiple normal maps into one texture array that only has to be loaded once.
Good for character clothing with a lot of materials.
image.png

Gus Kesaranond

Environment Technical Artist with 4 years of experience in Houdini procedural tools.

bottom of page