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
}
}
}
Related articles
Related questions
- Unity Shader achieves cutting effect
- Unity Shader realizes the fog of 2D games
- Unity Shader implements sketch-style rendering
- Unity Shader achieves graphics drawing (blue sky, white clouds and sea)
- Unity shader realizes the effect of vertex animation wave
- Unity shader to achieve glass refraction effect
- Unity Shader achieves dynamic fog effect
- Unity Shader achieves glass material effect
- Unity Shader intersection algorithm realizes simple anti-energy shield