現在、アプリケーションにシャドウ マップのサポートを実装しており、次のリンクに示されている手順に従っています: http://www.fabiensanglard.net/shadowmapping/index.php
しかし、彼がシャドウ マップの投影にテクスチャ マトリックスを使用していることに気付きましたが、テクスチャ マトリックスを使用せずにそれを行いたいと考えています。
シーンをレンダリングする方法は次のとおりです。
- 深度テクスチャの FBO を設定する
- ライトの視点から投影とモデル ビュー マトリックスを設定する
- カラーマスクを無効にしてシーンをレンダリングする
- 次のようにしてシャドウ マトリックスを設定します。 shadowMatrix = bias * lightProjectionMatrix * lightModelViewMatrix
- シャドウ マトリックスを実際のカメラ モデルビュー マトリックスの逆数で乗算します。
- shadowMatrix を mat4 ユニフォーム変数としてシェーダーに送信します。
私の頂点シェーダーには、さまざまな vec4 shadowCoord 変数があり、それは、shadowMatrix 均一に gl_ModelViewMatrix と gl_Vertex を乗算して計算されます (shadowCoord = shadowMatrix * gl_ModelViewMatrix * gl_Vertex)
フラグメント シェーダーは、上記のリンクに記載されているものとまったく同じです。その結果、シーンが完全に黒く表示されるか、シャドウに設定されているシェード/カラーが表示されます。
バイアス、lightProjectionMatrix、lightModelViewMatrix にカメラのモデルビュー マトリックスの逆数を掛けると、何か間違ったことをしていると思います。誰かが私が間違っていることを指摘できますか?
編集:複雑なコードを貼り付けなくても誰かが問題を特定できることを望んでいましたが、とにかく貼り付けられるものを貼り付けようとします。コードがごちゃごちゃしていて申し訳ありません。簡単にするために多くのコードを削除する必要がありました。
int vp[4];
kexMatrix lightProj, lightMV;
kexCamera tmpCam;
renderBackend.SetColorMask(0);
// save actual camera viewport
glGetIntegerv(GL_VIEWPORT, vp);
// set viewport to framebuffer object size (512x512)
// smFbo is my framebuffer class used for the shadowmap/depth
glViewport(0, 0, smFbo.Width(), smFbo.Height());
// bind framebuffer
smFbo.Bind();
glClear(GL_DEPTH_BUFFER_BIT);
// setup temp. camera for light source
tmpCam.SetOrigin(kexVec3(-2048, 860, 450)); // x, y, z with y being up, and z being forward/back
tmpCam.SetAngles(kexAngle(1.0f, 0.5f, 0.0f)); // yaw, pitch and roll in radians
tmpCam.SetupMatrices();
lightProj = tmpCam.Projection();
lightMV = tmpCam.ModelView();
// setup matrices for OGL
glMatrixMode(GL_PROJECTION);
glLoadMatrixf(lightProj.ToFloatPtr());
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf(lightMV.ToFloatPtr());
bShadowPass = true;
// note that each static actor object has its own matrix so before drawing I do:
// glPushMatrix();
// glMultMatrixf(actor->Matrix());
// draw and pop matrix
DrawStaticActors();
bShadowPass = false;
// unbind framebuffer object and restore viewport
smFbo.UnBind();
glViewport(vp[0], vp[1], vp[2], vp[3]);
renderBackend.SetColorMask(1);
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
kexMatrix bias;
bias.vectors[0].Set(0.5f, 0, 0, 0);
bias.vectors[1].Set(0, 0.5f, 0, 0);
bias.vectors[2].Set(0, 0, 0.5f, 0);
bias.vectors[3].Set(0.5f, 0.5f, 0.5f, 1.0f);
// setup matrices from world camera. handles gl projection/modelview setup as well
SetCameraView(world->Camera());
// shadowmap matrix for GLSL shader
shadowMatrix = bias * lightProj * lightMV * kexMatrix::Invert(world->Camera()->ModelView());
// draw scene as normal and sets up the shader
// shadowMap sampler2D uniform is binded to 1
// also calls smFbo.BindImage() which binds the actual texture to texture unit # 1
// shadowMatrix is also sent as uniform to shader
DrawStaticActors();
深度フレームバッファのセットアップ
// texture
glGenTextures(1, &fboTexId);
glBindTexture(GL_TEXTURE_2D, fboTexId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D,
0,
GL_DEPTH_COMPONENT,
fboWidth,
fboHeight,
0,
GL_DEPTH_COMPONENT,
GL_FLOAT,
0);
// framebuffer
glGenFramebuffers(1, &fboId);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
glDrawBuffer(GL_NONE);
glReadBuffer(GL_NONE);
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT,
GL_DEPTH_ATTACHMENT_EXT,
GL_TEXTURE_2D,
fboTexId,
0);
CheckStatus();
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glBindTexture(GL_TEXTURE_2D, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
FBOバインド機能
glBindFramebuffer(GL_FRAMEBUFFER_EXT, fboId);
glReadBuffer(GL_NONE);
glDrawBuffer(GL_NONE);
FBOアンバインド機能
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
FBOバインド画像機能
int unit = renderBackend.glState.currentUnit;
dtexture currentTexture = renderBackend.glState.textureUnits[unit].currentTexture;
if(fboTexId == currentTexture) {
return;
}
glBindTexture(GL_TEXTURE_2D, fboTexId);
renderBackend.glState.textureUnits[unit].currentTexture = fboTexId;
頂点シェーダー
//varying vec3 vertex_normal;
varying vec4 shadowCoord;
uniform mat4 shadowMatrix;
void main() {
gl_FrontColor = gl_Color;
gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_Vertex;
gl_TexCoord[0] = gl_MultiTexCoord0;
//vertex_normal = normalize(gl_NormalMatrix * gl_Normal);
shadowCoord = shadowMatrix * (gl_ModelViewMatrix * gl_Vertex);
}
フラグメントシェーダー
uniform sampler2D diffuse;
uniform sampler2D shadowMap;
//varying vec3 vertex_normal;
varying vec4 shadowCoord;
void main() {
vec4 color = texture2D(diffuse, gl_TexCoord[0].st);
vec4 shadowCoordinateWdivide = shadowCoord / shadowCoord.w;
float shadow = 1.0;
if(shadowCoordinateWdivide.x >= 0.0 && shadowCoordinateWdivide.x < 1.0 &&
shadowCoordinateWdivide.y >= 0.0 && shadowCoordinateWdivide.y < 1.0 &&
shadowCoordinateWdivide.z >= 0.0 && shadowCoordinateWdivide.z < 1.0) {
// Used to lower moiré pattern and self-shadowing
shadowCoordinateWdivide.z += 0.0005;
float distanceFromLight = texture2D(shadowMap, shadowCoordinateWdivide.st).z;
if(shadowCoord.w > 0.0) {
shadow = distanceFromLight < shadowCoordinateWdivide.z ? 0.0 : 1.0;
}
}
gl_FragColor = vec4((color * shadow).xyz, color.a);
}