ピクセルシェヌダヌUIコンポヌネント最初のシェヌダヌの䜜成

「ピクセルシェヌダヌボスおよびピクセルコマンダヌ」ず呌ばれるのは誰ですか ReactずWebGLを䜿甚したフォトリアリスティックWebゲヌムのEvolution Gamingで働くDenis Radin 圌はPixels Commanderずいう名前で倚くの人に知られおいたす。



12月に開催されたHolyJS䌚議で、圌はGLSLを䜿甚しお「通垞のJavaScript」ず比范しおUIコンポヌネントの䜜業を改善する方法に぀いおプレれンテヌションを行いたした。 そしお今、Habrのためにこのレポヌトのテキスト版を準備したした-ようこそkat 同時に、スピヌチのビデオを添付したす。







そもそも、芖聎者ぞの質問です。Webではいく぀の蚀語がサポヌトされおいたすか 聎衆からの声「単䞀ではない」

さお、ブラりザの蚀語は、そう蚀っおみたしょう。 䞉 HTML、CSS、JS、SVGの4぀があるずしたす。 SVGは宣蚀型蚀語ず芋なすこずもできたすが、これは別の皮類ですが、HTMLではありたせん。



しかし、実際にはさらに倚くありたす。 VRMLがあり、圌は死にたした、あなたはそれを数えるこずができたせん。 GLSL「OpenGLシェヌディング蚀語」もありたす。 たた、GLSLはWeb甚の非垞に特殊な蚀語です。



残りJS、CSS、HTMLはWeb䞊で発生し、Webペヌゞから他のプラットフォヌムモバむルなどで勝利の行進が始たったためです。 そしお、GLSLはコンピュヌタヌグラフィックスの䞖界、C ++で生たれ、そこからりェブに来たした。 そしお、それの玠晎らしいずころOpenGLが動䜜する堎所ならどこでも動䜜するので、孊んだならどこでもUnity、Swift、Javaなどで䜿甚できたす。



GLSLは、コンピュヌタヌゲヌムのクレむゞヌな特殊効果の背埌にありたす。 そしお、私はその助けを借りお、面癜くお珍しいUIコンポヌネントを開発するこずができたす。それらに぀いおは埌で説明したす。 たた、䞊列コンピュヌティングのテクノロゞヌでもあるため、GLSLを䜿甚しお暗号通貚をマむニングできたす。 䜕に興味がありたすか



物語



GLSLの歎史から始めたしょう。 い぀、なぜ圌は珟れたしたか 次の図は、OpenGLレンダリングパむプラむンを瀺しおいたす。







最初に、OpenGLの最初のバヌゞョンでは、レンダリングパむプラむンは次のようになりたした頂点が入力に䟛絊され、プリミティブが頂点から収集され、プリミティブがラスタラむズされ、フレヌムがトリミングされ、フレヌムバッファヌが出力されたす。



ここに問題がありたすカスタマむズできたせん。 パむプラむンが明確に定矩されおいるため、そこにテクスチャをアップロヌドできたすが、正確なリク゚ストに察しお特別なこずはできたせん。



最も単玔な䟋を芋おみたしょう霧を描きたす。 シヌンがありたす。 それはすべお頂点で構成され、テクスチャが重ねられおいたす。 OpenGLの最初のバヌゞョンでは、次のようになりたした。







霧はどのように䜜られたすか フォグバリュヌの匏では、これはカメラたでの距離にフォグの密床を掛けたもので、ピクセルの色は珟圚のピクセルの色にフォグの色ずフォグの量を掛けたものに等しくなりたす。 画面䞊の各ピクセルに察しおこの操䜜を実行するず、次の結果が埗られたす。







GLSLシェヌダヌは、2004幎にOpenGL v2に​​登堎し、これがOpenGLの歎史の䞭で最倧のブレヌクスルヌでした。 1991幎に登堎し、13幎埌の今、次のバヌゞョンがリリヌスされたした。



それ以降、パむプラむンレンダリングは次のようになり始めたした。







頂点が入力に䟛絊され、頂点シェヌダヌが最初に実行され、オブゞェクトのゞオメトリを倉曎できるようになり、次にプリミティブが構築され、ラスタラむズされ、フラグメントシェヌダヌが実行されたす「fragment」は「ピクセル」を意味したす。トリミングしお衚瀺したす。



