blob: e98735a5235366dfe079f664312a82a01ca8286c [file] [log] [blame]
////////////////////////////////////////////////////////////////////////////////
//
// Licensed to the Apache Software Foundation (ASF) under one or more
// contributor license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright ownership.
// The ASF licenses this file to You under the Apache License, Version 2.0
// (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
<languageVersion : 1.0;>
kernel SoftLight
< namespace : "Flame";
vendor : "Adobe";
version : 1;
description : "SoftLight blend mode";
>
{
input image4 dst;
input image4 src;
output pixel4 result;
void
evaluatePixel()
{
pixel4 a = sampleNearest(dst,outCoord()); // cb
pixel4 b = sampleNearest(src,outCoord()); // cs
// remove premultiplied (srcCP/srcA, dstCP/dstA)
pixel3 cb = a.rgb;
pixel3 cs = b.rgb;
if (a.a > 0.0) {
cb.rgb = a.rgb / a.a;
}
if (b.a > 0.0) {
cs.rgb = b.rgb / b.a;
}
// dstA' = (1-srcA)*dstA + srcA
result.a = (1.0-b.a)*a.a + b.a;
// B(cs,cb) = cb � (1 � 2*cs)*cb*(1-cb), if (cs <= 0.5)
// = cb + (2*cs � 1)*(D(cb) � cb), otherwise
float3 blendResult;
// red
if (cs.r <= 0.5) {
blendResult.r = cb.r - (1.0 - clamp(2.0*cs.r,0.0,1.0))*cb.r*(1.0-cb.r);
} else {
// this could be a helper function, but bytecode doesn't support this
// = ((16*x � 12)*x +4)*x, if x <= 0.25
// = x**0.5, otherwise
float dcb;
if (cb.r <= 0.25) {
dcb = ((16.0*cb.r - 12.0) *4.0)*cb.r;
} else {
dcb = sqrt(cb.r);
}
blendResult.r = cb.r + (2.0*cs.r - 1.0)*(dcb - cb.r);
}
// green
if (cs.g <= 0.5) {
blendResult.g = cb.g - (1.0 - 2.0*cs.g)*cb.g*(1.0-cb.g);
} else {
// = ((16*x � 12)*x +4)*x, if x <= 0.25
// = x**0.5, otherwise
float dcb;
if (cb.g <= 0.25) {
dcb = ((16.0*cb.g - 12.0) *4.0)*cb.g;
} else {
dcb = sqrt(cb.g);
}
blendResult.g = cb.g + (2.0*cs.g - 1.0)*(dcb - cb.g);
}
// blue
if (cs.b <= 0.5) {
blendResult.b = cb.b - (1.0 - 2.0*cs.b)*cb.b*(1.0-cb.b);
} else {
// = ((16*x � 12)*x +4)*x, if x <= 0.25
// = x**0.5, otherwise
float dcb;
if (cb.b <= 0.25) {
dcb = ((16.0*cb.b - 12.0) *4.0)*cb.b;
} else {
dcb = sqrt(cb.b);
}
blendResult.b = cb.b + (2.0*cs.b - 1.0)*(dcb - cb.b);
}
// dstCP' = (1-srcA)*dstCP + (1-dstA)*srcCP + srcA*dstA*Blend(srcCP/srcA, dstCP/dstA)
result.rgb = (1.0-b.a)*a.rgb + (1.0-a.a)*b.rgb + b.a*a.a*blendResult.rgb;
}
}