UnityShader ground holographic scanning occlusion object effect (screen space)


Some time ago, when I played "Call of Duty 11", I found that a very high-tech scanning grenade was added in it, which can generate a scanning circle similar to a holographic effect, and show the enemies behind the wall, similar to this:

 

Recently, I plan to achieve a similar effect in the third person, as follows:

Implementation plan:

1. Calculate the world coordinates of screen space pixels according to _CameraDepthTexture

2. Pass the world coordinates of the scan initiation position into the shader

3. Calculate the distance from the world coordinates of the screen space to the world coordinates of the scanning initiation position

4. Render the scanning area according to the relevant parameters


1. The depth information of the projection space is recorded in _CameraDepthTexture, and the world coordinates can be obtained by the following methods:

fixed depth = tex2D(_CameraDepthTexture, i.uv).r;
fixed4 projPos = fixed4(i.uv.x * 2 - 1, i.uv.y * 2 - 1, -depth * 2 + 1, 1);
worldPos = mul(internalCameraToWorld, worldPos);
worldPos /= worldPos.w;

2. Calculate the distance between the incoming initial position and the screen space world coordinates:

fixed dis = length(internalCentPos.xyz - worldPos.xyz);
 
fixed a = 1 - saturate((abs(dis - internalArg.x) - internalArg.y) / internalArg.z);
a = a * internalFade.x + c * internalFade.y;

Finally, the following effect can be obtained:

 
3. Save the rendering result of the previous step, and use CommandBuffer to render the target (such as the enemy) that needs to be marked as continuous display to this texture. Note that it is necessary to judge whether the target is in the camera. The effect is as follows:

public static void CallRender(Vector3 worldPosition, Renderer[] renderer)
    {
        if (!IsInitialized())
            return;
        if (instance.m_IsShowingEffect)
        {
            if (renderer == null)
                return;
            Vector3 pjpos = instance.m_Camera.worldToCameraMatrix.MultiplyPoint(worldPosition);
            pjpos = instance.m_Camera.projectionMatrix.MultiplyPoint(pjpos);
            if (pjpos.x < -1 || pjpos.x > 1 || pjpos.y < -1 || pjpos.y > 1 || pjpos.z < -1 || pjpos.z > 1)
                return;
            for (int i = 0; i < renderer.Length; i++)
            {
                instance.m_CommandBuffer.DrawRenderer(renderer[i], instance.m_ReplaceMaterial);
            }
        }
    }

 

4. Rasterize the screen uv according to the screen uv information, and calculate the color value sampled in each grid, the following results can be obtained:

 

float2 fl = floor(i.uv * _EffectScale);
float dp = tex2D(_PreTex, (fl + float2(0.5, 0.5)) / _EffectScale);
                 
float4 led = tex2D(_EffectTex, i.uv * _EffectScale - fl);
                 
col.rgb += led.rgb*dp;

5. Also based on the result of the grid just now, the uv of each small grid can be calculated, and the texture used as a holographic scanning effect is sampled according to the uv, and the following results are obtained:

 


6. Overlay the final result:

 


————————————————
Original link: https://blog.csdn.net/mobilebbki399/article/details/78379758

Guess you like

Origin blog.csdn.net/weixin_42565127/article/details/130326101