//////////////////////////////////////////////////////////////////////////////// | |
// | |
// 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 Color | |
< namespace : "Flame"; | |
vendor : "Adobe"; | |
version : 1; | |
description : "Color blend mode"; | |
> | |
{ | |
input image4 dst; | |
input image4 src; | |
output pixel4 result; | |
// PB bytecode can't do functions, use macros to define common functions | |
// gets the max number out of the three | |
#define max3( x, y, z ) ( max((x), max((y), (z))) ) | |
// gets the min number out of the three | |
#define min3( x, y, z ) ( min((x), min((y), (z))) ) | |
// gets the max number out of the three elements in a vector | |
#define max3v(C) ( max3((C.x), (C.y), (C.z)) ) | |
// gets the min number out of the three elements in a vector | |
#define min3v(C) ( min3((C.x), (C.y), (C.z)) ) | |
// Sat - returns float, takes in a pixel3, or pixel4 | |
#define saturation(C) ( (max3((C.r), (C.g), (C.b)) - min3((C.r), (C.g), (C.b))) ) | |
// Luminance - returns float, takes in a pixel3, or pixel4 | |
#define luminance(C) ( (((C.r) * 0.3) + ((C.g) * 0.59) + ((C.b) * 0.11)) ) | |
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; | |
// adjustment -> adjustedcs | |
float3 adjVec = (cb - cs); | |
float adjustment = luminance(adjVec); | |
float3 adjustedcs = cs + adjustment; | |
// Blend() | |
/* -------------------------------------------------------- | |
* void clipcolor(inout float3 color) | |
* clips color. | |
* input and output float3 color_cl | |
* | |
* -------------------------------------------------------- */ | |
float3 color_cl = adjustedcs; | |
float lum_cl = luminance(color_cl); | |
float3 lumVec = float3(lum_cl, lum_cl, lum_cl); | |
float mini = min3v(color_cl); | |
float maxi = max3v(color_cl); | |
if (mini < 0.0) { | |
mini = lum_cl - mini; | |
// max(..., 0.0000001) prevents divide by 0 | |
color_cl = lumVec + (color_cl - lumVec)*lum_cl/max(mini, 0.0000001); | |
} | |
if (maxi > 1.0) { | |
maxi = maxi - lum_cl; | |
// max(..., 0.0000001) prevents divide by 0 | |
color_cl = lumVec + (color_cl - lumVec)*(1.0 - lum_cl)/max(maxi, 0.0000001); | |
} | |
// end clipcolor - result: color_cl ---------------------- // | |
// 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*color_cl.rgb; | |
} | |
} |