欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Unity Shader相交算法实现简易防能量盾

程序员文章站 2023-02-19 15:01:48
unity shader学习:相交算法实现简易防能量盾主要思路:对比物体和场景深度图在观察空间下的深度差值,深度差越小表示相交,颜色越深,在加上边缘光勾出轮廓。shader部分:shader "unl...

unity shader学习:相交算法实现简易防能量盾

主要思路:对比物体和场景深度图在观察空间下的深度差值,深度差越小表示相交,颜色越深,在加上边缘光勾出轮廓。

Unity Shader相交算法实现简易防能量盾

Unity Shader相交算法实现简易防能量盾

shader部分:

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函数,得到归一化前的视口坐标xy
 //z分量为裁剪空间的z值,范围[-near,far]
 o.screenpos = computescreenpos(o.pos);
 o.uv = transform_tex(v.uv,_maintex);
 //compute_eyedepth函数,将z分量范围[-near,far]转换为[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;
 //获取深度纹理,通过lineareyedepth函数将采样的深度纹理值转换为对应的深度范围[near~far]
 float scenez = lineareyedepth(sample_depth_texture_proj(_cameradepthtexture,unity_proj_coord(i.screenpos)));
 //观察空间深度差,值越小颜色值越大
 float distance =1 - saturate(scenez - i.screenpos.z);
 //消除内部深度变化较大时产生的锯齿
 if (distance>0.999999)
 {
 distance = 0;
 }
 //调整深度差值的变化曲线
 distance = pow(saturate(_distancefactor * log(distance) + _distancefactor3), _distancefactor2);

 //角度越大边缘光越亮
 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);
 //根据边缘光以及深度差渐变
 col = float4(_rimcolor.rgb,lerp(col.a,_rimcolor.a, distance));
 col = lerp(col, _rimcolor, rim);
 return col;
 }

 endcg
 }
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。