OpenGLでシェーダーを使用して初めて基本的なシャドウマッピングを実装しましたが、いくつかの問題に直面しています。以下に、レンダリングされたシーンの例を示します。
私がフォローしているシャドウマッピングのプロセスは、光の視点からのビューマトリックスと、通常のレンダリングに使用される投影およびモデルマトリックスを使用して、シーンをフレームバッファーにレンダリングすることです。
2番目のパスでは、上記のMVPマトリックスをライトの視点から、位置をライトスペースに変換する頂点シェーダーに送信します。フラグメントシェーダーは遠近法による分割を行い、位置をテクスチャー座標に変更します。
これが私の頂点シェーダーです、
#version 150 core
uniform mat4 ModelViewMatrix;
uniform mat3 NormalMatrix;
uniform mat4 MVPMatrix;
uniform mat4 lightMVP;
uniform float scale;
in vec3 in_Position;
in vec3 in_Normal;
in vec2 in_TexCoord;
smooth out vec3 pass_Normal;
smooth out vec3 pass_Position;
smooth out vec2 TexCoord;
smooth out vec4 lightspace_Position;
void main(void){
pass_Normal = NormalMatrix * in_Normal;
pass_Position = (ModelViewMatrix * vec4(scale * in_Position, 1.0)).xyz;
lightspace_Position = lightMVP * vec4(scale * in_Position, 1.0);
TexCoord = in_TexCoord;
gl_Position = MVPMatrix * vec4(scale * in_Position, 1.0);
}
そして私のフラグメントシェーダー、
#version 150 core
struct Light{
vec3 direction;
};
uniform Light light;
uniform sampler2D inSampler;
uniform sampler2D inShadowMap;
smooth in vec3 pass_Normal;
smooth in vec3 pass_Position;
smooth in vec2 TexCoord;
smooth in vec4 lightspace_Position;
out vec4 out_Color;
float CalcShadowFactor(vec4 lightspace_Position){
vec3 ProjectionCoords = lightspace_Position.xyz / lightspace_Position.w;
vec2 UVCoords;
UVCoords.x = 0.5 * ProjectionCoords.x + 0.5;
UVCoords.y = 0.5 * ProjectionCoords.y + 0.5;
float Depth = texture(inShadowMap, UVCoords).x;
if(Depth < (ProjectionCoords.z + 0.001)) return 0.5;
else return 1.0;
}
void main(void){
vec3 Normal = normalize(pass_Normal);
vec3 light_Direction = -normalize(light.direction);
vec3 camera_Direction = normalize(-pass_Position);
vec3 half_vector = normalize(camera_Direction + light_Direction);
float diffuse = max(0.2, dot(Normal, light_Direction));
vec3 temp_Color = diffuse * vec3(1.0);
float specular = max( 0.0, dot( Normal, half_vector) );
float shadowFactor = CalcShadowFactor(lightspace_Position);
if(diffuse != 0 && shadowFactor > 0.5){
float fspecular = pow(specular, 128.0);
temp_Color += fspecular;
}
out_Color = vec4(shadowFactor * texture(inSampler, TexCoord).xyz * temp_Color, 1.0);
}
問題の1つは、写真でわかるようにセルフシャドウイングです。クレート自体に独自のシャドウが投影されています。私が試したのは、ポリゴンオフセットを有効にすること(つまり、glEnable(POLYGON_OFFSET_FILL)、glPolygonOffset(GLfloat、GLfloat))ですが、あまり変化しませんでした。フラグメントシェーダーでわかるように、静的オフセット値を0.001に設定しましたが、ライトの距離に応じて値を変更して、より望ましい効果を得る必要があるため、あまり便利ではありません。また、フレームバッファーにレンダリングするときに前面カリングを使用しようとしましたが、あまり変化しませんでした。
もう1つの問題は、ライトの視錐台の外側のピクセルがシェーディングされることです。影を落とすことができると思われる唯一の物体は木箱です。より適切な投影法とビュー行列を選択する必要があると思いますが、それを行う方法がわかりません。一般的な方法は何ですか、正射投影を選択する必要がありますか?
少しググるところから、これらの問題はささいなことではないことを理解しています。これらの問題の解決策を簡単に実装できる人はいますか?追加のヒントを教えていただけますか?
私のコードについてさらに情報が必要かどうか私に尋ねてください。
ここでとクレートのクローズアップのシャドウマッピングなしの比較です。セルフシャドウがより見やすくなります。