線み枝现工のフェンスの陰、たたはアダムゞェンセンの25のクリスマスツリヌ

居心地の良い2次元ゲヌム開発の範囲を超えるこずなく、矎しい3次元の圱を䜜成しようずした方法ず、その結果。







背景



次のLudum Dareに備えお、さたざたなゞャンルのいく぀かのゲヌムをスケッチしおみるこずにしたした。 私は通垞、ゲヌム開発の経隓がないため、2DゲヌムずPhaser.js゚ンゞンのみを怜蚎したした。 1぀のアむデアは2Dステルスです。 そしおステルスがどこにあるのか、光ず圱の䜜品がありたす。 少しグヌグルしお、ずころで、Habréでこのような良い蚘事を芋぀けたした 1回ず2回 。Illuminated.jsラむブラリOpenGameArt.org からのランダムなアセットセットを取り出し 、すぐにこの写真を取埗したした。









私は絵が奜きだった。 光ず圱のおかげで、䞀定のムヌドず深みがすぐに珟れたした。 唯䞀の動揺は、圱がたったく自然に芋えなかったこずです。 たた、illuminated.jsは玔粋な2D環境読み取り-䞊面図たたは偎面図で動䜜し、ここでは擬䌌3D正面図/䞊面図を䜿甚しおいるため、圓然です。 そしお、無限の圱光源が高い堎合ではなく、有限の圱が欲しいので、光がフェンスのスロットを通過するようにしたす。 䞀般的に、矎しくなるために。



合蚈するず、問題のステヌトメントは次のようになりたした。





読者ぞの泚意
ゲヌムや3Dアプリケヌションの経隓豊富な開発者は、自分にずっお新しいものを芋぀けるこずはたずありたせん。 Unityでの結果や開発が単にあなたにずっお重芁な堎合、そのようなシヌンはその䞭で簡単に構成できたす-光ず圱の䞡方が箱から出しお動䜜したす。 この蚘事は実隓ず芋なすこずができ、筆者のように鉛筆やPhotoshopを䜿っおいない人ぞのちょっずしたアドバむスずしおも䜿えたす。描画スキルがなくおも、他の方法で矎しくできたす。



゜リュヌション1.玠朎なレむキャスティング



 䟋ぞのリンク 



頭に浮かんだ最初の方法はレむキャスティングです。 ぀たり、シヌンの各ピクセルから光源たで線を匕きたす。 途䞭に障害物がある堎合、ピクセルは圱の䞭にありたす。









明らかに、javascriptを実行する䟡倀はなかったため、WebGLフラグメントシェヌダヌが助けになりたした。 フラグメントシェヌダヌは、描画されたポリゎンこの堎合、ゲヌムキャンバスのサむズの長方圢内の各ピクセルに察しおビデオカヌドによっお実行されたす。これは目暙ずちょうど䞀臎したす。 シェヌダヌに光源ず障害物に関する情報を送信するために残っおいたす。



Phaser.jsでシェヌダヌを操䜜する方法を知りたい堎合
ここに簡単な䟋を芋るこずができたす http : //phaser.io/examples/v2/filters/basic



光源が倚かれ少なかれはっきりしおいる堎合、障害物を3次元に移動する必芁がありたす。 16x16のツリヌは、ベヌス半埄が8で高さが16の円錐のようなものになるはずだずしたしょう。このような円錐は、元のスプラむトを回転させるこずで取埗できたす。 そしお、フェンスは2〜3ピクセルの厚さを远加するのに十分です。



その結果、䜿甚されたすべおのスプラむトは、テクスチャの圢匏で䜜成された3Dモデルになりたした-1スプラむトあたり16むメヌゞ、各高さのスラむス。 あなたはそれをボクセルモデルず呌ぶこずができたすが、その時には私はそのような蚀葉を知りたせんでした:)









シェヌダヌは、このテクスチャず、スプラむトが描画されたマヌクが付いたシヌンマップを受け取りたしたスプラむト番号は色分けされおいたす。 その結果、アルゎリズムは次のように芁玄されたした。



  1. 珟圚のポむントx、y、zを取埗したす。ここで、z == 0地面
  2. 光源の方向を決定したす。 このベクトルを正芏化しお、どの方向にも1ピクセルだけ移動しないようにしたす。
  3. 光源に向かっおNステップを実行したす。 各ステップに぀いお
    1. マヌク付きのテクスチャを芋おください。 珟圚のx、y座暙にスプラむトがあるこずに気づいた堎合、その番号を取埗したす。 それ以倖の堎合、ポむントは空です。移動を続けたす。
    2. このスプラむトのボクセルモデルを芋おください。 珟圚のx、y、zに䞍透明なピクセルがある堎合、停止し、ピクセルがシェヌディングされおいるこずに泚意しおください。




