What the heck are shaders?
I’m glad you asked. Shaders are tiny little programs that run on your computer's GPU, running a massive number of operations in parallel to create many of the wonderful effects you see in modern computer games. We use shaders all over Foundry, and since I spend a lot of time thinking and working on them I wanted to share a bit of the work I’ve been doing on our new unified object shader.
If you want to catch up, in previous Foundry Fridays I talked a bit about our first person rendering solution and touched on our lighting system. Before we delve into our new Foundry shader I think a little background on shaders is in order.
First you need to understand that almost everything you see in a video game is made out of triangles, and each triangle has three points that define it, which we call vertices.
These vertices are often spaced out more than each pixel on your screen. We frequently perform operations that move, animate or color each vertex.
A simple Vertex program will transform the object space position of each vertex into clip position, and perform some operations on the texture mapping. The really cool thing about vertex programs is that they only define the data at each vertex point in a triangle, and then the data is “interpolated” (blended) between each point when you sample the data later at the fragment (pixel) level. Imagine one vertex is blue, the other is green, then the middle point between the two will be teal.
The interpolated data from the vertex data is then transferred to a fragment shader (one fragment shader per pixel of the shader being drawn on screen). The fragment program then decides what will be drawn on screen. Here we sample a texture, given a uv coordinate to output a simple texture without any lighting information. If you want lighting or any fancy features from here you need to add a ton more code.
Unity has a really nifty feature called surface shaders. These shaders let you create consistent and powerful shaders with relatively little code. That’s because instead of defining the final “output” in a fragment program, you write a surface description in a special surface shader. This includes descriptive things like the color of the object and the reflectivity of the surface. Because we are just describing a surface we are not responsible for how the final pixel looks, and instead another shader operates on this data all at once at the end to create a consistent look with all other surface shaders.
Shader programs are designed to be as small and efficient as possible, but at the same time we ask them to do so many different things. A solution to this is to make each “feature” you have in your shader optional by compiling two versions- one with the feature and one without. Key shaders often have many different options and for each option, O, we have a total of 2 to the power of O shader variants.
Default Foundry Shader
Ok so now that we have that out of the way, lets talk about the new Foundry shader that we are moving towards using across most buildings, and characters. This shader utilizes surface shading and multi-compiled shader features. The “Default Foundry Shader” has numerous features we are experimenting with that can be mixed and matched and may one day find their way into the game.
Rim lighting takes the normal and view direction of the fragment and determines if it’s looking at a glancing angle for highlighting. You are probably most familiar with this effect in Mario games like Galaxy. This can add definition to the edges and silhouette of a building or character. Here I apply an extremely obnoxious amount of rim light to the drop pod to help visualize how the light is applied.
Factories in Foundry and pretty and clean, but what if they were dirty? Using a tri-planar “noise” texture I can selectively apply smudges on buildings (or entire factories) using the wear mask feature. You could imagine how this might play into a gameplay system in the future, but for right now it’s just an experiment.
An old screenshot test of what a “dirty” base might look like.
Buildings and characters can have selective tinting at runtime. Areas on the model are masked out to receive tinting and then this shader feature modifies the HSV value of the fragment to a new tint. We are already using this tinting system for the player “skin” selection option from the Next Fest demo, but here you can see that it’s not limited to predefined colors- it could even be animated or applied to buildings.
Shaders allow you to dramatically change the way your game looks and feels, but it’s easy to go overboard and create a performance nightmare. Surface shaders help keep things consistent and shader features let us optimize the amount of code actually run per surface to just what is needed. Foundry’s visuals and shaders are constantly evolving and I'm excited to see where we improve them next!
- Mark Laprairie
Follow us on socials:
Stay tuned for more news!