This tutorial introducesToon shader)Method,Cartoon rendering is a non-photorealistic rendering or a type. Cartoon rendering an object looks like a cartoon painting. Here is a simple method for rendering cartoon effects. Unlike general light rendering, the color transition between the pixels of objects rendered by cartoon effects is a step function, the color transition of objects rendered by light is a smooth continuous function. Figure 1 compares the cartoon rendering with the pixel-based rendering teapot. The difference in the color transition of the teapot is obvious.
To achieve the toon shading effect, you can test the diffuse reflection of each pixel in the fragment shader.DiffuseInNdotlValue, let the diffuse reflection form a step function, differentNdotlThe area corresponds to different colors. In Figure 2, different diffuse reflection intensity values of different parts are displayed. Different diffuse reflection values specify different pixel colors.
Figure 2NdotlValue Distribution
Now, you only need to calculate the diffuse reflection in the fragment shader.NdotlSo you can modify part of the code in fragment shader in tutorial 03.
[cpp] view plaincopy
- float3 N = normalize(normal);
- float3 L = normalize(LightPosition - Position);
- float NdotL = max(dot(N,L),0);
-
- float3 color;
-
- if( NdotL<0.5) color = float3(0.3,0.3,0.3);
- else if(NdotL>=0.5 && NdotL<0.85) color = diffuseColor;
- else if(NdotL>=0.85) color = specularColor;
In the above Code, color is the final output color of fragment shader. We can see that the shader code is very simple, but the objects rendered using the Code have no outlines, just like the teapot rendered in figure 1 (c. To add a profile to the teapot, you must consider the observation vector.VAnd normalN. SetVAndNIf the value is small, such as 0.2, we can consider the edge of the observed object (fig3 ).
Fig3 normalNAnd observation vectorV
In Figure 3,P1AndP2Represents the position where the camera is sitting,SIs a point on the surface of an object,NYesS. When we areP1When observing an object,SPoint is obviously not the outline of an object.NAndV1The dot product value of is relatively large, whileP2When you observe,SThe left part of the vertex is almost invisible.NAndV2The dot product value of is very small and close to 0.SIt is the outline of an object. Now, you only need to add some code in the shader.
[cpp] view plaincopy
- float3 N = normalize(normal);
- float3 L = normalize(LightPosition - Position);
- float3 V = normalize(eyePosition - P);
- float NdotL = max(dot(N,L),0);
- float NdotV = max(dot(N,V),0);
-
- float3 color;
-
- if( NdotL<0.5) color = float3(0.3,0.3,0.3);
- else if(NdotL>=0.5 && NdotL<0.85) color = diffuseColor;
- else if(NdotL>=0.85) color = specularColor;
-
- if(NdotV<0.2) color = float3(0,0,0);
The Code finally compares the ndotv size. If it is smaller than 0.2, we think that this pixel is at the edge of the range we see, then we will directly set the pixel color to black, in this way, the effect of figure (B) in Figure 1 can be achieved.
Although this toon shading method is very simple, there are also some shortcomings. If the edges and edges between the polygon that constitute an object are very clear, such as cubes, this method will cause the object to flash, because the normal changes greatly at the edge of the object.