Graphics Reference
In-Depth Information
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/ * Non-unit surface normal in world space * /
varying vec3 wsInterpolatedNormal;
/ * Unit world space dir'n to directional light source * /
uniform vec3 wsLight;
/ * the "intensity" that we'll threshold * /
varying float intensity;
void main( void ){
wsInterpolatedNormal =
normalize(g3d_ObjectToWorldNormalMatrix * gl_Normal);
wsInterpolatedEye =
wsEyePosition - (g3d_ObjectToWorldMatrix * gl_Vertex).xyz;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
intensity = dot(wsInterpolatedNormal, wsLight);
}
Listing 33.9: The pixel shader for the first toon-shading program.
1
2
3
4
5
6
7
8
9
10
11
... same declarations ...
void main() {
if (intensity > 0.95)
gl_FragColor.rgb = diffuseColor;
else if (intensity > 0.5)
gl_FragColor.rgb = diffuseColor * 0.6;
else if (intensity > 0.25)
gl_FragColor.rgb = diffuseColor * 0.4;
else
gl_FragColor.rgb = diffuseColor * 0.2;
}
The results, shown in Figure 33.6, are unsatisfactory: When the intensity is
linearly interpolated across a triangle and then thresholded, the result is a straight-
line boundary between the two color regions. When this is done for every polygon,
the result is that each color region has a visibly polygonal boundary.
Figure 33.6: Toon shading using
a vertex shader; notice the sharp
corners of the highlight area.
We can improve this substantially by using the interpolated surface normal
and interpolated light vector in the fragment shader to compute an intensity value
that varies smoothly across the polygon, and which, when thresholded, produces a
smooth boundary between color regions. In our case, with a directional light, only
the interpolation of the surface normal has an effect, but the program would also
work for more general lights.
Inline Exercise 33.1: This program gives yet another instance of the principle
that not every pair of operations commutes, and swapping the order for sim-
plicity or efficiency only works acceptably in some cases. Explain which two
operations are not commuting in this example.
Figure 33.7: Toon shading using
a
The revised program can use exactly the same vertex shader, except that we
no longer need to declare or compute intensity . The revised fragment shader is
shown in Listing 33.10, and the results are shown in Figure 33.7.
Notice that in the fragment shader, we took the normal vector that was
computed at each vertex, and then interpolated to the current fragment, and
normalized it.
fragment
shader.
Notice
the
smooth
boundary
between
the
shades of red.
 
 
Search WWH ::




Custom Search