Graveyard Keeperの内部:グラフィックエフェクトの実装方法

みなさんこんにちは! 全体の4年間、私はHabrで書いていません。 最後の一連の投稿は、前回のゲームで使用したさまざまなツールとテクニックに関するものでした(Unityで開発中)。 それ以来、ゲームのリリースに成功し、新しいゲームもリリースしました。 だから今、あなたは少し息を吐き、誰かに役立つかもしれないいくつかの新しい記事を書くことができます。









今日は、上記のGIFに表示される画像を作成するために使用したグラフィックトリックとトリックについてお話したいと思います。



私たちはゲームのビジュアルに非常に敏感であるため、ピクセルアートを可能な限り魅力的にするさまざまなエフェクトやその他のパンにかなりの時間と労力を費やしました。 おそらく誰かが自分自身に役立つ何かを見つけるでしょう。



そもそも、私たちのゲームでどのような写真になるかを簡単にリストします。



  1. 可変周囲光-時刻に応じた照明の通常の変化。
  2. LUTカラー補正-時刻(またはゾーンのタイプ)に応じて画像のトーンを変更します。
  3. 動的光源-トーチ、ストーブ、ランプ。
  4. 法線マップ-特に光源を移動するときに、オブジェクトにボリュームを与える役割を果たします。
  5. 3D配光数学-画面中央の光源が、より高いオブジェクトを正しく照らしますが、低いオブジェクトを照らさないようにします(つまり、照らされていない側でカメラに向けられます)。
  6. 影-スプライトによって作成され、回転し、光源の位置に応答します。
  7. オブジェクトの高さのシミュレーション-霧を正しく表示します。
  8. その他の装飾:雨、風、アニメーション(葉や草のシェーダーアニメーションを含む)など


より詳細に。



可変周囲光



ここでは、原則として、特別なことは何もありません。 夜-暗い、日中-明るい。 ライトの色は、時間勾配によって設定されます。 夜になると、光源は暗くなるだけでなく、青の色合いになります。



次のようになります。









LUTカラー補正



LUT(ルックアップテーブル)-色置換テーブル。 大雑把に言えば、これはRGBの3次元配列で、各ノードには色の値があり、対応する色の値に置き換える必要があります。 つまり、座標(1、1、1)に赤い点がある場合、これは、画像内のすべての白い色が赤に置き換えられることを意味します。 座標(1、1、1)が白(R = 1、G = 1、B = 1)の場合、変化はありません。 したがって、変更のないLUTは、これらの同じ座標に対応する各座標の色を持ちます。 つまり 点(0.4、0.5、0.8)が色(R = 0.4、G = 0.5、B = 0.8)です。



さて、便宜上、3Dテクスチャを2次元として表示することに注意してください。 たとえば、これは「カラーレンダリングを変更しない」「デフォルト」LUTの外観です。







基本的に実装され、迅速かつ便利に機能します。



設定も非常に簡単です。アーティストにゲームの画像を提供し、「夕方のように感じるように色調」と言います。 その後、色補正のすべてのレイヤーをデフォルトのLUTに適用し、夕方のLUTを取得します。



私たちの場合、アーティストは少し立ち往生し、1日のさまざまな時間(夜、夕暮れ、夕方など)に応じて10個もの異なるLUTを作成しました。 セットアップは次のようになります。









その結果、時刻に応じて、同じ場所の外観が異なります。







ここでは、窓からのライトスプライトの透明度も時刻によって変わります。



動的光源と法線マップ



Unityの光源は、ごく普通に使用されています。 さらに、スプライトごとに法線マップが描画されるため、ボリューム感を得ることができます。









このような法線は非常に簡単に描かれます。 アーティストは、おおよそ4つの側面から光を描きます。









そして、このスクリプトは法線マップに行きます:









これを行うシェーダー(およびソフトウェア)を探している場合は、スプライトランプの方向を見ることができます。



3Dライトシミュレーション



これはもう少し複雑です。 スプライトを選択してハイライトすることはできません。 スプライトが光源の「後ろ」にあるのか、「前に」あるのかを考慮する必要があります。



この写真に注意してください:









両方のツリーは光源から同じ距離にありますが、遠いツリーは照らされており、最も近いツリーは照らされていません(その照らされていない部分がカメラの方を向いているため)。



この問題を簡単に解決しました。 シェーダーは、光源とスプライトの間の垂直y軸に沿った距離を計算します。 そして、正の場合(スプライトの前の光源)、通常どおりスプライトを照らしますが、負の場合(スプライトが光源とオーバーラップします)、光の強度は非常に大きな係数を持つ距離から大きく減衰します。 係数が作成され、「照明なし」だけではなく、光源が移動して突然スプライトの後ろに表示されると、スプライトは即座に黒くならず、徐々に黒くなります。 しかし、それでもかなり迅速です。











影は、点を中心に回転するスプライトによって作成されます。 それらにさらに圧縮(スキュー)を加えようとしましたが、不要であることがわかりました。



合計で、各オブジェクトには最大4つのシャドウを含めることができます。 1つは太陽から、3つは動的光源からのものです。 以下の図は、原理を示しています。







「次の3つの光源を見つけて、それらへの影の距離/角度を計算する」というタスクは、Updateで展開するスクリプトによって解決されます。 はい、あまり速く動作しません。なぜなら あなたは多くの数学をしなければなりません。 今書いたら、Unityで並列ジョブの新しいシステムを使用します。 しかし、これはまだではないため、通常のスクリプトを可能な限り最適化しました。



重要なのは、スプライトの回転を変換せず、頂点シェーダーの内側にしたことです。 つまり 回転は動きません。 パラメーターがスプライトに設定されているだけです(すべて同じ、すべての影が黒なので、この色を使用しました)。シェーダーは既にスプライトの回転を担当しています。 これは高速です Unityでジオメトリをヤンクする必要はありません。



このアプローチのもう1つの欠点は、オブジェクトごとに影を個別に設定する(場合によってはペイントする)必要があることです。 確かに、多かれ少なかれ多かれ少なかれ普遍的なスプライト(薄い、太い、楕円形など)が必要です。



2番目の欠点は、地球との接触スポットが非常に長いオブジェクトの影を作成することが難しい場合があることです。 たとえば、フェンスの影を見てください。









完璧ではありません。 フェンス自体のスプライトを半透明にすると、次のようになります。









ただし、ここでは、スプライトが依然として垂直方向に非常に変形していることに注意する価値があります(元のシャドウスプライトはほとんど円のように見えます)。 それが、彼のターンがターンではなく歪みとして見える理由です。



霧と高さのシミュレーション



ゲームに霧があります。 このように見えます(上記は通常のバージョンで、以下は効果を示すための極端な100%の霧です)。







ご覧のとおり、家や木のてっぺんが霧から突き出ています。 実際、この効果の実現は非常に簡単でした。 霧は、ステージの深さ全体に分布する多くの水平雲で構成されています。 そして結果として、すべてのスプライトの上部がより少ないフォグスプライトによってブロックされていることがわかります。









ピクセルアートの風は別の話です。 多くのオプションはありません。 手でアニメートするか(これはアートの量ではほとんど不可能です)、変形シェーダーを記述しますが、thenい歪みに耐えなければならない場合があります。 もちろん、まったくアニメートすることはできませんが、写真は無生物に見えます。



シェーダーを使用して歪みオプションを選択しました。 次のようになります。









このシェーダーを市松模様のテクスチャに適用すると、何が起こるかが明確になります。









また、クラウン全体をアニメートするのではなく、個々の葉のみをアニメートすることにも注意してください。









小麦も風に揺れますが、すべてが単純です-頂点シェーダーはx座標を変形し、y成分を考慮します。 ポイントが高いほど、よろめきが強くなります。 これは、トップのみが互い違いになるように行われますが、ルートはそうではありません。 さらに、画面上のさまざまなスプライトがランダムにスイングするように、ウォブルフェーズがx / y座標から変化します。









同じシェーダーは、プレイヤーが小麦と草を通過するときに、それらを揺らす効果を作成するためにも使用されます。









おそらく今のところすべてです。 私は意図的にシーンとそのジオメトリを構築する問題に取り組んでいません。 これは別の記事の資料です。 残りについては、彼は開発で使用された主なソリューションについて話しました。



PS:技術的な面に興味がある人はコメントに書いてください。 おそらく、別の記事で説明します。 もちろん、必要でない限り。



PPS:この機会に、チーム内で有能な人(プログラマー、PM、KM、アーティスト)を見つけたいと言っています。 詳細はスタジオのウェブサイトにあります。 このフレーズが規則に違反していないことを願っています。



All Articles