水波効果実現の原理

この記事は2014年7月にQQスペースに掲載されました。転載場所を忘れてしまいました。原作者の権利を侵害している場合は、削除してください。テクノロジーを共有する精神でこの記事を公開しました、理解したいと思います

水波効果実現の原理

 免責事項:この特殊効果は私のオリジナルの作成ではありません。もちろん、誰がこの特殊効果を最初に作成したのかはわかりません。この水港効果の実現の原理を説明しようと思います。


vchelpのWebサイトからこのようなウォーターポートエフェクトのデモ(c#で記述)をダウンロードしたことがあります。コントロールを初めて見たときは非常に目立たないように感じましたが、誤ってマウスでドラッグしたときは、本当にすごいです。水の層が波打っています、私は言わなければなりません、私はその表現力に少し驚いています!このコントロールのコードをもう一度見てみました。200行しかありませんでしたが、一見したところ、コメントが少なかったため、すぐにはわかりませんでした。その後、国内のウェブページをいくつか見つけました。また、画像処理にも関わり、興味を持っているので、その実現原理が一目でわかります。したがって、この記事には私自身の作成はありません。より一般的な言語でその実現のプロセスを説明したいと思います。

より直感的にするために、レンダリングを最初に置き


ましょう。説明を始めましょう。私が見た中国語の説明Webサイトは次のとおりです。
特殊効果ワールド-ウォーターウェーブ
http://www.itcai.net/D01/7/540。 shtml

、right here基本的な舗装は省略されています。この特殊効果を実現するための基礎は次のとおりです。水波によって水面が波打つため、光の屈折方向が異なるため、物理的な世界で水波が見られます。 、水中シーンの画像をさまざまな程度の局所偏差にします。シフトして、水の波の視覚効果を形成します。

波紋のない平らな水面を想像してみてください。平らなガラス越しに水中のシーンを見ると、オフセットされた水中のシーンの画像が生成されます。小さい水波はわずかに歪んだ画像を生成しますが、大きい水波はより歪んだ画像を生成します。したがって、ピクセルオフセットサイズを介して水の波の視覚をシミュレートできます。さて、この文はこの特殊効果のシミュレーション原理です!

-------------------------------------------------- -------------------------------------------------- --------------------------
この原理は、実際にはフォトショップの変位フィルターの原理とまったく同じであることに注意してください。私はこのフィルターについて非常に詳細な理論的および応用的研究を行っています。このフィルターに関するチュートリアルは、China Photoshop AllianceForumにあります。説明します。この非常に興味深いフィルターは後で。そして、この特殊効果は、このフィルターに関する私の新しいアプリケーション研究も促進します。
-------------------------------------------------- -------------------------------------------------- ---------------------------


中学校の物理学の科目から、波が媒体を伝わると、すべての点が媒体の中で作られています。一種の単純な調和振動。したがって、画像の各ポイントの変数を設定します。これは、そのポイントのエネルギーまたは振幅として理解できます。このようにして、すべての点が一緒に波[、]配列を形成し、波[i、j]はピクセル(i、j)に対応します。水波のすべてのポイントは伝導プロセス中に時間とともに変化するため、波の配列の内容を変更する必要があります。ここでは、信号処理における漸化式と同様の仮定を紹介します。次の瞬間の波の値は、現在の瞬間の値に基づいて計算できると仮定します。直感的な感覚によると、この漸化式は主にネイバーネイバーフッドは関連しているので、この漸化式が提案されます。ここでは、上記の元のテキストの派生プロセスを段落で引用します
---------------------- --- ----------------------------------------------- --- ----------------------------------------------- --- -
【--------------------------------------------- --- ----------------------------------------------- --- ---------------------
ある瞬間、X0の振幅は、X0自体の振幅だけでなく、その周囲の4つのポイント(X1、X2、X3、X4)の影響も受けます(簡単にするために、他のすべてのポイントは無視します)。これらの4つのポイントがa0ポイントに与える影響は、機会均等と言えます。次に、この1回限りの式は次のようになります。

X0 '= a(X1 + X2 + X3 + X4)+ bX0         (式1)
        a、bは未定係数、X0'は0での次の瞬間の振幅です。X0    
        、X1、X2、X3、およびX4は現時点での振幅

以下のaとbを解いてみましょう。
水の減衰がゼロであると仮定します。このような理想的な条件下では、水の位置エネルギーの合計は変化しません。つまり、どの時点でも、すべてのポイントの振幅の合計は変更されません。次に、次の式を取得できます
。X0 '+ X1' + ... + Xn '= X0 + X1 + ... + Xn  

式1のように各点を計算し、次に取得するために、上記の式にそれを代入:
  (4A + B)X0 +(4A + B)X1 + ...(4A + B)Xnの= X0 + X1 +···+ Xnの
- -------------------------------------------------- -------------------------------------------------- -----------------】

-------------------------------- -------------------------------------------------- -------------------------------------------
(ここでの反復的な理論的根拠I私はまだそれを完全に理解しておらず、研究を続ける必要がありますが、このように直感的に想像することができます)。
ここでは、次の瞬間の値が、上下左右の4つの近傍位置を使用して概算されるという仮定を紹介します。この平面が無限大であると仮定すると、上記の式を代入すると、上下左右の隣接要素の計算で各要素が導入されて1倍になり、bが導入されて乗算されることがわかります。一度だけ計算するので、上記の式が得られます。したがって、振動が減衰しない場合に取得できます。4つの近傍の場合:(4a + b)= 1。この関係では、aとbを満たすものがたくさんあります。計算を簡単にするために、a = 1/2とb = -1が選択されています。

私は、デジタルの式1の式に精通しています画像処理。非常に一般的に使用されるテンプレートメソッドの形式。Photoshopのカスタムフィルターは、典型的なテンプレートアルゴリズムです。
これは、次のような計算テンプレートと同等です。
[0 1 0] [0 0 0]
[1 0 1] / 2+ [0 -1 0] 
[0 1 0] [0 0 0]

8つの近傍が導入された場合:次のテンプレートを選択できます。
[1 1 1] [0 0 0]
[1 0 1] / 4+ [0 -1 0] 
[1 1 1] [0 0 0]

もちろん、テンプレートの係数は加重値であり、フロントこれらの近傍が中心位置に同じ影響因子を持っていると私たちが信じていることを示しています。より大きなテンプレートが導入されると、モデルはより複雑になり、直感的な意味からより正確になる可能性がありますが、明らかに計算量が多くなります。上記のデモで使用されているテンプレートは、上記の2番目のテンプレートです。

このような再帰的な計算とは、水の波が減衰しない状況を指しますが、実際の性質はさまざまな抵抗のためにエネルギーを徐々に減衰させます。したがって、上記の計算結果は1回減衰します。たとえば、結果から1/16を減算します。このような特定の2の累乗を選択する理由は、シフトなどのより効率的なCPU命令を使用できるためです。

最後に、wave配列の内容を反復する必要があるため、同じサイズの2つの配列wave(t)とwave(t + 1)を使用できます。これらは交互に反復できるため、データは時間とともに進みます。デモでは、これら2つの配列を3次元配列、つまりwave [bitmapWidth、bitmapHeight、2]にマージします。3番目の添え字を使用して、0と1を切り替え、交代を完了します。


 //计算出下一个时刻非边缘处像素的新的波幅值
 for(int x=1; x<_waveWidth -1; x++)
 {
     for(int y=1; y<_waveHeight -1; y++)
     {
         //模板如下:
         //[1 1 1]        [0  0 0]
         //[1 0 1] /4 +   [0 -1 0]
        //[1 1 1]        [0  0 0]
        _waves[x,y,newBuffer] = (short)(
                                ((_waves[x-1,y-1,_activeBuffer] +
                                _waves[x,y-1,_activeBuffer] +
                                _waves[x+1,y-1,_activeBuffer] +
                                _waves[x-1,y,_activeBuffer] +
                                _waves[x+1,y,_activeBuffer] +
                                _waves[x-1,y+1,_activeBuffer] +
                                _waves[x,y+1,_activeBuffer] +
                                _waves[x+1,y+1,_activeBuffer]) >> 2) - _waves[x,y,newBuffer]);
        
        //damping , 使振幅衰减! 即原来的振幅*(1-1/16)
        if(_waves[x,y,newBuffer]!=0)
        {
            _waves[x,y,newBuffer] -= (short)(_waves[x,y,newBuffer] >> 4);                wavesFound = true;
        }
    }

次に、水波をトリガーする、つまり波の配列に初期値を入れる必要があります。自然界では、水波は明らかに円形であるため、グラフの円形領域に初期値を指定します。次に、波の配列を繰り返して、新しい瞬間の波の配列を計算します。

//设置x,y位置的wave值
for(int i = -radius; i<=radius; i++)
{
    for(int j = -radius; j<=radius; j++)
    {
        if(((x+i>=0) && (x+i<_waveWidth-1)) && ((y+j>=0) && (y+j<_waveHeight-1)))
        {
            dist = Math.Sqrt(i*i +j*j);
            if(dist<radius)
                _waves[x+i,y+j,_activeBuffer] = (short)(Math.Cos(dist*Math.PI  / radius) * height);
        }
    }
}

最後に、水の波を視覚効果に反映させる必要があります。このとき、波の配列を使用してピクセルオフセットを計算します。この仮定は、水波効果の原理です。波の配列の隣接する要素間の差は水平オフセットを反映し、同じ列内の隣接する要素間の差は垂直オフセットを反映します。ここでオフセットを取得した後は、フォトショップのディスプレイスメントフィルター方式とまったく同じです。オフセット位置を見つけて境界判定を行い、ソース画像のその位置のピクセルをコピーします。コードのこの部分は投稿されていません。

上記のプロセスで最も驚くべきことは、再帰を使用して次の瞬間の波のデータを計算することです。実際の効果は、シミュレーション効果が非常に優れていることを証明しています。しかし、このステップでは、それは感覚からしか理解できず、数学でそれを検証することはまだできていません。

同時に、フォトショップの分野での新しいアプリケーション、つまり水波効果ディスプレイスメントマップの作成もここで導き出されます。ディスプレイスメントフィルターの原理については、Photoshopフィールドのより詳細な部分が含まれているため、一言で説明することはできません。ここでは詳しく説明せず、結果を直接

示します。次のコードを使用します。ディスプレイスメントマップを生成するには:

//如果依然有水波!
 if(_weHaveWaves)
{
 this.ProcessWaves();
 
 BitmapData bmData =this.m_Bitmap.LockBits(
     new Rectangle(0,0,this.m_Bitmap.Width,this.m_Bitmap.Height), 
     ImageLockMode.ReadWrite,
     PixelFormat.Format24bppRgb);    //注意用24bpp格式!!!

int stride=bmData.Stride;    

//以下是不安全代码!!!
unsafe
{
    byte* p=(byte*)(void*)bmData.Scan0;
    for(int i=1;i<this.m_Bitmap.Width-1; i++)
    {
        for(int j=1; j<this.m_Bitmap.Height-1; j++)
        {
            //scale是缩放倍数!
            int waveX = (int)i >> _scale;
            int waveY = (int)j >> _scale;

            //check bounds
            if(waveX <= 0) waveX = 1;
            if(waveY <= 0) waveY = 1;
            if(waveX >= _waveWidth-1) waveX = _waveWidth-2;
            if(waveY >= _waveHeight-1) waveY = _waveHeight-2;

            //this gives us the effect of water breaking the light
            xOffset = (_waves[waveX-1,waveY,_activeBuffer] -_waves[waveX+1,waveY,_activeBuffer]) >> 3;
            yOffset = (_waves[waveX,waveY-1,_activeBuffer] -_waves[waveX,waveY+1,_activeBuffer]) >> 3;

            //根据偏移值,我们计算出置换图R和G通道!!!!
            //R通道!!!
            p[j*stride + i*3 + 2]=(byte)(xOffset%128+128);
            //G通道!!!
            p[j*stride + i*3 + 1]=(byte)(yOffset%128+128);
        }
    }
}

this.m_Bitmap.UnlockBits(bmData);

このようにして、このディスプレイスメントマップをPhotoshopのPSD形式として保存し、ディスプレイスメントフィルターで置き換えることができます。以下は、このディスプレイスメントマップを使用した場合の効果と、Photoshopでのアプリケーションです。もちろん、このコントロールによって生成される効果は、それはほとんど同じです。

これは、ディスプレイスメントマップを生成するためのツールです。


これはコードを使用して生成されたディスプレイスメントマップです:

Photoshopのディスプレイスメントフィルターを適用した、それは明らかに期待される結果です〜:


[注]上記の水波ディスプレイスメントマップ生成ツールのソースコード(メニューにあります):
http:/ /files.cnblogs.com/hoodlum1980/PsFilters.rar

おすすめ

転載: blog.csdn.net/zhengjian1996/article/details/112917190