21

最近、sRGB形式と、ハードウェアが一般的なモニターの色補正を自動的に実行できるようにする方法について少し読んでいます。私の読書の一部として、通常のテクスチャと戻り結果のpow関数を使用してこのステップをシミュレートできることがわかります。

とにかく、私はこれまでこの機能を使用したことがないので、2つの質問をしたいと思います。まず、私のスクリーンショットから、これがあなたが期待するものであることを誰かが確認できますか?左の画像は通常のRGBAで、右の画像はsRGBターゲットを使用しています。シーンにはアンビエントライトはなく、モデルは標準のフォンです(ライトはスポットライトです)。

左はRGBA、右はSRGBAを示しています

私が聞きたい2番目の質問は、どの時点でハードウェアによって実際に修正が実行されるかということです。たとえば、フレームをFBOに書き込んでから、後でFBOカラーバッファーを使用して画面サイズのクワッドをバックバッファーにレンダリングしています(すぐに遅延シェーディングに切り替える予定です)。FBOに接続されたsRGBテクスチャを使用する必要がありますか、それともバックバッファターゲットとしてsRGBテクスチャを指定するだけで済みますか?sRGBを使用している場合、すべてのテクスチャリソースをsRGBにする必要がありますか?

4

1 に答える 1

46

注: 以下の説明は、sRGB 色空間とは何か、ガンマ補正とは何か、リニア RGB 色空間とは何かなどを理解していることを前提としています。これは主に、テクノロジーの OpenGL 実装に焦点を当てています。

これらの主題の詳細な議論が必要な場合は、HDR/ガンマ補正に関するチュートリアル(線形色空間とガンマを理解するため) と、sRGB 画像に関するチュートリアルとガンマ補正の処理方法を参照することをお勧めします。

まず、私のスクリーンショットから、これがあなたが期待するものであることを誰か確認できますか?

その質問の意味がよくわかりません。適切なガンマ補正 (sRGB が多かれ少なかれ行うこと) を適用すると、通常、画像の暗い領域で詳細が得られ、「明るい」結果が得られます。

ただし、適切なガンマ補正を行うまでは、すべての画像が間違っていると考えるのが正しい方法です。画像が暗すぎましたが、ガンマ補正により適切な明るさに調整されています。物事が何色であるべきか、どのように明るい光であるべきかについてあなたが下したすべての決定は間違っていました.

2 つ目の質問は、ハードウェアによって実際に修正が実行されるのはどの時点かということです。

これは、カバーを続ける「たとえば」の部分とは非常に異なる質問です。

sRGB イメージ (覚えておいてください: テクスチャにはイメージが含まれますが、フレーム バッファにもイメージを含めることができます) は、次のコンテキストで使用できます。

  • ユーザーから画像に直接データを転送する (たとえば、glTexSubImage2D などを使用)。OpenGLは、既に sRGB 色空間にあるデータを提供していると想定しています。そのため、アップロード時にデータの翻訳はありません。これは、最も理にかなっているためです。通常、アーティストから取得した画像は、アーティストが他の色空間に配置するために多大な労力を費やした場合を除き、sRGB 色空間になります。ほとんどすべての画像エディタは sRGB で直接動作します。

  • サンプラーを介してシェーダーの値を読み取る (つまり、テクスチャにアクセスする)。これも非常に簡単です。OpenGL は、画像内のテクセル データが sRGB 色空間にあることを認識しています。OpenGL は、シェーダーがリニアRGB カラー データを必要としていると想定しています。したがって、sRGB イメージ フォーマットを使用してテクスチャからサンプリングしようとすると、sRGB->lRGB 変換が行われます。ところで、これは無料です。

    プラス面としては、GL 3.x+ 対応のハードウェアを使用している場合、ほぼ確実に線形色空間でフィルタリングを行うことができます。sRGB は非線形色空間であるため、sRGB 値の線形補間は常に間違っています。

  • フラグメント シェーダーから出力された値をフレーム バッファー イメージに格納します。ここが少し複雑なところです。レンダリング先のフレームバッファ イメージが sRGB 色空間にある場合でも、強制的に変換するには不十分です。明示的にする必要がありglEnable(GL_FRAMEBUFFER_SRGB)ます。これは、フラグメント シェーダーから書き込んでいる値が線形色空間値であることを OpenGL に伝えます。したがって、OpenGL はこれらを画像に格納するときに sRGB に変換する必要があります。

    繰り返しになりますが、GL 3.x+ ハードウェアを使用している場合は、ほぼ確実にリニア カラースペースでブレンドできます。つまり、OpenGL はフレームバッファから sRGB 値を読み取り、それをリニア RGB 値に変換し、それを入力リニア RGB 値 (シェーダから書き込んだ値) とブレンドし、ブレンドされた値を sRGB 色空間に変換して保存します。 . 繰り返しますが、それはあなたが望むものです。sRGB 色空間でのブレンドは常に悪いことです。

それを理解したので、あなたの例を見てみましょう。

たとえば、フレームを FBO に書き込んでから、後で FBO カラー バッファーを使用して画面サイズのクワッドをバック バッファーにレンダリングしています (ディファード シェーディングにすぐに切り替える予定です)。

これの問題は、正しい質問をしていないことです。特に遅延レンダリングに移行する際に留意する必要があるのは、次の質問です。

これはリニアRGBですか?

一般に、中間データをガンマ補正空間にできるだけ長く保存することは控えるべきです。したがって、中間バッファー (つまり、ライトを蓄積する場所) はsRGBであってはなりません。

これはコンバージョンのコストに関するものではありません。それは本当にあなたがしていることについてです。遅延レンダリングを行っている場合は、おそらく HDR ライティングなども行っているでしょう。したがって、光蓄積バッファは浮動小数点である必要があります。また、フロート バッファーは常に線形です。それらが直線的でない理由はありません。

無料のガンマ補正を利用したい場合 (実際に利用している場合)、最終的な画像 (デフォルトのフレームバッファ) は sRGB でなければなりません。すべての作業を HDR フロート バッファーで行い、最終的な表示のために結果をトーン マップする場合は、それを sRGB 画像に書き込む必要があります。

于 2012-04-27T10:07:38.317 に答える