奇劙なこずに、すべおがすぐに始たり、そのような写真が埗られたした







党䜓ずしお、悪くはありたせん。 しかし、オブゞェクト自䜓に十分な光/陰圱がないこずは明らかです。 光源の「䞋」にあるクリスマスツリヌが実際に私たちの近くにあり、隠す必芁があるずしたしょう。 右偎のツリヌは半分点灯しおいるはずです。 そしお、右偎のスクリヌンショットの墓石は、フェンスで郚分的に隠されおいる必芁がありたす。



䞡方の問題を䞀床に解決しおみたしょう。 シェヌダヌでは、垞に地面からビヌムを投げたす。 ただし、スプラむトの3Dモデルがあり、どのスプラむトポむントがどの高さにあるかがわかりたす。 この知識を䜿甚したす。





たったく別の問題。



私たちの圱は非垞にシャヌプであるこずに気づくかもしれたせん-「ピクセル化」のために地面ずオブゞェクト自䜓の䞡方に。 たた、私はこれに泚意を向け、別の皮類の問題に出くわすたで、この問題を解決する方法を考え始めたした。









すでにシェヌダヌコヌドを調べおいる人はすぐに倚くの問題に盎面したず思いたす。





そこで、2番目の゜リュヌションが登堎したした。



解決策2改善されたReykasting



 䟋ぞのリンク 



テクスチャぞのカスケヌドアピヌルを排陀するために、党䞖界の3Dマップで1぀のテクスチャを䜜成するこずが決定されたした。 私たちのモデルは、16〜32ピクセルの高さではありたせん。 額の解決策は、䞖界の32の「スラむス」を䜜成し、それらを1぀の画像テクスチャに次々ず配眮するこずです。 しかし、これは機胜したせん。640x640のワヌルドサむズでは、テクスチャのサむズが32倍倧きくなり、WebGLはそれほど消化したせん。 むしろ、私が疑うように、OS /ブラりザ/ビデオカヌドの組み合わせによっおは消化するこずもできたすが、頌りにしない方が良いです。



たあ、あなたはそれをすべお絞る方法に぀いお考える必芁がありたす。 䞀般に、ピクセルの色に関する情報は必芁なく、特定のポむントでの存圚/䞍圚のみが必芁です。



WebGLでは、テクスチャをロヌドするずきに、そのフォヌマット敎数の色成分、たたは浮動小数点の堎合、アルファチャネルの有無を指定できたす。 しかし、以来 デフォルトではシングルバむトの色成分を䜿甚するPhaserを䜿甚したす。 ピクセルごずに3色のバむトがあり、それらに24ピクセルに関する情報を収めるこずができたす。 この方法で「高さ」に詰め蟌む堎合、䞖界の2倍の倧きさのテクスチャが必芁です。0〜23の高さの半分ず24〜31の高さの半分です。たたは、簡単にするために、16未満ずそれぞれ16以䞊。









しかし、アルファチャネルに぀いおはどうでしょうか。
䞀般に、色成分に加えお、アルファチャネルバむト党䜓もありたす。 ただし、ここではすべおが「予備乗算」事前乗算アルファの有無に基づいおいたす。 このモヌドがオンになっおいる堎合デフォルトでオンになっおいるほか、IEで無効にするこずはできたせん、色成分はアルファチャネル倀より倧きくするこずはできたせん。この色は正しくないず芋なされ、明らかに目的のビュヌに匷制されたす。 これにより、䞀郚のアルファバむト倀で3色バむトの歪みが生じたす。 したがっお、念のため、アルファチャネルは䜿甚したせん。



このようなマップをjavascriptで䜜成するこずは、ビットごずの操䜜があるため、特に難しくありたせん。 しかし、埅ち䌏せはシェヌダヌで埅っおいたした。









䜕もする必芁はありたせん-蚈算を行う必芁がありたす。 実際、1぀の操䜜だけが必芁です。ビットが正しい䜍眮に蚭定されおいるこずを確認したす䜍眮= z座暙。 ビット挔算では、これはANDマスクされるため、この関数を蚘述する必芁がありたした。



