Home Home Archives About red box
Username:
Password:
 
rssPopular Content

Filed Under Art
digg Hatching Shaders
visits: 671 | score: 0 
posted by sysrpl on Sunday August 10, 2008 11:58 AM

shader was playing around writing some realtime glsl shaders ideas and decided to implement a hatching shader. In my opinion the end result is somewhat nice. Below are some screen caps. You can judge for yourself.

These shaders would be a nice enhancement to programmers and artists who use cel shading. You know how hand drawn comics sometimes use hatching for shading, this can be used to simulate that same look.

Video: Halftone Comic Kid

Video: Hatch Style Shaders

As far as the details of how it's implemented, I'll say this: It's all done in one pass, and the style, waviness, and thickness of lines are controlled by variables passed to the shader.

Here are some examples using different style parameters.


shaderDiagonal lines


shaderWavy horizontal lines


shaderHexagonal grid of circles


shaderUnhatched scene to show surface diffusion


Here is the glsl fragment shader I wrote that output all the above examples.

uniform float ambient;
uniform vec3 diffuse;
uniform float ring;
uniform float shininess;
uniform float specular;
uniform int lights;
uniform int style;
varying vec3 eye;
varying vec3 normal;
varying vec3 vertex;
uniform float thickness;

float balance(float sample, float weight) {
  if (weight < 1.0)
    weight = sample + weight;
  return clamp(pow(weight, 5.0), 0.0, 1.0);
}

float diagonal(float sample) {
  vec2 pixel = floor(vec2(gl_FragCoord));
  float a = 1.0;
  float b = mod(pixel.x - pixel.y, thickness);
  float c = thickness / 2.0;
  if (b < thickness) 
    a = abs(b - c) / c;
  return balance(sample, a);  
}

float waves(float sample) {
  vec2 pixel = floor(vec2(gl_FragCoord));
  float a = 1.0;
  float b = mod(pixel.y + sin(pixel.x / 10.0) * 4.0, thickness);
  float c = thickness / 2.0;
  if (b < thickness) 
    a = abs(b - c) / c;
  return balance(sample, a);  
}

float circles(float sample) {
  vec2 pixel = floor(vec2(gl_FragCoord));
  float b = thickness / 2.0;
  if (mod((pixel.y), thickness * 2.0) > thickness)
    pixel.x += b;
  pixel = mod(pixel, vec2(thickness));
  float a = distance(pixel, vec2(b)) / (thickness * 0.65);
  return balance(sample, a);  
}

vec3 shade(int index, vec3 eye, vec3 normal, vec3 color) {
  vec3 light = gl_LightSource[index].position.xyz + eye;
  vec3 c = gl_LightSource[index].diffuse.rgb;
  float w = gl_LightSource[index].position.w;
  vec3 l = normalize(light);
  float b = dot(normal, l) * w;
  if (b > 0.0) {
    color += diffuse * b * c;  
    vec3 r = reflect(-l, normal);
    float s = pow(max(dot(r, eye), 0.0), shininess) * w;
    s = smoothstep(ring, 1.0, s);
    color += s * specular;
  }
  return color;
}

void main(void) {
  vec3 color = diffuse * ambient;
  vec3 e = normalize(eye);
  vec3 n = normalize(normal);
  for (int i = 0; i < lights; i++)
    color = shade(i, e, n, color);
  float hatch;
  float scale = color.r;
  if (style == 0)
    hatch = diagonal(scale);
  else if (style == 1)
    hatch = waves(scale);
  else if (style == 2)
    hatch = circles(scale);
  else 
    hatch = 1.0;
  if (hatch > 0.25)  
    color = vec3(1.0);
  gl_FragColor = vec4(color * hatch, 1);
}


print send topic Rate this article  

Title:

image link indent align right align middle align left quote underline bold code quote
Comment:

page generated in 0.091 seconds | last modified 1/10/2017 3:48 AM
none  none