precision highp float; varying vec2 v_TexCoords; uniform vec2 u_RenderSize; uniform mat4 u_STMatrix; uniform float u_Time; uniform sampler2D u_Texture; uniform float blurRadius; uniform float faceX; uniform float faceY; uniform float faceRadius; uniform float faceFalloff; uniform float saturation; uniform float brightness; uniform float contrast; uniform float rGamma; uniform float gGamma; uniform float bGamma; uniform float splitAmount; uniform float splitPoint; uniform vec4 colorA; uniform vec4 colorB; uniform vec4 colorC; uniform vec4 colorD; #define SIZE 3. #define SAMPLE_COUNT 22 vec3 ContrastSaturationBrightness(vec3 color, float brt, float sat, float con) { const float AvgLumR = 0.5; const float AvgLumG = 0.5; const float AvgLumB = 0.5; const vec3 LumCoeff = vec3(0.2125, 0.7154, 0.0721); vec3 AvgLumin = vec3(AvgLumR, AvgLumG, AvgLumB); vec3 brtColor = color * brt; vec3 intensity = vec3(dot(brtColor, LumCoeff)); vec3 satColor = mix(intensity, brtColor, sat); vec3 conColor = mix(AvgLumin, satColor, con); return conColor; } vec3 colorAdjustment(vec3 color) { color = pow(color.rgb, vec3(rGamma, gGamma, bGamma)); color = ContrastSaturationBrightness(clamp(color.rgb, 0.0, 1.0), brightness, saturation, contrast); return color; } vec3 Bokeh(sampler2D tex, vec2 uv, float blurRadius, float amount) { // Blur by sampling in a disc pattern vec3 acc = vec3(0.0); vec3 div = vec3(0.0); vec2 pixel = vec2(u_RenderSize.y/u_RenderSize.x, 1.0) * (blurRadius * .006); vec2 discSampleLocations[SAMPLE_COUNT]; // Initialize Locations for Circular Samples // It feels like there must be a better way to do this, but I // have no idea how to initialize an array of vec2s in GLSL. discSampleLocations[0] = vec2(-0.560236, -0.390621); discSampleLocations[1] = vec2(-1.116177, -0.157593); discSampleLocations[2] = vec2(0.218887, -0.504156); discSampleLocations[3] = vec2(0.275405, 0.479383); discSampleLocations[4] = vec2(-0.036284, 0.910465); discSampleLocations[5] = vec2(-0.580405, 0.900334); discSampleLocations[6] = vec2(-0.902323, 0.504812); discSampleLocations[7] = vec2(-1.082202, 0.195710); discSampleLocations[8] = vec2(0.431844, 0.078299); discSampleLocations[9] = vec2(-0.780956, -0.130875); discSampleLocations[10] = vec2(0.462936, -0.241232); discSampleLocations[11] = vec2(0.173408, -0.110910); discSampleLocations[12] = vec2(-0.301986, -0.131181); discSampleLocations[13] = vec2(-0.054464, -0.364696); discSampleLocations[14] = vec2(-0.889312, -0.473860); discSampleLocations[15] = vec2(-0.707064, 0.184700); discSampleLocations[16] = vec2(0.065336, 0.175164); discSampleLocations[17] = vec2(-0.551313, 0.483489); discSampleLocations[18] = vec2(-0.316096, 0.219665); discSampleLocations[19] = vec2(-0.303382, 0.737777); discSampleLocations[20] = vec2(-0.080880, 0.480310); discSampleLocations[21] = vec2(-0.304073, 1.156303); for (int i=0; i < SAMPLE_COUNT; i++) { vec3 col = texture2D(tex, uv + pixel * discSampleLocations[i]).xyz;//, blurRadius*1.5).xyz; vec3 bokeh = vec3(5.0) + pow(col, vec3(9.0)) * amount; acc += col * bokeh; div += bokeh; } return acc / div; } vec4 Desaturate(vec3 color, float Desaturation) { vec3 grayXfer = vec3(0.3, 0.59, 0.11); vec3 gray = vec3(dot(grayXfer, color)); return vec4(mix(color, gray, Desaturation), 1.0); } float circularIn(float t) { return 1.0 - sqrt(1.0 - t * t); } vec3 blendAverage(vec3 base, vec3 blend) { return (base+blend)/2.0; } vec3 blendAverage(vec3 base, vec3 blend, float opacity) { return (blendAverage(base, blend) * opacity + base * (1.0 - opacity)); } void main() { vec2 uv = (u_STMatrix * vec4(v_TexCoords.x, v_TexCoords.y, 0.0, 1.0)).xy; vec4 camera = texture2D(u_Texture, uv); vec3 avg = mix( colorD.rgb, colorC.rgb, uv.y); vec3 effected = camera.rgb - avg + 0.5 ; vec3 base = mix(camera.rgb, effected, 1.0); vec2 face = vec2( faceX / u_RenderSize.x * 2.0, faceY / u_RenderSize.y * 2.0 ); vec2 r = uv * 2.0 - 1.0 - face; float fallOff = faceFalloff * faceRadius; float shoulder = smoothstep(0.45 - faceFalloff, 0.45 + faceFalloff, uv.y); float dis = smoothstep(faceRadius - faceFalloff, faceRadius + faceFalloff, distance(face, r)) * 0.5; dis = min(dis, shoulder); dis = mix(dis, 1.25, circularIn( smoothstep(2.1, 0.0, u_Time) ) ); const float a = 150.0; //vignette float aspect = u_RenderSize.x/u_RenderSize.y; vec2 midLeft = vec2(-0.4 * aspect, 0.4); vec2 botLeft = vec2(-0.6 * aspect, 0.6); vec2 center = vec2(0.0, 0.0); float vMin = distance( midLeft, center ); float vMax = distance( botLeft, center ); vec2 uvC = uv - 0.5; float vignette = smoothstep(vMax, vMin, distance(vec2(uvC.x*aspect, uvC.y), vec2(0.0, 0.0)) ); vec4 blurredImage = vec4(Bokeh(u_Texture, uv, blurRadius*dis, a), 20.0); vec4 gradMap = mix(colorB, colorA, Desaturate(blurredImage.rgb*vignette, 1.0).r); vec3 color = mix(blurredImage.rgb, gradMap.rgb, (1.-vignette)+splitAmount)*vignette; vec3 finalColor = colorAdjustment(blendAverage(color, base, 1.0)); finalColor = mix(gradMap.rgb, finalColor, vignette); gl_FragColor = vec4( finalColor, 1.0); }