Unity3d Shader Beginner's Tutorial (4/6)--Cartoon Shader (Entry edition) __unity3d

Source: Internet
Author: User

Diablo Series

Motivation

If you meet the following criteria, I suggest you read this tutorial: you would like to know more about the details of the surface shader. You want to implement an entry-level cartoon effect Shader (Toon Shader). You want to know how the gradient texture (ramp texture) is used. You want to know about the edge light (rim lighting) knowledge.

Preparatory work

We want to implement a toon shader-a shader that makes the model appear to have a cartoon effect, in the field of graphics, which is called the Unreal Graphics (Non photorealistic Rendering).

To achieve this cartoon effect, we have to do the following things: reduce the type of colors used on the original model. Customize the lighting model to make the light and shade boundaries clearer. Draws the edge of the model to black.

Work flow of surface shader

In the first part of the tutorial I used a simplified version of the surface shader flowchart, in fact, there are many things about the work flow of the surface shader. First, let's look at a relatively complete work flow chart:

(Translator Note: Many of the above are optional, and if we do not customize these parts, it will use the processing function provided by unity itself.) Here you pay particular attention to the use format of the optional section.

#pragma surface surfacefunction Lightmodel [optionalparams] for pixel processing functions surfacefunction, such as the frequently used surf we are more familiar with. For the illumination model, we can have two ways:

1. Use the unity of the light model Lambert, you do not need to customize the corresponding function

#pragma surface surf Lambert

2. Using the custom lighting model, you need a custom function with the function name Lighting+lightmodel, as follows:

#pragma surface surf Simplelambert
half4 Lightingsimplelambert (surfaceoutput s, Half3 lightdir, half atten) {...}
For Optionalparams we often have vertex and finalcolor, the format is as follows
#pragma surface surf Lambert finalcolor:mycolor vertex:myvert
void Myvert (InOut appdata_full V, out Input data) {...}
void MyColor (Input in, Surfaceoutput o, inout fixed4 color) {...}

You can see from this flowchart that there are a lot of custom parts in the surface shader. For example, we can first use a custom illumination model to process our illumination data and pass the data to the output structure of the surface shader, so that the surface shader produces the color value of the corresponding pixel. Finally we can use Finalcolor to disrupt the color value and output the final result to the screen.

Step 1-Reduce the color type on the texture

We use the previous shader with the bump texture and add some code to the shader.

In the beginning, we'll explain how to use the Finalcolor function to reduce the color type on the texture.

#pragma surface surf Lambert finalcolor:final

First we add finalcolor to the #pragma statement to tell the program that I will use the Finalcolor function. Note Here we name the functional function named final.

_tooniness ("Tooniness", Range (0.1,20)) = 4

We add the _tooniness property value (range type, range 0.1~20, default value is 4)-we will use

This value to limit the number of colors that the texture uses. Of course, we also need to define variables with the same name as references in shader.

float _tooniness;

Let's simply write a function that reduces the color type:

void final (Input in, Surfaceoutput o, inout fixed4 color) {

    color = floor (color * _tooniness)/_tooniness;

}

