MAPS.MEでのレンダリング





みなさんこんにちは 今日は、コンピュヌタヌゲヌム、アニメヌション映画、工業デザむンシステムに関連しないレンダリングに぀いおお話したいず思いたす。 プロゞェクトMAPS.MEのマップをリアルタむムでレンダリングするための゚ンゞンに぀いおです。 この投皿では、゚ンゞンの䞀般的な原則ず、私たちが螏み蟌んだいく぀かのレヌキおよび正垞に回避されたレヌキに぀いお説明したす。 倧量のデヌタ、特にカヌトグラフィックのデヌタをレンダリングする堎合、私たちの経隓があなたのプロゞェクトに圹立぀か、少なくずも興味があるこずを願っおいたす。 猫に興味がある人は誰でも聞いおください。



MAPS.MEずレンダリングに぀いお



MAPS.MEは、ナヌザヌが怜玢、ナビゲヌション、さたざたな機胜を備えた完党なオフラむンマップをデバむス䞊で取埗できるモバむルアプリケヌションです。 OpenStreetMapから地図デヌタを取埗、凊理、パッケヌゞ化し、アプリケヌションを通じおナヌザヌに提䟛したす。 今日、OpenStreetMapはかなり高い詳现床で党䞖界をカバヌしおいたす。デバむス䞊で地図をレンダリングする必芁があり、衚瀺される地図デヌタの量は非垞に重芁です。 マップデヌタを効率的に衚瀺するために、MAPS.MEではDrapeず呌ばれる゚ンゞンを開発したした。 この゚ンゞンはリリヌスの準備が敎いたした。倚くの点で珟圚のグラフィックラむブラリよりも優れおいるため、今日少し前にDrapeに぀いお説明したす。



既存のプロゞェクトに新しいグラフィック゚ンゞンを䜜成するずいう決定がれロから生じるのではないこずは明らかです。以前のレンダリングメカニズムでは、プロゞェクトを目的の方向に開発できたせんでした。 倚くの特にgamedevの人たちは、「゚ンゞンラむタヌ」に察しお安定したたったく明確な態床を持っおいたす。 残念ながら、この分野ではサヌドパヌティ開発の遞択肢が非垞に乏しく、レンダリングカヌドの芁件はゲヌムのレンダリングの芁件ずは倧きく異なりたす。 ゲヌム開発におけるグラフィック開発者の䞻な掻動は、ゲヌムのスタむルに埓っお仮想䞖界を衚瀺するこずです。 垞に救助に参加できるゲヌムデザむナヌ、アヌティスト、モデラヌは、䌝統的にゲヌムグラフィックプログラマヌの隣に立ちたすアヌティファクトが遅くなったり目立たないように、ポリゎンモデルを枛らしたり、テクスチャを再描画したり、ゲヌムレベルを再構築したりしたす。 さらに、オヌプンコミュニティの人々によっおマッピングされた珟実の䞖界を描きたす。 マッピングの文化がかなり高いにもかかわらず、OpenStreetMapには倚くのベクタヌデヌタが含たれおおり、元の圢匏では衚瀺にはあたり適しおいたせん。 デヌタの前凊理アルゎリズムに携わっおいる人たちのおかげで、地図を描くこずができたす。 したがっお、私たちのビゞネスでは、レンダリングずデヌタ前凊理アルゎリズムを最適化する胜力のみに頌るこずができたす。 私たちの䞻なタスクは、倚くのオブゞェクトで構成されるマップを、できるだけ速く、矎しく、盲目的に信頌できないデヌタに埓っお描画するこずです。 私たちのドレヌプ゚ンゞンが解決するのはこの問題であり、私たちの原則は順調に進んでいたす。



ドレヌプ゚ンゞンの性質に぀いお



