void CreateShadowMap()
{
// デュード モデルのワールド行列。
world = Matrix.CreateRotationY(MathHelper.ToRadians(rotateDude));
dudeBoxLocal.GetCorners(corners);
dudeBoxWorld = BoundingBoxHelper.Empty;
foreach (var corner in corners)
{
Vector3 cornerLocal = corner;
Vector3 cornerWorld;
Vector3.Transform(ref cornerLocal, ref world, out cornerWorld);
BoundingBoxHelper.Merge(ref dudeBoxWorld, ref cornerWorld);
}
// ライト カメラへ指定するシーン領域。
BoundingBox actualSceneBox;
if (useCameraFrustumSceneBox)
{
// 視錐台全体とする場合。
cameraFrustum.Matrix = camera.View * camera.Projection;
cameraFrustum.GetCorners(corners);
actualSceneBox = BoundingBox.CreateFromPoints(corners);
}
else
{
// 明示する場合。
actualSceneBox = sceneBox;
BoundingBoxHelper.Merge(ref actualSceneBox, camera.Position);
}
// 表示カメラの分割。
// デフォルトのラムダ値 0.5f ではカメラ手前が少し狭すぎるか?
// ここは表示カメラの far の値に応じて調整する。
pssm.Count = splitCount;
pssm.Lambda = 0.4f;
pssm.View = camera.View;
pssm.SceneBox = actualSceneBox;
pssm.Split(splitDistances, splitProjections);
// 使用するライト カメラ ビルダの選択。
LightCameraBuilder currentLightCameraBuilder;
switch (currentLightCameraType)
{
case LightCameraType.LiSPSM:
currentLightCameraBuilder = liSPSMLightCameraBuilder;
break;
case LightCameraType.Uniform:
currentLightCameraBuilder = uniformLightCameraBuilder;
break;
default:
currentLightCameraBuilder = basicLightCameraBuilder;
break;
}
// 各分割で共通のビルダ プロパティを設定。
currentLightCameraBuilder.EyeView = camera.View;
currentLightCameraBuilder.LightDirection = lightDirection;
currentLightCameraBuilder.SceneBox = sceneBox;
for (int i = 0; i < splitCount; i++)
{
// 射影行列は分割毎に異なる。
currentLightCameraBuilder.EyeProjection = splitProjections[i];
// ライトのビューおよび射影行列の算出。
Matrix lightView;
Matrix lightProjection;
currentLightCameraBuilder.Build(out lightView, out lightProjection);
// 後のモデル描画用にライト空間行列を算出。
Matrix.Multiply(ref lightView, ref lightProjection, out lightViewProjections[i]);
// シャドウ マップを描画。
shadowMaps[i].Form = shadowMapForm;
shadowMaps[i].Size = ShadowMapSizes[currentShadowMapSizeIndex];
shadowMaps[i].Draw(camera.View, splitProjections[i], lightView, lightProjection, DrawShadowCasters);
// VSM の場合は生成したシャドウ マップへブラーを適用。
if (shadowMapForm == ShadowMapForm.Variance)
{
if (gaussianBlur == null)
{
var shadowMapSize = ShadowMapSizes[currentShadowMapSizeIndex];
gaussianBlur = new GaussianBlur(
GraphicsDevice, shadowMapSize, shadowMapSize, SurfaceFormat.Vector2, gaussianBlurEffect);
gaussianBlur.Radius = 7;
gaussianBlur.Amount = 7;
}
gaussianBlur.Filter(shadowMaps[i].RenderTarget, shadowMaps[i].RenderTarget);
}
}
}