## Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

Moderator: SecondMan

DeFusion
Posts: 5
Joined: Tue Feb 05, 2019 5:59 am

### Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

Hi!

I've basically always used blend modes in Photoshop with looking at what it does, rather than understanding of what it does.
Now i start using Fusion and i want the Linear Light and Pin Light blend modes there, but it seems i need to know a lot of technical stuff for that, which i don't. And this tool, just gave me a black image: http://www.bryanray.name/wordpress/pin- ... ic-fusion/ I don't understand what it does.

Even when i started watching an introduction video to the Custom Tool in preparation for watching the 'Compositing School' YouTube playlist of Simon Ubsdell, i noticed i didn't even know what the technical underlying terms like controls like gain, lift or gamma meant. It feels like i can't even go into the 'Compositing School' with confidence.

So my questions:
- Is there an easy way to right away get these blend modes for now?
- What do you recommend for me to get a basic understanding of compositing and all it's terminology? Is there a good course or book for that that you recommend? (I would like it to be very very basic, low level/deep and understandable)

Midgardsormr
Fusionista
Posts: 918
Joined: Wed Nov 26, 2014 8:04 pm
Location: Los Angeles, CA, USA
Been thanked: 22 times
Contact:

### Re: Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

DeFusion wrote:
Thu Mar 14, 2019 8:49 am
Now i start using Fusion and i want the Linear Light and Pin Light blend modes there, but it seems i need to know a lot of technical stuff for that, which i don't. And this tool, just gave me a black image: http://www.bryanray.name/wordpress/pin- ... ic-fusion/ I don't understand what it does.

The PinLight macro has two inputs. The gold input is the Background—it's equivalent to every layer below the layer you're adding your pin lighted layer to. The green input is the layer that the blend mode will operate on.

The math is based on information found here: https://photoblogstop.com/photoshop/pho ... -explained
I did only limited testing. Basically I made a greyscale gradient and put it on top of a solid 0.5 background to see if the image was similar to what I saw when I did the same thing in Photoshop:

From the above website, I guess that Linear Dodge might be this:

Code: Select all

