Home>

Unity shader learning:intersect algorithm to achieve a simple anti-energy shield

Main ideas:Comparing the depth difference between the object and the scene depth map in the observation space,The smaller the depth difference indicates the intersection,The darker the color,Add outline light to outline.

Shader part:

shader "unlit/depthoutline"
{
 properties {
 _maintex ("maintex", 2d)="white" {}
 _rimfactor ("rimfactor", range (0.0,5.0))=1.0
 _distancefactor ("distancefactor", range (0.0,10.0))=1.0
 _rimcolor ("rimcolor", color)=(1,0,0,1)
 _distancefactor2 ("distancefactor2", range (0.0,10.0))=1.0
 _distancefactor3 ("distancefactor3", range (0.0,5.0))=1.0
 }
 subshader {
 tags {"queue"="transparent" "rendertype"="transparent" "ignoreprojector"="true"}
 pass {
 blend srcalpha oneminussrcalpha
 zwrite off
 cull off
 cgprogram
 #include "unitycg.cginc"
 #pragma vertex vert
 #pragma fragment frag
 sampler2d _maintex;
 float4 _maintex_st;
 sampler2d _cameradepthtexture;
 float _rimfactor;
 float _distancefactor;
 float4 _rimcolor;
 float _distancefactor2;
 float _distancefactor3;
 struct a2v {
 float4 vertex:position;
 float2 uv:texcoord0;
 float3 normal:normal;
 };
 struct v2f {
 float2 uv:texcoord0;
 float4 pos:sv_position;
 float4 screenpos:texcoord1;
 float3 worldnormal:texcoord2;
 float3 worldviewdir:texcoord3;
 };
 v2f vert (a2v v) {
 v2f o;
 o.pos=unityobjecttoclippos (v.vertex);
 //computescreenpos function to get the viewport coordinates xy before normalization
 //z component is the z value of the clipping space, range [-near, far]
 o.screenpos=computescreenpos (o.pos);
 o.uv=transform_tex (v.uv, _maintex);
 //compute_eyedepth function, convert the z component range [-near, far] to [near, far]
 compute_eyedepth (o.screenpos.z);
 o.worldnormal=unityobjecttoworldnormal (v.normal);
 o.worldviewdir=worldspaceviewdir (v.vertex) .xyz;
 return o;
 }
 float4 frag (v2f i):sv_target {
 float3 maintex=1-tex2d (_maintex, i.uv) .xyz;
 //Get depth texture,Convert the sampled depth texture value to the corresponding depth range through lineareyedepth function
 float scenez=lineareyedepth (sample_depth_texture_proj (_cameradepthtexture, unity_proj_coord (i.screenpos)));
 //observe the difference in spatial depth,The smaller the value, the greater the color value
 float distance=1-saturate (scenez-i.screenpos.z);
 //Eliminate the aliasing generated when the internal depth changes greatly
 if (distance>0.999999)
 {
 distance=0;
 }
 //Adjust the change curve of depth difference
 distance=pow (saturate (_distancefactor * log (distance) + _distancefactor3), _distancefactor2);
 //The greater the angle, the brighter the edge light
 float rim=1-abs (dot (normalize (i.worldnormal), normalize (i.worldviewdir)));
 rim=pow (rim, _rimfactor);
 float4 col=float4 (0,0,0,0);
 col=lerp (col, float4 (_rimcolor.rgb, 0.3), maintex.r);
 //Gradient according to edge light and depth difference
 col=float4 (_rimcolor.rgb, lerp (col.a, _rimcolor.a, distance));
 col=lerp (col, _rimcolor, rim);
 return col;
 }
 endcg
 }
 }
}
  • Previous JavaScript prohibits right-click to save the picture, prohibits the realization code of dragging and dropping pictures
  • Next JavaScript implementation code that prohibits users from saving pictures