void SunLightSource::UpdateSMCamera(Camera const & scene_camera) { float3 const dir = this->Direction(); float3 up_vec; if (abs(MathLib::dot(-dir, scene_camera.UpVec())) > 0.95f) { up_vec = scene_camera.RightVec(); } else { up_vec = scene_camera.UpVec(); } float4x4 light_view = MathLib::look_at_lh(-dir, float3(0, 0, 0), up_vec); AABBox const aabb = CalcFrustumExtents(scene_camera, scene_camera.NearPlane(), scene_camera.FarPlane(), light_view); float3 const & center = aabb.Center(); float3 view_pos = MathLib::transform_coord(float3(center.x(), center.y(), aabb.Min().z()), MathLib::inverse(light_view)); sm_camera_->ViewParams(view_pos, view_pos + dir, up_vec); float3 dimensions = aabb.Max() - aabb.Min(); sm_camera_->ProjOrthoParams(dimensions.x(), dimensions.y(), 0.0f, dimensions.z()); }
void OCTree::DivideNode(size_t index, uint32_t curr_depth) { if (octree_[index].obj_ptrs.size() > 1) { size_t const this_size = octree_.size(); AABBox const parent_bb = octree_[index].bb; float3 const parent_center = parent_bb.Center(); octree_[index].first_child_index = static_cast<int>(this_size); octree_[index].visible = BO_No; octree_.resize(this_size + 8); for (SceneObjsType::const_reference so : octree_[index].obj_ptrs) { AABBox const & aabb = *so->PosBoundWS(); int mark[6]; mark[0] = aabb.Min().x() >= parent_center.x() ? 1 : 0; mark[1] = aabb.Min().y() >= parent_center.y() ? 2 : 0; mark[2] = aabb.Min().z() >= parent_center.z() ? 4 : 0; mark[3] = aabb.Max().x() >= parent_center.x() ? 1 : 0; mark[4] = aabb.Max().y() >= parent_center.y() ? 2 : 0; mark[5] = aabb.Max().z() >= parent_center.z() ? 4 : 0; for (int j = 0; j < 8; ++ j) { if (j == ((j & 1) ? mark[3] : mark[0]) + ((j & 2) ? mark[4] : mark[1]) + ((j & 4) ? mark[5] : mark[2])) { octree_[this_size + j].obj_ptrs.push_back(so); } } } for (size_t j = 0; j < 8; ++ j) { octree_node_t& new_node = octree_[this_size + j]; new_node.first_child_index = -1; new_node.bb = AABBox(float3((j & 1) ? parent_center.x() : parent_bb.Min().x(), (j & 2) ? parent_center.y() : parent_bb.Min().y(), (j & 4) ? parent_center.z() : parent_bb.Min().z()), float3((j & 1) ? parent_bb.Max().x() : parent_center.x(), (j & 2) ? parent_bb.Max().y() : parent_center.y(), (j & 4) ? parent_bb.Max().z() : parent_center.z())); if (curr_depth < max_tree_depth_) { this->DivideNode(this_size + j, curr_depth + 1); } } SceneObjsType empty; octree_[index].obj_ptrs.swap(empty); } }
BoundOverlap OCTree::BoundVisible(size_t index, AABBox const & aabb) const { BOOST_ASSERT(index < octree_.size()); octree_node_t const & node = octree_[index]; if ((node.visible != BO_No) && MathLib::intersect_aabb_aabb(node.bb, aabb)) { if (BO_Yes == node.visible) { return BO_Yes; } else { BOOST_ASSERT(BO_Partial == node.visible); if (node.first_child_index != -1) { float3 const center = node.bb.Center(); int mark[6]; mark[0] = aabb.Min().x() >= center.x() ? 1 : 0; mark[1] = aabb.Min().y() >= center.y() ? 2 : 0; mark[2] = aabb.Min().z() >= center.z() ? 4 : 0; mark[3] = aabb.Max().x() >= center.x() ? 1 : 0; mark[4] = aabb.Max().y() >= center.y() ? 2 : 0; mark[5] = aabb.Max().z() >= center.z() ? 4 : 0; for (int j = 0; j < 8; ++ j) { if (j == ((j & 1) ? mark[3] : mark[0]) + ((j & 2) ? mark[4] : mark[1]) + ((j & 4) ? mark[5] : mark[2])) { BoundOverlap const bo = this->BoundVisible(node.first_child_index + j, aabb); if (bo != BO_No) { return bo; } } } return BO_No; } else { return BO_Partial; } } } else { return BO_No; } }
void PSSMCascadedShadowLayer::UpdateCascades(Camera const & camera, float4x4 const & light_view_proj, float3 const & light_space_border) { float const range = camera.FarPlane() - camera.NearPlane(); float const ratio = camera.FarPlane() / camera.NearPlane(); std::vector<float> distances(intervals_.size() + 1); for (size_t i = 0; i < intervals_.size(); ++ i) { float p = i / static_cast<float>(intervals_.size()); float log = camera.NearPlane() * std::pow(ratio, p); float uniform = camera.NearPlane() + range * p; distances[i] = lambda_ * (log - uniform) + uniform; } distances[intervals_.size()] = camera.FarPlane(); for (size_t i = 0; i < intervals_.size(); ++ i) { AABBox aabb = CalcFrustumExtents(camera, distances[i], distances[i + 1], light_view_proj); aabb &= AABBox(float3(-1, -1, -1), float3(+1, +1, +1)); aabb.Min() -= light_space_border; aabb.Max() += light_space_border; aabb.Min().x() = +aabb.Min().x() * 0.5f + 0.5f; aabb.Min().y() = -aabb.Min().y() * 0.5f + 0.5f; aabb.Max().x() = +aabb.Max().x() * 0.5f + 0.5f; aabb.Max().y() = -aabb.Max().y() * 0.5f + 0.5f; std::swap(aabb.Min().y(), aabb.Max().y()); float3 const scale = float3(1.0f, 1.0f, 1.0f) / (aabb.Max() - aabb.Min()); float3 const bias = -aabb.Min() * scale; intervals_[i] = float2(distances[i], distances[i + 1]); scales_[i] = scale; biases_[i] = bias; } this->UpdateCropMats(); }
void SDSMCascadedShadowLayer::UpdateCascades(Camera const & camera, float4x4 const & light_view_proj, float3 const & light_space_border) { RenderFactory& rf = Context::Instance().RenderFactoryInstance(); RenderEngine& re = rf.RenderEngineInstance(); uint32_t const num_cascades = static_cast<uint32_t>(intervals_.size()); uint32_t const copy_index = frame_index_ & 1; uint32_t const read_back_index = (0 == frame_index_) ? copy_index : !copy_index; if (cs_support_) { re.BindFrameBuffer(FrameBufferPtr()); float max_blur_light_space = 8.0f / 1024; float3 max_cascade_scale(max_blur_light_space / light_space_border.x(), max_blur_light_space / light_space_border.y(), std::numeric_limits<float>::max()); int const TILE_DIM = 128; int dispatch_x = (depth_tex_->Width(0) + TILE_DIM - 1) / TILE_DIM; int dispatch_y = (depth_tex_->Height(0) + TILE_DIM - 1) / TILE_DIM; *interval_buff_param_ = interval_buff_; *interval_buff_uint_param_ = interval_buff_; *interval_buff_read_param_ = interval_buff_; *cascade_min_buff_uint_param_ = cascade_min_buff_; *cascade_max_buff_uint_param_ = cascade_max_buff_; *cascade_min_buff_read_param_ = cascade_min_buff_; *cascade_max_buff_read_param_ = cascade_max_buff_; *scale_buff_param_ = scale_buff_; *bias_buff_param_ = bias_buff_; *depth_tex_param_ = depth_tex_; *num_cascades_param_ = static_cast<int32_t>(num_cascades); *inv_depth_width_height_param_ = float2(1.0f / depth_tex_->Width(0), 1.0f / depth_tex_->Height(0)); *near_far_param_ = float2(camera.NearPlane(), camera.FarPlane()); float4x4 const & inv_proj = camera.InverseProjMatrix(); float3 upper_left = MathLib::transform_coord(float3(-1, +1, 1), inv_proj); float3 upper_right = MathLib::transform_coord(float3(+1, +1, 1), inv_proj); float3 lower_left = MathLib::transform_coord(float3(-1, -1, 1), inv_proj); *upper_left_param_ = upper_left; *xy_dir_param_ = float2(upper_right.x() - upper_left.x(), lower_left.y() - upper_left.y()); *view_to_light_view_proj_param_ = camera.InverseViewMatrix() * light_view_proj; *light_space_border_param_ = light_space_border; *max_cascade_scale_param_ = max_cascade_scale; re.Dispatch(*clear_z_bounds_tech_, 1, 1, 1); re.Dispatch(*reduce_z_bounds_from_depth_tech_, dispatch_x, dispatch_y, 1); re.Dispatch(*compute_log_cascades_from_z_bounds_tech_, 1, 1, 1); re.Dispatch(*clear_cascade_bounds_tech_, 1, 1, 1); re.Dispatch(*reduce_bounds_from_depth_tech_, dispatch_x, dispatch_y, 1); re.Dispatch(*compute_custom_cascades_tech_, 1, 1, 1); interval_buff_->CopyToBuffer(*interval_cpu_buffs_[copy_index]); scale_buff_->CopyToBuffer(*scale_cpu_buffs_[copy_index]); bias_buff_->CopyToBuffer(*bias_cpu_buffs_[copy_index]); GraphicsBuffer::Mapper interval_mapper(*interval_cpu_buffs_[read_back_index], BA_Read_Only); GraphicsBuffer::Mapper scale_mapper(*scale_cpu_buffs_[read_back_index], BA_Read_Only); GraphicsBuffer::Mapper bias_mapper(*bias_cpu_buffs_[read_back_index], BA_Read_Only); float2* interval_ptr = interval_mapper.Pointer<float2>(); float3* scale_ptr = scale_mapper.Pointer<float3>(); float3* bias_ptr = bias_mapper.Pointer<float3>(); for (size_t i = 0; i < intervals_.size(); ++ i) { float3 const & scale = scale_ptr[i]; float3 const & bias = bias_ptr[i]; intervals_[i] = interval_ptr[i]; scales_[i] = scale; biases_[i] = bias; } } else { float2 const near_far(camera.NearPlane(), camera.FarPlane()); reduce_z_bounds_from_depth_pp_->SetParam(1, near_far); reduce_z_bounds_from_depth_pp_->Apply(); for (uint32_t i = 1; i < depth_deriative_tex_->NumMipMaps(); ++ i) { int width = depth_deriative_tex_->Width(i - 1); int height = depth_deriative_tex_->Height(i - 1); float delta_x = 1.0f / width; float delta_y = 1.0f / height; float4 delta_offset(delta_x, delta_y, -delta_x / 2, -delta_y / 2); reduce_z_bounds_from_depth_mip_map_pp_->SetParam(0, delta_offset); reduce_z_bounds_from_depth_mip_map_pp_->OutputPin(0, depth_deriative_small_tex_, i - 1); reduce_z_bounds_from_depth_mip_map_pp_->Apply(); int sw = depth_deriative_tex_->Width(i); int sh = depth_deriative_tex_->Height(i); depth_deriative_small_tex_->CopyToSubTexture2D(*depth_deriative_tex_, 0, i, 0, 0, sw, sh, 0, i - 1, 0, 0, sw, sh); } compute_log_cascades_from_z_bounds_pp_->SetParam(1, static_cast<int32_t>(num_cascades)); compute_log_cascades_from_z_bounds_pp_->SetParam(2, near_far); compute_log_cascades_from_z_bounds_pp_->Apply(); interval_tex_->CopyToSubTexture2D(*interval_cpu_texs_[copy_index], 0, 0, 0, 0, num_cascades, 1, 0, 0, 0, 0, num_cascades, 1); Texture::Mapper interval_mapper(*interval_cpu_texs_[read_back_index], 0, 0, TMA_Read_Only, 0, 0, num_cascades, 1); Vector_T<half, 2>* interval_ptr = interval_mapper.Pointer<Vector_T<half, 2> >(); for (size_t i = 0; i < intervals_.size(); ++ i) { float2 const interval(static_cast<float>(interval_ptr[i].x()), static_cast<float>(interval_ptr[i].y())); AABBox aabb = CalcFrustumExtents(camera, interval.x(), interval.y(), light_view_proj); aabb &= AABBox(float3(-1, -1, -1), float3(+1, +1, +1)); aabb.Min() -= light_space_border; aabb.Max() += light_space_border; aabb.Min().x() = +aabb.Min().x() * 0.5f + 0.5f; aabb.Min().y() = -aabb.Min().y() * 0.5f + 0.5f; aabb.Max().x() = +aabb.Max().x() * 0.5f + 0.5f; aabb.Max().y() = -aabb.Max().y() * 0.5f + 0.5f; std::swap(aabb.Min().y(), aabb.Max().y()); float3 const scale = float3(1.0f, 1.0f, 1.0f) / (aabb.Max() - aabb.Min()); float3 const bias = -aabb.Min() * scale; intervals_[i] = interval; scales_[i] = scale; biases_[i] = bias; } } this->UpdateCropMats(); ++ frame_index_; }