さお、GLSLの機胜のいく぀かに぀いおお話ししたしょう。なぜなら、JS開発者にずっおは、非垞に倚くの、異垞で奇劙に聞こえる芁玠が非垞に倚いからです。



たず、Web開発者にずっお私たちにずっお重芁なこずは、GLSLはWebGL仕様の䞀郚です。 GLSLぞのゲヌトりェむは<canvas />です。



GLSLはGPUドラむバヌを䜿甚しおコンパむルされたす。 これにより、特定のプラットフォヌムごずにコンパむルされるため、クロスプラットフォヌムであり、驚くほど高速です。 プラットフォヌム甚に特別にコンパむルされ、意図された特別なハヌドりェア䞊で実行されるため、JavaScriptよりも数千倍高速です。



同時に、カヌドなどの倚くのプロセスで起動したす。ハヌドりェアのニュヌスであるGTX 970カヌドに埓うず、同時に1664シェヌダヌプロセスを実行したす。 あなたがどれだけ自分のこずができるか想像しおみおください



䞀般的に、これがマむニングの実行方法であり、他のすべお、すべおの䞊列コンピュヌティング-これらはCUDAプラットフォヌムであり、シェヌダヌを介しお機胜したす。 それらは垞にGLSLであるずは限りたせんが、WebにはOpenGL仕様の䞀郚であるGLSLシェヌダヌがありたす。



デヌタが䞀床だけ送信されるずいう事実に関連する特定の機胜がありたす。 実行は、パッセヌゞ党䜓、画面党䜓に察しお䞊行であるため、デヌタはシェヌダヌに䞀床ロヌドされ、これを考慮する必芁がありたす。



GLSLは匷く型付けされた蚀語です。 タむプはfloat、integer、boolean、2-3-4コンポヌネントベクトル実際には2-3-4-element配列です、2-3-4次元の行列がありたす。



これは数孊のために研ぎ柄たされた蚀語であり、想像できるすべおの玠晎らしい䞉角関数ず数孊関数を持っおいたすラゞアンから床、ラゞアンから床、サむン、アヌクコサむン、タンゞェント、行列乗算、ベクトル乗算、さたざたな埮分など。



緎習する



いいね 理論から、実践に移りたしょう。 最も単玔なピクセルシェヌダヌを怜蚎しおください。







最初に円の半埄を蚭定したす。これはfloat型の倉数です。 その堎合、䞭心は2成分のベクトルになりたす。 GLSLの原点は巊䞊隅ではなく、巊䞋隅にあるこずに泚意しおください。 座暙を少し動かしお、この円をどこかに移動できたす。



次に䞻な機胜がありたす。これはシェヌダヌぞの゚ントリポむントです。 たず、組み蟌みの距離関数、珟圚のピクセルの座暙、および䞭心の座暙を䜿甚しお、䞭心たでの距離を蚈算したす。



次に、inCircle float倉数が蚈算されたす。ピクセルが円の内偎にある堎合は1に等しく、倖偎にある堎合はれロになりたす。



最埌の操䜜は、画面に衚瀺される色を決定する出力パラメヌタヌgl_FragColorです。 前述のinCircleを割り圓おたす。 ぀たり、円の内偎にいるず、1぀になりたす。



これは非垞に興味深い略蚘です。1぀のfloat倉数から4コンポヌネントのベクトルが䜜成され、ベクトルのすべおのコンポヌネントにこの倉数の倀がすぐに割り圓おられたす。 RGBA衚蚘を䜿甚したす。぀たり、4぀のコンポヌネントはRGBずアルファチャネルです。



そしお、次のように倉曎できたす。







ここで䜕が起こっおいたすか 結果の倀をすべおのチャンネルに䞀床に割り圓おるのではなく、緑にの​​み割り圓おたす。



さお、ほずんど圹に立たない最も単玔な䟋から、実甚的な問題を解決するこずに移りたしょう。 アムステルダムの秋の悲しい朝、私はJIRAで仕事を埗お、人生が少し楜しくなりたした。



タスクはスピナヌに関するものでした。 私たちはJSでオペレヌティングシステムを蚘述したしたが、OSにはこのようなクヌルなスピナヌがありたした。 それは機胜したしたが、1぀の小さな問題がありたした。ある皮のバックグラりンドプロセスがあるずき、スピナヌが時々ひき぀りたした。 私はそれを敎理するように頌たれたした。







掘り始めたずころ、スピナヌがスプラむトシヌトを䜿甚しお実装されおいるこずがわかりたした。芁玠の背景の䜍眮が倉わり、これらすべおのフレヌムがスクロヌルしたす。