{
Tools = ordered() {
linearDodge_maybe = Custom {
CtrlWZoom = false,
NameSet = true,
CustomData = {
Settings = {
[1] = {
Tools = ordered() {
CustomTool2 = Custom {
Inputs = {
LUTIn3 = Input {
SourceOp = "CustomTool2LUTIn3",
Source = "Value"
},
LUTIn1 = Input {
SourceOp = "CustomTool2LUTIn1",
Source = "Value"
},
Image1 = Input {
SourceOp = "CustomTool1",
Source = "Output"
},
LUTIn4 = Input {
SourceOp = "CustomTool2LUTIn4",
Source = "Value"
},
LUTIn2 = Input {
SourceOp = "CustomTool2LUTIn2",
Source = "Value"
}
},
Name = "CustomTool2",
CtrlWZoom = false,
ViewInfo = OperatorInfo { Pos = { 1210, 280.5 } },
CustomData = {
}
},
CustomTool2LUTIn1 = LUTBezier {
Name = "CustomTool2LUTIn1",
NameSet = true,
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Green = 0, Blue = 0, Red = 204 }
},
CustomTool2LUTIn2 = LUTBezier {
Name = "CustomTool2LUTIn2",
NameSet = true,
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Green = 204, Blue = 0, Red = 0 }
},
CustomTool2LUTIn3 = LUTBezier {
Name = "CustomTool2LUTIn3",
NameSet = true,
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Green = 0, Blue = 204, Red = 0 }
},
CustomTool2LUTIn4 = LUTBezier {
Name = "CustomTool2LUTIn4",
NameSet = true,
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Green = 204, Blue = 204, Red = 204 }
}
}
},
[2] = {
Tools = ordered() {
CustomTool2 = Custom {
Inputs = {
LUTIn3 = Input {
SourceOp = "CustomTool2LUTIn3",
Source = "Value"
},
LUTIn1 = Input {
SourceOp = "CustomTool2LUTIn1",
Source = "Value"
},
Image1 = Input {
SourceOp = "CustomTool1",
Source = "Output"
},
BlueExpression = Input { Value = "b1-b2" },
LUTIn2 = Input {
SourceOp = "CustomTool2LUTIn2",
Source = "Value"
},
LUTIn4 = Input {
SourceOp = "CustomTool2LUTIn4",
Source = "Value"
},
RedExpression = Input { Value = "r1-r2" },
GreenExpression = Input { Value = "g1-g2" }
},
CtrlWZoom = false,
ViewInfo = OperatorInfo { Pos = { 1210, 280.5 } },
CustomData = {
}
},
CustomTool2LUTIn1 = LUTBezier {
SplineColor = { Green = 0, Blue = 0, Red = 204 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
},
CustomTool2LUTIn2 = LUTBezier {
SplineColor = { Green = 204, Blue = 0, Red = 0 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
},
CustomTool2LUTIn3 = LUTBezier {
SplineColor = { Green = 0, Blue = 204, Red = 0 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
},
CustomTool2LUTIn4 = LUTBezier {
SplineColor = { Green = 204, Blue = 204, Red = 204 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
}
}
},
[3] = {
Tools = ordered() {
CustomTool2 = Custom {
Inputs = {
LUTIn3 = Input {
SourceOp = "CustomTool2LUTIn3",
Source = "Value"
},
LUTIn1 = Input {
SourceOp = "CustomTool2LUTIn1",
Source = "Value"
},
Image1 = Input {
SourceOp = "CustomTool1",
Source = "Output"
},
BlueExpression = Input { Value = "b1+b2" },
LUTIn2 = Input {
SourceOp = "CustomTool2LUTIn2",
Source = "Value"
},
LUTIn4 = Input {
SourceOp = "CustomTool2LUTIn4",
Source = "Value"
},
RedExpression = Input { Value = "r1+r2" },
GreenExpression = Input { Value = "g1+g2" }
},
CtrlWZoom = false,
ViewInfo = OperatorInfo { Pos = { 1210, 280.5 } },
CustomData = {
}
},
CustomTool2LUTIn1 = LUTBezier {
SplineColor = { Green = 0, Blue = 0, Red = 204 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
},
CustomTool2LUTIn2 = LUTBezier {
SplineColor = { Green = 204, Blue = 0, Red = 0 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
},
CustomTool2LUTIn3 = LUTBezier {
SplineColor = { Green = 0, Blue = 204, Red = 0 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
},
CustomTool2LUTIn4 = LUTBezier {
SplineColor = { Green = 204, Blue = 204, Red = 204 },
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
NameSet = true
}
}
},
}
},
Inputs = {
LUTIn1 = Input {
SourceOp = "linearDodge_maybeLUTIn1",
Source = "Value",
},
LUTIn2 = Input {
SourceOp = "linearDodge_maybeLUTIn2",
Source = "Value",
},
LUTIn3 = Input {
SourceOp = "linearDodge_maybeLUTIn3",
Source = "Value",
},
LUTIn4 = Input {
SourceOp = "linearDodge_maybeLUTIn4",
Source = "Value",
},
RedExpression = Input { Value = "if(c2 > 0.5, (c1+c2)*0.5,(c1+c2-1)*0.5)", },
GreenExpression = Input { Value = "if(c2 > 0.5, (c1+c2)*0.5,(c1+c2-1)*0.5)", },
BlueExpression = Input { Value = "if(c2 > 0.5, (c1+c2)*0.5,(c1+c2-1)*0.5)", },
ShowNumber1 = Input { Value = 0, },
ShowNumber2 = Input { Value = 0, },
ShowNumber3 = Input { Value = 0, },
ShowNumber4 = Input { Value = 0, },
ShowNumber5 = Input { Value = 0, },
ShowNumber6 = Input { Value = 0, },
ShowNumber7 = Input { Value = 0, },
ShowNumber8 = Input { Value = 0, },
ShowPoint1 = Input { Value = 0, },
ShowPoint2 = Input { Value = 0, },
ShowPoint3 = Input { Value = 0, },
ShowPoint4 = Input { Value = 0, },
ShowLUT1 = Input { Value = 0, },
ShowLUT2 = Input { Value = 0, },
ShowLUT3 = Input { Value = 0, },
ShowLUT4 = Input { Value = 0, },
},
ViewInfo = OperatorInfo { Pos = { 1129, 191 } },
},
linearDodge_maybeLUTIn1 = LUTBezier {
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Red = 204, Green = 0, Blue = 0 },
CtrlWShown = false,
NameSet = true,
},
linearDodge_maybeLUTIn2 = LUTBezier {
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Red = 0, Green = 204, Blue = 0 },
CtrlWShown = false,
NameSet = true,
},
linearDodge_maybeLUTIn3 = LUTBezier {
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Red = 0, Green = 0, Blue = 204 },
CtrlWShown = false,
NameSet = true,
},
linearDodge_maybeLUTIn4 = LUTBezier {
KeyColorSplines = {
[0] = {
[0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
[1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
}
},
SplineColor = { Red = 204, Green = 204, Blue = 204 },
CtrlWShown = false,
NameSet = true,
}
},
ActiveTool = "linearDodge_maybe"
}



I'm not sure what he means by "applied at half strength", though, so it may be wrong. My implementation above is (A+B)*0.5 above 0.5 and (A+B-1)*0.5 below 0.5, but it might have been A+(B*0.5) and A+(B*0.5)-1. I wish he'd just given the actual math instead of describing it in English.

Even when i started watching an introduction video to the Custom Tool in preparation for watching the 'Compositing School' YouTube playlist of Simon Ubsdell, i noticed i didn't even know what the technical underlying terms like controls like gain, lift or gamma meant. It feels like i can't even go into the 'Compositing School' with confidence.

Quickie lesson: I'll describe the major color correction operations in terms of both their math and their equivalents in Photoshop. PS tends to be more "Looks About Right" and less about the real numbers involved, so it can be a little difficult to make the jump to a more technical image processing workflow.

Gain: Roughly equivalent to moving the upper-right point in a Curves adjustment layer. Gain multiplies pixels by the value in the control. If you reduce it below 1, the image gets darker. If you raise it above 1, the image gets brighter. Photoshop tries to protect you from creating "clipped" values—pixels with a value above the maximum of 255 in 8-bit integer mode, so in Curves you can't raise that point above 1. Fusion and Nuke trust the artist more, permitting you to create illegal values if you wish.

Note that when adjust the Gain control, since it's multiplying, the strength of the effect gets weaker as pixels near a value of 0. This means that no matter where you move Gain, your black point will remain the same. You might occasionally hear someone refer to Gain as a Scale, also. If you look at your image in the Waveform sub-view, you can see why—the wave gets scaled up and down as you move the control.

Lift: Lift is the opposite of Gain. It's equivalent to moving that lower-left point in the Curves. The black point is raised and lowered, but the white point remains in place. Again, in Fusion you can lower Lift below 0, whereas Photoshop won't allow it.

Gamma: Gamma is roughly the same as adjusting the center of the curve. Mathematically, it's performing a power operation. The pixel's value raised to the power of the Gamma control. It's a way of getting brighter or darker pixels without changing the white or black points. The strength of a gamma adjustment falls off as you near those extremes, so its effects are most visible in the mid-tones. Gamma also modifies the saturation of the image. As it's reduced the image will become more saturated, so it may need a corresponding adjustment to the Saturation control to compensate if you're performing a Gamma on all three channels at once.

Brightness has no equivalence in Photoshop, as far as I know. It's a simple addition to the value of the pixels. It therefore possible to get both superwhite and sub-black pixels, and PS, as previously mentioned, doesn't like you to do that.

Contrast scales the values around middle grey, or 0.5. So that center value remains constant, but white and black will move in opposite directions.

Fusion's Contrast and Lift controls are quite 'twitchy', so it's usually a good idea to hold Ctrl while adjusting the sliders for finer control.

So my questions:
- Is there an easy way to right away get these blend modes for now?
- What do you recommend for me to get a basic understanding of compositing and all it's terminology? Is there a good course or book for that that you recommend? (I would like it to be very very basic, low level/deep and understandable)

I'd be remiss if I didn't recommend my partly-finished book located on the same website you already found:
http://www.bryanray.name/wordpress/comp ... -contents/

Unfortunately, the chapter of greatest interest right this minute is the appendix about image math and blending, and that's one I haven't finished (I ran into some roadblocks with a couple of the more esoteric modes in the ChannelBooleans tool). Still, the Anatomy of an Image would be useful reading, and the main part of the book will walk you through the basics of the most common visual effects compositing activities. The second draft is in progress; once it's done and I'm close to publishing, these articles will vanish from the web site, so read 'em while you got 'em!

intelligent machine
Fusionista
Posts: 341
Joined: Fri May 13, 2016 10:01 pm
Location: Austin, Texas, USA
Been thanked: 16 times
Contact:

### Re: Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

http://compositing.tv/Research/

Fusionator
Posts: 1334
Joined: Fri Aug 08, 2014 1:11 pm
Been thanked: 5 times

### Re: Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

This is the HLSL/Cg blendmode code I've used:
1. float3 Normal (float3 Bg, float3 Fg, float FgAlpha)
2. {
3.     return lerp(Bg,  Fg, FgAlpha);
4. }
5.
6. float3 Screen (float3 Bg, float3 Fg)
7. {
8.     return (1 - (1 - Bg) * (1 - Fg));
9. }
10.
11. float3 Multiply (float3 Bg, float3 Fg)
12. {
13.     return (Bg * Fg);
14. }
15.
16. float3 Overlay (float3 Bg, float3 Fg)
17. {
18.     return lerp(Bg * Fg * 2, (1.0 - 2.0 * (1.0 - Bg) * (1.0 - Fg)), Bg > .5);
19. }
20.
21. float3 HardLight (float3 Bg, float3 Fg)
22. {
23.     return Overlay(Fg, Bg);
24. }
25.
26. float3 SoftLight (float3 Bg, float3 Fg)
27. {
28.     return (1 - 2 * Fg) * Bg * Bg + 2 * Bg * Fg;
29. }
30.
31. float3 VividLight (float3 Bg, float3 Fg)
32. {
33.     return lerp(lerp(2 * Fg, max((1.0 - (1.0 - Bg) / (2 * Fg)), 0.0), Fg == 0), min(Bg/ saturate((1.0 - (2.0 * (Fg - 0.5)))), 1.0), saturate(Fg));
34. }
35.
36. float3 LinearLight (float3 Bg, float3 Fg)
37. {
38.     return lerp(Bg + 2 * Fg - 1, Bg + 2 * (Fg - .5), Fg > .5);
39. }
40.
41. float3 PinLight (float3 Bg, float3 Fg)
42. {
43.     return lerp(min(Bg, 2 * Fg), max(Bg, 2 * (Fg - .5)), Fg > .5);
44. }
45.
46. float3 ColorDodge (float3 Bg, float3 Fg)
47. {
48.     return  (Fg >= float(1)) ? Fg : min(Bg / (float3(1) - Fg), 1);
49. }
50.
51. float3 ColorBurn (float3 Bg, float3 Fg)
52. {
53.     return (Fg <= 0) ? Fg : float3(1) - min(float3(1), (float3(1) - Bg)/Fg);
54. }
55.
56. float3 Darken (float3 Bg, float3 Fg)
57. {
58.     return min(Bg, Fg);
59. }
60.
61. float3 Lighten (float3 Bg, float3 Fg)
62. {
63.     return max(Bg, Fg);
64. }
65.
66. float3 Difference (float3 Bg, float3 Fg)
67. {
68.     return abs(Bg - Fg);
69. }
70.
71. float3 Exclusion (float3 Bg, float3 Fg)
72. {
73.     return Bg + Fg - 2 * Bg * Fg;
74. }
75.
76. float3 Add (float3 Bg, float3 Fg)
77. {
78.     return Bg + Fg;
79. }
80.
81. float3 Subtract (float3 Bg, float3 Fg)
82. {
83.     return Fg - Bg;
84. }
85.
86. float3 LinearBurn (float3 Bg, float3 Fg)
87. {
88.     return (Bg + Fg - 1);
89. }

JUNE
Fusioneer
Posts: 202
Joined: Wed Aug 06, 2014 5:45 am
Been thanked: 7 times
Contact:

### Re: Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

Pin Light

Code: Select all

float3 pinLight(float3 src, float3 dst){
return mix(mix(2.0f * src, dst, step(0.5f * dst, src)),
max((float3)(0.0f), 2.0f * src - 1.0f),
step(dst, (2.0f * src - 1.0f))
);
}

Linear Light

Code: Select all

float3 linearLight(float3 src, float3 dst){return clamp(2.0f * src + dst - 1.0f, 0.0f, 1.0f);;
}


Fusionator
Posts: 1334
Joined: Fri Aug 08, 2014 1:11 pm
Been thanked: 5 times

### Re: Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

DeFusion wrote:
Thu Mar 14, 2019 8:49 am
i noticed i didn't even know what the technical underlying terms like controls like gain, lift or gamma meant.
Oh, I had the math for most of how BrightnessContrast works (I left out saturation from this example because it's boring) posted a while back.

viewtopic.php?f=16&t=802#p6515

Midgardsormr
Fusionista
Posts: 918
Joined: Wed Nov 26, 2014 8:04 pm
Location: Los Angeles, CA, USA
Been thanked: 22 times
Contact:

### Re: Blending modes like Linear Light or Pin Light? (And basic compositing theory?)

Someone has pointed out to me that I should expand my description of a gamma adjustment a bit more, as it was both incorrect and incomplete. The gamma control actually provides the reciprocal of the exponent. That is, if you raise it to 2.2, the result is p^0.4545…

In a floating-point image, you can have values below 0.0 and above 1.0. Although 0 & 1 are held in place by the nature of the math involved, values outside the range will still be modified. However, the behavior reverses itself above 1. Raising the gamma will cause reduced brightness. Below 0 things get… odd. There are complex numbers involved. And I don't mean they're 'complicated' (although that's also true), I mean they're imaginary. I haven't taken the time to work out exactly how it should work, but if you try it, you get a sort of 'S' curve result. Here's a screenshot of the Waveform:

Untitled.jpg

Watching the Waveform while you made adjustments can be very instructive. Here's the Background and Brightness/Contrast nodes I used:

Code: Select all

{
Tools = ordered() {
BrightnessContrast1 = BrightnessContrast {
CtrlWZoom = false,
Inputs = {
Gamma = Input { Value = 2.607, },
Input = Input {
SourceOp = "Background1",
Source = "Output",
},
},
ViewInfo = OperatorInfo { Pos = { 640, 223 } },
},
Background1 = Background {
Inputs = {
Width = Input { Value = 1920, },
Height = Input { Value = 1080, },
Depth = Input { Value = 3, },
["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
Type = Input { Value = FuID { "Horizontal" }, },
TopLeftRed = Input { Value = -0.5, },
TopLeftGreen = Input { Value = -0.5, },
TopLeftBlue = Input { Value = -0.5, },
TopRightRed = Input { Value = 1.5, },
TopRightGreen = Input { Value = 1.5, },
TopRightBlue = Input { Value = 1.5, },
},
ViewInfo = OperatorInfo { Pos = { 530, 223 } },
}
}
}

It's just a horizontal gradient from -1.5 to +1.5. To see the Waveform, you can either use the Sub-View or put the image into a Viewer, right-click the Viewer and choose Views > Waveform. Then zoom out using the typical Fusion controls so you can see the entire wave.
You do not have the required permissions to view the files attached to this post.