void RenderableLineBox::Init() { RenderFactory& rf = Context::Instance().RenderFactoryInstance(); RenderEffectPtr effect = SyncLoadRenderEffect("RenderableHelper.fxml"); technique_ = simple_forward_tech_ = effect->TechniqueByName("LineTec"); v0_ep_ = effect->ParameterByName("v0"); v1_ep_ = effect->ParameterByName("v1"); v2_ep_ = effect->ParameterByName("v2"); v3_ep_ = effect->ParameterByName("v3"); v4_ep_ = effect->ParameterByName("v4"); v5_ep_ = effect->ParameterByName("v5"); v6_ep_ = effect->ParameterByName("v6"); v7_ep_ = effect->ParameterByName("v7"); color_ep_ = effect->ParameterByName("color"); mvp_param_ = effect->ParameterByName("mvp"); float vertices[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; uint16_t indices[] = { 0, 1, 1, 3, 3, 2, 2, 0, 4, 5, 5, 7, 7, 6, 6, 4, 0, 4, 1, 5, 2, 6, 3, 7 }; rl_ = rf.MakeRenderLayout(); rl_->TopologyType(RenderLayout::TT_LineList); ElementInitData init_data; init_data.row_pitch = sizeof(vertices); init_data.slice_pitch = 0; init_data.data = vertices; GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindVertexStream(vb, make_tuple(vertex_element(VEU_Position, 0, EF_R32F))); init_data.row_pitch = sizeof(indices); init_data.slice_pitch = 0; init_data.data = indices; GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindIndexStream(ib, EF_R16UI); tc_aabb_ = AABBox(float3(0, 0, 0), float3(0, 0, 0)); *(effect->ParameterByName("pos_center")) = float3(0, 0, 0); *(effect->ParameterByName("pos_extent")) = float3(1, 1, 1); effect_attrs_ |= EA_SimpleForward; }
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); } }
RenderableSkyBox::RenderableSkyBox() : RenderableHelper(L"SkyBox") { RenderFactory& rf = Context::Instance().RenderFactoryInstance(); RenderEffectPtr effect = SyncLoadRenderEffect("SkyBox.fxml"); if (deferred_effect_) { this->BindDeferredEffect(effect); depth_tech_ = effect->TechniqueByName("DepthSkyBoxTech"); gbuffer_rt0_tech_ = effect->TechniqueByName("GBufferSkyBoxRT0Tech"); gbuffer_rt1_tech_ = effect->TechniqueByName("GBufferSkyBoxRT1Tech"); gbuffer_mrt_tech_ = effect->TechniqueByName("GBufferSkyBoxMRTTech"); special_shading_tech_ = effect->TechniqueByName("SkyBoxTech"); this->Technique(gbuffer_rt0_tech_); effect_attrs_ |= EA_SpecialShading; } else { this->Technique(effect->TechniqueByName("SkyBoxTech")); } float3 xyzs[] = { float3(1.0f, 1.0f, 1.0f), float3(1.0f, -1.0f, 1.0f), float3(-1.0f, 1.0f, 1.0f), float3(-1.0f, -1.0f, 1.0f), }; ElementInitData init_data; init_data.row_pitch = sizeof(xyzs); init_data.slice_pitch = 0; init_data.data = xyzs; rl_ = rf.MakeRenderLayout(); rl_->TopologyType(RenderLayout::TT_TriangleStrip); GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindVertexStream(vb, make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F))); pos_aabb_ = MathLib::compute_aabbox(&xyzs[0], &xyzs[4]); tc_aabb_ = AABBox(float3(0, 0, 0), float3(0, 0, 0)); }
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(); }
Sphere::Sphere(const double radius) : Geometry(AABBox(Point(-radius,-radius,-radius), Point(radius,radius,radius))), m_radius(radius) { m_radiusSqFixed = (m_radius-Ray::default_tmin)*(m_radius-Ray::default_tmin); }
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_; }
RenderDecal::RenderDecal(TexturePtr const & normal_tex, TexturePtr const & diffuse_tex, float3 const & diffuse_clr, TexturePtr const & specular_tex, float3 const & specular_level, float shininess) : RenderableHelper(L"Decal") { this->BindDeferredEffect(SyncLoadRenderEffect("Decal.fxml")); gbuffer_alpha_test_rt0_tech_ = deferred_effect_->TechniqueByName("DecalGBufferAlphaTestRT0Tech"); gbuffer_alpha_test_rt1_tech_ = deferred_effect_->TechniqueByName("DecalGBufferAlphaTestRT1Tech"); gbuffer_alpha_test_mrt_tech_ = deferred_effect_->TechniqueByName("DecalGBufferAlphaTestMRTTech"); technique_ = gbuffer_alpha_test_rt0_tech_; pos_aabb_ = AABBox(float3(-1, -1, -1), float3(1, 1, 1)); tc_aabb_ = AABBox(float3(0, 0, 0), float3(1, 1, 0)); float3 xyzs[] = { pos_aabb_.Corner(0), pos_aabb_.Corner(1), pos_aabb_.Corner(2), pos_aabb_.Corner(3), pos_aabb_.Corner(4), pos_aabb_.Corner(5), pos_aabb_.Corner(6), pos_aabb_.Corner(7) }; uint16_t indices[] = { 0, 2, 3, 3, 1, 0, 5, 7, 6, 6, 4, 5, 4, 0, 1, 1, 5, 4, 4, 6, 2, 2, 0, 4, 2, 6, 7, 7, 3, 2, 1, 3, 7, 7, 5, 1 }; RenderFactory& rf = Context::Instance().RenderFactoryInstance(); rl_ = rf.MakeRenderLayout(); rl_->TopologyType(RenderLayout::TT_TriangleList); ElementInitData init_data; init_data.row_pitch = sizeof(xyzs); init_data.slice_pitch = 0; init_data.data = xyzs; GraphicsBufferPtr vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindVertexStream(vb, make_tuple(vertex_element(VEU_Position, 0, EF_BGR32F))); init_data.row_pitch = sizeof(indices); init_data.slice_pitch = 0; init_data.data = indices; GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindIndexStream(ib, EF_R16UI); model_mat_ = float4x4::Identity(); effect_attrs_ |= EA_AlphaTest; inv_mv_ep_ = technique_->Effect().ParameterByName("inv_mv"); g_buffer_rt0_tex_param_ = deferred_effect_->ParameterByName("g_buffer_rt0_tex"); normal_tex_ = normal_tex; diffuse_tex_ = diffuse_tex; diffuse_clr_ = diffuse_clr; specular_tex_ = specular_tex; specular_level_ = specular_level.x(); shininess_ = shininess; }
RenderablePlane::RenderablePlane(float length, float width, int length_segs, int width_segs, bool has_tex_coord, bool has_tangent) : RenderableHelper(L"RenderablePlane") { RenderFactory& rf = Context::Instance().RenderFactoryInstance(); rl_ = rf.MakeRenderLayout(); rl_->TopologyType(RenderLayout::TT_TriangleList); std::vector<int16_t> positions; for (int y = 0; y < width_segs + 1; ++ y) { for (int x = 0; x < length_segs + 1; ++ x) { float3 pos(static_cast<float>(x) / length_segs, 1 - (static_cast<float>(y) / width_segs), 0.5f); int16_t s_pos[4] = { static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(pos.x() * 65535 - 32768), -32768, 32767)), static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(pos.y() * 65535 - 32768), -32768, 32767)), static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(pos.z() * 65535 - 32768), -32768, 32767)), 32767 }; positions.push_back(s_pos[0]); positions.push_back(s_pos[1]); positions.push_back(s_pos[2]); positions.push_back(s_pos[3]); } } ElementInitData init_data; init_data.row_pitch = static_cast<uint32_t>(positions.size() * sizeof(positions[0])); init_data.slice_pitch = 0; init_data.data = &positions[0]; GraphicsBufferPtr pos_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindVertexStream(pos_vb, make_tuple(vertex_element(VEU_Position, 0, EF_SIGNED_ABGR16))); if (has_tex_coord) { std::vector<int16_t> tex_coords; for (int y = 0; y < width_segs + 1; ++ y) { for (int x = 0; x < length_segs + 1; ++ x) { float3 tex_coord(static_cast<float>(x) / length_segs * 0.5f + 0.5f, static_cast<float>(y) / width_segs * 0.5f + 0.5f, 0.5f); int16_t s_tc[2] = { static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(tex_coord.x() * 65535 - 32768), -32768, 32767)), static_cast<int16_t>(MathLib::clamp<int32_t>(static_cast<int32_t>(tex_coord.y() * 65535 - 32768), -32768, 32767)), }; tex_coords.push_back(s_tc[0]); tex_coords.push_back(s_tc[1]); } } init_data.row_pitch = static_cast<uint32_t>(tex_coords.size() * sizeof(tex_coords[0])); init_data.slice_pitch = 0; init_data.data = &tex_coords[0]; GraphicsBufferPtr tex_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindVertexStream(tex_vb, make_tuple(vertex_element(VEU_TextureCoord, 0, EF_SIGNED_GR16))); } if (has_tangent) { std::vector<uint32_t> tangent(positions.size() / 4); ElementFormat fmt; if (rf.RenderEngineInstance().DeviceCaps().vertex_format_support(EF_ABGR8)) { fmt = EF_ABGR8; tangent.assign(tangent.size(), 0x807F7FFE); } else { BOOST_ASSERT(rf.RenderEngineInstance().DeviceCaps().vertex_format_support(EF_ARGB8)); fmt = EF_ARGB8; tangent.assign(tangent.size(), 0x80FE7F7F); } init_data.row_pitch = static_cast<uint32_t>(tangent.size() * sizeof(tangent[0])); init_data.slice_pitch = 0; init_data.data = &tangent[0]; GraphicsBufferPtr tex_vb = rf.MakeVertexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindVertexStream(tex_vb, make_tuple(vertex_element(VEU_Tangent, 0, fmt))); } std::vector<uint16_t> index; for (int y = 0; y < width_segs; ++ y) { for (int x = 0; x < length_segs; ++ x) { index.push_back(static_cast<uint16_t>((y + 0) * (length_segs + 1) + (x + 0))); index.push_back(static_cast<uint16_t>((y + 0) * (length_segs + 1) + (x + 1))); index.push_back(static_cast<uint16_t>((y + 1) * (length_segs + 1) + (x + 1))); index.push_back(static_cast<uint16_t>((y + 1) * (length_segs + 1) + (x + 1))); index.push_back(static_cast<uint16_t>((y + 1) * (length_segs + 1) + (x + 0))); index.push_back(static_cast<uint16_t>((y + 0) * (length_segs + 1) + (x + 0))); } } init_data.row_pitch = static_cast<uint32_t>(index.size() * sizeof(index[0])); init_data.slice_pitch = 0; init_data.data = &index[0]; GraphicsBufferPtr ib = rf.MakeIndexBuffer(BU_Static, EAH_GPU_Read | EAH_Immutable, &init_data); rl_->BindIndexStream(ib, EF_R16UI); pos_aabb_ = AABBox(float3(-length / 2, -width / 2, 0), float3(+length / 2, +width / 2, 0)); tc_aabb_ = AABBox(float3(0, 0, 0), float3(1, 1, 0)); }
inline bool YZRect::computeAABBox(float, float, AABBox& bbox) const { bbox = AABBox(glm::vec3(_k-0.0001, _y_dim.x, _z_dim.x), glm::vec3(_k+0.0001, _y_dim.y, _z_dim.y)); return true; }
void ShadowMapRenderer::setupVirtualLightCamera(Camera* camera, DirectionalLightNode* lightNode, int cascadeIndex) { const float BOUND_EXPAND_FACTOR = 0.8f; _Assert(camera != NULL); _Assert(cascadeIndex >= 0 && cascadeIndex < CASCADE_COUNTS); DirectionalLight* dirLight = lightNode->GetDirLight(); Vector3 lightDir = dirLight->GetDirection(); lightDir.Normalize(); Vector3 frustumPos[5]; { float farZ = 0; float aspect = 0; float fov = 0; camera->GetCameraParams(NULL, &farZ, &fov, &aspect); farZ *= calcCascadeDist(cascadeIndex); float fy = farZ * tanf(fov / 2.0f); float fx = aspect * fy; frustumPos[0] = Vector3::Zero; frustumPos[1] = Vector3(-fx, fy, farZ); frustumPos[2] = Vector3( fx, fy, farZ); frustumPos[3] = Vector3(-fx, -fy, farZ); frustumPos[4] = Vector3( fx, -fy, farZ); } D3DXMATRIX matCameraViewInv; D3DXMatrixInverse(&matCameraViewInv, 0, &camera->ViewMatrix()); D3DXMATRIX matLightView; { Vector3 lightPos = lightNode->GetWorldPosition(); D3DXMATRIX matRotTranspose, matTransInverse; D3DXMatrixTranspose(&matRotTranspose, &(lightNode->GetWorldOrient().Matrix())); D3DXMatrixTranslation(&matTransInverse, -lightPos.x, -lightPos.y, -lightPos.z); matLightView = matTransInverse * matRotTranspose; } AABBox lightSpaceBound; for(int i = 0; i < 5; ++i) { Vector3 posW = PosVecTransform(frustumPos[i], matCameraViewInv); Vector3 posL = PosVecTransform(posW, matLightView); lightSpaceBound = AABBox::CombinePoint(lightSpaceBound, posL); } float nearZ = 0.1f; float farZ = 0; float width = 0; float height = 0; { Vector3 lookDir = camera->GetWorldForward(); lookDir.Normalize(); float adjustFactor = lookDir.Dot(lightDir); // lookDir与lightDir贴近时, 向后扩展virtualCamera范围 float expandDist = adjustFactor * BOUND_EXPAND_FACTOR * fabsf(lightSpaceBound.mMax.z - lightSpaceBound.mMin.z); Vector3 centerL = lightSpaceBound.GetCenter(); D3DXMATRIX matLightViewInv; D3DXMatrixInverse(&matLightViewInv, 0, &matLightView); Vector3 centerW = PosVecTransform(centerL, matLightViewInv); float lightDist = fabsf(lightSpaceBound.mMax.z - lightSpaceBound.mMin.z) / 2.0f; width = fabsf(lightSpaceBound.mMax.x - lightSpaceBound.mMin.x); height = fabsf(lightSpaceBound.mMax.y - lightSpaceBound.mMin.y); farZ = 2.0f * lightDist + expandDist; mVirtualCamera[cascadeIndex].pos = centerW - (lightDist + expandDist) * lightDir; } D3DXMATRIX matLightProj; D3DXMatrixOrthoLH(&matLightProj, width, height, nearZ, farZ); D3DXMATRIX matVirtualCameraView; { Vector3 virtualCameraPos = mVirtualCamera[cascadeIndex].pos; D3DXMATRIX matRotTranspose, matTransInverse; D3DXMatrixTranspose(&matRotTranspose, &(lightNode->GetWorldOrient().Matrix())); D3DXMatrixTranslation(&matTransInverse, -virtualCameraPos.x, -virtualCameraPos.y, -virtualCameraPos.z); matVirtualCameraView = matTransInverse * matRotTranspose; mVirtualCamera[cascadeIndex].bound = AABBox::MatTransform(AABBox(Vector3(0, 0, farZ/2.0f), width, height, farZ), InversedMatrix(matVirtualCameraView)); } mVirtualCamera[cascadeIndex].matVP = matVirtualCameraView * matLightProj; }
// Build KD tree for tris void KDNode::build(std::vector<Triangle*> &tris, int depth){ leaf = false; triangles = std::vector<Triangle*>(); left = NULL; right = NULL; box = AABBox(); if (tris.size() == 0) return; if (depth > 25 || tris.size() <= 6) { triangles = tris; leaf = true; box = tris[0]->get_bounding_box(); for (long i=1; i<tris.size(); i++) { box.expand(tris[i]->get_bounding_box()); } left = new KDNode(); right = new KDNode(); left->triangles = std::vector<Triangle*>(); right->triangles = std::vector<Triangle*>(); return; } box = tris[0]->get_bounding_box(); Vec midpt = Vec(); double tris_recp = 1.0/tris.size(); for (long i=1; i<tris.size(); i++) { box.expand(tris[i]->get_bounding_box()); midpt = midpt + (tris[i]->get_midpoint() * tris_recp); } std::vector<Triangle*> left_tris; std::vector<Triangle*> right_tris; int axis = box.get_longest_axis(); for (long i=0; i<tris.size(); i++) { switch (axis) { case 0: midpt.x >= tris[i]->get_midpoint().x ? right_tris.push_back(tris[i]) : left_tris.push_back(tris[i]); break; case 1: midpt.y >= tris[i]->get_midpoint().y ? right_tris.push_back(tris[i]) : left_tris.push_back(tris[i]); break; case 2: midpt.z >= tris[i]->get_midpoint().z ? right_tris.push_back(tris[i]) : left_tris.push_back(tris[i]); break; } } if (tris.size() == left_tris.size() || tris.size() == right_tris.size()) { triangles = tris; leaf = true; box = tris[0]->get_bounding_box(); for (long i=1; i<tris.size(); i++) { box.expand(tris[i]->get_bounding_box()); } left = new KDNode(); right = new KDNode(); left->triangles = std::vector<Triangle*>(); right->triangles = std::vector<Triangle*>(); return; } left = new KDNode(); right = new KDNode(); left->build(left_tris, depth+1); right->build(right_tris, depth+1); return; }
void OCTree::ClipScene() { if (rebuild_tree_) { octree_.resize(1); AABBox bb_root(float3(0, 0, 0), float3(0, 0, 0)); octree_[0].first_child_index = -1; octree_[0].visible = BO_No; for (SceneObjsType::const_reference obj : scene_objs_) { uint32_t const attr = obj->Attrib(); if ((attr & SceneObject::SOA_Cullable) && !(attr & SceneObject::SOA_Moveable)) { bb_root |= *obj->PosBoundWS(); octree_[0].obj_ptrs.push_back(obj); } } float3 const & center = bb_root.Center(); float3 const & extent = bb_root.HalfSize(); float longest_dim = std::max(std::max(extent.x(), extent.y()), extent.z()); float3 new_extent(longest_dim, longest_dim, longest_dim); octree_[0].bb = AABBox(center - new_extent, center + new_extent); this->DivideNode(0, 1); rebuild_tree_ = false; } #ifdef KLAYGE_DRAW_NODES if (!node_renderable_) { node_renderable_ = MakeSharedPtr<NodeRenderable>(); } checked_pointer_cast<NodeRenderable>(node_renderable_)->ClearInstances(); #endif if (!octree_.empty()) { this->NodeVisible(0); } App3DFramework& app = Context::Instance().AppInstance(); Camera& camera = app.ActiveCamera(); float4x4 view_proj = camera.ViewProjMatrix(); DeferredRenderingLayerPtr const & drl = Context::Instance().DeferredRenderingLayerInstance(); if (drl) { int32_t cas_index = drl->CurrCascadeIndex(); if (cas_index >= 0) { view_proj *= drl->GetCascadedShadowLayer()->CascadeCropMatrix(cas_index); } } if (camera.OmniDirectionalMode()) { for (SceneObjsType::const_reference obj : scene_objs_) { if (obj->Visible()) { uint32_t const attr = obj->Attrib(); if (attr & SceneObject::SOA_Moveable) { obj->UpdateAbsModelMatrix(); } if (attr & SceneObject::SOA_Cullable) { AABBoxPtr aabb_ws = obj->PosBoundWS(); obj->VisibleMark((MathLib::perspective_area(camera.EyePos(), view_proj, *aabb_ws) > small_obj_threshold_) ? BO_Yes : BO_No); } } else { obj->VisibleMark(BO_No); } } } else { if (!octree_.empty()) { this->MarkNodeObjs(0, false); } for (SceneObjsType::const_reference obj : scene_objs_) { if (obj->Visible()) { BoundOverlap visible = this->VisibleTestFromParent(obj, camera.EyePos(), view_proj); if (BO_Partial == visible) { uint32_t const attr = obj->Attrib(); if (attr & SceneObject::SOA_Moveable) { obj->UpdateAbsModelMatrix(); } if (attr & SceneObject::SOA_Cullable) { if (attr & SceneObject::SOA_Moveable) { obj->VisibleMark(this->AABBVisible(*obj->PosBoundWS())); } else { obj->VisibleMark(visible); } } else { obj->VisibleMark(BO_Yes); } } else { obj->VisibleMark(visible); } } } } #ifdef KLAYGE_DRAW_NODES node_renderable_->Render(); #endif }