kmdreko's

A SIMPLE BLOG

A Simple Sketch Effect, Part 2

FEBRUARY 15, 2025 | C++, OPENGL, GRAPHICS

I recently saw a video by runevision on Surface-Stable Fractal Dithering - it shows a shader technique that effectively adds details to textures as you get closer. It reminded me that I had done something very similar a while back when working on sketch-stylized rendering that I showed off in a previous post. Though mine strived to simulate lines drawn like hatch shading rather than a dither pattern.

Its been a while since it has been on my mind but I'll do my best to describe how it worked. The code is available on my GitHub here.

Infinitely Detailed Stripes

The core of the technique is to draw a bunch of parallel lines since that is roughly what hatch shading looks like. Simple stripes are easy to do, but I didn't want the "strokes" to be huge as you got closer nor did I want them to totally disappear at a distance.

I decided the easiest place to start was to project every pixel onto a world-space plane so that model/texture size and position were not a factor and I also set it at an angle to avoid that mapping onto surfaces poorly. I also provided a scale factor to indicate "how thick to draw the line" in world space that was correlated against the depth so the scaling was the same for close and far away objects. The scale was also affected by the texture normal since otherwise grazing angle stripes would look much thinner than head-on angled stripes.

Once you have a scale and a stable world-space mapping, the pixel can be drawn either black or white based on those factors. I incorporated multiple "layers" of stripes each with double the "detail" of the prior. Imagine one layer where stripes are drawn at 0.5, 1.5, 2.5, etc with the width of the line based on the scale. Another layer would have stripes at 0.25, 0.75, 1.25, etc with the same line width. However a layer would not be drawn if the scale is larger than the half-width between, otherwise you'd get a lot overlap at a distance. I used ten layers so that the full clipping range of 0.1 to 100.0 were covered. The layers also worked in an SDF-style way so that the stripes of a more detailed layer would ease in instead of pop in.

I should create a shader just based on this idea; it would look pretty trippy.

Hand-drawn Aesthetics

Obviously, solid black and white stripes don't look natural. To make it look more realistic, I incorporated noise. I used a perlin noise generator and mixed it with the SDF-style stripes to fade them in and out along their length. Each layer individually used its own perlin noise values so that it didn't just look like perlin + stripes. I think I also used an overall noise texture to indicate overall what areas were more "shaded".

Another touch was to make the world coordinate mapping slightly different for each layer so they can be at an off angle and provide more "imperfection".

And another bonus that I got for free was that the way I combined the perlin and the stripes meant that they could appear to "curve" slightly, which I think is a nice touch.

Future Work

There is obviously a lot more that could be done to make it look even better:

Maybe I'll get around to improving it some day.