/*{ "CATEGORIES": [ "Masking", "Color Effect", "Utility" ], "CREDIT": "by zoidberg", "DESCRIPTION": "Takes a mask image and applies it to the input image's alpha channel.", "INPUTS": [ { "NAME": "inputImage", "TYPE": "image" }, { "LABEL": "mask image", "NAME": "maskImage", "TYPE": "image" }, { "DEFAULT": 0, "LABEL": "mask size mode", "LABELS": [ "Fit", "Fill", "Stretch", "Copy" ], "NAME": "maskSizingMode", "TYPE": "long", "VALUES": [ 0, 1, 2, 3 ] }, { "DEFAULT": 0, "MAX": 1, "MIN": -1, "NAME": "bright", "TYPE": "float" }, { "DEFAULT": 1, "MAX": 4, "MIN": -4, "NAME": "contrast", "TYPE": "float" }, { "DEFAULT": 2, "LABEL": "Alpha Mode", "LABELS": [ "Additive", "Multiply", "Replace" ], "NAME": "alphaMode", "TYPE": "long", "VALUES": [ 0, 1, 2 ] }, { "DEFAULT": 0, "NAME": "applyAlpha", "TYPE": "bool" } ], "ISFVSN": "2" } */ const vec4 lumcoeff = vec4(0.299, 0.587, 0.114, 0.0); // 'a' and 'b' are rects (x and y are the originx, z and w are the width and height) // 'm' is the sizing mode as described above (fit/fill/stretch/copy) vec4 RectThatFitsRectInRect(vec4 a, vec4 b, int m); void main() { vec4 srcPixel = IMG_THIS_PIXEL(inputImage); // get the rect of the mask image after it's been resized according to the passed sizing mode. this is in pixel coords relative to the rendering space! //vec4 rectOfResizedMaskImage = RectThatFitsRectInRect(vec4(0.0, 0.0, _maskImage_imgRect.z, _maskImage_imgRect.w), vec4(0,0,RENDERSIZE.x,RENDERSIZE.y), maskSizingMode); vec4 rectOfResizedMaskImage = RectThatFitsRectInRect(vec4(0.0, 0.0, IMG_SIZE(maskImage).x, IMG_SIZE(maskImage).y), vec4(0,0,RENDERSIZE.x,RENDERSIZE.y), maskSizingMode); // i know the pixel coords of this frag in the render space- convert this to NORMALIZED texture coords for the resized mask image vec2 normMaskSrcCoord; normMaskSrcCoord.x = (gl_FragCoord.x-rectOfResizedMaskImage.x)/rectOfResizedMaskImage.z; normMaskSrcCoord.y = (gl_FragCoord.y-rectOfResizedMaskImage.y)/rectOfResizedMaskImage.w; // get the color of the pixel from the mask image for these normalized coords vec4 tmpColorA = IMG_NORM_PIXEL(maskImage, normMaskSrcCoord); // apply bright/contrast to this pixel value vec4 tmpColorB = tmpColorA + vec4(bright, bright, bright, 0.0); tmpColorA.rgb = ((vec3(2.0) * (tmpColorB.rgb - vec3(0.5))) * vec3(contrast) / vec3(2.0)) + vec3(0.5); tmpColorA.a = ((2.0 * (tmpColorB.a - 0.5)) * abs(contrast) / 2.0) + 0.5; // get the luminance of this pixel value: this will be the new alpha for the source pixel float luminance = dot(tmpColorA,lumcoeff); // if the alpha mode isn't replacing, add or multiply now // (this makes it possible to stack multiple mask FX or preserve alpha from input) if (alphaMode == 0) { luminance = luminance + srcPixel.a; } else if (alphaMode == 1) { luminance = luminance * srcPixel.a; } if (applyAlpha) gl_FragColor = vec4(luminance*srcPixel.r, luminance*srcPixel.g, luminance*srcPixel.b, 1.0); else gl_FragColor = vec4(srcPixel.r, srcPixel.g, srcPixel.b, luminance); } // rect that fits 'a' in 'b' using sizing mode 'm' vec4 RectThatFitsRectInRect(vec4 a, vec4 b, int m) { float bAspect = b.z/b.w; float aAspect = a.z/a.w; if (aAspect==bAspect) { return b; } vec4 returnMe = vec4(0.0); // fit if (m==0) { // if the rect i'm trying to fit stuff *into* is wider than the rect i'm resizing if (bAspect > aAspect) { returnMe.w = b.w; returnMe.z = returnMe.w * aAspect; } // else if the rect i'm resizing is wider than the rect it's going into else if (bAspect < aAspect) { returnMe.z = b.z; returnMe.w = returnMe.z / aAspect; } else { returnMe.z = b.z; returnMe.w = b.w; } returnMe.x = (b.z-returnMe.z)/2.0+b.x; returnMe.y = (b.w-returnMe.w)/2.0+b.y; } // fill else if (m==1) { // if the rect i'm trying to fit stuff *into* is wider than the rect i'm resizing if (bAspect > aAspect) { returnMe.z = b.z; returnMe.w = returnMe.z / aAspect; } // else if the rect i'm resizing is wider than the rect it's going into else if (bAspect < aAspect) { returnMe.w = b.w; returnMe.z = returnMe.w * aAspect; } else { returnMe.z = b.z; returnMe.w = b.w; } returnMe.x = (b.z-returnMe.z)/2.0+b.x; returnMe.y = (b.w-returnMe.w)/2.0+b.y; } // stretch else if (m==2) { returnMe = vec4(b.x, b.y, b.z, b.w); } // copy else if (m==3) { returnMe.z = float(int(a.z)); returnMe.w = float(int(a.w)); returnMe.x = float(int((b.z-returnMe.z)/2.0+b.x)); returnMe.y = float(int((b.w-returnMe.w)/2.0+b.y)); } return returnMe; }