Unity shader之Flowmap貼圖的原理

一、FlowMap的原理

流動貼圖,爲了實現一個流動的效果,然而它存儲的信息是頂點的移動向量信息,只佔用RG通道,將一個歸一化二維向量保存到像素中,所以我們看到的flowmap都是如下顏色的(0.5, 0.5, 0);

它的實現思路是借鑑了向量場的概念,可以看一下參考中的向量場相關介紹;

在shader的實現中,它利用了uv動畫的原理,也就是我們需要根據flowmap中的信息做uv偏移,然後通過時間來改變偏移大小,從而產生一個流動效果;但是,我們不能允許uv的偏移量過大,因爲隨着時間疊加後,如果偏移量過大,肯定會導致採樣錯誤,所以我們需要將時間來控制到0,1的一個循環中,這樣就可以保證不會出現採樣的異常了;

片元着色器如下所示,

            fixed4 frag (v2f i) : SV_Target
            {
                float3 flowDir = tex2D(_FlowMapTex, i.uv) * 2.0f - 1.0f;
                flowDir *= _Speed;

                float phase0 = abs(fmod(_Time.y, 2) - 1);

                half3 tex0 = tex2D(_MainTex, i.uv + flowDir.xy * phase0);
                return fixed4(tex0, 1);
            }

但是上述這種實現方式會在一個週期之後有跳變的效果;

爲了解決這個跳變的效果,採用的解決方案是採樣兩次,然後在這兩次採樣之間做一個插值,然後做一個插值;注意插值係數也是要動態改變的,而且插值係數採用了絕對值的計算,也就是它是循環的(從0到1,再從1到0,而不會從1跳變到0)

            fixed4 frag (v2f i) : SV_Target
            {
                float3 flowDir = tex2D(_FlowMapTex, i.uv) * 2.0f - 1.0f;
                flowDir *= _Speed;

                float phase0 = abs(fmod(_Time.y, 2) - 1);
                float phase1 = frac(_Time.y  + 0.5f);

                half3 tex0 = tex2D(_MainTex, i.uv + flowDir.xy * phase0);
                half3 tex1 = tex2D(_MainTex, i.uv + flowDir.xy * phase1);

                float flowLerp = abs((phase0 - 0.5f) / 0.5f);
                half3 finalColor = lerp(tex0, tex1, flowLerp);

                return fixed4(finalColor, 1);
            }

二、參考

知乎 簡單瞭解flowmap的使用(UE4)-https://zhuanlan.zhihu.com/p/33288033

知乎-向量場的介紹:https://zhuanlan.zhihu.com/p/46362611

Medium-FlowMap着色器教程(UE4):https://medium.com/@thelouishong/shader-tutorial-flow-map-4410af832a8d

Github-Unity Flow Map Shader代碼:https://gist.github.com/TarasOsiris/e0e6e6c3b8fdb0d8074b

http://alex.vlachos.com/graphics/Vlachos-SIGGRAPH10-WaterFlow.pdf

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章