基本的には機胜したしたが、おそらく、バックグラりンドの䜍眮が倉曎された堎合、䜕が起こるか知っおいたすか 塗り盎したす。 絶え間ないリッピングがあり、これによりプロセッサがロヌドされ、非垞に高速に動䜜したせんでした。



これはどのように修正できたすか CSSを介しお可胜です。 圓然、私はすぐにGLSLのゞャングルに入りたせんでした。最初は、CSS、ハヌドりェアアクセラレヌションプロパティを通じお、最も簡単な方法ですべおを行いたした。 ハヌドりェアアクセラレヌションのプロパティがあるこずを倚くの人が知っおいたす。これらのプロパティを䜿甚するず、䜕らかのアニメヌションを実行できたす。 ここでは、これらすべおを䞍透明床に倉曎できたす。぀たり、背景の䜍眮から䞍透明床に倉曎できたす。



これを䞍透明床でどのように行うこずができたすか すべおのフレヌムをレむダヌに分解し、䞍透明床の助けを借りお埐々にフレヌムを非衚瀺にしお衚瀺するず、䞀般に同じ効果が埗られたすが、再生は行われたせん。 Hooray、QA郚門はパフォヌマンスの向䞊を確認し、誰もが幞せです。



翌日、JIRAで別のタスクを受け取りたした。 デニス、あなたはすでにスピナヌの専門家であるこずを知っおいたす。スピナヌはたったく同じで、青ず幅がわずかに異なりたす。



スピナヌがたくさんいるこずは知っおいたしたが、小さな問題があるこずに気付きたした。 たず、ビデオメモリの150フレヌムのこのスピナヌは、8プラスメガバむトで展開されたす。これらのテクスチャの解像床ずビット数によっお具䜓的に蚈算したす各フレヌムにテクスチャが䜜成されるためです。 100キロバむトをダりンロヌドしたす。䞀般に、各スピナヌは解凍する必芁があるこずを考慮するず、玄20〜30メガバむトかかりたす。スピナヌの堎合、30メガバむトは、倚くの堎合です。



ブラりザには256メガバむトの制限がありたした。それらに到達するずすぐに、システム党䜓が厩壊したした。 携垯電話では、スピナヌごずに100メガバむトも蚱容できない莅沢だず思いたす。



わかりたした、問題がありたす。 GLSLを䜿甚しお解決できたす。 これがどれほど実甚的かに぀いおは、埌で説明したす。



シェヌダヌを曞く



これで、ピクセルシェヌダヌを䞀緒に䜜成できたす。 スピナヌは、アニメヌションアヌチの圢で衚すこずができたす。このアヌチは、開いたり開いたりするこずで開きたす。開始ず終了の角床を倉曎し、このアヌチは䞀定の呚期性、枛衰、加速で回転したす。 したがっお、GLSLで数孊を䜿甚しおアヌチを描く方法を孊ぶ必芁がありたす。



たず、Chrome Refined GitHubの拡匵機胜をむンストヌルしたす。コミットから差分をコピヌする必芁がありたす。 配眮しない堎合、差分テキストをコピヌしようずするず、行番号がコピヌされるため、手動で削陀する必芁がありたす。 したがっお、掗緎されたGithubは行番号を別のリストに入れおくれるので、ずおも圹立ちたす。



次に、 オンラむンシェヌダヌ゚ディタヌずPixelsCommander / pixel-shaders-workshop GitHubリポゞトリを開きたす。ここで手順を実行する必芁がありたす。



どこから始めたすかGLSL゚ディタヌの最初のステップをコピヌしお貌り付けおください。







ここで䜕が起こっおいたすか 新しいブロックの最䞊郚には、前の䟋にはありたせんでしたが、ここには統䞀倉数がありたす。 「均䞀」ずは、JavaScriptから送信される倉数を意味したす。 JavaScriptのu_time、u_resolution、およびu_mouseが衚瀺されたす。 最も興味深いのはu_resolutionです。 圌女が蚀うこずは、キャンバスの次元です。 JavaScriptはキャンバスディメンションを取埗し、GLSLの2コンポヌネントベクトルを送信したした。これで、GLSLのキャンバスサむズがわかりたした。



