美文网首页
护盾/能量场效果

护盾/能量场效果

作者: LEO_青蛙 | 来源:发表于2020-06-21 18:52 被阅读0次
    护盾/能量场效果

    GitHub项目地址

    实现原理:
    1、边缘发光
    2、相交高亮,主要指能量场和别的物体相交的地方是高亮显示
    3、扭曲效果,指物体被能量场包围出现的扭曲

    1、边缘发光

    边缘发光效果,在我前面的文章中有介绍。

    //vert
    float3 worldNormal = UnityObjectToWorldNormal(v.normal);
    float4 worldPos = mul(unity_ObjectToWorld, v.vertex);
    float3 worldView = normalize(UnityWorldSpaceViewDir(worldPos));
    o.rimLight = 1 - abs(dot(worldNormal, worldView));
    //frag
    float rim = pow(i.rimLight, _RimPower);
    fixed3 rimColor = _RimColor.rgb * rim;
    

    2、相交高亮

    相交高亮,需要获取深度图和能量场的深度。
    (1)获取深度图

    //C#通知摄像机,获取深度图
    Camera.main.depthTextureMode |= DepthTextureMode.Depth;
    
    //shader获取深度图
    sampler2D _CameraDepthTexture;
    
    //vert计算屏幕坐标,范围[0, w],未齐次除法
    o.screenPos = ComputeScreenPos(o.vertex);
    
    //frag计算观察空间的深度值
    float depth = SAMPLE_DEPTH_TEXTURE_PROJ(_CameraDepthTexture, UNITY_PROJ_COORD(i.screenPos));
    float sceneZ = LinearEyeDepth(depth);
    

    (2)求能量场的深度值

    o.vertex = UnityObjectToClipPos(v.vertex);
    //计算观察空间的深度值z,并储存到o.screenPos.z
    COMPUTE_EYEDEPTH(o.screenPos.z);
    

    得到这两个深度值后,就可以计算相交

    float partZ = i.screenPos.z;
    float diff = sceneZ - partZ;
    float intersect = pow(1 - diff, _IntersectPower);
    float rim = pow(i.rimLight, _RimPower);
    float glow = max(intersect, rim);
    fixed3 rimColor = _RimColor.rgb * glow;
    

    2、扭曲效果

    扭曲效果的实现,我们需要抓取屏幕图像,有两种方式:
    (1)渲染纹理RenderTexture+额外摄像机(效率更高)
    (2)GrabPass(实现简单)
    这里我使用GrabPass的方式,GrabPass通常用于渲染透明物体,需要把物体的渲染队列设置成透明队列(即"Queue"="Transparent")。这样才可以保证当渲染该物体时,所有的不透明物体都已经被绘制在屏幕上,从而获取正确的屏幕图像。

    //获取屏幕图像
    GrabPass
    {
       "_GrabTempTex"
    }
    sampler2D _GrabTempTex;
    o.grabPos = ComputeGrabScreenPos(o.vertex);
    fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);
    

    能量球范围内的屏幕图像,随时间调整uv的偏移来模拟扭曲的效果。

    //frag
    float4 offset = tex2D(_NoiseTex, i.uv - Time.xy) * _DistortTimeFactor;
    i.grabPos.xy -= offset.xy * _DistortStrength;
    fixed4 color = tex2Dproj(_GrabTempTex, i.grabPos);
    
    扭曲效果

    注意事项:


    使用两个Pass渲染

    上图中,左边的效果使用了一个Pass渲染,右边的效果使用了两个Pass渲染。
    造成这样的区别,是因为使用一个Pass渲染,深度测试ZTest会把背后的颜色值覆盖掉。

    相关文章

      网友评论

          本文标题:护盾/能量场效果

          本文链接:https://www.haomeiwen.com/subject/bwuaxktx.html