diff options
-rw-r--r-- | editor/plugins/node_3d_editor_plugin.cpp | 2 | ||||
-rw-r--r-- | editor/plugins/script_editor_plugin.cpp | 42 | ||||
-rw-r--r-- | editor/plugins/script_editor_plugin.h | 2 | ||||
-rw-r--r-- | modules/gltf/gltf_document.cpp | 2 | ||||
-rw-r--r-- | modules/lightmapper_rd/lm_compute.glsl | 73 | ||||
-rw-r--r-- | modules/raycast/raycast_occlusion_cull.cpp | 123 | ||||
-rw-r--r-- | modules/raycast/raycast_occlusion_cull.h | 17 | ||||
-rw-r--r-- | scene/animation/animation_blend_tree.cpp | 2 | ||||
-rw-r--r-- | servers/rendering/renderer_scene_occlusion_cull.h | 24 |
9 files changed, 159 insertions, 128 deletions
diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 5263352502..cf451dce91 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -4820,7 +4820,7 @@ void _update_all_gizmos(Node *p_node) { } void Node3DEditor::update_all_gizmos(Node *p_node) { - if (!p_node && get_tree()) { + if (!p_node && is_inside_tree()) { p_node = get_tree()->get_edited_scene_root(); } diff --git a/editor/plugins/script_editor_plugin.cpp b/editor/plugins/script_editor_plugin.cpp index ee9103be44..07e4d4ebf0 100644 --- a/editor/plugins/script_editor_plugin.cpp +++ b/editor/plugins/script_editor_plugin.cpp @@ -808,39 +808,35 @@ void ScriptEditor::_copy_script_path() { } void ScriptEditor::_close_other_tabs() { - int child_count = tab_container->get_child_count(); int current_idx = tab_container->get_current_tab(); - for (int i = child_count - 1; i >= 0; i--) { - if (i == current_idx) { - continue; - } - - tab_container->set_current_tab(i); - ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); - - if (se) { - // Maybe there are unsaved changes - if (se->is_unsaved()) { - _ask_close_current_unsaved_tab(se); - continue; - } + for (int i = tab_container->get_child_count() - 1; i >= 0; i--) { + if (i != current_idx) { + script_close_queue.push_back(i); } - - _close_current_tab(false); } + _queue_close_tabs(); } void ScriptEditor::_close_all_tabs() { - int child_count = tab_container->get_child_count(); - for (int i = child_count - 1; i >= 0; i--) { - tab_container->set_current_tab(i); - ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(i)); + for (int i = tab_container->get_child_count() - 1; i >= 0; i--) { + script_close_queue.push_back(i); + } + _queue_close_tabs(); +} + +void ScriptEditor::_queue_close_tabs() { + while (!script_close_queue.is_empty()) { + int idx = script_close_queue.front()->get(); + script_close_queue.pop_front(); + tab_container->set_current_tab(idx); + ScriptEditorBase *se = Object::cast_to<ScriptEditorBase>(tab_container->get_child(idx)); if (se) { - // Maybe there are unsaved changes + // Maybe there are unsaved changes. if (se->is_unsaved()) { _ask_close_current_unsaved_tab(se); - continue; + erase_tab_confirm->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &ScriptEditor::_queue_close_tabs), varray(), CONNECT_ONESHOT); + break; } } diff --git a/editor/plugins/script_editor_plugin.h b/editor/plugins/script_editor_plugin.h index 920c3070e6..7620605570 100644 --- a/editor/plugins/script_editor_plugin.h +++ b/editor/plugins/script_editor_plugin.h @@ -309,6 +309,7 @@ class ScriptEditor : public PanelContainer { int history_pos; List<String> previous_scripts; + List<int> script_close_queue; void _tab_changed(int p_which); void _menu_option(int p_option); @@ -341,6 +342,7 @@ class ScriptEditor : public PanelContainer { void _close_docs_tab(); void _close_other_tabs(); void _close_all_tabs(); + void _queue_close_tabs(); void _copy_script_path(); diff --git a/modules/gltf/gltf_document.cpp b/modules/gltf/gltf_document.cpp index d4f4221663..df2856ec7c 100644 --- a/modules/gltf/gltf_document.cpp +++ b/modules/gltf/gltf_document.cpp @@ -6744,6 +6744,8 @@ Error GLTFDocument::_serialize_file(Ref<GLTFState> state, const String p_path) { Error GLTFDocument::save_scene(Node *p_node, const String &p_path, const String &p_src_path, uint32_t p_flags, float p_bake_fps, Ref<GLTFState> r_state) { + ERR_FAIL_NULL_V(p_node, ERR_INVALID_PARAMETER); + Ref<GLTFDocument> gltf_document; gltf_document.instantiate(); if (r_state == Ref<GLTFState>()) { diff --git a/modules/lightmapper_rd/lm_compute.glsl b/modules/lightmapper_rd/lm_compute.glsl index a71652d5c4..25b334c5eb 100644 --- a/modules/lightmapper_rd/lm_compute.glsl +++ b/modules/lightmapper_rd/lm_compute.glsl @@ -115,7 +115,12 @@ bool ray_hits_triangle(vec3 from, vec3 dir, float max_dist, vec3 p0, vec3 p1, ve return (r_distance > params.bias) && (r_distance < max_dist) && all(greaterThanEqual(r_barycentric, vec3(0.0))); } -bool trace_ray(vec3 p_from, vec3 p_to +const uint RAY_MISS = 0; +const uint RAY_FRONT = 1; +const uint RAY_BACK = 2; +const uint RAY_ANY = 3; + +uint trace_ray(vec3 p_from, vec3 p_to #if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) , out uint r_triangle, out vec3 r_barycentric @@ -125,6 +130,7 @@ bool trace_ray(vec3 p_from, vec3 p_to out float r_distance, out vec3 r_normal #endif ) { + /* world coords */ vec3 rel = p_to - p_from; @@ -150,10 +156,7 @@ bool trace_ray(vec3 p_from, vec3 p_to while (all(greaterThanEqual(icell, ivec3(0))) && all(lessThan(icell, ivec3(params.grid_size))) && iters < 1000) { uvec2 cell_data = texelFetch(usampler3D(grid, linear_sampler), icell, 0).xy; if (cell_data.x > 0) { //triangles here - bool hit = false; -#if defined(MODE_UNOCCLUDE) - bool hit_backface = false; -#endif + uint hit = RAY_MISS; float best_distance = 1e20; for (uint i = 0; i < cell_data.x; i++) { @@ -173,57 +176,46 @@ bool trace_ray(vec3 p_from, vec3 p_to vec3 vtx0 = vertices.data[triangle.indices.x].position; vec3 vtx1 = vertices.data[triangle.indices.y].position; vec3 vtx2 = vertices.data[triangle.indices.z].position; -#if defined(MODE_UNOCCLUDE) +#if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) vec3 normal = -normalize(cross((vtx0 - vtx1), (vtx0 - vtx2))); bool backface = dot(normal, dir) >= 0.0; #endif + float distance; vec3 barycentric; if (ray_hits_triangle(p_from, dir, rel_len, vtx0, vtx1, vtx2, distance, barycentric)) { #ifdef MODE_DIRECT_LIGHT - return true; //any hit good + return RAY_ANY; //any hit good #endif -#if defined(MODE_UNOCCLUDE) +#if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) if (!backface) { // the case of meshes having both a front and back face in the same plane is more common than // expected, so if this is a front-face, bias it closer to the ray origin, so it always wins over the back-face distance = max(params.bias, distance - params.bias); } - hit = true; - if (distance < best_distance) { - hit_backface = backface; + hit = backface ? RAY_BACK : RAY_FRONT; best_distance = distance; +#if defined(MODE_UNOCCLUDE) r_distance = distance; r_normal = normal; - } - #endif - #if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) - - hit = true; - if (distance < best_distance) { - best_distance = distance; r_triangle = tidx; r_barycentric = barycentric; +#endif } #endif } } -#if defined(MODE_UNOCCLUDE) +#if defined(MODE_UNOCCLUDE) || defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) - if (hit) { - return hit_backface; - } -#endif -#if defined(MODE_BOUNCE_LIGHT) || defined(MODE_LIGHT_PROBES) - if (hit) { - return true; + if (hit != RAY_MISS) { + return hit; } #endif } @@ -239,7 +231,7 @@ bool trace_ray(vec3 p_from, vec3 p_to iters++; } - return false; + return RAY_MISS; } const float PI = 3.14159265f; @@ -339,7 +331,7 @@ void main() { continue; //no need to do anything } - if (!trace_ray(position + light_dir * params.bias, light_pos)) { + if (trace_ray(position + light_dir * params.bias, light_pos) == RAY_MISS) { vec3 light = lights.data[i].color * lights.data[i].energy * attenuation; if (lights.data[i].static_bake) { static_light += light; @@ -410,6 +402,7 @@ void main() { vec4(0.0, 0.0, 0.0, 1.0)); #endif vec3 light_average = vec3(0.0); + float active_rays = 0.0; for (uint i = params.ray_from; i < params.ray_to; i++) { vec3 ray_dir = normal_mat * vogel_hemisphere(i, params.ray_count, quick_hash(vec2(atlas_pos))); @@ -417,7 +410,8 @@ void main() { vec3 barycentric; vec3 light = vec3(0.0); - if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + uint trace_result = trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric); + if (trace_result == RAY_FRONT) { //hit a triangle vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; @@ -425,7 +419,8 @@ void main() { vec3 uvw = vec3(barycentric.x * uv0 + barycentric.y * uv1 + barycentric.z * uv2, float(triangles.data[tidx].slice)); light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; - } else if (params.env_transform[0][3] == 0.0) { // Use env_transform[0][3] to indicate when we are computing the first bounce + active_rays += 1.0; + } else if (trace_result == RAY_MISS && params.env_transform[0][3] == 0.0) { // Use env_transform[0][3] to indicate when we are computing the first bounce // Did not hit a triangle, reach out for the sky vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); @@ -439,6 +434,7 @@ void main() { st /= vec2(PI * 2.0, PI); light = textureLod(sampler2D(environment, linear_sampler), st, 0.0).rgb; + active_rays += 1.0; } light_average += light; @@ -462,7 +458,9 @@ void main() { if (params.ray_from == 0) { light_total = vec3(0.0); } else { - light_total = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice)).rgb; + vec4 accum = imageLoad(bounce_accum, ivec3(atlas_pos, params.atlas_slice)); + light_total = accum.rgb; + active_rays += accum.a; } light_total += light_average; @@ -477,7 +475,9 @@ void main() { #endif if (params.ray_to == params.ray_count) { - light_total /= float(params.ray_count); + if (active_rays > 0) { + light_total /= active_rays; + } imageStore(dest_light, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); #ifndef USE_SH_LIGHTMAPS vec4 accum = imageLoad(accum_light, ivec3(atlas_pos, params.atlas_slice)); @@ -485,7 +485,7 @@ void main() { imageStore(accum_light, ivec3(atlas_pos, params.atlas_slice), accum); #endif } else { - imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, 1.0)); + imageStore(bounce_accum, ivec3(atlas_pos, params.atlas_slice), vec4(light_total, active_rays)); } #endif @@ -518,7 +518,7 @@ void main() { float d; vec3 norm; - if (trace_ray(base_pos, ray_to, d, norm)) { + if (trace_ray(base_pos, ray_to, d, norm) == RAY_BACK) { if (d < min_d) { vertex_pos = base_pos + rays[i] * d + norm * params.bias * 10.0; //this bias needs to be greater than the regular bias, because otherwise later, rays will go the other side when pointing back. min_d = d; @@ -558,7 +558,8 @@ void main() { vec3 barycentric; vec3 light; - if (trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric)) { + uint trace_result = trace_ray(position + ray_dir * params.bias, position + ray_dir * length(params.world_size), tidx, barycentric); + if (trace_result == RAY_FRONT) { vec2 uv0 = vertices.data[triangles.data[tidx].indices.x].uv; vec2 uv1 = vertices.data[triangles.data[tidx].indices.y].uv; vec2 uv2 = vertices.data[triangles.data[tidx].indices.z].uv; @@ -566,7 +567,7 @@ void main() { light = textureLod(sampler2DArray(source_light, linear_sampler), uvw, 0.0).rgb; light += textureLod(sampler2DArray(source_direct_light, linear_sampler), uvw, 0.0).rgb; - } else { + } else if (trace_result == RAY_MISS) { //did not hit a triangle, reach out for the sky vec3 sky_dir = normalize(mat3(params.env_transform) * ray_dir); diff --git a/modules/raycast/raycast_occlusion_cull.cpp b/modules/raycast/raycast_occlusion_cull.cpp index 88c0145ebc..a55b81c05d 100644 --- a/modules/raycast/raycast_occlusion_cull.cpp +++ b/modules/raycast/raycast_occlusion_cull.cpp @@ -66,28 +66,45 @@ void RaycastOcclusionCull::RaycastHZBuffer::resize(const Size2i &p_size) { void RaycastOcclusionCull::RaycastHZBuffer::update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool) { CameraRayThreadData td; - td.camera_matrix = p_cam_projection; - td.camera_transform = p_cam_transform; - td.camera_orthogonal = p_cam_orthogonal; td.thread_count = p_thread_work_pool.get_thread_count(); + td.z_near = p_cam_projection.get_z_near(); + td.z_far = p_cam_projection.get_z_far() * 1.05f; + td.camera_pos = p_cam_transform.origin; + td.camera_dir = -p_cam_transform.basis.get_axis(2); + td.camera_orthogonal = p_cam_orthogonal; + + CameraMatrix inv_camera_matrix = p_cam_projection.inverse(); + Vector3 camera_corner_proj = Vector3(-1.0f, -1.0f, -1.0f); + Vector3 camera_corner_view = inv_camera_matrix.xform(camera_corner_proj); + td.pixel_corner = p_cam_transform.xform(camera_corner_view); + + Vector3 top_corner_proj = Vector3(-1.0f, 1.0f, -1.0f); + Vector3 top_corner_view = inv_camera_matrix.xform(top_corner_proj); + Vector3 top_corner_world = p_cam_transform.xform(top_corner_view); + + Vector3 left_corner_proj = Vector3(1.0f, -1.0f, -1.0f); + Vector3 left_corner_view = inv_camera_matrix.xform(left_corner_proj); + Vector3 left_corner_world = p_cam_transform.xform(left_corner_view); + + td.pixel_u_interp = left_corner_world - td.pixel_corner; + td.pixel_v_interp = top_corner_world - td.pixel_corner; + + debug_tex_range = td.z_far; + p_thread_work_pool.do_work(td.thread_count, this, &RaycastHZBuffer::_camera_rays_threaded, &td); } -void RaycastOcclusionCull::RaycastHZBuffer::_camera_rays_threaded(uint32_t p_thread, RaycastOcclusionCull::RaycastHZBuffer::CameraRayThreadData *p_data) { +void RaycastOcclusionCull::RaycastHZBuffer::_camera_rays_threaded(uint32_t p_thread, const CameraRayThreadData *p_data) { uint32_t packs_total = camera_rays.size(); uint32_t total_threads = p_data->thread_count; uint32_t from = p_thread * packs_total / total_threads; uint32_t to = (p_thread + 1 == total_threads) ? packs_total : ((p_thread + 1) * packs_total / total_threads); - _generate_camera_rays(p_data->camera_transform, p_data->camera_matrix, p_data->camera_orthogonal, from, to); + _generate_camera_rays(p_data, from, to); } -void RaycastOcclusionCull::RaycastHZBuffer::_generate_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, int p_from, int p_to) { - Size2i buffer_size = sizes[0]; - - CameraMatrix inv_camera_matrix = p_cam_projection.inverse(); - float z_far = p_cam_projection.get_z_far() * 1.05f; - debug_tex_range = z_far; +void RaycastOcclusionCull::RaycastHZBuffer::_generate_camera_rays(const CameraRayThreadData *p_data, int p_from, int p_to) { + const Size2i &buffer_size = sizes[0]; RayPacket *ray_packets = camera_rays.ptr(); uint32_t *ray_masks = camera_ray_masks.ptr(); @@ -98,56 +115,52 @@ void RaycastOcclusionCull::RaycastHZBuffer::_generate_camera_rays(const Transfor int tile_y = (i / packs_size.x) * TILE_SIZE; for (int j = 0; j < TILE_RAYS; j++) { - float x = tile_x + j % TILE_SIZE; - float y = tile_y + j / TILE_SIZE; - - ray_masks[i * TILE_RAYS + j] = ~0U; + int x = tile_x + j % TILE_SIZE; + int y = tile_y + j / TILE_SIZE; if (x >= buffer_size.x || y >= buffer_size.y) { ray_masks[i * TILE_RAYS + j] = 0U; - } else { - float u = x / (buffer_size.x - 1); - float v = y / (buffer_size.y - 1); - u = u * 2.0f - 1.0f; - v = v * 2.0f - 1.0f; - - Plane pixel_proj = Plane(u, v, -1.0, 1.0); - Plane pixel_view = inv_camera_matrix.xform4(pixel_proj); - Vector3 pixel_world = p_cam_transform.xform(pixel_view.normal); - - Vector3 dir; - if (p_cam_orthogonal) { - dir = -p_cam_transform.basis.get_axis(2); - } else { - dir = (pixel_world - p_cam_transform.origin).normalized(); - } - - packet.ray.org_x[j] = pixel_world.x; - packet.ray.org_y[j] = pixel_world.y; - packet.ray.org_z[j] = pixel_world.z; + continue; + } - packet.ray.dir_x[j] = dir.x; - packet.ray.dir_y[j] = dir.y; - packet.ray.dir_z[j] = dir.z; + ray_masks[i * TILE_RAYS + j] = ~0U; - packet.ray.tnear[j] = 0.0f; + float u = (float(x) + 0.5f) / buffer_size.x; + float v = (float(y) + 0.5f) / buffer_size.y; + Vector3 pixel_pos = p_data->pixel_corner + u * p_data->pixel_u_interp + v * p_data->pixel_v_interp; - packet.ray.time[j] = 0.0f; + packet.ray.tnear[j] = p_data->z_near; - packet.ray.flags[j] = 0; - packet.ray.mask[j] = -1; - packet.hit.geomID[j] = RTC_INVALID_GEOMETRY_ID; + Vector3 dir; + if (p_data->camera_orthogonal) { + dir = -p_data->camera_dir; + packet.ray.org_x[j] = pixel_pos.x - dir.x * p_data->z_near; + packet.ray.org_y[j] = pixel_pos.y - dir.y * p_data->z_near; + packet.ray.org_z[j] = pixel_pos.z - dir.z * p_data->z_near; + } else { + dir = (pixel_pos - p_data->camera_pos).normalized(); + packet.ray.org_x[j] = p_data->camera_pos.x; + packet.ray.org_y[j] = p_data->camera_pos.y; + packet.ray.org_z[j] = p_data->camera_pos.z; + packet.ray.tnear[j] /= dir.dot(p_data->camera_dir); } - packet.ray.tfar[j] = z_far; + packet.ray.dir_x[j] = dir.x; + packet.ray.dir_y[j] = dir.y; + packet.ray.dir_z[j] = dir.z; + + packet.ray.tfar[j] = p_data->z_far; + packet.ray.time[j] = 0.0f; + + packet.ray.flags[j] = 0; + packet.ray.mask[j] = -1; + packet.hit.geomID[j] = RTC_INVALID_GEOMETRY_ID; } } } -void RaycastOcclusionCull::RaycastHZBuffer::sort_rays() { - if (is_empty()) { - return; - } +void RaycastOcclusionCull::RaycastHZBuffer::sort_rays(const Vector3 &p_camera_dir, bool p_orthogonal) { + ERR_FAIL_COND(is_empty()); Size2i buffer_size = sizes[0]; for (int i = 0; i < packs_size.y; i++) { @@ -161,7 +174,17 @@ void RaycastOcclusionCull::RaycastHZBuffer::sort_rays() { } int k = tile_i * TILE_SIZE + tile_j; int packet_index = i * packs_size.x + j; - mips[0][y * buffer_size.x + x] = camera_rays[packet_index].ray.tfar[k]; + float d = camera_rays[packet_index].ray.tfar[k]; + + if (!p_orthogonal) { + const float &dir_x = camera_rays[packet_index].ray.dir_x[k]; + const float &dir_y = camera_rays[packet_index].ray.dir_y[k]; + const float &dir_z = camera_rays[packet_index].ray.dir_z[k]; + float cos_theta = p_camera_dir.x * dir_x + p_camera_dir.y * dir_y + p_camera_dir.z * dir_z; + d *= cos_theta; + } + + mips[0][y * buffer_size.x + x] = d; } } } @@ -514,7 +537,7 @@ void RaycastOcclusionCull::buffer_update(RID p_buffer, const Transform3D &p_cam_ buffer.update_camera_rays(p_cam_transform, p_cam_projection, p_cam_orthogonal, p_thread_pool); scenario.raycast(buffer.camera_rays, buffer.camera_ray_masks, p_thread_pool); - buffer.sort_rays(); + buffer.sort_rays(-p_cam_transform.basis.get_axis(2), p_cam_orthogonal); buffer.update_mips(); } diff --git a/modules/raycast/raycast_occlusion_cull.h b/modules/raycast/raycast_occlusion_cull.h index 85710a790c..cc87a6342c 100644 --- a/modules/raycast/raycast_occlusion_cull.h +++ b/modules/raycast/raycast_occlusion_cull.h @@ -51,15 +51,20 @@ public: Size2i packs_size; struct CameraRayThreadData { - CameraMatrix camera_matrix; - Transform3D camera_transform; - bool camera_orthogonal; int thread_count; + float z_near; + float z_far; + Vector3 camera_dir; + Vector3 camera_pos; + Vector3 pixel_corner; + Vector3 pixel_u_interp; + Vector3 pixel_v_interp; + bool camera_orthogonal; Size2i buffer_size; }; - void _camera_rays_threaded(uint32_t p_thread, CameraRayThreadData *p_data); - void _generate_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, int p_from, int p_to); + void _camera_rays_threaded(uint32_t p_thread, const CameraRayThreadData *p_data); + void _generate_camera_rays(const CameraRayThreadData *p_data, int p_from, int p_to); public: LocalVector<RayPacket> camera_rays; @@ -68,7 +73,7 @@ public: virtual void clear() override; virtual void resize(const Size2i &p_size) override; - void sort_rays(); + void sort_rays(const Vector3 &p_camera_dir, bool p_orthogonal); void update_camera_rays(const Transform3D &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, ThreadWorkPool &p_thread_work_pool); }; diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp index d11387902a..91755b5824 100644 --- a/scene/animation/animation_blend_tree.cpp +++ b/scene/animation/animation_blend_tree.cpp @@ -718,7 +718,7 @@ double AnimationNodeTransition::process(double p_time, bool p_seek) { } else { // cross-fading from prev to current - float blend = xfade ? (prev_xfading / xfade) : 1; + float blend = xfade == 0 ? 0 : (prev_xfading / xfade); if (!p_seek && switched) { //just switched, seek to start of current diff --git a/servers/rendering/renderer_scene_occlusion_cull.h b/servers/rendering/renderer_scene_occlusion_cull.h index e06b3ba153..4e4b1b94db 100644 --- a/servers/rendering/renderer_scene_occlusion_cull.h +++ b/servers/rendering/renderer_scene_occlusion_cull.h @@ -76,26 +76,28 @@ public: return false; } - float min_depth; - if (p_cam_projection.is_orthogonal()) { - min_depth = (-closest_point_view.z) - p_near; - } else { - float r = -p_near / closest_point_view.z; - Vector3 closest_point_proj = Vector3(closest_point_view.x * r, closest_point_view.y * r, -p_near); - min_depth = closest_point_proj.distance_to(closest_point_view); - } + float min_depth = -closest_point_view.z * 0.95f; Vector2 rect_min = Vector2(FLT_MAX, FLT_MAX); Vector2 rect_max = Vector2(FLT_MIN, FLT_MIN); for (int j = 0; j < 8; j++) { - Vector3 c = RendererSceneOcclusionCull::HZBuffer::corners[j]; + const Vector3 &c = RendererSceneOcclusionCull::HZBuffer::corners[j]; Vector3 nc = Vector3(1, 1, 1) - c; Vector3 corner = Vector3(p_bounds[0] * c.x + p_bounds[3] * nc.x, p_bounds[1] * c.y + p_bounds[4] * nc.y, p_bounds[2] * c.z + p_bounds[5] * nc.z); Vector3 view = p_cam_inv_transform.xform(corner); - Vector3 projected = p_cam_projection.xform(view); - Vector2 normalized = Vector2(projected.x * 0.5f + 0.5f, projected.y * 0.5f + 0.5f); + Plane vp = Plane(view, 1.0); + Plane projected = p_cam_projection.xform4(vp); + + float w = projected.d; + if (w < 1.0) { + rect_min = Vector2(0.0f, 0.0f); + rect_max = Vector2(1.0f, 1.0f); + break; + } + + Vector2 normalized = Vector2(projected.normal.x / w * 0.5f + 0.5f, projected.normal.y / w * 0.5f + 0.5f); rect_min = rect_min.min(normalized); rect_max = rect_max.max(normalized); } |