Playing with BlendState vs Photoshop Blend Modes

So I am new to the math behind the blending and how it works with the BlendState.

When I tried to create an overlay BlendState I ran into problems. As practice to figure out how it works I decided to try and translate the formulas I found at Insight into Photoshop 7.0 Blending Modes to BlendStates where I could. However I soon found that this seems to not be possible using BlendStates in most cases (just darken, multiply, lighten and linear dodge).

Below is a list of what I have come up with so far. What I’m looking for is confirmation if my assumptions for the ones that do not work are correct. And because of that I would need to create a custom PixelShader to get the effect, or is the BlendState more flexible then I am asuming.

Basicly I’m just trying to figure out if I have grasp on how the BlendState works. Also are there any common BlendStates that have a useful purpose outside what I’ve listed.

Regards,
Jenne


Darken

R = min(Source, Destination)

return new BlendState {
    ColorSourceBlend = Blend.One,
    ColorDestinationBlend = Blend.One,
    ColorBlendFunction = BlendFunction.Min
};

Multiply

R = Source * Destination

return new BlendState {
    ColorSourceBlend = Blend.DestinationColor,
    ColorDestinationBlend = Blend.Zero,
    ColorBlendFunction = BlendFunction.Add
};

ColorBurn

R = 1 - (1 - Source) / Destination

Requires shader because of division?

LinearBurn

R = Source + Destination - 1

Requires a shader because of the -1 after the additive blend? Requires (Source.One + Destination.One) - 1 from what I can tell this can’t be done with this.

Lighten

R = max(Source, Destination)

return new BlendState {
    ColorSourceBlend = Blend.One,
    ColorDestinationBlend = Blend.One,
    ColorBlendFunction = BlendFunction.Max
};

Screen

R = 1 - InverseSource * InverseDestination

Requires shader because we don’t have a 1 constant nor can we set one side of the function to both inverse

ColorDodge

R = Source / InverseDestination

Requires shader because of division?

LinearDodge

R = Source + Destination

return new BlendState {
    ColorSourceBlend = Blend.One,
    ColorDestinationBlend = Blend.One,
    ColorBlendFunction = BlendFunction.Add
};

##Now the following should require a shader if I’m correct because of all the more complex formulas.

Overlay

A combination of multiply and screen

if (Source > 0.5) R = 1 - (1 - 2 * (Source - 0.5)) * (InverseDestination)
if (Source <= 0.5) R = (2 * Source) * Destination

SoftLight

A combination of multiply and screen

if (Destination > 0.5) R = 1 - (InverseSource) * (1 - (Destination - 0.5))
if (Destination <= 0.5) R = Source * (Destination + 0.5)

HardLight

A combination of multiply and screen

if (Destination > 0.5) R = 1 - (InverseSource) * (1 - 2 * (Destination - 0.5))
if (Destination <= 0.5) R = Source * (2 * Destination)

VividLight

A combination of color burn and color dodge

if (Destination > 0.5) R = 1 - (InverseSource) / (2 * (Destination - 0.5))
if (Destination <= 0.5) R = Source / (1 - 2 * Destination)

LinearLight

A combination of linear burn and linear dodge

if (Destination > 0.5) R = Source + 2 * (Destination - 0.5)
if (Destination <= 0.5) R = Source + 2 * Destination - 1

PinLight

A combination of darken and lighten

if (Destination > 0.5) R = max(Source, 2 * (Destination - 0.5))
if (Destination <= 0.5) R = min(Source, 2 * Destination))

Difference

R = abs(Source - Destination)

Exclusion

R = 0.5 - 2 * (Source - 0.5) * (Destination - 0.5)

3 Likes

This is a good informational post, but I don’t have much to add to it.