正直な輝きとスピード

おそらくPhotoshopで少し作業した人は誰でも、レイヤーの外側の輝きの効果を見て、それで遊んでみました。 Photoshopには、この同じ外部グローの2つのテクニックがあります。 ソフトで正確。 ソフトは私にはそれほど面白くありませんでしたが、正確に見ると私は思いました。



次のようになります。



これは単一のピクセルラインです。 大まかに言って、グラデーションは画像内の最も近いピクセルまでの距離を反映しています。 これは距離です-さまざまなエフェクトを作成するのに非常においしいかもしれません。 これはあらゆる種類の輪郭であり、独自のグラデーションであり、
周囲のガス排出効果でさえも。
距離マップが使用可能な場合に取得できる効果の例 。 例では、Delphiで記述されたOpenGL + GLSLを使用しています


このグローの主な問題は、大きなサイズの計算の難しさです。 100ピクセルのグローがある場合、画像の各ピクセルについて100 * 100の隣接ピクセルをチェックする必要があります。 また、800 * 600などの画像の場合、わずか4,800,000,000のチェックになります。



ただし、Photoshopはこれに悩まされることはなく、大きなサイズ(最大250)であっても正確なグローを完全に構築します。 解決策があります。 そして、私は彼を見つけたいと思っていました。 私はそのような輝きの高速アルゴリズムをグーグルで管理することはできませんでした。 ほとんどのアルゴリズムはぼかしを使用してグローを作成しますが、1ピクセルの線では画像と同じ効果は得られず、単にぼかしになることは誰もが知っています。



それで自転車を運転しました。



私たちは何をしますか
用語から始めましょう。

PNG画像用に100ピクセルのグローを作成します。 これは:



元の画像がアーカイブされます。 また、トピック内の写真でレイアウトするために、背景を黒で塗りつぶしました。 オリジナルでは、 これ透明な背景上の白い画像です。

すべてのピクセルを既存および非既存と呼びます。 既存のピクセルは0より大きいアルファであり、実際にはグローの構築に関与しています。



ステージ1
実際、各ピクセルが半径100ピクセル内で最も近い既存のピクセルを探す必要はありません。 既存の各ピクセルは、そのようなグローを大まかに言って、隣接するピクセルに単に破棄されます。



このグローでは、色はピクセルまでの距離を意味します。 したがって、すべては、既存のピクセルごとにグローイメージを「描画」することになります。 そして、結果の効果のポイントが最も近くなるように-最小値のみを「描画」します。

存在しないピクセルを破棄することで、グローを描画する時間を大幅に短縮しましたが、それでもまだ大きなものです。 次に何をする?



ステージ2
注意深く見ると、4辺の点が既存のピクセルに囲まれていることがわかります。



その後、一意のピクセルはまったく破棄されません。 赤いドットを処理して描画するすべてのものは、番号が付けられたゾーンのそれぞれで、隣接するピクセルと擦られます。 したがって、近隣のポイントを分析すると、多くの既存のポイントを破棄できます。 この分析の結果は次の画像です。



白-削除された既存のポイント。 グレー-本物の輝きを与えるポイント。 黒-存在しないドット。

実際、輪郭を残しているだけで、そこからグローを作成します。



そのため、私たちのアルゴリズムは桁違いに高速になりましたが、Photoshopの実装と比較すると、カメとしてはまだ遅いです。 上の写真の100ピクセルの手袋を持っているので、作成に2〜3秒かかりました。



ステージ3
前の手順は非常に簡単でした。 アルゴリズムの作業は大幅に加速されましたが、まだ境界線上のピクセルに対して必死のオーバードローがあります。

グローを破棄する必要がある3つのピクセルが互いに隣り合う場合の状況を詳しく見てみましょう。



実際、3(赤)ピクセルのうち、明るい赤は実際の線を1本だけ提供し、他のすべての情報は暗い赤のピクセルのグローをレンダリングするときに再描画されます。 私はこれについて幾何学的な証明をしませんが、読者にとっては非常に明白だと思います。 このように1ピクセルを横に移動すると:



その後、左の「レイ」を失います。 1つのピクセルがあり、明るい赤に近い場合があります。 さらに、真っ赤なピクセルからグローを落とすまったく新しい領域があります。



下のピクセルを横に移動して、何が起こるかを確認します。



再び2本の光線が残っています。

さまざまな状況をひねり、慎重に考えて、結論に至りました。 3つの隣接するピクセルがない場合、ピクセルは側面にビームを与えます。 インデックス付きの隣接ピクセルの例:



インデックス7、0、1の隣接ピクセルがない場合、左の光線になります

レイ左上-インデックス0、1、2の隣接ピクセルがない場合

レイアップ-隣接するピクセルが存在しない場合1、2、3

など

さらに、光線の間にもピクセルがあります。 そのため、隣接する光線が2つある場合のみになります。 つまり すでに述べた写真によると:



光線が正しく、光線が正しい。 それらの間にグローピクセルを描画する必要があります。



したがって、オーバードローを大幅に削減できます。



実装
Vampyre Imaging Libraryを使用して、デルファイにこのアルゴリズムを実装しました。 最初に、記事で既にフラッシュされた記憶に準備します
グロー画像






それから準備します
境界ピクセル画像
あなたが増加した場合に見られる、彼らは灰色です


グローイメージ論理的に16ゾーンにヒットします。



DrawGlowPartコードの関数は、インデックスによって厳密に定義されたゾーンのみを描画できます。 各ゾーンのサイクルをいじる必要がありました。 さらに、DrawGlowPart関数は、インデックス16のゾーンを描画できます。これは、描画する既存のピクセルの周囲の1ピクセルです。 次の図は、このピクセルが明るい赤の左側にあることを示しています。





ここでの大騒ぎの結果は、そのような不吉な絵です:



私のマシンではわずか150ミリ秒です。 これはすでに人間です。

このアルゴリズムはGPUによく適合します。GPUに余裕を持たせて、さらに成長させ、リアルタイムでそのようなグローを実際に構築できるようにするつもりです。 残念ながら、150msはまだリアルタイムではありませんが、ロード時間はすでに許容されています。



Photoshopで
Photoshopでは、グローブは明らかに私のアルゴリズムに従って実装されていません。コードを故意に循環させても驚かないでしょう。 Photoshopの1ピクセルからの輝きをよく見ると、かなり良いモニターでその「多角形」を見ることができます。



開発者は境界ピクセルに基づいて輪郭を作成し、それをシフトしてポリゴンを取得すると思われます。 また、これによりオーバードライブがさらに減少すると考えられます。 誰かがこのトピックに関する資料を持っている場合-私は読んで喜んでいるでしょう。



記事へのリンク
1. アルゴリズムの実装 。 バイナリファイル+ソースコード。 コンパイルにはVampyre Imaging Libraryが必要です。 最初のパラメーターは入力ファイルです。 2-グローのサイズ(ピクセル単位)。

2. 効果の例 。 リアルタイムでグローを生成するのではなく、事前に生成されたグローを使用します。 レンダリングには、OpenGL + GLSLが使用されます。



All Articles