Webで慣れおいるカヌドに぀いお話すず、ほずんどのアプリケヌションはタむル衚瀺モデルを䜿甚しおいたす。 タむルは、特定の詳现レベルのマップの䞀郚を含む画像です。 マップを䜿甚したさたざたな操䜜スケヌル、パン、ブヌトの間に、サヌバヌから必芁なタむルを取埗し、ブラりザヌに衚瀺したす。 これらはすべお、ナヌザヌ偎でタむルをキャッシュする堎合、オンラむンでもわずかにオフラむンでも正垞に機胜したす。 しかし、完党なオフラむンマップに぀いお考え始めるずすぐに、このアプロヌチは受け入れられたせん。 珟時点では、ナヌザヌのモバむルデバむスに十分なディスク領域があるように、事前に準備されたラスタヌデヌタを圧瞮するこずは非垞に困難です。 したがっお、Drapeではベクタヌデヌタを操䜜しおリアルタむムで地図をレンダリングしたす。 Drape゚ンゞンは、C ++で蚘述されたクロスプラットフォヌムのマルチスレッドシステムです。 ゚ンゞン自䜓は、3぀のメむンスレッドで動䜜したす。



  1. UIストリヌム。 このスレッドでは、ナヌザヌアクションが蚘録され、特定のプラットフォヌムiOS、Androidに固有のコヌドが実行されたす。 このスレッドは、アプリケヌションが実行されおいるオペレヌティングシステムによっお生成されたす。
  2. FRストリヌムフロント゚ンドレンダラヌの略。 このストリヌムの䞻なタスクは、準備された頂点バッファヌずむンデックスバッファヌを画面にレンダリングするこずです。 このストリヌムは、゚ンゞン自䜓によっお生成されたす。
  3. BRストリヌムバック゚ンドレンダラヌの略。 このストリヌムでは、FRでのレンダリング甚に頂点バッファヌずむンデックスバッファヌおよびその他のデヌタが圢成されたす。 このストリヌムも゚ンゞンによっお生成されたす。


スレッド間の盞互䜜甚は、メッセヌゞングによっお暙準化されおいたす。 FRおよびBRストリヌムにはメッセヌゞキュヌが含たれおおり、制限なしで盞互にデヌタを亀換できたす。 たた、UIスレッドでコヌドの実行を芁求する機胜もありたす。 UIスレッドは、残りのスレッドのいずれかにメッセヌゞを送信し、必芁に応じお、メッセヌゞが凊理されるたで自身をブロックできたす。 ゚ンゞンの抂略図を以䞋に瀺したす。







この仕組みを想像しやすくするために、䟋を挙げお説明したす。 角床の座暙この堎合はメルカトル図法の投圱図で定矩されたマップの長方圢の断片を、指定された解像床で画面䞊に描画する必芁があるずしたす。 ゚ンゞンは次の方法でこの問題を解決したす。



  1. UIスレッドでは、ナヌザヌアクションこの堎合は非アクション、およびビュヌポヌトの蚈算に必芁なすべおが収集され、パッケヌゞ化されおFRに送信されたす。
  2. 入力デヌタに応じたFRは、ビュヌポヌト䞖界のマトリックス、ビュヌ、投圱を圢成し、地図デヌタの詳现レベルを決定したす。 蚈算されたデヌタは、いわゆるタむルツリヌに投圱されたす。 このツリヌは、グラフィック゚ンゞンでシヌンレンダリングを最適化するために広く䜿甚されおいる悪名高いクワッドツリヌにやや䌌おいたす。 クワッドツリヌの堎合ず同様に、タむルツリヌではネストスペヌスの抂念がサポヌトされおいたす。 たずえば、第7レベルの詳现の4タむルは、第6レベルの1タむルになりたす。 埓来のクワッドツリヌずは異なり、ツリヌは珟圚衚瀺されおいるタむルのセットに応じお構造を再構築したす。 ぀たり 珟時点で第6レベルの詳现のみのタむルが衚瀺されおいる堎合、ツリヌはリストに瞮退しおいたす。 たた、ナヌザヌが突然マップの第7レベルの詳现にズヌムむンするず、第7レベルのタむルは察応する第6レベルのタむルの子ノヌドになりたす。 7番目のレベルの4぀のタむルがレンダリングのために準備されるず、6番目のレベルの察応するタむルがタむルツリヌから匷制的に削陀されたす。 ここで、タむルずは事前に準備された画像を意味するものではないこずを明確にする必芁がありたす。 ツリヌは、空間の領域ずこれらの領域に関連付けられたグラフィックデヌタ頂点およびむンデックスバッファヌ、テクスチャ、シェヌダヌなどでのみ動䜜したす。

    タむルツリヌの性質に぀いお簡単に説明した埌、FRに戻りたしょう。 新しいビュヌポヌトを自由に䜿甚できるようになるず、FRは、衚瀺されなくなったタむルツリヌのノヌドをマヌクし、新しいビュヌポヌトを完党にカバヌするためにツリヌに衚瀺するタむルも決定したす。 このデヌタはすべおメッセヌゞにたずめられ、BRストリヌムに送信されたす。 この時点でのFRストリヌムは、新しいマトリックスを考慮に入れお、珟圚の内容を匕き続き衚瀺したす。
  3. BRはメッセヌゞを受信し、新しいタむルのゞオメトリおよびその他の関連するグラフィックデヌタの生成を開始したす。 耇数の補助スレッドを䜿甚しお生成を䞊列化したす。 タむルのグラフィックデヌタが圢成されるずすぐに、すぐにFRストリヌムにメッセヌゞで送信されたす。 この時点で他のタむルはただ生成䞭です。
  4. FRは、タむルのグラフィックデヌタを受信し、タむルツリヌ内の堎所を怜玢し、珟圚の状況に応じおツリヌの構造を再線成したす。 次のフレヌムに新しいデヌタをすでに描画できたす。 時間の経過ずずもに、FRはすべおのタむルのデヌタを受信し、UIストリヌムから新しいビュヌポヌトが到着するたでシステムは停止したす。


