Unity Shader相交算法实现简易防能量盾
程序员文章站
2023-02-19 15:01:48
unity shader学习:相交算法实现简易防能量盾主要思路:对比物体和场景深度图在观察空间下的深度差值,深度差越小表示相交,颜色越深,在加上边缘光勾出轮廓。shader部分:shader "unl...
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 } } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。