`noise`

or `musgrave`

) or serve a specific function (like `voronoi`

or `bands`

). None of these are easily adapted to generate the not quite microscopic dust particles that leave their marks in for example fingerprints. While developing such a shader I came across a great video by CGPGrey on Holland/The Netherlands, in which he mentions the national breakfast confectionery *hagelslag*(chocolate sprinkles). Because the shader we present here is easily adapted to generate sprinkle patters, I dubbed it the hagelslag shader, although originally I intended to present a picture of rod-like bacteria such as Bacillus subtilis, my guess is that people find this a tastier example.

The environment lighting and background plate in the picture is provided by HDRSource the Gold Room from HDRLabs.com. And yes I know the bread crust doesn't look tasty at all, that is why I always removed it as a child.

The code I presented earlier doesn't work on all version of the OSL compiler. The culprit was the return statement inside the actual shader definition. I think this is a bug in OSL , a return from a shader function should be possible, but I updated the code nevertheless. I tested it on Blender r53600 and r54202 on 64 bits Windows 7

The code below is self contained, which means I have included a replacement for the missing `distance()`

function but I do not discuss that one here as I published a small blog article on it elsewhere. The basic pattern is based on determining the distance to randomly scattered line segments. In its most pure form it might look like this:

The shader code is presented below and the inputs of the shader are (beside the position and scale) the number of sprinkles to produce per area (

`Np`

), a random `Seed`

to vary the pattern, the `Radius`

which controls the width of the sprinkle, and the `Size`

which governs the length of the sprinkles. The output `Fac`

is between 1 and 0, gradually reducing from centerline to edge.
#include "stdosl.h" // replacement for the missing distance(p, p1, p2) function float minimum_distance(point v, point w, point p) { vector s = w - v; float l2 = dot(s,s); if (l2 == 0.0) return distance(p, v); float t = dot(p - v, s) / l2; if (t < 0.0) return distance(p, v); else if (t > 1.0) return distance(p, w); vector projection = v + t * (s); return distance(p, projection); } shader sprinkles( point Pos = P, float Scale = 1, int Np = 1, int Seed = 42, float Radius = 0.05, float Size = 1, output float Fac = 0 ){ point p = Pos * Scale; point f = floor(p); int xx,yy,np; vector one = 1; for( xx=-1; xx<=1; xx++){ for( yy=-1; yy<=1; yy++){ point ff = f + vector(xx,yy,0); vector dp = vector(5,7,11); vector da = vector(5,3,1); vector dm = vector(7,5,2); for( np=0; np < Np; np++){ vector pd1 = 2*cellnoise(ff+dp)-one; vector pd2 = 2*cellnoise(ff+dp+Seed)-one; dp += da; dp *= dm; dp = mod(dp,10000); point p1 = ff + pd1; point p2 = ff + pd2; p2 = (p2 - p1)*Size+p1; // reduce to 2D p1[2]=0; p2[2]=0; p [2]=0; float r = minimum_distance(p1,p2,p); if ( r < Radius ) { //printf("%2.f %.2f\n",p,r); Fac = 1 - r/Radius; } } } } }

## Example node setup

The node setup for the plain pattern looks like this:It uses a mix node that switches between two material based on whether

`Fac`

is larger than zero. The shader node used for the image of the sandwich with the chocolate sprinkles is a variation on that:

Because the radius of a chocolate sprinkles varies a little bit along its length, we perturb the

`Radius`

with some noise (red box). The yellow box lets us switch between a completely transparent material and a chocolate material. (We use a transparent material here because we stacked two layers of sprinkles on top of each other, with different values for `Seed`

to get a the effect of a thick layer of sprinkles. The green box converts the linear values of `Fac`

to a rounded bump by calculating the sqaure root (power 0.5) and plugging it into a bump node. The brown box is our chocolate material, simply a dark brown but rather glossy material.
You may be interested that I am including your great work in the collection of shaders that I have started at https://github.com/sambler/osl-shaders

ReplyDeleteOne thing I was trying to add with this shader was a way to define a colour for each piece or maybe an index for each piece that could be fed into a colour ramp so we could do coloured sprinkles. The best I could come up with was using a coloured cell noise but that changed colour within each piece.