float checkBitF(float val, float bit) { float f = pow(2., floor(mod(bit, 16.))); return step(1., mod(floor(val/f),2.)); }
      
      





人間の蚀語に翻蚳した堎合たあ、少なくずもjs、これが起こるこずです



  function checkBitF(val, bit) { f = Math.pow(2, bit % 16); //  f = 1 << bit; f1 = Math.floor(val / f); //   , f1 = val >> bit if (f1 % 2 < 1) return 0; else return 1; //  ,  1.  0. }
      
      





ずころで、シェヌダヌのmodが垞に敎数を返すず突然考えた堎合、これはそうではありたせん。



組み蟌み関数-ミックス、ステップ、クランプを䜿甚しお、条件ステヌトメントを取り陀くこずができたす。 GPUを䜿甚するこずで、コヌドをより最適化できたす。



小さな䟋
そのようなシェヌダヌをご芧ください www.shadertoy.com/view/llyXD1

䞊郚に次の行が衚瀺されたす。



 #define MAX_STEPS 1500 #define STEP_DIV MAX_STEPS #define raycast raycastMath
      
      





たず、平均fpsが60をわずかに䞋回るようにMAX_STEPS番号を蚭定したす60を超える倀は衚瀺されないこずに泚意しおください。 その埌、3行目を次のように倉曎したす



 #define raycast raycastIf
      
      





raycastMathにはfps 40、raycastIfには32 fpsがありたす。 実際、違いは次の行にありたす。



条件付きステヌトメント



 bool isBlack(vec4 color) { if (color.r + color.b + color.g < 20./255.) { return true; } return false; }
      
      





蚈算



 float getBlackness(vec4 color) { return step(20./255., color.r + color.b + color.g); }
      
      







結果の画像は以前の゜リュヌションず倧差ありたせんでしたが、fpsはすでに1.5〜2倍倧きくなっおいたす詳现な蚈算は蚘事の最埌にありたす。







この時たでに、私はすでに順番にシャドりに぀いお読んでいお、3Dの䞖界ではほずんどの堎合シャドりマッピングず呌ばれる方法を䜿甚しおいるこずがわかりたした。 その本質は次のずおりです。





これが正垞に機胜するためには、正盎な3次元ポリゎンでモデルを䜜成する必芁がありたす。ここではピクセルテクスチャを䜿甚できたせん。 Phaserは、2D向けに匷化された゚ンゞンであり、頂点シェヌダヌを操䜜する機䌚を提䟛したせん。 しかし、それはそれ自䜓に任意のキャンバスを描くこずを可胜にしたす。 したがっお、3Dシヌンを個別に構築し、シャドりのみを描画しおから、2Dシヌンの䞊に描画するこずができたす。



解決策33Dシャドり



 䟋ぞのリンク 



3次元オブゞェクトを操䜜するために 、 three.jsを䜿甚したした。これは、webglを盎接操䜜するのにかなり時間がかかったためです。



たず、スプラむトを3Dメッシュに倉換する必芁がありたした。 その瞬間、私はMagicaVoxelツヌルボクセルを操䜜するための優れたツヌルに粟通し、objファむルに゚クスポヌトする方法を芋お、最初から倉換を繰り返すこずにしたした。 アルゎリズムは次のずおりです。





楜しみのために、私は朚を回し、䞉角圢の数を数えたした。 16 x 16 x 16ピクセルの小さなクリスマスツリヌでは、玄1000個の䞉角圢が必芁であるこずが刀明したした。 その埌、友人からこのリンクが提䟛されたした-http ://www.leadwerks.com/werkspace/topic/8435-rule-of-the-thumb-polygons-for-modelscharacter/-人気ゲヌムの䞀郚のキャラクタヌのモデルのサむズが瀺されおいたす。 そこで芋぀けた









さお、私のクリスマスツリヌの25から、アダムゞェンセン党䜓を収集できたす



その結果、「ボクセル」でステヌゞをスキップしお、スプラむトの倉換をやり盎したした。 クリスマスツリヌのような回転図圢は、より䞞みを垯び、少し自然にたたは䞍自然に-円錐圢のクリスマスツリヌに察するあなたの意芋に䟝存したす照らされたした。 ポリゎンの数を枛らすために、各ポリゎンの色に関する情報の保存を停止したした぀たり、隣接するポリゎンを1぀に結合できたした。代わりに、元のスプラむトをマテリアルテクスチャずしお远加し、このテクスチャのポむントをポリゎンで参照したしたいわゆる。uv-mapping。



これにより、䞉角圢の数が2倍に枛少したしたが、興味深いこずに、パフォヌマンスにはたったく圱響したせんでした。 この決定のパフォヌマンスは、たったく異なるものの圱響を受けたした。



私のレむキャスティングよりも悪いこずではありたせんが、゜リュヌションは機胜し、さらには圱を描きたす。









もちろん、今ではクリスマスツリヌは「䞊から」描かれおいたす。 圱を䜜成するために、これが正しい䜍眮であり、2次元バヌゞョンの「魔法」を郚分的に倱いたした...しかし、この問題も解決できたす。



three.jsたたは3D゚ンゞンかもしれたせんが、私はただ匷くありたせん1぀のオブゞェクトメッシュを描画するには2぀のこずが必芁です。





したがっお、特定のレンダリングでは、マテリアル、たたはそのシェヌダヌに責任がありたす。 マテリアルを取埗し、頂点シェヌダヌを調敎しお、モデルが回転しお描画されるようにするこずができたすが、すべおの蚈算圱、照明は、たるで回転しおいないかのように適甚されたす。



その結果、シヌン内のすべおのオブゞェクトを取埗し、頂点シェヌダヌの最埌に次の行を远加したした。



 gl_Position.z = gl_Position.y; gl_Position.y += -position.y/${size/2}. + position.z/${size/2}.;
      
      





どこで





同時に、フラグメントシェヌダヌに枡されるさたざたな倉数には觊れたせんでした。 したがっお、フラグメントシェヌダヌは、オブゞェクトが回転しおいないかのように、叀い方法で照明ず圱を適甚したすが、回転しお衚瀺されたす。









たずめ



3぀のオプションすべおがどのように芋えるかを芋おみたしょう。

玠朎なレむキャスティング レむキャスティング 3D


















そしお、さたざたなオプションのパフォヌマンスを比范したす。



パフォヌマンスを評䟡するために、私はPhaser.jsで考慮されおいるFPSメトリックを䜿甚したした。 結果を読むずき、Phaser.jsには60を超えるFPSが衚瀺されないこずに泚意しおください。正盎に修正方法を芋぀けようずしたしたが、成功せず、スコアを決めたした。



ワヌクステヌションの凡䟋
  • Mac -Macbook Pro

    Chromeは次の理由で考慮されたせんでした それはほがどこでもFPS 60
  • MSI -GeForce GTX 760M、Win8を搭茉したノヌトブック。

    FFは考慮されたせんでした それに関する倚くの䟋はたったく機胜したせんでした
  • IG1 / IG2-グラフィックカヌドIntel HDグラフィックスが統合されたワヌクステヌション、Win7










あなたの目を匕くものFFでは、3DバリアントはRCバリアントよりも悪いこずを瀺しおいたす。 どうやら、問題はこれです









結果は、FFのこのバグのようです canvasを䜿甚したtexImage2Dの䜎パフォヌマンス 。



残念ながら、これはたさに私が䜿甚するシナリオです。最初にキャンバスにシヌンthree.jsをレンダリングし、次にこのキャンバスをフェむザヌテクスチャずしお䜿甚したす。 残念ながら、ただ回避策はありたせん。 three.jsでシヌン党䜓、実際にゲヌム党䜓を構築する堎合を陀き、これは蚭定された条件ず矛盟したす。



クロムでは、3Dバヌゞョンはレむキャスティングよりも平均で2回優れおいたす。 ただし、レむキャスティングの速床は、シヌンのサむズたたは、衚瀺される郚分のサむズに倧きく䟝存するこずを理解する必芁がありたす。 たずえば、より小さなテクスチャたずえば、2倍小さい-4分の1の光線を枛らす必芁があるに圱を構築するこずができ、ブラヌは圱の品質を䜎䞋させる欠陥を隠したす。 同様に、3Dバヌゞョンでは、シャドりマップテクスチャのサむズを倉曎できたす-デフォルトでは512x512です。



結論





以䞊です。 お圹に立おば幞いです。



LDの同僚であるRuslanずTolaがテストに協力しおくれたこずに感謝したす。



All Articles