HDRFormats サンプル

高ダイナミック レンジ (HDR) ライティング エフェクトには、0 ~ 255 以外のカラー値を処理する機能が要求され、通常これは、高レンジ カラー データをテクスチャーとして格納することによって処理されます。HDR アプリケーションには浮動小数点テクスチャー フォーマットを選ぶのが自然ですが、すべてのターゲット システムでこのフォーマットを使用できるとは限りません。このサンプルでは、さまざまなデバイスとの互換性を確保するために、高ダイナミック レンジ データを整数フォーマットにエンコードする方法を示します。

Ee417767.HDRFormats(ja-jp,VS.85).jpg

Path

ソース SDK ルート\Samples\C++\Direct3D\HDRFormats
実行可能ファイル SDK ルート\Samples\C++\Direct3D\Bin\x86 または x64\HDRFormats.exe

サンプルの概要

高ダイナミック レンジ ライティング テクニックは、アプリケーションにリアリティを付加します。また、実装が極めて容易で、既存のレンダリング パイプラインにも緊密に統合でき、必要な処理時間もそれほどかかりません。ただし、ほとんどの HDR テクニックは浮動小数点テクスチャー フォーマットに依存するため、ターゲット システムによっては使用できない場合があります。浮動小数点テクスチャーをサポートしていないデバイスで HDR テクニックを使用できるようにするには、1 つの手段として、高レンジ浮動小数点データを整数フォーマットにエンコードし、必要に応じて即時にデコードする方法があります。

整数テクスチャーは、浮動小数点テクスチャーの代替としては完璧でないことに注意してください。整数へのエンコードには、精度を損ねる、浮動小数点ソースの範囲が一部欠落する、エンコードとデコード処理によってパフォーマンスが低下する、などの欠点があります。このエンコードとデコードはピクセル シェーダー内でシームレスに実行されるので、極端に負荷がかかることはありませんが、これは利用できるシェーダー命令数のいくつかを使用するため、フレームレートが若干低下する可能性があります。スカイボックスなどの静的要素には、初期化時に 1 度だけエンコードを行って、実行時のサイクルを節約することができます。

実装

アプリケーションでは、2 つの高ダイナミック レンジ テクニックを使用します。すなわち、トーン マッピングとブルーミングです。これらのテクニックの効果にあまり詳しくない場合、または一般的な高ダイナミック レンジ イメージの詳細を知りたい場合は、HDR ライティングのプログラミング ガイドを一読し、SDK に含まれる HDRLighting サンプルと HDRCubeMap サンプルを表示してください。

このサンプルで使用するテクニックでは、HDR データをテクスチャーとして格納する能力がクリティカルです。シーンを HDR レンダー ターゲットにレンダリングすること、環境マップ テクスチャーが HDR であること、シーンの輝度の測定に使用する一時テクスチャーすべてを HDR データに格納することがそれぞれ必要となります。浮動小数点テクスチャーをサポートしているデバイスでは、最も効率のよいシンプルな実装が実現しますが、作業手順を若干追加すれば、整数テクスチャーを使用して HDR データを格納することも可能になります。このサンプルでは、2 つのエンコード スキームを実装します。

RGB16

チャンネルあたり 16 ビットの整数フォーマットを使用すると、65536 個の離散値を使用して、チャンネルごとのデータを格納できます。このエンコードは、0.0f から任意の最大値 (このサンプルでは100.0f) を範囲とする 65536 個の値の単純な線形分布です。アルファ チャンネルは使用しません。エンコードされた RGB16 カラーから浮動小数点値をデコードするには、次の式を使用します。

decoded.rgb = encoded.rgb dot max_value

RGBE8

このエンコードは RGB16 よりも高度で、対数分布を使用することにより、はるかに広範囲のカラー データを処理できます。各チャンネルはカラー成分の仮数を格納し、アルファ チャンネルは共有指数を格納します。柔軟性が高まる分、余分な計算負荷も加わります。エンコードされた RGBE8 カラーから浮動小数点値をデコードするには、次の式を使用します。

decoded.rgb = encoded.rgb * 2encoded.a

次の図は、使用タイミングに従って上から順にシーンをレンダリングするのに使用されるテクスチャーを示しています。青の枠線で囲まれた図には高ダイナミック レンジ データが含まれており、RGBE8 エンコードを使用して表示されています。

Ee417767.HDRFormats2(ja-jp,VS.85).jpg

シーンのレンダリング プロセスは、ネイティブの浮動小数点テクスチャー モードでも、エンコードされた整数テクスチャー モードでも、ほとんど変わりません。高ダイナミック レンジ テクスチャーを読み取るピクセル シェーダーで必要となるのは、エンコードされた整数テクスチャーを読み取る際の追加のデコード手順と、HDR データを整数テクスチャーに書き込む際の同様のエンコード手順だけです。シェーダーに一定の引数を使用することで、同じシェーダーのコンパイル方法を変えてすべてのエンコード スキームで使用することができます。次の例は、モデルをライティングするピクセル シェーダーを示しています。

//-----------------------------------------------------------------------------// Name: ScenePS// Type: Pixel Shader// Desc: Environment mapping and simplified hemispheric lighting//-----------------------------------------------------------------------------float4 ScenePS( SceneVS_Output Input,                 uniform bool RGBE8,                uniform bool RGB16 ) : COLOR{    // Sample the environment map    float3 vReflect = reflect( Input.ViewVec_World, Input.Normal_World );    float4 vEnvironment = texCUBE( CubeSampler, vReflect );        if( RGBE8 )        vEnvironment.rgb = DecodeRGBE8( vEnvironment );    else if( RGB16 )        vEnvironment.rgb = DecodeRGB16( vEnvironment );           // Simple overhead lighting    float3 vColor = saturate( MODEL_COLOR * Input.Normal_World.y );        // Add in reflection    vColor = lerp( vColor, vEnvironment.rgb, MODEL_REFLECTIVITY );        if( RGBE8 )        return EncodeRGBE8( vColor );    else if( RGB16 )        return EncodeRGB16( vColor );    else        return float4( vColor, 1.0f );}