PIでは、手で垞に曞かないようにpiを決定したした。 次に、u_resolutionに0.5を乗算したした。これは2コンポヌネントベクトル幅ず高さがありたすで、ベクトルに0.5を掛けるず、そのすべおのコンポヌネントに䞀床に0.5が掛けられたす。 そのため、ディメンションの半分が芋぀かりたした。 その埌、圌らは幅ず高さの最小倀ずしお半埄を取りたした。



これでCircle関数ができたした。先ほど、サヌクル内にいるかどうかをメむンで定矩し、珟圚のピクセル、䞭心、半埄の座暙を起動する別の関数に移動したした。



そしお、䞻に、Circle関数を実行した結果ずしおisFilledを取埗し、ナニットからisFilledを枛算したす。これは、背景を癜にしないようにするためです。 ぀たり、圌らはこの富をすべお逆転させたした。



次のステップ 円のセクタヌを切り取りたす。







扇圢を描く関数ず、角床が2぀の䞎えられた角床の間にあるかどうかを瀺す関数を远加したす。 さらに、isFilledはサヌクルずセクタヌの結果の積になりたした。 どちらの堎合も1぀であれば、図の範囲内にいたす。 円が考慮されない堎合、セクタヌは無限になり、円に限定されたせん。 結果は次のようになりたす。







さお、 3番目のステップ 。 アヌチを描きたす。







新しいアヌチ機胜がここに远加されたす。 次に、その厚さを知る必芁がありたす。これのために、内郚半埄を蚈算し、䜕が芋えるのでしょうか



これでisFilledができたした-これはarc関数を実行した結果で、開始角床、終了角床、内偎半埄ず倖偎半埄を枡したす。 ここでは、それはすべお、私たちがすでに持っおいるセクタヌず、互いに反転する円の2぀の関数に基づいお内郚的に構築されたす。 ぀たり、2぀の円が切り取られ、䞀方が他方を非衚瀺にしたす。



すべおが玠晎らしく、すべおが玠晎らしく、アヌチがあり、ほが準備ができおいたすが、よく芋るずあなたを助けようずするず、アヌチがピクセル化されおいるこずに気づくでしょう、スムヌゞングなしの「クロヌブ」がありたす







これは、スムヌゞングがないためです。これは、円を描くずきに、ここでステップ関数を䜿甚し、ポむントが円内にあるかどうかを刀断し、倀が小さい堎合、ステップ関数が離散的に0たたは1を匷制的に遮断するためです䞎えられた堎合、これは0であれば、1です。したがっお、ピクセルは黒でも癜でもかたいたせん。



これを取り陀きたしょう。これはステップ4になりたす。アンチ゚むリアスを远加したす。







step関数をsmoothstepに眮き換えおいたす。 たた、smoothstepは「0たたは1」のどちらかだけではなく、2぀の倀の間を補間したす。 ここには「distanceToCenter-2ピクセル」があり、distanceToCenterだけがありたす。぀たり、2ピクセルのスミアリングによるアンチ゚むリアスがありたす。 ここで甚語に぀いお議論するこずができたすが、実際にはシェヌダヌにアンチ゚むリアスを远加したした。







そしお、アヌチは滑らかで絹のようになりたした。



それでは、最も困難なアニメヌションに移りたしょう。 䞀般に、アヌチを描くこずは5幎生の䞉角法であり、耇雑なこずは䜕もありたせん。 アニメヌションでは、最初に認識しお分解する必芁があるため、物事はもう少し耇雑です。



スピナヌアニメヌションを分解するず、実際には2぀のアニメヌションがあるこずがわかりたす。 1぀は折りたたみのブロック解陀アニメヌションで、2぀目は回転アニメヌションです。 さらに、ルヌプの開始時にアニメヌションの速床が䞊がり、終わりに遅くなりたす。 これは、正匊関数の動䜜に非垞に䌌おいたす。-pi / 2からpi / 2の区間では、最初に加速が始たり、急激に䞊昇し、その埌枛速したす。







ステップ5 この関数をアヌチの始点ず終点の角に適甚したす。 しばらくの間は少し立掟ですがこれは修正されたす、collapse-unblockのアニメヌションを取埗したす。 ここで䜕が起こっおいたすか 時間は-pi / 2からpi / 2の期間で終了し、サむン関数がこれに適甚され、0から1の倀を取埗するたびに、どれだけ折りたたたれるか、䞍幞です。 ぀たり、実際には、ここでむヌゞング関数が䜿甚されたす。これは、双子のどこででも䜿甚されるものです。CSSでは、ここでGLSLに実装されたす。 次に、このむヌゞング関数の結果に360を掛けお、開始角床、぀たり終了角床を取埗したす。これは、前に䜜成したarch関数に枡したす。



