原貼地址: https://forum.unity.com/threads/spherize-alternative.907757/
題主問道:
我想做一個Gimp中的Spherize(球面化)濾鏡效果, 然后使用了ShaderGraph中的Spherize節點, 但是效果不對.
bgolus回答:
你想要的效果叫做stereographic projection(球極投影, 立體投影), 在PhotoShop/Gimp中被叫做Spherize.
ShaderLab
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 } } }
ShaderGraph


一些說明:
1. ShaderGraph中的Spherize在檔案中介紹如下:
Applies a spherical warping effect similar to a fisheye camera lens
也就是魚眼效果
演算法大約如下:
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), 也就是保持不變.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/31166.html
標籤:其他
