作者:i_dovelemon
日期:2017/04/19
来源:CSDN
主题:Shadow Map, PSSM
math::Matrix RenderImp::BuildRefLightSpaceMatrix() {
math::Vector light_dir = -scene::Scene::GetLight(0).dir; // For opengl, +z point out of the screen
light_dir.w = 0;
// Build light space
math::Vector lit_space_right = math::Cross(light_dir, math::Vector(0.0f, 1.0f, 0.0f));
lit_space_right.Normalize();
math::Vector lit_space_up = math::Cross(light_dir, lit_space_right);
lit_space_up.Normalize();
math::Matrix light_space_to_world_space;
light_space_to_world_space.MakeRotateMatrix(lit_space_right, lit_space_up, light_dir);
return light_space_to_world_space;
}
void RenderImp::BuildBasicLightFrustums(math::Matrix light_space_to_world_space) {
math::Matrix view_to_world = scene::Scene::GetCamera(scene::PRIMIAY_CAM)->GetViewMatrix();
view_to_world.Inverse();
math::Matrix world_to_light = light_space_to_world_space;
world_to_light.Inverse();
math::Matrix view_to_light;
view_to_light.MakeIdentityMatrix();
view_to_light.Mul(world_to_light);
view_to_light.Mul(view_to_world);
for (int32_t i = 0; i < kPSSMSplitNum; i++) {
math::Vector points[8];
m_SplitFrustums[i].GetPoints(points);
for (int32_t j = 0; j < 8; j++) {
points[j] = view_to_light * points[j];
}
math::AABB bv(points);
bv.m_Max.z += kMaxSceneSize; // Make frustum include all potential shadow caster objects
points[Render::NLU] = math::Vector(bv.m_Min.x, bv.m_Max.y, bv.m_Max.z); // NLU
points[Render::NLD] = math::Vector(bv.m_Min.x, bv.m_Min.y, bv.m_Max.z); // NLD
points[Render::NRU] = math::Vector(bv.m_Max.x, bv.m_Max.y, bv.m_Max.z); // NRU
points[Render::NRD] = math::Vector(bv.m_Max.x, bv.m_Min.y, bv.m_Max.z); // NRD
points[Render::FLU] = math::Vector(bv.m_Min.x, bv.m_Max.y, bv.m_Min.z); // FLU
points[Render::FLD] = math::Vector(bv.m_Min.x, bv.m_Min.y, bv.m_Min.z); // FLD
points[Render::FRU] = math::Vector(bv.m_Max.x, bv.m_Max.y, bv.m_Min.z); // FRU
points[Render::FRD] = math::Vector(bv.m_Max.x, bv.m_Min.y, bv.m_Min.z); // FRD
m_LightSpaceFrustum[i].Build(points);
}
}
bv.m_Max.z += kMaxSceneSize; // Make frustum include all potential shadow caster objects
void RenderImp::ShrinkLightFrustum(math::AABB casters, math::AABB receivers, Frustum& frustum) {
math::AABB frustum_bv = frustum.GetBoundBox();
frustum_bv.m_Min.x = std::max(std::max(receivers.m_Min.x, casters.m_Min.x), frustum_bv.m_Min.x);
frustum_bv.m_Max.x = std::min(std::min(receivers.m_Max.x, casters.m_Max.x), frustum_bv.m_Max.x);
frustum_bv.m_Min.y = std::max(std::max(receivers.m_Min.y, casters.m_Min.y), frustum_bv.m_Min.y);
frustum_bv.m_Max.y = std::min(std::min(receivers.m_Max.y, casters.m_Max.y), frustum_bv.m_Max.y);
frustum_bv.m_Min.z = std::max(receivers.m_Min.z, frustum_bv.m_Min.z);
frustum_bv.m_Max.z = std::max(casters.m_Max.z, frustum_bv.m_Max.z);
math::Vector points[8];
points[Render::NLU] = math::Vector(frustum_bv.m_Min.x, frustum_bv.m_Max.y, frustum_bv.m_Max.z); // NLU
points[Render::NLD] = math::Vector(frustum_bv.m_Min.x, frustum_bv.m_Min.y, frustum_bv.m_Max.z); // NLD
points[Render::NRU] = math::Vector(frustum_bv.m_Max.x, frustum_bv.m_Max.y, frustum_bv.m_Max.z); // NRU
points[Render::NRD] = math::Vector(frustum_bv.m_Max.x, frustum_bv.m_Min.y, frustum_bv.m_Max.z); // NRD
points[Render::FLU] = math::Vector(frustum_bv.m_Min.x, frustum_bv.m_Max.y, frustum_bv.m_Min.z); // FLU
points[Render::FLD] = math::Vector(frustum_bv.m_Min.x, frustum_bv.m_Min.y, frustum_bv.m_Min.z); // FLD
points[Render::FRU] = math::Vector(frustum_bv.m_Max.x, frustum_bv.m_Max.y, frustum_bv.m_Min.z); // FRU
points[Render::FRD] = math::Vector(frustum_bv.m_Max.x, frustum_bv.m_Min.y, frustum_bv.m_Min.z); // FRD
frustum.Build(points);
}