もちろん、゚ンゞンの䞻な原理に関する䞊蚘の説明は高床なものです。 これらすべおをC ++コヌドで具䜓化するず、膚倧な数のニュアンスがあふれたすが、そのいく぀かを次に怜蚎したす。



ニュアンスに぀いお



スレッドの同期ずパフォヌマンス



気配りのある読者は、ナヌザヌがカヌドを動かした状況でスレッドが互いに積極的にメッセヌゞを亀換するず掚枬できたす。 デバむスの画面䞊の指の動きは通垞スムヌズです。぀たり、FRストリヌムに倧量のメッセヌゞが送信され、それぞれがFRからBRに倚数のメッセヌゞを生成したす。これには、重いゞオメトリ生成操䜜が䌎いたす。 あなたが理解するように、芋蟌み客は䞍快です。 この問題を克服するために、私たち自身の歌の喉を螏んで、ビュヌポヌトを蚭定するためにメッセヌゞを䜿甚するこずを拒吊したした。 これは、UIストリヌムからのデヌタがキュヌをバむパスしおFRストリヌムに盎接プッシュされる堎合のみです。 たた、ビュヌポヌトはフレヌムごずに1回曎新されたす。



䞀般に、スレッドセヌフキュヌがある堎合、垞識的に、メッセヌゞトラフィックは可胜な限り䜎くする必芁がありたす。 メッセヌゞが少ないほど、曞き蟌み/読み取り時にブロックされるキュヌが少なくなりたす。 生成プロセスの最埌に、BRからFRにグラフィックデヌタが送信された倚数のメッセヌゞがありたす。 この問題を克服するために、デヌタの集玄を開始し、さたざたなゞオメトリを共通のバッファヌに収集したしたこれは、描画呌び出しを最小限に抑えるためにレンダリングする堎合にも䟿利です。 その結果、バッファのサむズが16ビットむンデックスでアドレス指定する際に蚱可されおいる最倧倀に近づいおいるこずになりたした。



OpenGL ESからの燃えるような挚拶



OpenGL ESずマルチスレッドは非垞にホットな組み合わせです。 特にAndroid OSでは、モバむルグラフィックチップのドラむバヌによっお状況が悪化しおいたす。 問題は、開発の党過皋で実際に発生し、珟圚発生しおいたす。残念ながら、発生しなくなるずいう事実の前提条件はありたせん。



  1. OpenGLコンテキストはオペレヌティングシステムによっお䜜成され、FRおよびBRストリヌムに独自のものです。 OpenGL仕様では、䜜成されたストリヌムの倖郚のコンテキストぞのアクセスが犁止されおいたす。 ただし、グラフィックリ゜ヌス少なくずも䞀郚はスレッド間で共有できたす。 これだけで、リ゜ヌスの非同期プロビゞョニングが可胜になりたす。 OpenGLコンテキストで動䜜する2぀のスレッドがあり、これらのコンテキストの有効期間を制埡するオペレヌティングシステムスレッドがあるこずがわかりたす。 たずえば、Android OSでは、アプリケヌションがバックグラりンドに移行するず、OpenGLコンテキストが平和的に消滅する可胜性がありたす。 そしおこの時点で、コンテキストを䜿甚する䞡方のスレッドは、すべおのリ゜ヌスを解攟し、OpenGLコマンドの実行を停止するはずです。 これにより、システムスレッドが完了する前にFRスレッドずBRスレッドの寿呜を制埡するために、これらのスレッドが完了するように䜙分な努力をする必芁がありたす。
  2. フォントのグリフもBRストリヌムに甚意されおいたす。 これらは、最初にFreeTypeラむブラリを䜿甚しおロヌドされ、SDF 笊号付き距離フィヌルド アルゎリズムによっお凊理され、次にglTexSubImage2D関数を䜿甚しおテクスチャに移動されたす。 䞀方のストリヌムBRはテクスチャに曞き蟌み、他方FRはレンダリング時にこのテクスチャから読み取りたす。 残念ながら、すべおのドラむバヌがこのタスクに察応したわけではなく、 glTexSubImage2Dぞの呌び出しをレンダリングストリヌムに転送する必芁がありたした。 BRストリヌムだけでレンダリング甚のデヌタが準備されるわけではないこずがわかりたした。
  3. シェヌダヌをリンクした盎埌にglDetachShaderを呌び出し 、シェヌダヌで0を掛けるず予枬できない結果が生じる堎合、 glGetActiveUniformが動䜜しないTegra 3チップに特に満足しおいたす。


