その9(おまけ)
第9章:影が出ないときの確認ポイント
目的
つまずきやすいところを、症状別に確認できるようにする。
1. 影がまったく出ない
確認すること
Stage::Draw()でDirect3D::BeginShadowPass()を呼んでいるか。Model::DrawShadow(hDonut_)を呼んでいるか。Direct3D::EndShadowPass()を呼んでいるか。Stage::Draw()のメインパス前にPSSetShaderResources(1, 1, &pShadowSRV)を呼んでいるか。Simple3D.hlslにg_shadowMap : register(t1)があるか。Simple3D.hlslにg_shadowSampler : register(s1)があるか。Stage::Update()でmatLightVPを送っているか。
2. 画面全体が暗くなる
原因候補
hRoom_ を DrawShadow() している可能性が高い。
理由
部屋全体をシャドウパスに描くと、部屋の壁や天井がライトを遮って、室内全体が影になることがある。
対応
最初は、シャドウパスにはドーナツだけを描く。
Model::DrawShadow(hDonut_);
// Model::DrawShadow(hRoom_); は呼ばない
3. ドーナツの表面がザラザラする
原因候補
自分自身に影を落としている。
これをシャドウアクネという。
対応
Simple3D.hlsl の bias を大きくする。
この教材では現在この値を使っている。
float bias = 0.015;
それでも出る場合は少しずつ大きくする。
float bias = 0.02;
ただし、大きくしすぎると影が浮いたり消えたりする。
4. 影が消える、または薄すぎる
確認すること
biasが大きすぎないか。GetLightProjectionMatrix()の正射影サイズが広すぎないか。- シャドウマップ解像度が低すぎないか。
この教材ではまず次の値を使う。
XMMatrixOrthographicLH(20.0f, 20.0f, 1.0f, 50.0f);
5. 影の位置がライト方向と合わない
確認すること
GetLightViewMatrix()のlightEyeの向き。Simple3D.hlslのライト方向lightPositionの扱い。matLightVP = lightV * lightPの順番。DrawShadow()のmatLightWVP = World * LightView * LightProjectionの順番。
今回の配布プログラムでは、lightPosition を「光が来る方向ベクトル」として扱うため、lightEye は -lightDir * 10.0f とする。
XMVECTOR lightDir = XMVector3Normalize(XMLoadFloat4(&lightPosition));
XMVECTOR lightEye = -lightDir * 10.0f;
6. 次フレームで警告や描画崩れが出る
原因候補
シャドウマップをSRVにセットしたまま、次のフレームでDSVとして使おうとしている。
対応
メインパスの後で必ずSRVを解除する。
ID3D11ShaderResourceView* nullSRV = nullptr;
Direct3D::pContext->PSSetShaderResources(1, 1, &nullSRV);
7. この教材で使わないもの
この教材ではステンシルは使わない。
ステンシルで影の領域を作る
のではなく、
Simple3D.hlsl のピクセルシェーダーで深度比較する
方式に統一する。
No Comments