Photoshop math with GLSL shaders
January 5, 2009I usualy play with Photoshop to try post-processing effects on photos or game screenshots, it’s a lot faster than coding directly anything in shaders, but at the end I wanted to see my effects running in real-time. So I adapted a big part of the C-like code from this famous Photoshop blending mode math page + missing blending modes to GLSL (and now HLSL!) code and I added a few other useful things from Photoshop, such as Hue/Saturation/Luminance conversion, desaturation, contrast.
For example, I tried combining a few things in my Editor:
Translating Photoshop operations on layers gives this kind of code:
uniform sampler2D Tex;
uniform sampler1D GradientMap;
uniform sampler1D GradientGround;
varying vec2 uv;
void main()
{
vec3 color = texture2D(Tex, uv).xyz;
// Split-tone
vec4 colorDesat = Desaturate(color, 1.0);
vec3 splitColor = texture1D(GradientMap, colorDesat.r).rgb;
vec3 pass1 = BlendColor(color, splitColor);
// Vertical gradient
vec4 verticalGradientColor = texture1D(GradientGround, uv.y);
vec3 pass2 = mix(pass1, BlendColor(pass1, verticalGradientColor.rgb), verticalGradientColor.a);
// Luminosity
vec3 pass3 = mix(pass2, BlendLuminosity(pass2, color + vec3(0.08)), 0.5);
// Linear light at 40%
vec3 pass4 = mix(pass3, BlendLinearLight(pass3, color), 0.4);
// Final
gl_FragColor = vec4(pass4, 1.0);
}
Here is the list of blending modes and functions I got:
Blending modes:
- Normal
- Lighten
- Darken
- Multiply
- Average
- Add
- Substract
- Difference
- Negation
- Exclusion
- Screen
- Overlay
- SoftLight
- HardLight
- ColorDodge
- ColorBurn
- LinearDodge
- LinearBurn
- LinearLight
- VividLight
- PinLight
- HardMix
- Reflect
- Glow
- Phoenix
- Hue
- Saturation
- Color
- Luminosity
Functions:
- Desaturation
- RGBToHSL (RGB to Hue/Saturation/Luminance)
- HSLToRGB (Hue/Saturation/Luminance to RGB)
- Contrast
Here is my GLSL code, almost all the blending modes are macros and some do per-channel operation so it could run faster using vector operations with masks (to take into account the values per component), but still I guess it could help ๐
Download PhotoshopMath.glsl
—
Update:
Oh and by the way you noticed the Split-Tone pass in my example:
// Split-tone
vec4 colorDesat = Desaturate(color, 1.0);
vec3 splitColor = texture1D(GradientMap, colorDesat.r).rgb;
vec3 result = BlendColor(color, splitColor);
It’s just the same thing than the Gradient Map… of the Create new fill or adjustment layer in Photoshop but blended in Color mode, which reminds me Color Temperature and Cross-Processing effects ๐
—
Update:
I updated the .glsl file, because I forgot a line in the ContrastSaturationBrightness() function and I had some issues on specific hardware due to conditional returns, so now it’s fixed.
And now, here is the HLSL version ๐
Download PhotoshopMath.hlsl
Great post! Implemented many of the photoshop blend modes in HLSL myself a while ago, but not as many as you’ve done here.
by repii January 7, 2009 at 1:45 am[…] I added the code in my Photoshop Math (GLSL/HLSL) shaders. […]
by Photoshop gamma correction shader « Romz blog January 22, 2009 at 12:52 amHello, and thanks for your webside and sorry my bad english.
I will like to know how I change in the fragment shader the HUE of a texture . and not modify the saturation and brithness
Thanks for all
by israel January 24, 2009 at 3:13 amYou can use my code and do:
by Romz January 24, 2009 at 2:03 pmvec3 hsl = RGBToHSL(texture2d(yourTexture, yourUV).rgb);
hsl.x = whateverYouWant; // .x is hue, .y is saturation, .z is brightness
vec3 color = HSLToRGB(hsl);
Thanks very much.Works well.
I will see you web page to knews comments.
Thanks for all.
by israel January 24, 2009 at 8:00 pmHi, I’ve been beating my brains out trying to blend two layers in case both are semitransparent. My results slightly differ from photoshop.
I write this shader (for ex., for difference):
// Performs “over”-type blending (colors must be premultiplied by alpha)
float4 blend(float4 overlying, float4 underlying)
{
float3 blended = overlying.rgb + ((1-overlying.a)*underlying.rgb);
float alpha = underlying.a + (1-underlying.a)*overlying.a;
return float4(blended, alpha);
}
// Performs advanced “over”-type blending
// (newcolor is the result of advanced blending (for ex, overlying.rgb * underlying.rgb))
float4 blend(float3 newcolor, float4 overlying, float4 underlying)
{
// Here the problem! (I think…)
float alpha = overlying.a * underlying.a;
float3 blended = newcolor*alpha + ((1-alpha)*overlying.rgb);
return blend(float4(blended, overlying.a), underlying);
}
// Input images
sampler2D underlyingSampler : register(s0);
sampler2D overlyingSampler : register(s1);
// Opacity of source image
float opacity : register(c0);
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 overlying = tex2D(overlyingSampler, uv);
float4 underlying = tex2D(underlyingSampler, uv);
overlying.a *= opacity;
overlying.rgb *= overlying.a;
underlying.rgb *= underlying.a;
float4 result = blend(abs(overlying.rgb – underlying.rgb), overlying, underlying);
by Daniel May 24, 2009 at 9:42 amreturn float4(result.rgb/result.a, result.a);
}
[…] wasnโt working. I tried to figure out what was wrong with it, but eventually I ran into another post that had a different way of expressing the math โฆ it was in HLSL! Plugging in this HLSL worked! […]
by Cory Plotts’ Blog » Blend Modes, Part II June 17, 2009 at 5:25 amI don’t know If I said it already but …This blog rocks! I gotta say, that I read a lot of blogs on a daily basis and for the most part, people lack substance but, I just wanted to make a quick comment to say I’m glad I found your blog. Thanks, ๐
A definite great read….
by BloggerDude October 9, 2009 at 1:19 amIn photoshop there are some additional bleding mode that missing here
by Lexus JC October 11, 2009 at 9:25 pm1) Darker Color:
Get the color of color with min luminosity
float bgLuminosity = 0.3 * bg.Red + 0.59 * bg.Green + 0.11 * bg.Blue;
float fgLuminosity = 0.3 * fg.Red + 0.59 * fg.Green + 0.11 * fg.Blue;
if (bgLuminosity fgLuminosity)
result = bg;
else
result = fg;
2) The second mode is Lighter color:
Get the color of color with max luminosity
float bgLuminosity = 0.3 * bg.Red + 0.59 * bg.Green + 0.11 * bg.Blue;
float fgLuminosity = 0.3 * fg.Red + 0.59 * fg.Green + 0.11 * fg.Blue;
if (bgLuminosity > fgLuminosity)
result = bg;
else
result = fg;
Just a question.. what license are you releasing this under ?
by Xn May 17, 2010 at 12:07 pmCan it be used in a commercial project free of charge ?
The Luminance blend mode seems incorrect, at least if Photoshop CS4 is any sort of reference.
Photoshop’s Luminance is calculated as:
Luminance = 0.30R + 0.59G + 0.11B
You can verify this by placing any image in Luminance blend mode over any grayscale image. Compare the result to taking the original image and using the Channel Mixer (monochrome output) with settings 30, 59 and 11.
HSL Lightness (L) is calculated as:
L = (max(R, G, B) – min(R, G, B)) / 2
This is from your own algorithms. The two formulas are clearly not the same.
Using U for Luminance, I don’t know what the RGB2HSU formula is (although I could guess) nor what the HSU2RGB formula is. I would love to find out.
by Tony Freixas June 8, 2010 at 4:21 pm[…] Photoshop effects Possibly related posts: (automatically generated)Scenarios for jscJSC Ultra Application to Support […]
by Write WebGL in C# with JSC « c# to javascript, actionscript July 27, 2010 at 9:03 amThanks for this excellent post.
by Bruno August 5, 2010 at 10:34 pmWill soon be integrated in my soft !
With the HLSL I was able to achieve significantly better performance when using these blending functions without the ‘if’ conditionals. Instead I use the following macro to create an interpolation factor for a lerp:
#define HardFactor(factor) max(sign(##factor – 0.5), 0)
That macro results in 0 for values less than 0.5 or 1 for values greater than 0.5. Nice little trick to keep around as long as you use it wisely.
by default_ex September 23, 2010 at 10:37 amAny chance in these being ported to GLSL ES2?
by blitz June 1, 2011 at 2:45 amXn had a very good question… Can this be used in a commercial application?
by Filipe July 26, 2011 at 2:56 pmBTW, great blog, very helpful.
Thanks!
You can use it for a commercial application.
by Romz August 3, 2011 at 9:05 pmIf you have credits in your game/app, you can have a special thanks for me (Romain Dura), or if you have a blog with screenshots or whatever you can link to this page when you post something using my code.
And you can reply here with a link to your application/website so we can see what you guys did.
Whatever you think is right.
Do you think it would be possible to post process the effects achieved using normal maps (bump, parallax), so that you could use deferred shading and not have to push through or use normal maps? Probably you would need some map to encode surface irregularity which if it ended up on the first render would kick the post processor to emulate whatever the encode proposed.
by Ste3e January 4, 2012 at 5:35 amHi Romain,
I’m quite new to all the shader stuff and would like some help if possible.
My goal is to get a photoshop plugin for Mac which will enable to filter a layer and get a CRT like render.
I get the code for the effect wanted here: http://filespart.com/go/74a8a3f6eedc84b1122a8ce9193c0bf8.html
Now what could I do with it please?
I use photoshop CS5 on a Mac with Intel CPU and a GMA 950.
Thanks in advance.
by emm February 9, 2012 at 10:37 pmHi guys did any know how to compile a hlsl version?
It seems multiple macro does not supported – like
#define Blend(base, blend, funcf) float3(funcf(base.r, blend.r), funcf(base.g, blend.g), funcf(base.b, blend.b))
#define BlendScreen(base, blend) Blend(base, blend, BlendScreenf)
But when we write it directly in PS : like Blend(float3(), float3(), BlendScreenf) -then it works? Any opinion on such behavior?
by lurky June 15, 2012 at 6:42 pmcompile params i’ve used: fxc /T fx_2_0 /Fo *.fxo *.fx
by lurky June 15, 2012 at 6:43 pmthe PhotoshopMathFX.hlsl included in the effect file with techniques
[…] the overlay is the Photoshop Overlay Blending Mode. I am using the formulas from this classic postย https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/. The naรฏve implementation of the Overlay blending requires one branch for each of the RGB […]
by Eliminating branches in shaders | xissburg July 13, 2012 at 5:51 am[…] So these macros make it quite easy to increase or reduce contrast, shift and clip tonal range, lighten or darken shadows and highlights. I added the (GLSL / HLSL) code to the Photoshop Math shaders. […]
by Levels control shader « Romz blog August 27, 2012 at 7:51 pm[…] blog Computer graphics, shaders, generative coding « Photoshop math with GLSL shaders Photoshop gamma correction shader » Photoshop math with HLSL shaders January 8, […]
by Photoshop math with HLSL shaders « Romz blog August 27, 2012 at 7:52 pmyou saved me a big pile of work. I LOVE YOU. thanks!
by Sandro September 23, 2012 at 1:19 pm[…] o overlay รฉ o Photoshop Overlay Blending Mode, onde as fรณrmulas consegui nesse post clรกssico https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/. A implementaรงรฃo padrรฃo do overlay requer um condicional para cada um dos canais RGB. […]
by Eliminando condicionais em shaders | xissburg November 19, 2012 at 4:35 pmWow, this is awesome. Thanks for sharing your hard work, you just made my day!
by Mary June 9, 2013 at 7:20 am[…] https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/ […]
by Photoshop blending mode to OpenGL ES without shaders | Ask & Answers October 30, 2013 at 5:37 pmUndeniably consider that which you said. Your favorite justification seemed to be
on the web the easiest thing to consider of.
I say to you, I certainly get irked even as other
folks think about issues that they just don’t know about.
You managed to hit the nail upon the highest as smartly as defined out the whole thing without
having side-effects , people can take a signal.
Will probably be again to get more. Thank you
by Ian September 13, 2014 at 5:28 pmGenerally I do not read post on blogs, but I would like to say that this write-up very
by Louis Vuitton USA September 15, 2014 at 3:31 amforced me to try and do it! Your writing taste has been surprised me.
Thanks, quite great article.
[…] For the Photoshop steps, Romain Dura has helpfully converted the math functions to GLSL, and the gaussian blur steps from cgwg’s halated CRT shader can drop right […]
by Designing a Large-scale Phosphor Filter/Shader April 23, 2015 at 1:20 pmI’m programmer, when code about shader, i get slow speed, all about GPU, how to fix?
by opengl es August 19, 2015 at 5:21 am[…] https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/ […]
by Photoshop blending mode to OpenGL ES without shaders | Questions December 13, 2015 at 12:00 pmI used color blend,but it’s dark then photoshop cs6.Please try it and slove it.tks.
by Fuatnow August 23, 2016 at 12:52 am[…] Photoshop math with GLSL shaders […]
by ํฌํ ์ต์ ๋ธ๋ ๋ ๋ชจ๋ ์์ ๋ฐ hlsl์์ด๋ - ๋ฌ๋ ค๋ผ ์์ ๊ฑฐ July 3, 2017 at 5:42 amthe color/hue/sat/lum blends all seem to be wrong,
by indexofrefraction February 23, 2018 at 3:59 amExample: color blend rgb(0.01,0,0) over rgb(0.5,0.5,0.5) gets you a full red.
follow up… in BlendColor() blendHSL.z is completely ignored!
by indexofrefraction February 23, 2018 at 5:32 amthe outcome is the same for blend rgb(1,0,0) or rgb(0.1,0,0)
… maybe using an additional mix would be correct?
vec3 BlendColor(vec3 base, vec3 blend)
{
vec3 blendHSL = RGBToHSL(blend);
return mix(base, HSLToRGB(vec3(blendHSL.r, blendHSL.g, RGBToHSL(base).b)), blendHSL.z);
}
Hi! Thanks for an awesome work!
by Emil April 20, 2018 at 9:20 amIm absolutely new to shaders and I’m working on blending two volume slices by “difference”. I couldn’t find anything in your code but you say in the description that you have the blending mode ‘difference’ as well. Would greatly appreciate some input on how i could do that!
Regards
[…] Impression 3D Casablanca – Maroc. 3d impression de metal. Aniwaa.fr – Comparatif prix imprimantes 3D et scanners 3D. Photoshop math with GLSL shaders | Projects, Software, Programming, GLSL – Romz Blog. […]
by Nargop | Pearltrees March 1, 2019 at 7:34 am[…] https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/ […]
by opengl-es - Di fusione di Photoshop in modalitร OpenGL ES senza shader July 7, 2019 at 10:51 pm[…] https://mouaif.wordpress.com/2009/01/05/photoshop-math-with-glsl-shaders/ […]
by Photoshop blending mode to OpenGL ES without shaders - ErrorsFixing December 8, 2021 at 11:28 amthe old link is broken, this should be used instead: https://app.box.com/s/y1tpmj61r8
by Daniil Kurachkin April 9, 2023 at 8:44 pm