Wednesday 10 April 2013

Cross-Hatching Shader

Cross hatching is a fun way of adding cartoon like detail and shading to a scene. It details a scene by adding lines right-angles to create a mesh like appearance. While most often used in hand drawings or paintings, it can be used as a computer graphics effect. In OpenGL, a rather simple shader exists to create a similar kind of scene. All we need is a fragment shader to handle the cross hatching of our scene.

A hand-drawn cross hatching example
For cross hatching, we'll need a 2D texture that will tell us what fragment is being rendered and a luminace value to help determine whether or not our current fragment lies on a particular line. This will also make it easy to draw more lines in areas that need more shading.


uniform sampler2D Texture;
 float lum = length(texture2D(Texture, gl_TexCoord[0].xy).rgb);


First, we will want to draw the enter scene as black. The reason for this is that we'll later be adding in white to create the cross hatching effect.


gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);

Next is where the fun happens. By determining the strength of a shadow, we can take the mod of the fragment coordinates x and y, add or subtract them together and divide by ten. If it is equivalent to 0, we draw white. We can change the frequency of lines by adding or subtracting to the added value of the added fragment coordinates. Here is an example from learningwebgl.com


/*
    Straight port of code from
    http://learningwebgl.com/blog/?p=2858
*/


void main()
{
    float lum = length(texture2D(Texture, gl_TexCoord[0].xy).rgb);
     
    gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
     
    if (lum < 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 (lum < 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 (lum < 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 (lum < 0.3) {
        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);
        }
    }
}

   
And a resulting product I made using this exact code:


No comments:

Post a Comment