0% found this document useful (0 votes)
8 views13 pages

1shaders

This document provides a tutorial on combining shaders into a single pass, discussing the benefits and challenges of multi-pass shaders versus combined shaders. It outlines key considerations for shader compatibility, such as performance, sample count, coordinates, textures, and inputs. The tutorial concludes with a step-by-step approach to merging shader code and emphasizes the importance of shader order for efficiency.

Uploaded by

pulp noir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
8 views13 pages

1shaders

This document provides a tutorial on combining shaders into a single pass, discussing the benefits and challenges of multi-pass shaders versus combined shaders. It outlines key considerations for shader compatibility, such as performance, sample count, coordinates, textures, and inputs. The tutorial concludes with a step-by-step approach to merging shader code and emphasizes the importance of shader order for efficiency.

Uploaded by

pulp noir
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

GM Shaders Subscribe Sign in

Combining Shaders
How and when to combine shaders into a single pass.
XOR
APR 19, 2025

5 5 Share

Howdy folks,
Hope you are doing well! Previously, I wrote about setting up “multi-pass”
shaders as a way of layering shaders together (or repeating a shader
multiple times):

GM Shaders Mini: Recursive shaders


XOR · AUGUST 19, 2022

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
GM Shaders Mini: Recursive shaders

Today's mini tutorial is about recursive shader effects as a way of layering multiple passes
of shaders together.

Read full story

This is commonly used for blurring because it can be more efficient to apply
a large blur in separate passes (for example, instead of a 9x9 Gaussian
blur, you can do a 9x1 blur and 1x9 blur, 2*N samples instead of N^2).
However, multipass effects have downsides. They are more difficult to
implement, requiring surfaces/canvases, additional draw calls, and more
video memory usage. They will complicate your draw pipeline process, and
in some cases, are unfeasible. The alternative is to combine two shaders
together. So, when is it worth it to combine shaders?

When To Combine Shaders


PDFmyURL converts web pages and even full websites to PDF easily and quickly.
Here’s a quick checklist to go over when considering shader compatibility,
roughly in order of most important to least important:

Performance: Are the effects expensive? Chances are, if both shaders


being combined are expensive, the combined shader will be very
expensive. Unless you can think of some clever optimizations that
simplify it, it’s probably not going to work!
Sample Count: Do these shaders require lots of texture samples? If
you have an outline shader that uses 8 texture samples and a blur
shader that uses 32 samples, you’ll likely have to do 8 outline samples
for every blur sample, meaning you’ll be using 8*32 or 256 samples!
That is a lot of texture samples for moderately-sized textures!
Generally, it’s safe to combine a multi-sample shader with a single
sample shader, but be careful if both shaders use a lot of samples. The
shader order does matter, though. If you have an expensive 1-sample
shader before a cheap 8-sample blur, you have to do the expensive
code 8 times! If the blurring occurs first, you’d only have to do the
expensive part once.

Coordinates: Check if the shaders are operating in the same


coordinates. You might have one shader that is a screenspace effect
applied to pixel coordinates on the screen, another might be world-
space coordinates, or texel coordinates. That doesn’t necessarily mean
they are incompatible, but it will take some unit conversion and may
add some complications.
Textures: Do your shaders require specific texture sizes? What about
texture filtering (e.g., linear interpolation vs nearest neighbor)? How
about texture boundaries? Distortion effects, outlines, or blurs may
PDFmyURL converts web pages and even full websites to PDF easily and quickly.
sample outside of the texture boundary, so you’ll have to consider how
you handle these cases. Sometimes it may be texture repeat, texture
clamping, or discarding outside fragments. Make sure they can be
adapted to work together! You’ll also want to consider the GPU
settings: mainly blend modes and alpha testing.

Uniforms and Inputs: When combining shaders, you’ll need all the
uniforms from both of the shaders. While the limits are pretty high,
shaders do have limits, especially when it comes to having lots of large
textures or uniform arrays. You also want to make sure the shader
inputs and outputs match (attributes and varyings in old-school GLSL).
The good news is that sometimes you can reduce shader complexity by
reusing uniforms for both effects (like resolution or time).

If you’ve made it past that, then you’re probably ready to start combining!

Merging Shader Code


That checklist also hints a bit about how shaders are combined. The first
step is to turn your shaders into functions. Let’s start with a sample
grayscale shader like this:

//Saturation macro (0.0 = gray, 1.0 = full color)


#define SATURATION 0.0

varying vec2 v_vTexcoord;

void main()
{

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
vec2 uv = v_vTexcoord;

//Sample base texture.


vec4 tex = texture2D(gm_BaseTexture, uv);

//Output color and alpha


vec4 col = tex;
//Grayscale luma
//https://GMshaders.com/tutorials/tips_and_tricks/#useful
float gray = dot(tex, vec4(0.299, 0.587, 0.114, 0.0));
//Mix between gray and color with saturation
col.rgb = gray + (col.rgb - gray) * SATURATION;
}

We can rewrite this as a function, with fragment shader inputs as the


arguments. In this case, we just have the UV coordinates:

//Simple saturation shader:


vec4 saturation(vec2 uv)
{
//Sample base texture.
vec4 tex = texture2D(gm_BaseTexture, uv);

//Output color and alpha


vec4 col = tex;
//Grayscale luma
//https://GMshaders.com/tutorials/tips_and_tricks/#useful
float gray = dot(tex, vec4(0.299, 0.587, 0.114, 0.0));
//Mix between gray and color with saturation
col.rgb = gray + (col.rgb - gray) * SATURATION;

return col;
}

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
Uniforms and macros can be directly referenced in the function, so they do
not need to be added as arguments. This is a fairly light-weight function. It
doesn’t require a bunch of texture samples, for-loops, branching, or lots of
math. Now let’s say you want to combine it with this chromatic aberration
shader:

