Crosshatch shaders

Here’s something I was playing with over the summer and never got round to posting. Most of the WebGL stuff in my tutorials aims at something like realism; this post by my friend and colleague Jonathan Hartley persuaded me that there’s much more to creating interesting 3D stuff.

So let’s take a look at some WebGL code that uses the cross-hatching technique used in drawing, where shading is done using layers of perpendicular lines. Here’s a first example, a cross-hatched sphere:

A cross-hatched sphere

(Click here for the live version)

The JavaScript code is really very simple — it’s just the moon demo from lesson 11 with the texture and mouse-handling stuff stripped out. The interesting bit is in the fragment shader where, once we’ve worked out how bright the fragment is going to be and put it in a variable lightWeighting, we do this:

        gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
        if (length(lightWeighting) < 1.00) {
            if (mod(gl_FragCoord.x + gl_FragCoord.y, 10.0) == 0.0) {
                gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
            }
        }
        if (length(lightWeighting) < 0.75) {
            if (mod(gl_FragCoord.x - gl_FragCoord.y, 10.0) == 0.0) {
                gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
            }
        }
        if (length(lightWeighting) < 0.50) {
            if (mod(gl_FragCoord.x + gl_FragCoord.y - 5.0, 10.0) == 0.0) {
                gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
            }
        }

        if (length(lightWeighting) < 0.3465) {
            if (mod(gl_FragCoord.x - gl_FragCoord.y - 5.0, 10.0) == 0.0) {
                gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
            }
        }

The interesting thing here is the GLSL built-in variable gl_FragCoord. According to the OpenGL ES 2.0 GLSL specification, this holds "holds the window relative coordinates x, y, z, and 1/w values for the fragment". For our purposes, what matters here is that the x and y parts hold 2D coordinates that tell us what pixel the current fragment will be rendered to. Given that, a bit of simple geometry lets us work out how to detect whether or not our current fragment lies on a particular line, and that makes it easy to draw increasing numbers of cross-hatch lines as the shadows get darker.

So having done the hard work by writing that shader, it was easy to put together something more fun: a spinning cross-hatched teapot!

A cross-hatched teapot

(Click here for the live version)

You can leave a response, or trackback from your own site.

7 Responses to “Crosshatch shaders”

  1. steve says:

    Doesn’t work for me, just some random dots that I can barely see are in the outline of a teapot. :)

    My machine is so _superb_ for testing that I should donate it to science or something… I’d prefer to have a machine that works. :)

  2. Casey says:

    Both these demos don’t work for me. Like steve said, they just display random dots.

  3. giles says:

    @steve, @Casey — thanks for letting me know. Casey — which OS/graphics hardware do you have? Perhaps your machine is the same model as Steve’s…?

  4. [...] as a custom plugin. Inspiration from Toneburst, Learning Web GL” and Martin [...]

  5. [...] So i was wondering if it possible to create this kind of pencil sketch feel style with shader, it turns out easier then i thought, you can see an excellent post here. [...]

Leave a Reply

Subscribe to RSS Feed Follow Learning WebGL on Twitter