There are lots of nice answers here addressing how to get that "hand drawn" look with the shape of the lines. I'm going to sketch an approach to getting the texture right. I spent a bit of time this afternoon staring at some lines drawn with a 9B pencil on paper and decided that what it looked most like was a brass rubbing. That is, the stroke of the pencil reveals the texture of the paper underneath. This is most like a fading in TikZ/PGF parlance.
The cheap and nasty paper that I buy doesn't have much of a grain to it (I have kids, they do art, I buy about 5 reams every six months). The pattern looks more like noise. So having learnt about Perlin noise recently, I thought that would be an appropriate thing to simulate the paper texture with. I soon decided that a TeX implementation would be daft, so went hunting for a Lua version and found one of the closely related Simplex noise (also due to Perlin; the link goes to a Lua implementation; the author uses strong language both in comments and function names). So I hacked that into a Lua file for LuaTeX and wrote a little demonstration LaTeX file.
I'm calling this an approach because it needs considerable work to be useful. For one thing, even though I'm using Lua to do the heavy processing then it takes time to render the fading. So given that noise isn't usually required to be too random, one should do a lot of caching: both of the original generated numbers and the graphic used for the fading itself. There's also a fair bit about fadings that I don't understand, particularly related to how the fading and the picture match up.
What should happen is that one uses one fading for the whole picture so that strokes laid over each other end up using the same noise and thus work as though they are on top of the same piece of paper. This would also need a little work to do with positioning.
The code isn't too complicated. Here's the LaTeX file:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{fadings}
\directlua{
dofile('tikzgraphite.lua')
}
\makeatletter
\tikzset{show bounding box/.code={
\message{^^JBounding box is (\the\pgf@picminx,\the\pgf@picminy) to (\the\pgf@picmaxx,\the\pgf@picmaxy)^^J}
}
}
\makeatother
\begin{document}
\begin{tikzfadingfrompicture}[name=graphite]
\foreach \i in {0,...,160} \foreach \j in {0,...,40}
\fill[transparent! \directlua{tex.print(math.floor(50*(Noise2D(\i,\j)+1)))}] (\i pt, \j pt) rectangle (\i + 1 pt, \j + 1 pt);
\end{tikzfadingfrompicture}
\begin{tikzpicture}
\draw[path fading=graphite,fit fading=false,fading transform={shift={(70pt,15pt)}},line width=.5cm,line cap=round,black!75] (0,0) to[bend left] (5,0);
\tikzset{show bounding box}
\end{tikzpicture}
\end{document}
The show bounding box
key is so that I can get an idea of how big to make the fading. I don't want to scale it as I want a good texture, and I don't want to generate it too big as it takes a looooonnnnnggggg time to render.
Here's the lua file:
local Gradients3D = {{1,1,0},{-1,1,0},{1,-1,0},{-1,-1,0},
{1,0,1},{-1,0,1},{1,0,-1},{-1,0,-1},
{0,1,1},{0,-1,1},{0,1,-1},{0,-1,-1}}
local simplex = {
{0,1,2,3},{0,1,3,2},{0,0,0,0},{0,2,3,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,2,3,0},
{0,2,1,3},{0,0,0,0},{0,3,1,2},{0,3,2,1},{0,0,0,0},{0,0,0,0},{0,0,0,0},{1,3,2,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
{1,2,0,3},{0,0,0,0},{1,3,0,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,3,0,1},{2,3,1,0},
{1,0,2,3},{1,0,3,2},{0,0,0,0},{0,0,0,0},{0,0,0,0},{2,0,3,1},{0,0,0,0},{2,1,3,0},
{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0},
{2,0,1,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,0,1,2},{3,0,2,1},{0,0,0,0},{3,1,2,0},
{2,1,0,3},{0,0,0,0},{0,0,0,0},{0,0,0,0},{3,1,0,2},{0,0,0,0},{3,2,0,1},{3,2,1,0}}
local p = {151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180}
for i=1,#p do
p[i-1] = p[i]
p[i] = nil
end
for i=1,#Gradients3D do
Gradients3D[i-1] = Gradients3D[i]
Gradients3D[i] = nil
end
local perm = {}
for i=0,255 do
perm[i] = p[i]
perm[i+256] = p[i]
end
function Dot2D(tbl, x, y)
return tbl[1]*x + tbl[2]*y;
end
local Prev2D = {}
-- 2D simplex noise
function Noise2D(xin, yin)
if Prev2D[xin] and Prev2D[xin][yin] then return Prev2D[xin][yin] end
local n0, n1, n2; -- Noise contributions from the three corners
-- Skew the input space to determine which simplex cell we're in
local F2 = 0.5*(math.sqrt(3.0)-1.0);
local s = (xin+yin)*F2; -- Hairy factor for 2D
local i = math.floor(xin+s);
local j = math.floor(yin+s);
local G2 = (3.0-math.sqrt(3.0))/6.0;
local t = (i+j)*G2;
local X0 = i-t; -- Unskew the cell origin back to (x,y) space
local Y0 = j-t;
local x0 = xin-X0; -- The x,y distances from the cell origin
local y0 = yin-Y0;
-- For the 2D case, the simplex shape is an equilateral triangle.
-- Determine which simplex we are in.
local i1, j1; -- Offsets for second (middle) corner of simplex in (i,j) coords
if(x0>y0) then
i1=1
j1=0 -- lower triangle, XY order: (0,0)->(1,0)->(1,1)
else
i1=0
j1=1 -- upper triangle, YX order: (0,0)->(0,1)->(1,1)
end
-- A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
-- a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
-- c = (3-sqrt(3))/6
local x1 = x0 - i1 + G2; -- Offsets for middle corner in (x,y) unskewed coords
local y1 = y0 - j1 + G2;
local x2 = x0 - 1.0 + 2.0 * G2; -- Offsets for last corner in (x,y) unskewed coords
local y2 = y0 - 1.0 + 2.0 * G2;
-- Work out the hashed gradient indices of the three simplex corners
local ii = i%256
local jj = j%256
local gi0 = perm[ii+perm[jj]] % 12;
local gi1 = perm[ii+i1+perm[jj+j1]] % 12;
local gi2 = perm[ii+1+perm[jj+1]] % 12;
-- Calculate the contribution from the three corners
local t0 = 0.5 - x0*x0-y0*y0;
if t0<0 then
n0 = 0.0;
else
t0 = t0 * t0
n0 = t0 * t0 * Dot2D(Gradients3D[gi0], x0, y0); -- (x,y) of Gradients3D used for 2D gradient
end
local t1 = 0.5 - x1*x1-y1*y1;
if (t1<0) then
n1 = 0.0;
else
t1 = t1*t1
n1 = t1 * t1 * Dot2D(Gradients3D[gi1], x1, y1);
end
local t2 = 0.5 - x2*x2-y2*y2;
if (t2<0) then
n2 = 0.0;
else
t2 = t2*t2
n2 = t2 * t2 * Dot2D(Gradients3D[gi2], x2, y2);
end
-- Add contributions from each corner to get the final noise value.
-- The result is scaled to return values in the localerval [-1,1].
local retval = 70.0 * (n0 + n1 + n2)
if not Prev2D[xin] then Prev2D[xin] = {} end
Prev2D[xin][yin] = retval
return retval;
end
It is almost entirely just clipped out from the lua implementation linked above. There's no obvious licence information there, but consider it covered under whatever-licence-it-would-be-there.
Here's the result of that code: