不規則な形状のヘルスバーを手続き的にレンダリングするにはどうすればよいですか?


35

従来の長方形または心臓ベースのヘルスバーの問題は、十分に理解されており、簡単に解決できます。しかし、以下で作成したモックアップのように、より「創造的に形作られた」ヘルスバーに受け入れられるソリューションは何ですか?

空の健康 完全な健康、部分的な健康

これを行う明白な方法は、「中間の」スプライトを使用することです。したがって、3番目の画像は、さまざまなレベルの健康のための他の多くのトランジションとともに、独自のスプライトになります。しかし、それは実に洗練されていないようであり、健康状態間のスムーズな移行を作成するために必要な中間者の数は多くなります。

私が思いつく他の唯一のアイデアは、「空の健康」スプライトの上に「完全な健康」スプライトをオーバーレイし、健康の各目盛りを表すピクセル座標のセットをプリベイクし、健康として不透明または透明にすることです上下します。

この質問は言語やプラットフォームにとらわれないことを意図していますが、回答に役立つ場合は、任意の言語/ライブラリ/フレームワークで具体的なサンプルを提供してください。


5
「N̶a̶n̶o̶m̶a̶c̶h̶i̶n̶e̶s̶シェーダー、息子」
ムケシュ・インガム

私はあなたがそれらをプリベークのではなく、ピクセル座標を表示するには、コンピュータの計算/非表示が持つことができるから、数学的に定義することができ、その変遷のように感じる
リチャード・チンクル

ハート型のヘルスバーはどのように「簡単に解決」できますか?
MooseBoys

1
@MooseBoysハート型ではなく、ハート型の健康について話していました。ゼルダの伝説ゲームを考えてください。これ以上はっきりしないでごめんなさい。
msd7734

@RichardTingle、良いアイデア:)
ジョン

回答:


48

シェーダーでこれを実現する非常に簡単な方法があります。3つのテクスチャが必要です:空のヘルスバー、ヘルスバーテクスチャ、一方の端に1つの極端な(たとえば、最も暗い黒または最も透明なアルファ値)の分布の勾配を持つマスクもう一方の端に。それは画像に最もよく示されていますが、現在は曲線グラデーションを線形のみ描画することはできません-しかし、あなたのアーティストは何の問題もないと確信しています: ここに画像の説明を入力してください 今、シェーダーでテクスチャとしきい値の両方をサンプリングし、そうでないすべてのピクセルを破棄します入力のしきい値よりも明るい(シェーダー入力のヘルス%に基づく)。
あなたは可能性テクスチャの代わりにマスキングに数式を使用しますが、それを行った場合、上記の数式で作成できる形状(=単純な形状)に非常に制限されます。
* コメントを見る


9
多くの場合(OPの例を含む)、色に別のテクスチャを使用するのはやり過ぎです。ほとんどの場合、グレースケールマスクグラデーションをシェーダーのユニフォームとして指定された色に再マッピングするだけで、特定のしきい値未満のマスク値はすべて破棄できます。
bcrist

1
実際には、黒ではなく最も暗いものは必要ありません。アルファチャネルを使用して、不要なピクセルを除外できます。
ジャックエイドリー

1
@JackAidleyはそれが可能であることを確信していますが、可能な限り柔軟なソリューションを望んでいました。ほとんどのAAAタイトルでは、HPは単に「赤」ではありませんが、質感があります。
ウォンドラ

1
@bcristの良い点は、最適化として提案することを検討したことです。しかし、私はそれを適切に描くことができなかったので、可能な限りシンプルに保ち、実装のために最適化を残すことにしました。
ウォンドラ

@wondra OPのサンプルルックを含む多くの場合、テクスチャではなく、プロシージャグラデーションまたは1次元カラールックアップ(マスクレベルを入力として)を使用できます。
Random832

34

ピクセルシェーダーとして数学的に実装:

CPUで、V2でHealthDirectionとそのドット積を計算します ここに画像の説明を入力してください

GPUで、各ピクセルの中心点から離れる正規化された方向を計算します。各ドット積をHealthDirections 'と比較して、「背景」をシェーディングするか、カラーにするかを選択します。 ここに画像の説明を入力してください

このアルゴリズムを「反転」し、他の方向から作業した場合、各ピクセルの方向を「元に戻して」パーセンテージに戻し、代わりにそれぞれをHealthPercentと比較できます。各ピクセルの割合を計算すると、GPUで赤から緑へのフェードを実行するのは簡単になります。

最初にアルゴリズムをクワッドに適用してバーを描画します。rangeMinとrangeMax(ベイク処理可能)およびclip()の間の色を出力するか、他の場所で透明に出力します。次に、アルファを使用して、その上に(変更された)スプライトを描画します。CADでバーをトレースし、塗りつぶしてから、ペイントのソリッドカラーシェイプを「マジックワンド」して削除しました。私の手は、AutoCADとペイントを手作業で混合しているため、がらくたに見えます。内側のエッジを透明にブレンドすると仮定すると、完璧

白い境界線は、クワッドの境界です。それと赤いXは参照専用です:

ここに画像の説明を入力してください

「穴のあるスプライト」は、ヘルスバーと同時にレンダリングする必要はありません。すべてのヘルスバーが完成した後、それらは一度にインスタンス化され描画されます。アルゴリズムはシェーダーに内蔵されているため、インスタンス化を追加して、インスタンス化された1つの描画呼び出しですべてのヘルスバーを描画することもできます。画面上のすべてのヘルスバーを描画するには、2つのDrawInstanced(...)呼び出しが必要であり、「クレイジーファースト」である必要があります。


1
このように円形にマスクする場合、円形フェード用にプロットする三角形を変更するだけで、より効率的に実装できます。
ジャックエイドリー

@JackAidley、もっと具体的にお願いします。私はこのマスキングを考慮していないためです。進行状況バーは、最初のパスの後、サンプリングなしで、2つの三角形のみに完全にレンダリングされます。スプライトにはたまたま穴が開いており、最後に全体が「ふり」をしています。(これは一種のマスクですが、アルゴリズムの不可欠な部分ではありませんか?)ありがとう
ジョン

あなたがしていることは、すでにグレーの色が設定されている背景スプライトの上に、色付きのバーのマスクされたバージョンを描画することと同じです。メソッドにはカスタムシェーダーが必要で、すべてのピクセルに書き込むため、シェイプの必要な部分のみを描画するよりも遅いメソッドになります。
ジャックエイドリー

@JackAidley、しかし背景のスプライトはありませんか?虹は、float3ワールド位置を4つだけ使用して描画されます。UV、「背景スプライト」はありません。また、ピクセルシェーダーが小さなクワッドで機能しなくなることを心配していますか?また、RangeMinとRangeMaxは、これらのフラグメントのほとんどを即座に切り取ります。
ジョン

元の画像に示されているように境界線を取得するには、背景スプライトが必要です。これらを省略している場合、はい、方法は異なります。
ジャックエイドリー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.