3

問題の説明

私は現在、ディファード レンダラーにポイント ライトを実装していますが、ライトの境界付近でのみ目立つ重いピクセル化/三角測量がどこから来ているのかを判断するのに苦労しています。

この問題は、どこかで精度が失われたことが原因のようですが、正確な原因を突き止めることはできませんでした。法線は明らかな可能性ですが、directx を使用している同級生がいて、法線を同様の方法で問題なく処理しています。

ゲームのユニット (64 ユニット/メートル) で約 2 メートル離れたところから:

deferred_full_scene

数センチ離れて。「ピクセル化」は、世界に近づいてもサイズが変わらないことに注意してください。ただし、カメラの向きを変えると泳いでいるように見えます。

deferred_closeup

RGBA8 レンダー ターゲットで予想される球状のバンディングを示すフォワード レンダラーのクローズ アップとの比較 (各色の値は 0 ~ 255 のみ)。私の延期された写真では、後壁が通常の球状のバンディングを示していることに注意してください。

クローズアップ_フォワード

ライト ボリュームは、緑色のワイヤフレームで示されています。

light_volume_and_scene

ご覧のとおり、表面に近づかない限り効果は見えません (ゲームの単位で約 1 メートル)。


位置再構築

まず、光が重なる画面の部分のみをレンダリングするために使用している球状メッシュを使用していることに言及する必要があります。ここで提案されているように、深度が深度バッファー以上の場合、背面のみをレンダリングします。

フラグメントのカメラ空間位置を再構築するために、ライト ボリュームのカメラ空間フラグメントからベクトルを取得し、それを正規化し、gbuffer からの線形深度でスケーリングしています。これは、ここで説明した方法(線形深度を使用)ここ (球状のライト ボリューム)のハイブリッドのようなものです。

position_reconstruction


ジオメトリ バッファ

私のgBufferの設定は次のとおりです。

enum render_targets { e_dist_32f = 0, e_diffuse_rgb8, e_norm_xyz8_specpow_a8, e_light_rgb8_specintes_a8, num_rt };
//...
GLint internal_formats[num_rt] = {  GL_R32F, GL_RGBA8, GL_RGBA8, GL_RGBA8 };
GLint formats[num_rt]          = {   GL_RED,  GL_RGBA,  GL_RGBA,  GL_RGBA };
GLint types[num_rt]            = { GL_FLOAT, GL_FLOAT, GL_FLOAT, GL_FLOAT };
for(uint i = 0; i < num_rt; ++i)
{
  glBindTexture(GL_TEXTURE_2D, _render_targets[i]);
  glTexImage2D(GL_TEXTURE_2D, 0, internal_formats[i], _width, _height, 0, formats[i], types[i], nullptr);
}
// Separate non-linear depth buffer used for depth testing
glBindTexture(GL_TEXTURE_2D, _depth_tex_id);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, _width, _height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, nullptr);

4

1 に答える 1

3

通常の精度

問題は、法線の精度が十分でないことでした。コンポーネントあたり 8 ビットの場合、255 の個別の可能な値を意味します。照明の上にオーバーレイされた gbuffer の法線を調べると、法線値と lit の「ピクセル」値が 1 対 1 で対応していることがわかりました。

同級生が同じ問題を抱えていない理由がわかりません (彼はさらに調査する予定です)。

normal_precision

さらに調査した結果、これを表す用語が量子化であることがわかりました。その別の例は、19 ページのスペキュラー ハイライトで見ることができます


解決

通常のレンダー ターゲットをRG16Fに変更したら、問題は解決しました。

ここで提案されている方法を使用して、法線を保存および取得すると、次の結果が得られます。

量子化なし

法線をよりコンパクトに保存する必要があります (コンポーネントを 2 つしか格納できません)。誰かが同じ状況に陥った場合、これはテクニックの良い調査です.


[編集1]

Andon と GuyRT の両方がコメントで指摘しているように、16 ビットは私が必要とするものには少し過剰です。彼らが提案したように、私は RGB10_A2 に切り替えました。丸みを帯びた表面でも、非常に満足のいく結果が得られます。余分な 2 ビットは大いに役立ちます (256 対 1024 の離散値)。

これが今の様子です。

ここに画像の説明を入力

また、(今後この投稿を参照する人のために) 私が RG16F 用に投稿した画像には、法線を圧縮/解凍するために使用していた方法からの望ましくないバンディングがあることに注意してください (関連するエラーがありました)。


[編集2]

この問題について同級生 (RGB8 を問題なく使用している) とさらに話し合った後、これを実現するための要素の完璧な組み合わせを持っている可能性があることに言及する価値があると思います。私がこのレンダラーを構築しているゲームは、ソナーのような能力を備えた真っ暗な環境にプレイヤーを置くホラー ゲームです。通常、シーンでは、さまざまな角度で多数のライトを使用します (私のクラスメートの環境はすべて非常によく照らされています - 彼らは屋外のレーシング ゲームを作成しています)。比較的近くにある非常に丸い物体にのみ現れるという事実と相まって、私がこれを誘発した理由かもしれません. これはすべて、私の側の(少し教育を受けた)推測にすぎません。

于 2014-03-10T08:19:22.397 に答える