In the above function, we first multiply the color (RGBA type) by the _tooniess, and then use the floor (x) function (take the largest integer not greater than X) to place the floating point portion of the result, and then divide by _tooniness (for example, the original color.rgba= ( 0.3,0.4,0.5,1.0), _tooniness=4, after processing, the last color.rgba= (0.25,0.25,0.5.1.0), we found that the color value of the component can only be one of the 0,1/4,2/4,3/4,1, which is the _ The role of tooniness, the color from the range of 0~1 into only five values, thereby reducing the color type.

The following is the source of the shader, complete resources please click here:

Shader "Custom/toonshader" {
    Properties {
        _maintex ("Base (RGB)", 2D) = "White" {}
        Use this variable temporarily
        _mainbump ("Bump", 2D) = "Bump" {}
        //The variable is mainly used to reduce the color type of
        _tooniness ("Tooniness", Range (0.1,20)) = 4
    }
    Subshader {
        Tags {"Rendertype" = "Opaque"}
        LOD
        
        cgprogram
        #pragma surface surf Lambert finalcolor: Final

        sampler2d _maintex;
        Add a _tooniness reference
         float _tooniness;

        struct Input {
            float2 uv_maintex;
        };

        void Surf (Input in, InOut surfaceoutput o) {
            Half4 c = tex2d (_maintex, In.uv_maintex);
            O.albedo = C.rgb;
            O.alpha = C.A;
        }
        
        Add final function, modify pixel color
        void final (Input in, Surfaceoutput o, inout fixed4 color) {
            color = floor (color * _toonine SS)/_tooniness;
        }
        ENDCG
    } 
    fallback "diffuse"
}

Compare the effects of using this shader:

Before use:

After use:

Adjusting _tooniness can change the number of colors (or the precision of a color). The general cartoon effect on the character color is also very few, so this shader also more in line with the habit of cartoon drawing. But this shader can't be called a real cartoon shader.

Step 2-toon Illumination Model

Next we implement a Toon illumination model that gives the illumination a sharp edge on the model, rather than the transition effect in the original model.

To make up for the shader in the last section (not really the cartoon effect), we add a variable _colormerge on this basis, note that the _colormerge here is actually similar to the _tooniness function in the previous section of the shader. Also to reduce the color type. Also in the new shader we use _tooniness for the Toon illumination function-this is more reasonable.

_colormerge ("Color Merge, Range (0.1, 20)) = 0

The corresponding variable is

float _colormerge;

Now we will add a custom illumination model toon to the shader. We will use the Toon illumination calculation function to replace the Lambert illumination model we have been using.

We modify the #pragma statement in code to

#pragma surface Surf Toon

Notice that we removed the Finalcolor function-I've moved the corresponding function into the surf function to calculate the color before the light (we'll get more change, more cartoon effect).

It has been said that we want to use the Toon Illumination model to implement the Lightingtoon function-lightingtoon The name is the combination of #pragma in lighting and toon statements.

Half4 Lightingtoon (surfaceoutput s, Half3 lightdir, half atten)
{
    half4 C;
    Half ndotl = dot (s.normal, lightdir);
    Ndotl = Floor (NDOTL * _tooniness)/_tooniness;
    C.rgb = S.albedo * _lightcolor0.rgb * ndotl * atten * 2;
    C.A = S.alpha;
    return c;
}

The illumination function always accepts three parameters-the output structure of the surface shader (surfaceoutput s), the illumination direction (Half3 Lightdir) and the Light attenuation factor (half atten) (the light attenuation factor attenuation is mainly a computational point light source, The attenuation of the searchlight to simulate the shading effect. )

The Lightingtoon function always returns the color (half4 type) of pixels after illumination.

Let's briefly describe how the Toon illumination model works-first we calculate the light direction and the dot-multiplicative result of the pixel's normal point. Remember if the dot-multiply result (that is, the cosine of the two vectors) is 1, which means that the two vectors are in the same direction, if-1, then the two vectors are reversed, and if 0, the two vectors are just perpendicular. This knowledge point is useful for lighting calculations-for example, a pixel is directly directed toward the light, and the pixel displays its own color. If the two vectors have an angle greater than 90, that is, the pixel back to the light direction, the corresponding color will become black, if the angle between the 0~90, we are based on the angle of the interpolation of the color of the pixel.

Unity will process all the lighting in the scene to calculate the effect of the model in all light. And after we return the pixel value from the surface function, unity also automatically adds diffuse light (ambient light) and light intensity (intensity) to the pixel--what we want to say here is that if the pixel is not affected by the current illumination, Then it will appear as black.

For our toon shading.

The surf function simply uses the _colormerge to simplify the color category.

void Surf (Input in, InOut surfaceoutput o) {
    Half4 c = tex2d (_maintex, In.uv_maintex);
    O.normal = Unpacknormal (tex2d (_mainbump, In.uv_mainbump));
    O.albedo = Floor (c.rgb*_colormerge)/_colormerge;
    O.alpha = C.A;
}

The following is the source of the shader, complete resources please click here:

 Shader "Custom/toonshader" {Properties {_maintex ("Base (RGB)", 2D) = "White" {} _mainbump ("Bu
        MP ", 2D" = "Bump" {}///The variable is used primarily to lower the color category _tooniness ("Tooniness", Range (0.1,20)) = 4} subshader { Tags {"Rendertype" = "Opaque"} LOD cgprogram #pragma surface surf Lambert fin
        Alcolor:final sampler2d _maintex;
        Sampler2d _mainbump;

        Add a _tooniness reference float _tooniness;
            struct Input {float2 Uv_maintex;
        FLOAT2 Uv_mainbump;

        };
            void Surf (Input in, InOut surfaceoutput o) {half4 c = tex2d (_maintex, In.uv_maintex);
            O.albedo = C.rgb;
        O.alpha = C.A; }//Add final function, modify pixel color void final (Input in, Surfaceoutput o, inout fixed4 color) {C
        Olor = Floor (color * _tooniness)/_tooniness; } ENDCG} fallback "diffuse"} 

Step 3-Use a gradient texture

Sometimes (especially in animations), the color of pixel values can suddenly darken or darken. We actually want to make this color change a little smoother. To make a smooth effect, we can write a smooth effect of the function, but the simplest way is to use a ramp texture to produce smooth transition effect, but without losing the toon effect of the requirements of less color.

Before we ask for Ndotl, there is a problem, for example, when we _tooniness=4, we found that if the color between ndotl=0.249 and ndotl=0.251 would suddenly change, we would use the ramp texture for this, We can see that the above texture changes in color edges using a smooth transition, which solves the problem raised in the previous paragraph.

The reason we can use this method is because the UV coordinates of the texture are exactly 0~1, so we can take the value of Ndotl as the U value and set the V value to 0.5, so that we only need to sample the ramp texture with this agreed UV value and get the corresponding color value.

Obviously we first want to add the ramp texture attribute value.

_ramp ("Ramp texture", 2D) = "White" {}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.