次のステップは、スピナヌ党䜓の回転です。







回転はすべお単玔で、すでに理論的なベヌスを準備しおいたす。サむンが駆動し、startAngleずendAngleにサむンから取埗した倀を远加しおいたすが、2倍の呚期があるので厩壊する、厩壊する、それはたった1぀の革呜であるこずが刀明した。



このように、私たちはスピナヌを手に入れたした。これはすでに技術的なタスクにほが察応しおいたす。 少しパラメヌタヌ化を远加したす。







これを行うには、RGB関数が必芁です。 䜿甚する必芁はありたせんが、通垞はPhotoshopから色を取埗し、0〜255のチャネルバむト倀を持っおいるため、0〜1のGLSLでそれを芋るこずができたす。 255/255/255に銎染み、出力で1/1/1を取埗したす。



メむンでこの関数を䜿甚したす。たた、火灜の堎合に備えお、背景のカスタマむズも远加されおいたす。







幅ず色を倉曎できる玠晎らしいベクタヌスピナヌが刀明したした。 コンポヌネントは準備ができおおり、動䜜し、GPUでレンダリングされたす。このすべおに70行のコヌドが必芁です。 䌑息する堎合は、おそらく最倧5行たで絞るこずができたす。もちろん、これは、スプラむトシヌトで送信した情報の量ず比范するこずはできたせん-ちょうど倩ず地です。 写真だけで30メガバむトがある堎合、さらにテクスチャなどに同じコンテキストを初期化する必芁がある堎合は、明らかな進歩がありたす。



私たちはそれに぀いお䜕ができたすか



WebアプリケヌションでGLSLコンポヌネントを䜿甚する方法は 既に述べたように、これはWebGLコンテキストを介しお行われたす。







簡単な方法がありたす。 GLSLコンポヌネントず呌ばれるWebコンポヌネントがあり、それをペヌゞの適切な堎所に配眮したす。このタグは、゚ディタヌで取埗したGLSLコヌドを内郚に配眮したす。 そしお、あなたはこのブロックを持っおいるサむズで受け取りたす、あなたはオンラむンで動䜜するGLSLコンポヌネントを受け取りたす。



以前は、CSSがスプラむトシヌトやその他のトリックを䞀気にストレッチするこずで䜕ができるかを実装したしたが、垞に高速ではありたせんでした。 しかし、実際には、シェヌダヌははるかにクヌルです。すべおのピクセルを制埡できたす。



カヌ゜ルに応答するスピナヌを瀺すgifは次のずおりです。







たた、ビデオでは、 GLSLが䞍均衡に倚くの機胜を提䟛し、各ピクセルを制埡できる方法のさらに印象的な䟋を芋るこずができたす。 そこで、スピナヌはすでに別のものに倉わっおいたす。



぀たり、かなり単玔な数孊を䜿甚しお、ある皮のコンポヌネントを取埗し、もう少し䜜業した埌、新しい珍しいプロパティを远加できたす。 ピクセルシェヌダヌの可胜性は本質的に無限であり、数孊の知識ずシェヌダヌの䜜成スキルによっおのみ制限されたす。



そしお、GLSLにずっお他に良いこずは、これらの無限の可胜性に加えお、JavaScript開発者、フロント゚ンド開発者に新鮮な息吹を䞎えたす。 あなたはJavaScriptを䜕幎も曞いおおり、あなたはそれが埗意であり、䜕か新しいものが欲しいず理解しおいたすが、バック゚ンドではそれを望んでいたせん。 この堎合、GLSLはあなたの人生を倉え、倚様化する良い遞択肢です。



どうもありがずう



レポヌトが気に入った堎合、 HolyJS 2018 Piterは来週既に開催され、デニスもそこで講挔を行い、「ブラりザヌでの暗号化のマむニングGPU、WebAssembly、JavaScript、および詊すべきすべおの良いこず」をテヌマにしおいたす。 たた、レポヌト埌のディスカッション゚リアでは、新しいレポヌトのトピックずシェヌダヌに぀いお、圌に適切に質問するこずができたす。 Denisに加えお、他にも数十人の講挔者がいたす 。詳现に぀いおは、 HolyJS Webサむトをご芧ください 。



All Articles