Unity論壇問答-Spherize(球面化)效果

原貼地址: https://forum.unity.com/threads/spherize-alternative.907757/算法

題主問道:
我想作一個Gimp中的Spherize(球面化)濾鏡效果, 而後使用了ShaderGraph中的Spherize節點, 可是效果不對.

bgolus回答:
你想要的效果叫作stereographic projection(球極投影, 立體投影), 在PhotoShop/Gimp中被叫作Spherize.
ShaderLabapp

Shader "Unlit/StereographicProjectionBubble"
{
    Properties
    {
        _MainTex ("Texture", 2D) = "white" {}
        _PanSpeed ("Pan Speed", Float) = 0.1
        _Spherify ("Spherify", Range(0,1)) = 1
    }
    SubShader
    {
        Tags { "Queue"="Transparent" "RenderType"="Transparent" "PreviewType"="Plane" }
        LOD 100

        Blend SrcAlpha OneMinusSrcAlpha

        Pass
        {
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"

            struct v2f
            {
                float4 pos : SV_POSITION;
                float2 uv : TEXCOORD0;
            };

            sampler2D _MainTex;
            float4 _MainTex_ST;

            float _PanSpeed;
            float _Spherify;

            v2f vert (appdata_base v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.texcoord.xy;
                return o;
            }

            fixed4 frag (v2f i) : SV_Target
            {
                float2 centered_uv = i.uv * 2.0 - 1.0;
                float z = sqrt(1.0 - saturate(dot(centered_uv.xy, centered_uv.xy)));
                float2 spherified_uv = centered_uv / (z + 1.0);
                float2 uv = spherified_uv * 0.5 + 0.5;

                uv = lerp(i.uv, uv, _Spherify);
                uv = TRANSFORM_TEX(uv, _MainTex);
                uv.x += frac(_Time.y * _PanSpeed);
                fixed4 col = tex2D(_MainTex, uv);

                half sqrDist = dot(centered_uv.xy, centered_uv.xy);
                half mask = 1.0 - sqrDist;
                mask = saturate(mask / fwidth(mask));

                col.a *= mask;

                return col;
            }
            ENDCG
        }
    }
}

ShaderGraphspa

 

一些說明:
    1. ShaderGraph中的Spherize在文檔中介紹以下:
    Applies a spherical warping effect similar to a fisheye camera lens3d

    也就是魚眼效果
    
    算法大約以下:
        a. 計算點P到圓心的距離d
        b. P' = P * d^4
    當P點在圓周上時, P'與P重合
    P點在圓內時, d<1, P' < P, 而且越接近圓心, P'相比於P越小
    P點在圓外時則相反, d >1, P'>P, 越遠離圓心, P'相比於P越大
    
    2. 關於球極投影
    一個半徑爲1的球體, 從北極點N出發, 過下半球的點P作一條射線, 較赤道平面於P', 參考下圖
   
   
    其中P點的座標爲(x, y, z), P'的座標爲(X, Y, 0), 它們之間的關係爲:
    
    
    ShaderLab的代碼首先將UV轉換到(-1, 1), 而後投射到下半球, 計算出z, 注意這裏計算獲得的z是正數, 而下半球的z應該是負數, 因此1-z變成了1+z.
    再計算出P'座標, 最後在映射回(0, 1), 從圖易知, 越靠近圓心部分, 圖形放大的越厲害, 反之縮小的越厲害.
    當UV的值超出圓的範圍, 此時z = 0, P' = (x, y), 也就是保持不變.code

相關文章
相關標籤/搜索