シェーダーで色収差の影響をどのように実装しますか?
色ごとに異なる焦点距離を使用して世界をレンダリングすると、問題は解決しますか(1つの深度レンダリングパスのみを使用する場合)。
シェーダーで色収差の影響をどのように実装しますか?
色ごとに異なる焦点距離を使用して世界をレンダリングすると、問題は解決しますか(1つの深度レンダリングパスのみを使用する場合)。
回答:
色収差は、レンズがすべての色を同じ焦点に合わせることができない場合に発生します。このエフェクトを偽造し、クイックフルスクリーンポストプロセスとしてレンダリングする簡単な方法は、フラグメントシェーダーの各カラーチャンネルにオフセットを適用することです。
チャネルごとに異なるオフセットを使用することで、目的の効果を適切に再現できます。このテクニックの例はここにあります; フラグメントシェーダーは次のようになります。
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が利用可能で、基本的な反射および屈折効果の例と、色収差効果の例が含まれています。