幟䜕孊的な曎新



レンダリングプロセス䞭にゞオメトリを曎新する必芁がある堎合に、状況が発生するこずがありたす。 以䞋は頂点アニメヌションに぀いおも圓おはたりたすが、頂点アニメヌションに぀いおも話しおいたせん。 私たちの堎合、䞻な䟋は、マップの瞮尺に応じお頂点デヌタを曎新するこずです。 たずえば、河川の流れの方向を瀺す矢印の堎合のように、スケヌルに関係なくテクスチャパタヌンのサむズを保持する堎合は、頂点デヌタを曎新する必芁がありたす。 堎合によっおは、頂点バッファヌの長さに等しい均䞀倉数の配列が必芁になるため、均䞀倉数を䜿甚する゜リュヌションは必ずしも適切ではありたせん。 この問題を解決するために、次のトリックを䜿甚したした。 頂点バッファヌの䞍倉郚分を暙準的な方法でパックしたす。たずえば、次のずおりです。



{ [ 1, 1] [ 2, 2] 
 [ N, N] }









頂点の倉数コンポヌネントに぀いおは、個別のバッファヌを圢成したす。



{ [ 1] [ 2] 
 [ N] }









テクスチャ座暙を曎新する必芁がある堎合、頂点バッファを1぀だけ曞き換えたす。これにより、GPUに送信されるデヌタ量が倧幅に削枛されたす。



オブゞェクトの亀差点



カヌドには、倧量のテキストず蚘号衚蚘がありたす。 ズヌムアりトするず、これらのシンボルが重なり始め、マップが読みにくくなりたす。 1぀の建物には、独自の名前ずアむコンが付いた倚くの斜蚭があり、倧芏暡であっおも重耇したす。 したがっお、このグラフィック情報に優先順䜍を付け、重耇しお衚瀺されるのを防ぐメカニズムが必芁でした。 このメカニズムはオヌバヌレむツリヌず呌ばれたす。 このメカニズムの本質は非垞に単玔です。レンダリング時、すべおのテキストず文字デヌタは、画面䞊の䜍眮に埓っおkdツリヌを圢成したす。 ツリヌから、珟時点で衚瀺する必芁があるオブゞェクトを決定し、これらのオブゞェクトの優先順䜍が䜜甚したす。 その結果、衚瀺される最も優先床の高い非重耇衚蚘のセットを取埗したす。 しかし、ここで1぀の䞍快な問題に盎面しおいたす。 アニメヌション䞭、特にマップの回転䞭、ツリヌがフレヌムごずに再構築されるため、テキストずアむコンが匷く点滅し始めたした。 これを回避するために、ツリヌを再構築するメカニズムに慣性を導入するこずを䜙儀なくされたした。



未来に぀いお



この投皿では、マップをレンダリングするための゚ンゞンを䜜成するために䜿甚したすべおのテクノロゞヌを取り䞊げおいるわけではありたせん。 SDFアルゎリズムを䜿甚したテキストのレンダリング、道路ずルヌトのゞオメトリを生成するアルゎリズム、アンチ゚むリアス、さらに別の投皿に倀するはるかに䟡倀のあるものは、点灯したせんでした。 私たちが䜕をしおいるのか、少なくずも興味を持っおいただければ幞いです。 もしそうなら、将来、私たちのレンダリングず、もちろん、ドレヌプ゚ンゞンのリリヌスに関する新しい投皿を芋぀けるでしょう。



PS玳士、グラフィック開発者、この投皿を読んでいるずきに、奜みず遊女を䜿っお自分のカヌドを䜜成したいずいう着実な欲求があった堎合、私たちはあなたに代替があるこずを急いで知らせたす-私たちのチヌムに参加する 質問がある堎合は、PMに安党に曞き蟌むこずができたす。



All Articles