See update at bottom
It looks like the GPUImageFalseColorFilter was copied from another filter - I can see the intensity property in the shader, although it doesn't actually do anything. I have added setters and Obj-c wrappers for it, but now I can't seem to get gl_fragColor
return value to take intensity as a parameter.
Here's the shader working with 100% intensity:
precision lowp float;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp float intensity;
uniform vec4 shadowTintColor;
uniform vec4 highlightTintColor;
const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
void main()
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
float luminance = dot(textureColor.rgb, luminanceWeighting);
gl_FragColor = vec4( mix(shadowTintColor.rgb, highlightTintColor.rgb, luminance), textureColor.a);
}
);
I've tried:
gl_FragColor = vec4( mix(shadowTintColor.rgb, highlightTintColor.rgb, luminance), intensity);
gl_FragColor = mix(textureColor, mix(shadowTintColor.rgb, highlightTintColor.rgb, luminance), intensity);
and a handful of others, but the filter crashes with a myriad of errors (No matching function for call to mix(vec4, vec3, float)
, Too many arguments to constructor of 'vec4'
).
How can I get the intensity property to take?
And for bonus points, the original filter was written to take vec4 tint colors as input, but only uses vec3 tint colors in the filter. In addition to the global "intensity" property, I'd like to support an alpha channel on each individual tint colour.
Update:
Made some serious headway with this - it's now accepting individual intensity params like so:
precision lowp float;
varying highp vec2 textureCoordinate;
uniform sampler2D inputImageTexture;
uniform lowp float shadowTintIntensity;
uniform lowp float highlightTintIntensity;
uniform vec4 shadowTintColor;
uniform vec4 highlightTintColor;
const mediump vec3 luminanceWeighting = vec3(0.2125, 0.7154, 0.0721);
{
lowp vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
highp float luminance = dot(textureColor.rgb, luminanceWeighting);
highp vec4 shadowResult = mix(textureColor, max(textureColor, vec4( mix(shadowTintColor.rgb, textureColor.rgb, luminance), textureColor.a)), shadowTintIntensity);
highp vec4 mixedResult = mix(textureColor, min(shadowResult, vec4( mix(shadowResult.rgb, highlightTintColor.rgb, luminance), textureColor.a)), highlightTintIntensity / 3.0);
gl_FragColor = mixedResult;
}
);
I can now get it to affect the image properly with intensity, but it seems a little off in the luminance weighting? I manually added a / 3.0
multiplier on the highlight calculator, and it seems to have balanced out the shadow and highlight intensity effect, but this doesn't feel like the right way to go about it. Edit: this doesn't even blend them together properly at all - if the highlightTint isn't specified, the effect doesn't work.
How can I properly blend the final images together?
Finally got this to work by using mix
and blending the two results with the luminance constant:
vec4 textureColor = texture2D(inputImageTexture, textureCoordinate);
float luminance = dot(textureColor.rgb, luminanceWeighting);
vec4 shadowResult = mix(textureColor, max(textureColor, vec4( mix(shadowTintColor.rgb, textureColor.rgb, luminance), textureColor.a)), shadowTintIntensity);
vec4 highlightResult = mix(textureColor, min(shadowResult, vec4( mix(shadowResult.rgb, highlightTintColor.rgb, luminance), textureColor.a)), highlightTintIntensity);
gl_FragColor = vec4( mix(shadowResult.rgb, highlightResult.rgb, luminance), textureColor.a);
// ^ ^