After lunch, I want to replicate the sketch shader I wrote for the Pencil-vs-Camera project. Additionally, I wrote a one-pass shader for dotted drawing / sketch post processing effect, which I think is more aesthetically pleasing.
Dotted Drawing Demo
Click on the play button in the left bottom corner of the embedded ShaderToy window below, to play the real-time dotted drawing shader; or click on this link to redirect to the demo page.
It runs at over 60fps on my GTX 980 & 1080. If it does not run smoothly on your workstation, please comment below.
Press the mouse for a slower but more classic sketching effect, though I prefer the dotted version.
GLSL Code
Shader forked and related ones are listed in the code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
/** * Sketch Effect by Ruofei Du (DuRuofei.com) * Link to demo: https://www.shadertoy.com/view/ldSyzV * starea @ ShaderToy, License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. * * Reference: * [1] Pencil vs Camera. http://www.duruofei.com/Research/pencilvscamera * * Forked: * [1] Pol's Photoshop Blends Branchless: https://www.shadertoy.com/view/Md3GzX * [2] Gaussian Blur: https://www.shadertoy.com/view/ltBXRh * [3] williammalo2's Blur with only one pixel read: https://www.shadertoy.com/view/XtGGzz * [3] demofox's greyscale: https://www.shadertoy.com/view/XdXSzX * [4] iq's Postprocessing: https://www.shadertoy.com/view/4dfGzn * * Related & Better Implementation: * [1] flockaroo's Notebook Drawings: https://www.shadertoy.com/view/XtVGD1 * [2] HLorenzi's Hand-drawn sketch: https://www.shadertoy.com/view/MsSGD1 **/ const float PI = 3.1415926536; const float PI2 = PI * 2.0; const int mSize = 9; const int kSize = (mSize-1)/2; const float sigma = 3.0; float kernel[mSize]; float normpdf(in float x, in float sigma) { return 0.39894 * exp(-0.5 * x * x / (sigma * sigma)) / sigma; } vec3 colorDodge(in vec3 src, in vec3 dst) { return step(0.0, dst) * mix(min(vec3(1.0), dst/ (1.0 - src)), vec3(1.0), step(1.0, src)); } float greyScale(in vec3 col) { return dot(col, vec3(0.3, 0.59, 0.11)); //return dot(col, vec3(0.2126, 0.7152, 0.0722)); //sRGB } vec2 random(vec2 p){ p = fract(p * vec2(443.897, 441.423)); p += dot(p, p.yx+19.19); return fract((p.xx+p.yx)*p.xy); } void mainImage( out vec4 fragColor, in vec2 fragCoord ) { vec2 q = fragCoord.xy / iResolution.xy; vec3 col = texture(iChannel0, q).rgb; vec2 r = random(q); r.x *= PI2; vec2 cr = vec2(sin(r.x),cos(r.x))*sqrt(r.y); vec3 blurred = texture(iChannel0, q + cr * (vec2(mSize) / iResolution.xy) ).rgb; if (iMouse.z > 0.5) { blurred = vec3(0.0); float Z = 0.0; for (int j = 0; j <= kSize; ++j) { kernel[kSize+j] = kernel[kSize-j] = normpdf(float(j), sigma); } for (int j = 0; j < mSize; ++j) { Z += kernel[j]; } for (int i = -kSize; i <= kSize; ++i) { for (int j = -kSize; j <= kSize; ++j) { blurred += kernel[kSize+j]*kernel[kSize+i]*texture(iChannel0, (fragCoord.xy+vec2(float(i),float(j))) / iResolution.xy).rgb; } } blurred = blurred / Z / Z; } vec3 inv = vec3(1.0) - blurred; // color dodge vec3 lighten = colorDodge(col, inv); // grey scale vec3 res = vec3(greyScale(lighten)); // more contrast res = vec3(pow(res.x, 3.0)); //res = clamp(res * 0.7 + 0.3 * res * res * 1.2, 0.0, 1.0); // edge effect if (iMouse.z > 0.5) res *= 0.25 + 0.75 * pow( 16.0 * q.x * q.y * (1.0 - q.x) * (1.0 - q.y), 0.15 ); fragColor = vec4(res, 1.0); } |
More Pictures
Original image comes from: http://www.cs.cmu.edu/~chuck/lennapg/lenna.shtml