GM Shaders Mini: Chromatic Aberration


XOR · JUNE 11, 2023

An introduction to quality color shift effects

Read full story

Following a similar process, we end up with this function for radial CA:

//From GM Shaders Chromatic Aberration:


//shadertoy.com/view/DtGSRt

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
//Chromatic blur intensity
#define BLUR 0.05
//Chromatic constrast
#define CONTRAST 2.0
//Must be an even number
#define SAMPLES 20.0

vec4 chromatic(vec2 uv)


{
//Color output starts at 0.
vec4 color_sum = vec4(0);
vec4 weight_sum = vec4(0);

//Iterate 20 times from 0 to 1


for(float i = 0.0; i<=1.0; i+=1.0/SAMPLES)
{
//Add a texture sample approaching the center (0.5, 0.5)
//This center could moved to change how the direction of
aberation
//The mix amount determines the intensity of the aberration
smearing
vec2 coord = mix(uv, vec2(0.5), BLUR*(i-0.5));

vec4 weight = vec4(i,1.0 - abs(i+i-1.0), 1.0-i, 0.5);


weight = mix(vec4(0.5), weight, CONTRAST);

//Here we use the saturation effect as input


vec4 color = texture2D(gm_BaseTexture, coord);
color_sum += color * color * weight;
//Shift sample tint color from red to green to blue
//The total should be multiplied by the 2/number of samples,
(e.g. 0.1)
weight_sum += weight;
}

//Output the resulting color

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
return sqrt(clamp(color_sum / weight_sum, 0.0, 1.0));
}

Now that we have both shaders as functions, we can put them together in
one fragment shader. While we’re doing that, we should combine the
uniforms, macros, functions, and shader inputs. This is a good time to
remove any redundancies you find along the way and share functions and
uniforms if possible.

Order of Effects
Now is the point where you can actually combine the two functions as
needed. In this case, I want to apply the desaturation first and then apply
the chromatic aberration. To do this, I need to replace the texture2D in the
“chromatic” function with my “saturation” function. If I wanted to apply
the chromatic aberration first and desaturate after, I would put the
chromatic function inside the saturation function. This way would be
faster because it wouldn’t require executing the saturation function within a
for-loop, but we don’t want to desaturate after applying a color effect.

I’ve put together a ShaderToy example for this.

Newsletter Update
Just a heads-up, the cost for paid subscriptions is going up to $8/mo or
$80/yr soon. This will help me keep a consistent schedule and take fewer
contracts. If you’ve ever wanted to join, now is the last chance to get it for
$50/yr!
PDFmyURL converts web pages and even full websites to PDF easily and quickly.
Subscribe for more tutorials

Type your email... Subscribe

Thank you for the support!

Conclusion
Thankfully, the process for combining shaders is intuitive most of the time.
It can be summed up be turning your shaders into functions and feeding
one function into another as needed. The inner function is applied first. It’s
preferable to do the most samples first because shader costs can
compound quickly.

To recap, before you consider combining, you should look at:

Performance - Expensive shader + expensive shader ≈ very expensive!

Sample Count - Avoid combining shaders that use a lot of texture


samples.

Coordinates - Make sure the type of coordinates matches up correctly.

Textures - They should share texture settings and formats.

Inputs - Vertex formats, uniforms, and varying will have to match up.

If you pass that test, then it may be worth trying.

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
Extras
Here are my 3 examples of one-pass blur shaders

1 Pass Blur - A simple, cheap disk blur based on the golden angle.

Mip Blur - An efficient blur that makes use of mipmapping.

Bokeh - A rich Depth of Field effect that is good for backgrounds.

That’s all for today. Thank you for reading and have a great night!

-Xor

Subscribe to GM Shaders
By Xor · Launched 2 years ago
A series of mini shader tutorials for game developers and beyond!

Type your email... Subscribe

By subscribing, I agree to Substack's Terms of Use, and


acknowledge its Information Collection Notice and Privacy
Policy.

5 Likes

5 5 Share

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
Discussion about this post

Comments Restacks

Write a comment...

Hanprogramer 4d
Liked by Xor

Thank you for the tutorial! My question is, is there any tool I can use to parse GLSL codes
to do this automatically?
LIKE (1) REPLY SHARE

1 reply by Xor

design4use 3d

Shader beginner here - great tutorial.

Let's say I wanted to combine two shaders with both moving elements, one in the
background that does moving color gradients, and one in the foreground that applies a
circular ripple/shockwave effect on top of it.

How would you approach this conceptually? The mental challenge for me is that both are
moving unlike a static photo background texture which I can just read.
LIKE REPLY SHARE

2 replies by Xor and others

3 more comments...

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
Top Latest Discussions

Reading Math Papers


An overview of mathematics for programmers
APR 10 • XOR

GM Shaders Guest: Radiance Cascades


Part One: Introduction to Radiance Cascades
APR 13, 2024 • XOR AND ALEX

Signed Distance Fields


How SDFs work in shaders and how to write your own
FEB 19 • XOR

See all

Ready for more?

Type your email... Subscribe

PDFmyURL converts web pages and even full websites to PDF easily and quickly.
© 2025 Xor ∙ Privacy ∙ Terms ∙ Collection notice

Start writing Get the app

Substack is the home for great culture

PDFmyURL converts web pages and even full websites to PDF easily and quickly.

You might also like