色収差をどのように実装しますか?


22

シェーダーで色収差の影響をどのように実装しますか?

色ごとに異なる焦点距離を使用して世界をレンダリングすると、問題は解決しますか(1つの深度レンダリングパスのみを使用する場合)。


なぜ色収差を実装したいのですか?
ashes999

3
ブルームが達成されるのと同じ方法で進めることができます。通常のシーンと3つのぼやけたバージョンを組み合わせる必要があります。これらの3つのテクスチャのそれぞれは、主に3つの基本色で色付けする必要があります。もちろん、3つのテクスチャに異なるぼかしストラテジーを使用する場合、バリエーションが可能です(たとえば、角度オフセットが異なる方向ぼかしがトリックを行うことがあります)。
テオドロン

3
@ ashes999-おそらくスナイパースコープまたは他の長いレンズは、リアリズムのタッチを追加しますか?色収差は、多くの複合レンズ設計のアーティファクトです。
キース

また、色収差を実装して、ゲームを表示しているレンズによって引き起こされる収差に対処することもできます。たとえば、Oculus Riftでプレイするゲームでは、ビューの端に色収差があることをお勧めします。
ジョセフマンスフィールド

回答:


22

色収差は、レンズがすべての色を同じ焦点に合わせることができない場合に発生します。このエフェクトを偽造し、クイックフルスクリーンポストプロセスとしてレンダリングする簡単な方法は、フラグメントシェーダーの各カラーチャンネルにオフセットを適用することです。

チャネルごとに異なるオフセットを使用することで、目的の効果を適切に再現できます。このテクニックの例はここにあります; フラグメントシェーダーは次のようになります。

void main () {
    // Previously, you'd have rendered your complete scene into a texture
    // bound to "fullScreenTexture."
    vec4 rValue = texture2D(fullscreenTexture, gl_TexCoords[0] - rOffset);  
    vec4 gValue = texture2D(fullscreenTexture, gl_TexCoords[0] - gOffset);
    vec4 bValue = texture2D(fullscreenTexture, gl_TexCoords[0] - bOffset);  

    // Combine the offset colors.
    gl_FragColor = vec4(rValue.r, gValue.g, bValue.b, 1.0);
}

ただし、この単純なハックでは、色収差がレンズ効果であるという事実を実際に考慮していません。より良いシミュレーションを得るには、実際にレンズとして機能するものをレンダリングする必要があります。これは、反射または屈折するオブジェクトをレンダリングする方法に似ています。その結果、典型的な反射/屈折シェーダーは、色収差を実装するための基礎となります。

通常、頂点シェーダーのGLSLの屈折関数を使用して、ビューベクトルと定義された屈折のインデックスに基づいて単一の屈折ベクトルを計算します。

void main () {
    // ...

    // RefractionVector is a varying vec3.
    // 'ratio' is the ratio of the two indices of refraction.
    RefractionVector = refract(incidentVector, normalVector, ratio);

    // ...
}

次に、そのベクトルをフラグメントシェーダーで使用して、(環境マップへの)キューブテクスチャルックアップを実行します。通常、これは反射効果とともに行われ、計算されたフレネル項を使用して結合されます。

色収差をシミュレートするには、頂点シェーダーで3つの異なる屈折ベクトル計算を実行し、それぞれ異なる屈折指数を使用してわずかにオフセットすることができます。

void main () {
    // ...

    // RefractionVector is a varying vec3, as above.
    // 'ratioR,' et cetera, is the ratio of indices of refraction for
    // the red, green and blue components respectively.
    RedRefractionVector = refract(incidentVector, normalVector, ratioR);
    GreenRefractionVector = refract(incidentVector, normalVector, ratioG);
    BlueRefractionVector = refract(incidentVector, normalVector, ratioB);

    // ...
}

これらの3つの異なるベクトルを使用して、3つの異なるキューブマップルックアップを実行できます。これらは、単純な例で色が混合された方法と同様に、一緒に混合できます。

void main () {
    vec3 color;
    color.r = vec3(textureCube(EnvironmentMap, RedRefractionVector)).r;
    color.g = vec3(textureCube(EnvironmentMap, GreenRefractionVector)).g;
    color.b = vec3(textureCube(EnvironmentMap, BlueRefractionVector)).b;

    gl_FragColor = vec4(color, 1.0);
}

詳細については、OpenGL Orange Bookが利用可能で、基本的な反射および屈折効果の例と、色収差効果の例が含まれています。


1つのテクスチャサンプルのみを使用し、それを着色するアプローチはありますか?3対1のレイのトレースが非常に高価なレイトレーシングのようなアプリケーションには非常に有益です。
タラ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.