Home>

This is a non-realistic rendering of the Lele Brothers book,The algorithm is quite interesting,Interested friends can give it a try.

The basic principle of the sketch effect:first draw the outline of the object,Calculate the diffuse reflection part of the object,The darker the diffuse reflection, the darker the color,Then set the weight of the sample map according to the value of diffuse reflection.

Sampling map:

Shader part:

shader "unlit/sketch"
{
 properties
 {
 _color ("color", color)=(1,1,1,1)
 //Map tile coefficient
   _tilefactor ("tilefactor", range (0, 10))=1
 _hatch0 ("hatch0", 2d)="white" {}
   _hatch1 ("hatch1", 2d)="white" {}
   _hatch2 ("hatch2", 2d)="white" {}
   _hatch3 ("hatch3", 2d)="white" {}
   _hatch4 ("hatch4", 2d)="white" {}
   _hatch5 ("hatch5", 2d)="white" {}
 //Stroke coefficient
 _outlinefactor ("outlinefactor", range (0.0,0.1))=0.01
 }
 subshader
 {
 tags {"queue"="transparent"}
 //The stroke uses two passes, the first pass is extruded a little along the normal,Only output stroke color
 pass
 {
  //Remove the positive,Render only the back
  cull front
  //Turn off deep writing
  zwrite off
  //Control the depth offset,Stroke pass away from the camera,Prevent interspersion with normal pass
  offset 1,1
  cgprogram
      #include "unitycg.cginc"
      #pragma vertex vert
      #pragma fragment frag
   float _outlinefactor;
   struct v2f
   {
    float4 pos:sv_position;
   };
   v2f vert (appdata_full v)
   {
    v2f o;
    o.pos=unityobjecttoclippos (v.vertex);
    //Convert normal direction to view space
    float3 vnormal=mul ((float3x3) unity_matrix_it_mv, v.normal);
    //Convert the normal xy coordinates of the view space to the projection space
    float2 offset=transformviewtoprojection (vnormal.xy);
    //The output is offset in the final projection stage
    o.pos.xy +=offset * _outlinefactor;
    return o;
   }
   fixed4 frag (v2f i):sv_target
   {
    return float4 (0,0,0,1);
   }
  endcg
 }
 pass
 {
  cgprogram
      #include "unitycg.cginc"
      #include "lighting.cginc"
  //Use shadow to add
      #include "autolight.cginc"
  #pragma vertex vert
  #pragma fragment frag
  //Shadow the main parallel light
      #pragma multi_compile_fwdbase
  float4 _color;
     float _tilefactor;
  sampler2d _hatch0;
  sampler2d _hatch1;
  sampler2d _hatch2;
  sampler2d _hatch3;
  sampler2d _hatch4;
  sampler2d _hatch5;
  struct v2f
  {
  float2 uv:texcoord0;
  float4 vertex:sv_position;
  //6 textures deepened in sequence
  float3 hatchweights0:texcoord1;
  float3 hatchweights1:texcoord2;
  //Declare the shadow
  shadow_coords (4)
  float3 worldpos:texcoord3;
  };
  v2f vert (appdata_full v)
  {
  v2f o;
  o.vertex=unityobjecttoclippos (v.vertex);
  //The larger the tiling coefficient,The denser the displayed texture
  o.uv=v.texcoord * _tilefactor;
  float3 worldlightdir=normalize (worldspacelightdir (v.vertex));
  float3 worldnormal=unityobjecttoworldnormal (v.normal);
  //diffuse reflection
  float diffuse=max (0, dot (worldlightdir, worldnormal));
  o.worldpos=mul (unity_objecttoworld, v.vertex) .xyz;
  //The weight of the six pictures
  o.hatchweights0=float3 (0, 0, 0);
  o.hatchweights1=float3 (0, 0, 0);
  //Calculate the weight based on the diffuse reflection value,The darker the diffuse reflection,Denser lines
  float hatchfactor=diffuse * 7.0;
  if (hatchfactor>6.0) {
  }
  else if (hatchfactor>5.0) {
   o.hatchweights0.x=hatchfactor-5.0;
  }
  else if (hatchfactor>4.0) {
   o.hatchweights0.x=hatchfactor-4.0;
   o.hatchweights0.y=1.0-o.hatchweights0.x;
  }
  else if (hatchfactor>3.0) {
   o.hatchweights0.y=hatchfactor-3.0;
   o.hatchweights0.z=1.0-o.hatchweights0.y;
  }
  else if (hatchfactor>2.0) {
   o.hatchweights0.z=hatchfactor-2.0;
   o.hatchweights1.x=1.0-o.hatchweights0.z;
  }
  else if (hatchfactor>1.0) {
   o.hatchweights1.x=hatchfactor-1.0;
   o.hatchweights1.y=1.0-o.hatchweights1.x;
  }
  else {
   o.hatchweights1.y=hatchfactor;
   o.hatchweights1.z=1.0-o.hatchweights1.y;
  }
  //pass the calculated shadow to the fragment
  transfer_shadow (o);
  return o;
  }
  fixed4 frag (v2f i):sv_target
  {
  float4 hatchtex0=tex2d (_hatch0, i.uv) * i.hatchweights0.x;
  float4 hatchtex1=tex2d (_hatch1, i.uv) * i.hatchweights0.y;
  float4 hatchtex2=tex2d (_hatch2, i.uv) * i.hatchweights0.z;
  float4 hatchtex3=tex2d (_hatch3, i.uv) * i.hatchweights1.x;
  float4 hatchtex4=tex2d (_hatch4, i.uv) * i.hatchweights1.y;
  float4 hatchtex5=tex2d (_hatch5, i.uv) * i.hatchweights1.z;
  //The greater the weight of the dark part of the diffuse reflection,Less white
  float4 whitecolor=float4 (1, 1, 1, 1) * (1-i.hatchweights0.x-i.hatchweights0.y-i.hatchweights0.z-i.hatchweights1.x-i.hatchweights1.y-i.hatchweights1 .z);
  float4 hatchcolor=hatchtex0 + hatchtex1 + hatchtex2 + hatchtex3 + hatchtex4 + hatchtex5 + whitecolor;
  //make the object accept the shadow
  unity_light_attenuation (atten, i, i.worldpos);
  return float4 (hatchcolor.rgb * _color.rgb * atten, 1.0);
  }
  endcg
 }
 }
}
  • Previous Method for processing json data using JSONPath in fastjson
  • Next How to switch hosts file using python