Unity Shader - Curved World - 类似 地铁跑酷,动物森友会 的世界扭曲效果 - 球形透视

Posted Jave.Lin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity Shader - Curved World - 类似 地铁跑酷,动物森友会 的世界扭曲效果 - 球形透视相关的知识,希望对你有一定的参考价值。

文章目录


我发现莉莉丝的《神觉者》在战斗中也有使用到这个效果,视觉效果提升还是很大的


比如,球形投影前的效果

球形投影后的效果

GIF:


ShaderLab cginc


固定 Vector.forward 方向的球形透视

参考: Shader in Unity & Curved world shader & Change material color 实现的效果

实现的只能是 Vector.forward 方向的球形投影

#ifndef __CURVE_WORLD_LIB_H__
#define __CURVE_WORLD_LIB_H__

// jave.lin 2023/02/01 curve world library

    #ifdef _CURVE_WORLD_ON

        uniform float _Curve_Depth;
        uniform float _Depth_Divider;

        void CurveWorldApply(inout float3 positionWS, out float3 positionOS)
        
            float3 deltaVec = positionWS - _WorldSpaceCameraPos.xyz;
            float  E = -_Curve_Depth * _Depth_Divider;
            float  detlaVecZ2 = deltaVec.z * deltaVec.z;
            detlaVecZ2 *= E;
            float3 offset = float3(0.0, detlaVecZ2, 0.0);
            positionWS += offset;
            positionOS = mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz;
        

        #define CURVE_WORLD_APPLY(positionWS, positionOS) CurveWorldApply(positionWS, positionOS);

    #else

        #define CURVE_WORLD_APPLY(positionWS, positionOS)

    #endif

#endif

根据镜头任意视角方向的球形透视

#ifndef __CURVE_WORLD_LIB_H__
#define __CURVE_WORLD_LIB_H__

// jave.lin 2023/02/01 curve world library

    #ifdef _CURVE_WORLD_ON

        uniform float _Curve_Depth;
        uniform float _Depth_Divider;
        //uniform int _CW_Enabled;
        uniform float4 _Cam_Forward;

        void CurveWorldApply(inout float3 positionWS, out float3 positionOS)
        
            //float3 srcPosWS = positionWS;
            //float3 srcPosOS = positionOS;

            // jave.lin : zDist ref to : AutoLight.cginc

            float3 deltaVec = _WorldSpaceCameraPos - positionWS;
            //float zDist = dot(deltaVec, UNITY_MATRIX_V[2].xyz);
            float zDist = dot(deltaVec, _Cam_Forward.xyz);
            float  E = -_Curve_Depth * _Depth_Divider;
            float  zDist2 = zDist * zDist;
            zDist2 *= E;
            float3 offset = float3(0.0, zDist2, 0.0);
            positionWS += offset;
            positionOS = mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz;

            //positionWS = lerp(srcPosWS, positionWS, _CW_Enabled);
            //positionOS = lerp(srcPosOS, positionOS, _CW_Enabled);
        

        #define CURVE_WORLD_APPLY(positionWS, positionOS) CurveWorldApply(positionWS, positionOS);

    #else

        #define CURVE_WORLD_APPLY(positionWS, positionOS)

    #endif

#endif

添加开始弯曲透视的 z 距离偏移

留意: uniform float _Z_Dist_Offset;

#ifndef __CURVE_WORLD_LIB_H__
#define __CURVE_WORLD_LIB_H__

// jave.lin 2023/02/01 curve world library

    #ifdef _CURVE_WORLD_ON

        uniform float _Curve_Depth;
        uniform float _Depth_Divider;
        //uniform int _CW_Enabled;
        uniform float4 _Cam_Forward;
        uniform float _Z_Dist_Offset;

        void CurveWorldApply(inout float3 positionWS, out float3 positionOS)
        
            //float3 srcPosWS = positionWS;
            //float3 srcPosOS = positionOS;

            // jave.lin : zDist ref to : AutoLight.cginc

            float3 deltaVec = _WorldSpaceCameraPos - positionWS;
            //float zDist = dot(deltaVec, UNITY_MATRIX_V[2].xyz);
            float zDist = max(0, dot(deltaVec, _Cam_Forward.xyz) - _Z_Dist_Offset);
            float E = -_Curve_Depth * _Depth_Divider;
            float zDist2 = zDist * zDist;
            zDist2 *= E;
            float3 offset = float3(0.0, zDist2, 0.0);
            positionWS += offset;
            positionOS = mul(unity_WorldToObject, float4(positionWS, 1.0)).xyz;

            //positionWS = lerp(srcPosWS, positionWS, _CW_Enabled);
            //positionOS = lerp(srcPosOS, positionOS, _CW_Enabled);
        

        #define CURVE_WORLD_APPLY(positionWS, positionOS) CurveWorldApply(positionWS, positionOS);

    #else

        #define CURVE_WORLD_APPLY(positionWS, positionOS)

    #endif

#endif

CurveWorldControl.cs

// jave.lin : curve world control

using UnityEngine;

[ExecuteInEditMode]
public class CurveWorldControl : MonoBehaviour

    private bool _last_on = false;
    public bool on = true;
    [Range(0.005f, 1.0f)]
    public float curveDepth = 0.015f;
    public float depthDivider = 0.0f;

    public Camera cam;

    private static int _Curve_Depth = Shader.PropertyToID("_Curve_Depth");
    private static int _Depth_Divider = Shader.PropertyToID("_Depth_Divider");
    private static int _Cam_Forward = Shader.PropertyToID("_Cam_Forward");
    private void Update()
    
        if (cam == null)
        
            Shader.DisableKeyword("_CURVE_WORLD_ON");
            return;
        

        if (_last_on != on)
        
            if (on)
            
                Shader.EnableKeyword("_CURVE_WORLD_ON");
            
            else
            
                Shader.DisableKeyword("_CURVE_WORLD_ON");
            
            _last_on = on;
        

        if (_last_on)
        
            Shader.SetGlobalFloat(_Curve_Depth, curveDepth);
            Shader.SetGlobalFloat(_Depth_Divider, depthDivider);
            var view_forward = cam.worldToCameraMatrix.GetColumn(2);
            Shader.SetGlobalVector(_Cam_Forward, view_forward);
        
    


需要修改的代码

修改所有 3D shader 即可

  1. pass添加代码:
  • #pragma multi_compile _ _CURVE_WORLD_ON
  • #include “CurveWorldLib.cginc”
  • CURVE_WORLD_APPLY(posWorld.xyz, v.vertex.xyz)
  1. 要添加的pass
  • ForwardBase
  • ForwardAdd
  • ShadowCaster
  1. CurveWorldControl.cs 的 DontDestryOnLoad
  2. 对应场景才开启 CurveWorldControl

Project

TestingSphereProjectionEffect - 参考: Shader in Unity & Curved world shader & Change material color 实现的效果


References

全部看完,相信你可以做一款很有意思的游戏,或是游戏中很有特色的效果

unity怎么编辑shader

有个插件叫做Shader Forge 可以可视化的编辑shader效果 不过效率可能没那么高
也可以自己学一下shader的语言然后再编辑
参考技术A shader也算一门语言,要系统的学习才可以编辑shader。

以上是关于Unity Shader - Curved World - 类似 地铁跑酷,动物森友会 的世界扭曲效果 - 球形透视的主要内容,如果未能解决你的问题,请参考以下文章

unity shader怎么混合两张贴图

unity shader有啥好处

unity shader有啥用

unity用脚本怎么让shader重绘

unity shader 能加密吗

unity能改默认的shader吗