From a6f3bc7c696af03e3875f78e098d2476e409d15e Mon Sep 17 00:00:00 2001 From: Juan Linietsky Date: Fri, 27 Mar 2020 15:21:27 -0300 Subject: Renaming of servers for coherency. VisualServer -> RenderingServer PhysicsServer -> PhysicsServer3D Physics2DServer -> PhysicsServer2D NavigationServer -> NavigationServer3D Navigation2DServer -> NavigationServer2D Also renamed corresponding files. --- core/debugger/debugger_marshalls.cpp | 2 +- core/debugger/debugger_marshalls.h | 4 +- core/debugger/remote_debugger.cpp | 18 +- drivers/dummy/rasterizer_dummy.h | 122 +- drivers/gles2/rasterizer_canvas_gles2.cpp | 216 +- drivers/gles2/rasterizer_canvas_gles2.h | 2 +- drivers/gles2/rasterizer_gles2.cpp | 4 +- drivers/gles2/rasterizer_gles2.h | 2 +- drivers/gles2/rasterizer_scene_gles2.cpp | 304 +- drivers/gles2/rasterizer_scene_gles2.h | 32 +- drivers/gles2/rasterizer_storage_gles2.cpp | 548 +- drivers/gles2/rasterizer_storage_gles2.h | 118 +- drivers/gles2/shader_compiler_gles2.cpp | 346 +- drivers/gles2/shader_compiler_gles2.h | 10 +- drivers/gles2/shader_gles2.h | 2 +- drivers/gles2/shaders/blend_shape.glsl | 2 +- drivers/unix/os_unix.cpp | 2 +- drivers/vulkan/rendering_device_vulkan.h | 2 +- editor/animation_track_editor_plugins.cpp | 8 +- editor/editor_inspector.cpp | 2 +- editor/editor_node.cpp | 34 +- editor/editor_plugin.cpp | 62 +- editor/editor_resource_preview.cpp | 2 +- editor/import/editor_import_collada.cpp | 8 +- editor/import/resource_importer_texture.cpp | 2 +- editor/import/resource_importer_texture.h | 8 +- editor/node_3d_editor_gizmos.cpp | 42 +- editor/plugins/animation_player_editor_plugin.cpp | 70 +- editor/plugins/audio_stream_editor_plugin.cpp | 2 +- editor/plugins/canvas_item_editor_plugin.cpp | 18 +- editor/plugins/editor_preview_plugins.cpp | 194 +- editor/plugins/material_editor_plugin.cpp | 36 +- editor/plugins/node_3d_editor_plugin.cpp | 198 +- editor/plugins/node_3d_editor_plugin.h | 2 +- editor/plugins/polygon_2d_editor_plugin.cpp | 4 +- editor/plugins/shader_editor_plugin.cpp | 12 +- editor/plugins/shader_editor_plugin.h | 2 +- editor/plugins/texture_region_editor_plugin.cpp | 4 +- editor/plugins/tile_set_editor_plugin.cpp | 6 +- editor/plugins/visual_shader_editor_plugin.cpp | 4 +- editor/property_editor.cpp | 2 +- editor/scene_tree_dock.cpp | 2 +- gles_builders.py | 2 +- main/main.cpp | 84 +- main/performance.cpp | 38 +- main/tests/test_math.cpp | 2 +- main/tests/test_physics.cpp | 130 +- main/tests/test_physics_2d.cpp | 86 +- main/tests/test_render.cpp | 24 +- main/tests/test_shader_lang.cpp | 2 +- modules/assimp/editor_scene_importer_assimp.cpp | 20 +- modules/basis_universal/register_types.cpp | 22 +- modules/basis_universal/texture_basisu.cpp | 10 +- modules/bullet/area_bullet.cpp | 48 +- modules/bullet/area_bullet.h | 14 +- modules/bullet/bullet_physics_server.cpp | 384 +- modules/bullet/bullet_physics_server.h | 18 +- modules/bullet/collision_object_bullet.cpp | 2 +- modules/bullet/cone_twist_joint_bullet.cpp | 28 +- modules/bullet/cone_twist_joint_bullet.h | 6 +- modules/bullet/generic_6dof_joint_bullet.cpp | 98 +- modules/bullet/generic_6dof_joint_bullet.h | 12 +- modules/bullet/godot_result_callbacks.cpp | 4 +- modules/bullet/godot_result_callbacks.h | 14 +- modules/bullet/hinge_joint_bullet.cpp | 54 +- modules/bullet/hinge_joint_bullet.h | 10 +- modules/bullet/joint_bullet.h | 4 +- modules/bullet/pin_joint_bullet.cpp | 16 +- modules/bullet/pin_joint_bullet.h | 6 +- modules/bullet/register_types.cpp | 8 +- modules/bullet/rid_bullet.h | 8 +- modules/bullet/rigid_body_bullet.cpp | 126 +- modules/bullet/rigid_body_bullet.h | 26 +- modules/bullet/shape_bullet.cpp | 38 +- modules/bullet/shape_bullet.h | 22 +- modules/bullet/slider_joint_bullet.cpp | 94 +- modules/bullet/slider_joint_bullet.h | 6 +- modules/bullet/soft_body_bullet.cpp | 16 +- modules/bullet/soft_body_bullet.h | 4 +- modules/bullet/space_bullet.cpp | 86 +- modules/bullet/space_bullet.h | 22 +- modules/csg/csg_shape.cpp | 28 +- modules/gdnative/arvr/arvr_interface_gdnative.cpp | 8 +- modules/gdnavigation/gd_navigation_server.cpp | 2 +- modules/gdnavigation/gd_navigation_server.h | 4 +- modules/gdnavigation/register_types.cpp | 6 +- modules/glslang/register_types.cpp | 2 +- modules/gridmap/grid_map.cpp | 146 +- modules/gridmap/grid_map.h | 4 +- modules/gridmap/grid_map_editor_plugin.cpp | 128 +- modules/mobile_vr/mobile_vr_interface.cpp | 2 +- modules/opensimplex/noise_texture.cpp | 10 +- platform/android/os_android.cpp | 12 +- platform/android/os_android.h | 4 +- platform/haiku/os_haiku.cpp | 20 +- platform/haiku/os_haiku.h | 4 +- platform/iphone/os_iphone.cpp | 22 +- platform/iphone/os_iphone.h | 6 +- platform/javascript/os_javascript.cpp | 6 +- platform/javascript/os_javascript.h | 2 +- platform/linuxbsd/display_server_x11.cpp | 6 +- platform/linuxbsd/display_server_x11.h | 4 +- platform/linuxbsd/os_linuxbsd.h | 4 +- platform/server/os_server.cpp | 10 +- platform/server/os_server.h | 6 +- platform/uwp/os_uwp.cpp | 14 +- platform/uwp/os_uwp.h | 6 +- platform/windows/display_server_windows.h | 6 +- platform/windows/os_windows.cpp | 4 +- platform/windows/os_windows.h | 4 +- scene/2d/area_2d.cpp | 40 +- scene/2d/audio_stream_player_2d.cpp | 4 +- scene/2d/back_buffer_copy.cpp | 6 +- scene/2d/camera_2d.cpp | 2 +- scene/2d/canvas_modulate.cpp | 10 +- scene/2d/collision_object_2d.cpp | 56 +- scene/2d/collision_polygon_2d.cpp | 2 +- scene/2d/collision_shape_2d.cpp | 2 +- scene/2d/cpu_particles_2d.cpp | 46 +- scene/2d/gpu_particles_2d.cpp | 52 +- scene/2d/joints_2d.cpp | 34 +- scene/2d/light_2d.cpp | 56 +- scene/2d/light_occluder_2d.cpp | 32 +- scene/2d/line_2d.cpp | 2 +- scene/2d/navigation_2d.cpp | 20 +- scene/2d/navigation_agent_2d.cpp | 30 +- scene/2d/navigation_obstacle_2d.cpp | 20 +- scene/2d/navigation_region_2d.cpp | 20 +- scene/2d/node_2d.cpp | 16 +- scene/2d/parallax_layer.cpp | 2 +- scene/2d/physics_body_2d.cpp | 128 +- scene/2d/physics_body_2d.h | 8 +- scene/2d/polygon_2d.cpp | 8 +- scene/2d/ray_cast_2d.cpp | 6 +- scene/2d/skeleton_2d.cpp | 10 +- scene/2d/sprite_2d.cpp | 2 +- scene/2d/tile_map.cpp | 96 +- scene/2d/y_sort.cpp | 4 +- scene/3d/area_3d.cpp | 40 +- scene/3d/audio_stream_player_3d.cpp | 4 +- scene/3d/baked_lightmap.cpp | 30 +- scene/3d/camera_3d.cpp | 38 +- scene/3d/collision_object_3d.cpp | 44 +- scene/3d/collision_shape_3d.cpp | 6 +- scene/3d/cpu_particles_3d.cpp | 30 +- scene/3d/gi_probe.cpp | 44 +- scene/3d/gpu_particles_3d.cpp | 58 +- scene/3d/immediate_geometry_3d.cpp | 22 +- scene/3d/immediate_geometry_3d.h | 2 +- scene/3d/light_3d.cpp | 56 +- scene/3d/light_3d.h | 48 +- scene/3d/mesh_instance_3d.cpp | 10 +- scene/3d/navigation_3d.cpp | 26 +- scene/3d/navigation_agent_3d.cpp | 32 +- scene/3d/navigation_obstacle_3d.cpp | 24 +- scene/3d/navigation_region_3d.cpp | 20 +- scene/3d/physics_body_3d.cpp | 376 +- scene/3d/physics_body_3d.h | 18 +- scene/3d/physics_joint_3d.cpp | 66 +- scene/3d/physics_joint_3d.h | 138 +- scene/3d/ray_cast_3d.cpp | 6 +- scene/3d/reflection_probe.cpp | 34 +- scene/3d/reflection_probe.h | 2 +- scene/3d/skeleton_3d.cpp | 12 +- scene/3d/soft_body_3d.cpp | 148 +- scene/3d/soft_body_3d.h | 6 +- scene/3d/spring_arm_3d.cpp | 4 +- scene/3d/sprite_3d.cpp | 40 +- scene/3d/vehicle_body_3d.cpp | 24 +- scene/3d/vehicle_body_3d.h | 18 +- scene/3d/visual_instance_3d.cpp | 46 +- scene/3d/visual_instance_3d.h | 16 +- scene/animation/root_motion_view.cpp | 28 +- scene/gui/button.cpp | 2 +- scene/gui/check_box.cpp | 2 +- scene/gui/check_button.cpp | 2 +- scene/gui/control.cpp | 8 +- scene/gui/item_list.cpp | 4 +- scene/gui/label.cpp | 4 +- scene/gui/line_edit.cpp | 18 +- scene/gui/nine_patch_rect.cpp | 4 +- scene/gui/rich_text_label.cpp | 8 +- scene/gui/text_edit.cpp | 78 +- scene/gui/texture_progress.cpp | 2 +- scene/gui/texture_rect.cpp | 2 +- scene/gui/tree.cpp | 28 +- scene/main/canvas_item.cpp | 127 +- scene/main/canvas_item.h | 4 +- scene/main/canvas_layer.cpp | 32 +- scene/main/scene_tree.cpp | 14 +- scene/main/viewport.cpp | 184 +- scene/main/viewport.h | 2 +- scene/main/window.cpp | 34 +- scene/resources/box_shape_3d.cpp | 6 +- scene/resources/capsule_shape_2d.cpp | 10 +- scene/resources/capsule_shape_3d.cpp | 6 +- scene/resources/circle_shape_2d.cpp | 10 +- scene/resources/concave_polygon_shape_2d.cpp | 12 +- scene/resources/concave_polygon_shape_3d.cpp | 8 +- scene/resources/convex_polygon_shape_2d.cpp | 10 +- scene/resources/convex_polygon_shape_3d.cpp | 6 +- scene/resources/cylinder_shape_3d.cpp | 6 +- scene/resources/dynamic_font.cpp | 2 +- scene/resources/environment.cpp | 166 +- scene/resources/environment.h | 2 +- scene/resources/font.cpp | 2 +- scene/resources/height_map_shape_3d.cpp | 6 +- scene/resources/line_shape_2d.cpp | 12 +- scene/resources/material.cpp | 120 +- scene/resources/material.h | 8 +- scene/resources/mesh.cpp | 66 +- scene/resources/mesh.h | 44 +- scene/resources/multimesh.cpp | 36 +- scene/resources/multimesh.h | 6 +- scene/resources/particles_material.cpp | 116 +- scene/resources/physics_material.h | 2 +- scene/resources/primitive_meshes.cpp | 102 +- scene/resources/ray_shape_3d.cpp | 6 +- scene/resources/rectangle_shape_2d.cpp | 10 +- scene/resources/segment_shape_2d.cpp | 18 +- scene/resources/shader.cpp | 18 +- scene/resources/shader.h | 2 +- scene/resources/shape_2d.cpp | 14 +- scene/resources/shape_3d.cpp | 6 +- scene/resources/sky.cpp | 10 +- scene/resources/sky_material.cpp | 74 +- scene/resources/sphere_shape_3d.cpp | 6 +- scene/resources/style_box.cpp | 6 +- scene/resources/style_box.h | 2 +- scene/resources/surface_tool.cpp | 108 +- scene/resources/texture.cpp | 206 +- scene/resources/texture.h | 52 +- scene/resources/tile_set.cpp | 2 +- scene/resources/visual_shader.cpp | 20 +- scene/resources/world_2d.cpp | 26 +- scene/resources/world_2d.h | 4 +- scene/resources/world_3d.cpp | 34 +- scene/resources/world_3d.h | 6 +- scene/resources/world_margin_shape_3d.cpp | 6 +- servers/SCsub | 4 +- servers/arvr_server.cpp | 2 +- servers/camera/camera_feed.cpp | 28 +- servers/camera/camera_feed.h | 4 +- servers/camera_server.cpp | 2 +- servers/display_server.h | 2 +- servers/navigation_2d_server.cpp | 229 - servers/navigation_2d_server.h | 163 - servers/navigation_server.cpp | 107 - servers/navigation_server.h | 199 - servers/navigation_server_2d.cpp | 229 + servers/navigation_server_2d.h | 163 + servers/navigation_server_3d.cpp | 107 + servers/navigation_server_3d.h | 199 + servers/physics/SCsub | 7 - servers/physics/area_pair_sw.cpp | 159 - servers/physics/area_pair_sw.h | 70 - servers/physics/area_sw.cpp | 264 - servers/physics/area_sw.h | 203 - servers/physics/body_pair_sw.cpp | 495 -- servers/physics/body_pair_sw.h | 97 - servers/physics/body_sw.cpp | 814 --- servers/physics/body_sw.h | 475 -- servers/physics/broad_phase_basic.cpp | 225 - servers/physics/broad_phase_basic.h | 108 - servers/physics/broad_phase_octree.cpp | 129 - servers/physics/broad_phase_octree.h | 73 - servers/physics/broad_phase_sw.cpp | 36 - servers/physics/broad_phase_sw.h | 73 - servers/physics/collision_object_sw.cpp | 239 - servers/physics/collision_object_sw.h | 164 - servers/physics/collision_solver_sat.cpp | 1591 ----- servers/physics/collision_solver_sat.h | 38 - servers/physics/collision_solver_sw.cpp | 372 -- servers/physics/collision_solver_sw.h | 53 - servers/physics/constraint_sw.h | 85 - servers/physics/gjk_epa.cpp | 946 --- servers/physics/gjk_epa.h | 40 - servers/physics/joints/SCsub | 5 - servers/physics/joints/cone_twist_joint_sw.cpp | 366 - servers/physics/joints/cone_twist_joint_sw.h | 142 - servers/physics/joints/generic_6dof_joint_sw.cpp | 686 -- servers/physics/joints/generic_6dof_joint_sw.h | 401 -- servers/physics/joints/hinge_joint_sw.cpp | 450 -- servers/physics/joints/hinge_joint_sw.h | 117 - servers/physics/joints/jacobian_entry_sw.h | 169 - servers/physics/joints/pin_joint_sw.cpp | 167 - servers/physics/joints/pin_joint_sw.h | 96 - servers/physics/joints/slider_joint_sw.cpp | 443 -- servers/physics/joints/slider_joint_sw.h | 249 - servers/physics/joints_sw.h | 46 - servers/physics/physics_server_sw.cpp | 1589 ----- servers/physics/physics_server_sw.h | 382 -- servers/physics/shape_sw.cpp | 1655 ----- servers/physics/shape_sw.h | 470 -- servers/physics/space_sw.cpp | 1242 ---- servers/physics/space_sw.h | 208 - servers/physics/step_sw.cpp | 299 - servers/physics/step_sw.h | 50 - servers/physics_2d/area_2d_sw.cpp | 48 +- servers/physics_2d/area_2d_sw.h | 14 +- servers/physics_2d/area_pair_2d_sw.cpp | 8 +- servers/physics_2d/body_2d_sw.cpp | 148 +- servers/physics_2d/body_2d_sw.h | 36 +- servers/physics_2d/body_pair_2d_sw.cpp | 12 +- servers/physics_2d/collision_object_2d_sw.cpp | 14 +- servers/physics_2d/collision_object_2d_sw.h | 2 +- servers/physics_2d/collision_solver_2d_sat.cpp | 12 +- servers/physics_2d/collision_solver_2d_sw.cpp | 16 +- servers/physics_2d/joints_2d_sw.cpp | 24 +- servers/physics_2d/joints_2d_sw.h | 16 +- servers/physics_2d/physics_2d_server_sw.cpp | 1464 ---- servers/physics_2d/physics_2d_server_sw.h | 296 - servers/physics_2d/physics_2d_server_wrap_mt.cpp | 173 - servers/physics_2d/physics_2d_server_wrap_mt.h | 348 - servers/physics_2d/physics_server_2d_sw.cpp | 1464 ++++ servers/physics_2d/physics_server_2d_sw.h | 296 + servers/physics_2d/physics_server_2d_wrap_mt.cpp | 173 + servers/physics_2d/physics_server_2d_wrap_mt.h | 348 + servers/physics_2d/shape_2d_sw.h | 20 +- servers/physics_2d/space_2d_sw.cpp | 98 +- servers/physics_2d/space_2d_sw.h | 12 +- servers/physics_2d/step_2d_sw.cpp | 6 +- servers/physics_2d_server.cpp | 840 --- servers/physics_2d_server.h | 699 -- servers/physics_3d/SCsub | 7 + servers/physics_3d/area_3d_sw.cpp | 264 + servers/physics_3d/area_3d_sw.h | 203 + servers/physics_3d/area_pair_3d_sw.cpp | 159 + servers/physics_3d/area_pair_3d_sw.h | 70 + servers/physics_3d/body_3d_sw.cpp | 814 +++ servers/physics_3d/body_3d_sw.h | 475 ++ servers/physics_3d/body_pair_3d_sw.cpp | 495 ++ servers/physics_3d/body_pair_3d_sw.h | 97 + servers/physics_3d/broad_phase_3d_basic.cpp | 225 + servers/physics_3d/broad_phase_3d_basic.h | 108 + servers/physics_3d/broad_phase_3d_sw.cpp | 36 + servers/physics_3d/broad_phase_3d_sw.h | 73 + servers/physics_3d/broad_phase_octree.cpp | 129 + servers/physics_3d/broad_phase_octree.h | 73 + servers/physics_3d/collision_object_3d_sw.cpp | 239 + servers/physics_3d/collision_object_3d_sw.h | 164 + servers/physics_3d/collision_solver_3d_sat.cpp | 1591 +++++ servers/physics_3d/collision_solver_3d_sat.h | 38 + servers/physics_3d/collision_solver_3d_sw.cpp | 372 ++ servers/physics_3d/collision_solver_3d_sw.h | 53 + servers/physics_3d/constraint_3d_sw.h | 85 + servers/physics_3d/gjk_epa.cpp | 946 +++ servers/physics_3d/gjk_epa.h | 40 + servers/physics_3d/joints/SCsub | 5 + .../physics_3d/joints/cone_twist_joint_3d_sw.cpp | 366 + servers/physics_3d/joints/cone_twist_joint_3d_sw.h | 142 + .../physics_3d/joints/generic_6dof_joint_3d_sw.cpp | 686 ++ .../physics_3d/joints/generic_6dof_joint_3d_sw.h | 401 ++ servers/physics_3d/joints/hinge_joint_3d_sw.cpp | 450 ++ servers/physics_3d/joints/hinge_joint_3d_sw.h | 117 + servers/physics_3d/joints/jacobian_entry_3d_sw.h | 169 + servers/physics_3d/joints/pin_joint_3d_sw.cpp | 167 + servers/physics_3d/joints/pin_joint_3d_sw.h | 96 + servers/physics_3d/joints/slider_joint_3d_sw.cpp | 443 ++ servers/physics_3d/joints/slider_joint_3d_sw.h | 249 + servers/physics_3d/joints_3d_sw.h | 46 + servers/physics_3d/physics_server_3d_sw.cpp | 1589 +++++ servers/physics_3d/physics_server_3d_sw.h | 382 ++ servers/physics_3d/shape_3d_sw.cpp | 1655 +++++ servers/physics_3d/shape_3d_sw.h | 470 ++ servers/physics_3d/space_3d_sw.cpp | 1242 ++++ servers/physics_3d/space_3d_sw.h | 208 + servers/physics_3d/step_3d_sw.cpp | 299 + servers/physics_3d/step_3d_sw.h | 50 + servers/physics_server.cpp | 800 --- servers/physics_server.h | 844 --- servers/physics_server_2d.cpp | 840 +++ servers/physics_server_2d.h | 699 ++ servers/physics_server_3d.cpp | 800 +++ servers/physics_server_3d.h | 844 +++ servers/register_server_types.cpp | 78 +- servers/rendering/SCsub | 7 + servers/rendering/rasterizer.cpp | 77 + servers/rendering/rasterizer.h | 1307 ++++ servers/rendering/rasterizer_rd/SCsub | 7 + servers/rendering/rasterizer_rd/cubemap_coeffs.h | 28 + .../rasterizer_rd/light_cluster_builder.cpp | 255 + .../rasterizer_rd/light_cluster_builder.h | 291 + .../rasterizer_rd/rasterizer_canvas_rd.cpp | 2558 +++++++ .../rendering/rasterizer_rd/rasterizer_canvas_rd.h | 501 ++ .../rasterizer_rd/rasterizer_effects_rd.cpp | 1092 +++ .../rasterizer_rd/rasterizer_effects_rd.h | 457 ++ servers/rendering/rasterizer_rd/rasterizer_rd.cpp | 177 + servers/rendering/rasterizer_rd/rasterizer_rd.h | 95 + .../rasterizer_rd/rasterizer_scene_high_end_rd.cpp | 2729 ++++++++ .../rasterizer_rd/rasterizer_scene_high_end_rd.h | 585 ++ .../rasterizer_rd/rasterizer_scene_rd.cpp | 4039 +++++++++++ .../rendering/rasterizer_rd/rasterizer_scene_rd.h | 1109 ++++ .../rasterizer_rd/rasterizer_storage_rd.cpp | 4822 ++++++++++++++ .../rasterizer_rd/rasterizer_storage_rd.h | 1135 ++++ .../render_pipeline_vertex_format_cache_rd.cpp | 97 + .../render_pipeline_vertex_format_cache_rd.h | 96 + .../rendering/rasterizer_rd/shader_compiler_rd.cpp | 1243 ++++ .../rendering/rasterizer_rd/shader_compiler_rd.h | 123 + servers/rendering/rasterizer_rd/shader_rd.cpp | 495 ++ servers/rendering/rasterizer_rd/shader_rd.h | 136 + servers/rendering/rasterizer_rd/shaders/SCsub | 24 + servers/rendering/rasterizer_rd/shaders/blur.glsl | 294 + .../rendering/rasterizer_rd/shaders/blur_inc.glsl | 35 + .../rendering/rasterizer_rd/shaders/bokeh_dof.glsl | 258 + .../rendering/rasterizer_rd/shaders/canvas.glsl | 584 ++ .../rasterizer_rd/shaders/canvas_occlusion.glsl | 40 + .../rasterizer_rd/shaders/canvas_uniforms_inc.glsl | 141 + servers/rendering/rasterizer_rd/shaders/copy.glsl | 86 + .../rasterizer_rd/shaders/cubemap_downsampler.glsl | 188 + .../rasterizer_rd/shaders/cubemap_filter.glsl | 328 + .../rasterizer_rd/shaders/cubemap_roughness.glsl | 147 + .../rendering/rasterizer_rd/shaders/giprobe.glsl | 788 +++ .../rasterizer_rd/shaders/giprobe_debug.glsl | 208 + .../rasterizer_rd/shaders/giprobe_sdf.glsl | 187 + .../rasterizer_rd/shaders/giprobe_write.glsl | 335 + .../rasterizer_rd/shaders/luminance_reduce.glsl | 87 + .../rasterizer_rd/shaders/roughness_limiter.glsl | 73 + .../rasterizer_rd/shaders/scene_high_end.glsl | 1718 +++++ .../rasterizer_rd/shaders/scene_high_end_inc.glsl | 266 + servers/rendering/rasterizer_rd/shaders/sky.glsl | 181 + servers/rendering/rasterizer_rd/shaders/ssao.glsl | 252 + .../rendering/rasterizer_rd/shaders/ssao_blur.glsl | 157 + .../rasterizer_rd/shaders/ssao_minify.glsl | 48 + .../rendering/rasterizer_rd/shaders/tonemap.glsl | 305 + servers/rendering/rendering_device.cpp | 64 + servers/rendering/rendering_device.h | 1032 +++ servers/rendering/rendering_server_canvas.cpp | 1479 +++++ servers/rendering/rendering_server_canvas.h | 270 + servers/rendering/rendering_server_globals.cpp | 40 + servers/rendering/rendering_server_globals.h | 54 + servers/rendering/rendering_server_raster.cpp | 271 + servers/rendering/rendering_server_raster.h | 761 +++ servers/rendering/rendering_server_scene.cpp | 2839 ++++++++ servers/rendering/rendering_server_scene.h | 440 ++ servers/rendering/rendering_server_viewport.cpp | 780 +++ servers/rendering/rendering_server_viewport.h | 208 + servers/rendering/rendering_server_wrap_mt.cpp | 197 + servers/rendering/rendering_server_wrap_mt.h | 678 ++ servers/rendering/shader_language.cpp | 7006 ++++++++++++++++++++ servers/rendering/shader_language.h | 900 +++ servers/rendering/shader_types.cpp | 328 + servers/rendering/shader_types.h | 62 + servers/rendering_server.cpp | 2363 +++++++ servers/rendering_server.h | 1157 ++++ servers/visual/SCsub | 7 - servers/visual/rasterizer.cpp | 77 - servers/visual/rasterizer.h | 1307 ---- servers/visual/rasterizer_rd/SCsub | 7 - servers/visual/rasterizer_rd/cubemap_coeffs.h | 28 - .../visual/rasterizer_rd/light_cluster_builder.cpp | 255 - .../visual/rasterizer_rd/light_cluster_builder.h | 291 - .../visual/rasterizer_rd/rasterizer_canvas_rd.cpp | 2558 ------- .../visual/rasterizer_rd/rasterizer_canvas_rd.h | 501 -- .../visual/rasterizer_rd/rasterizer_effects_rd.cpp | 1092 --- .../visual/rasterizer_rd/rasterizer_effects_rd.h | 457 -- servers/visual/rasterizer_rd/rasterizer_rd.cpp | 177 - servers/visual/rasterizer_rd/rasterizer_rd.h | 95 - .../rasterizer_rd/rasterizer_scene_high_end_rd.cpp | 2729 -------- .../rasterizer_rd/rasterizer_scene_high_end_rd.h | 585 -- .../visual/rasterizer_rd/rasterizer_scene_rd.cpp | 4039 ----------- servers/visual/rasterizer_rd/rasterizer_scene_rd.h | 1109 ---- .../visual/rasterizer_rd/rasterizer_storage_rd.cpp | 4822 -------------- .../visual/rasterizer_rd/rasterizer_storage_rd.h | 1135 ---- .../render_pipeline_vertex_format_cache_rd.cpp | 97 - .../render_pipeline_vertex_format_cache_rd.h | 96 - .../visual/rasterizer_rd/shader_compiler_rd.cpp | 1243 ---- servers/visual/rasterizer_rd/shader_compiler_rd.h | 123 - servers/visual/rasterizer_rd/shader_rd.cpp | 495 -- servers/visual/rasterizer_rd/shader_rd.h | 136 - servers/visual/rasterizer_rd/shaders/SCsub | 24 - servers/visual/rasterizer_rd/shaders/blur.glsl | 294 - servers/visual/rasterizer_rd/shaders/blur_inc.glsl | 35 - .../visual/rasterizer_rd/shaders/bokeh_dof.glsl | 258 - servers/visual/rasterizer_rd/shaders/canvas.glsl | 584 -- .../rasterizer_rd/shaders/canvas_occlusion.glsl | 40 - .../rasterizer_rd/shaders/canvas_uniforms_inc.glsl | 141 - servers/visual/rasterizer_rd/shaders/copy.glsl | 86 - .../rasterizer_rd/shaders/cubemap_downsampler.glsl | 188 - .../rasterizer_rd/shaders/cubemap_filter.glsl | 328 - .../rasterizer_rd/shaders/cubemap_roughness.glsl | 147 - servers/visual/rasterizer_rd/shaders/giprobe.glsl | 788 --- .../rasterizer_rd/shaders/giprobe_debug.glsl | 208 - .../visual/rasterizer_rd/shaders/giprobe_sdf.glsl | 187 - .../rasterizer_rd/shaders/giprobe_write.glsl | 335 - .../rasterizer_rd/shaders/luminance_reduce.glsl | 87 - .../rasterizer_rd/shaders/roughness_limiter.glsl | 73 - .../rasterizer_rd/shaders/scene_high_end.glsl | 1718 ----- .../rasterizer_rd/shaders/scene_high_end_inc.glsl | 266 - servers/visual/rasterizer_rd/shaders/sky.glsl | 181 - servers/visual/rasterizer_rd/shaders/ssao.glsl | 252 - .../visual/rasterizer_rd/shaders/ssao_blur.glsl | 157 - .../visual/rasterizer_rd/shaders/ssao_minify.glsl | 48 - servers/visual/rasterizer_rd/shaders/tonemap.glsl | 305 - servers/visual/rendering_device.cpp | 64 - servers/visual/rendering_device.h | 1032 --- servers/visual/shader_language.cpp | 7006 -------------------- servers/visual/shader_language.h | 900 --- servers/visual/shader_types.cpp | 328 - servers/visual/shader_types.h | 62 - servers/visual/visual_server_canvas.cpp | 1479 ----- servers/visual/visual_server_canvas.h | 270 - servers/visual/visual_server_globals.cpp | 40 - servers/visual/visual_server_globals.h | 54 - servers/visual/visual_server_raster.cpp | 271 - servers/visual/visual_server_raster.h | 761 --- servers/visual/visual_server_scene.cpp | 2839 -------- servers/visual/visual_server_scene.h | 440 -- servers/visual/visual_server_viewport.cpp | 780 --- servers/visual/visual_server_viewport.h | 208 - servers/visual/visual_server_wrap_mt.cpp | 197 - servers/visual/visual_server_wrap_mt.h | 678 -- servers/visual_server.cpp | 2363 ------- servers/visual_server.h | 1157 ---- 514 files changed, 77934 insertions(+), 77935 deletions(-) delete mode 100644 servers/navigation_2d_server.cpp delete mode 100644 servers/navigation_2d_server.h delete mode 100644 servers/navigation_server.cpp delete mode 100644 servers/navigation_server.h create mode 100644 servers/navigation_server_2d.cpp create mode 100644 servers/navigation_server_2d.h create mode 100644 servers/navigation_server_3d.cpp create mode 100644 servers/navigation_server_3d.h delete mode 100644 servers/physics/SCsub delete mode 100644 servers/physics/area_pair_sw.cpp delete mode 100644 servers/physics/area_pair_sw.h delete mode 100644 servers/physics/area_sw.cpp delete mode 100644 servers/physics/area_sw.h delete mode 100644 servers/physics/body_pair_sw.cpp delete mode 100644 servers/physics/body_pair_sw.h delete mode 100644 servers/physics/body_sw.cpp delete mode 100644 servers/physics/body_sw.h delete mode 100644 servers/physics/broad_phase_basic.cpp delete mode 100644 servers/physics/broad_phase_basic.h delete mode 100644 servers/physics/broad_phase_octree.cpp delete mode 100644 servers/physics/broad_phase_octree.h delete mode 100644 servers/physics/broad_phase_sw.cpp delete mode 100644 servers/physics/broad_phase_sw.h delete mode 100644 servers/physics/collision_object_sw.cpp delete mode 100644 servers/physics/collision_object_sw.h delete mode 100644 servers/physics/collision_solver_sat.cpp delete mode 100644 servers/physics/collision_solver_sat.h delete mode 100644 servers/physics/collision_solver_sw.cpp delete mode 100644 servers/physics/collision_solver_sw.h delete mode 100644 servers/physics/constraint_sw.h delete mode 100644 servers/physics/gjk_epa.cpp delete mode 100644 servers/physics/gjk_epa.h delete mode 100644 servers/physics/joints/SCsub delete mode 100644 servers/physics/joints/cone_twist_joint_sw.cpp delete mode 100644 servers/physics/joints/cone_twist_joint_sw.h delete mode 100644 servers/physics/joints/generic_6dof_joint_sw.cpp delete mode 100644 servers/physics/joints/generic_6dof_joint_sw.h delete mode 100644 servers/physics/joints/hinge_joint_sw.cpp delete mode 100644 servers/physics/joints/hinge_joint_sw.h delete mode 100644 servers/physics/joints/jacobian_entry_sw.h delete mode 100644 servers/physics/joints/pin_joint_sw.cpp delete mode 100644 servers/physics/joints/pin_joint_sw.h delete mode 100644 servers/physics/joints/slider_joint_sw.cpp delete mode 100644 servers/physics/joints/slider_joint_sw.h delete mode 100644 servers/physics/joints_sw.h delete mode 100644 servers/physics/physics_server_sw.cpp delete mode 100644 servers/physics/physics_server_sw.h delete mode 100644 servers/physics/shape_sw.cpp delete mode 100644 servers/physics/shape_sw.h delete mode 100644 servers/physics/space_sw.cpp delete mode 100644 servers/physics/space_sw.h delete mode 100644 servers/physics/step_sw.cpp delete mode 100644 servers/physics/step_sw.h delete mode 100644 servers/physics_2d/physics_2d_server_sw.cpp delete mode 100644 servers/physics_2d/physics_2d_server_sw.h delete mode 100644 servers/physics_2d/physics_2d_server_wrap_mt.cpp delete mode 100644 servers/physics_2d/physics_2d_server_wrap_mt.h create mode 100644 servers/physics_2d/physics_server_2d_sw.cpp create mode 100644 servers/physics_2d/physics_server_2d_sw.h create mode 100644 servers/physics_2d/physics_server_2d_wrap_mt.cpp create mode 100644 servers/physics_2d/physics_server_2d_wrap_mt.h delete mode 100644 servers/physics_2d_server.cpp delete mode 100644 servers/physics_2d_server.h create mode 100644 servers/physics_3d/SCsub create mode 100644 servers/physics_3d/area_3d_sw.cpp create mode 100644 servers/physics_3d/area_3d_sw.h create mode 100644 servers/physics_3d/area_pair_3d_sw.cpp create mode 100644 servers/physics_3d/area_pair_3d_sw.h create mode 100644 servers/physics_3d/body_3d_sw.cpp create mode 100644 servers/physics_3d/body_3d_sw.h create mode 100644 servers/physics_3d/body_pair_3d_sw.cpp create mode 100644 servers/physics_3d/body_pair_3d_sw.h create mode 100644 servers/physics_3d/broad_phase_3d_basic.cpp create mode 100644 servers/physics_3d/broad_phase_3d_basic.h create mode 100644 servers/physics_3d/broad_phase_3d_sw.cpp create mode 100644 servers/physics_3d/broad_phase_3d_sw.h create mode 100644 servers/physics_3d/broad_phase_octree.cpp create mode 100644 servers/physics_3d/broad_phase_octree.h create mode 100644 servers/physics_3d/collision_object_3d_sw.cpp create mode 100644 servers/physics_3d/collision_object_3d_sw.h create mode 100644 servers/physics_3d/collision_solver_3d_sat.cpp create mode 100644 servers/physics_3d/collision_solver_3d_sat.h create mode 100644 servers/physics_3d/collision_solver_3d_sw.cpp create mode 100644 servers/physics_3d/collision_solver_3d_sw.h create mode 100644 servers/physics_3d/constraint_3d_sw.h create mode 100644 servers/physics_3d/gjk_epa.cpp create mode 100644 servers/physics_3d/gjk_epa.h create mode 100644 servers/physics_3d/joints/SCsub create mode 100644 servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp create mode 100644 servers/physics_3d/joints/cone_twist_joint_3d_sw.h create mode 100644 servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp create mode 100644 servers/physics_3d/joints/generic_6dof_joint_3d_sw.h create mode 100644 servers/physics_3d/joints/hinge_joint_3d_sw.cpp create mode 100644 servers/physics_3d/joints/hinge_joint_3d_sw.h create mode 100644 servers/physics_3d/joints/jacobian_entry_3d_sw.h create mode 100644 servers/physics_3d/joints/pin_joint_3d_sw.cpp create mode 100644 servers/physics_3d/joints/pin_joint_3d_sw.h create mode 100644 servers/physics_3d/joints/slider_joint_3d_sw.cpp create mode 100644 servers/physics_3d/joints/slider_joint_3d_sw.h create mode 100644 servers/physics_3d/joints_3d_sw.h create mode 100644 servers/physics_3d/physics_server_3d_sw.cpp create mode 100644 servers/physics_3d/physics_server_3d_sw.h create mode 100644 servers/physics_3d/shape_3d_sw.cpp create mode 100644 servers/physics_3d/shape_3d_sw.h create mode 100644 servers/physics_3d/space_3d_sw.cpp create mode 100644 servers/physics_3d/space_3d_sw.h create mode 100644 servers/physics_3d/step_3d_sw.cpp create mode 100644 servers/physics_3d/step_3d_sw.h delete mode 100644 servers/physics_server.cpp delete mode 100644 servers/physics_server.h create mode 100644 servers/physics_server_2d.cpp create mode 100644 servers/physics_server_2d.h create mode 100644 servers/physics_server_3d.cpp create mode 100644 servers/physics_server_3d.h create mode 100644 servers/rendering/SCsub create mode 100644 servers/rendering/rasterizer.cpp create mode 100644 servers/rendering/rasterizer.h create mode 100644 servers/rendering/rasterizer_rd/SCsub create mode 100644 servers/rendering/rasterizer_rd/cubemap_coeffs.h create mode 100644 servers/rendering/rasterizer_rd/light_cluster_builder.cpp create mode 100644 servers/rendering/rasterizer_rd/light_cluster_builder.h create mode 100644 servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h create mode 100644 servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/rasterizer_effects_rd.h create mode 100644 servers/rendering/rasterizer_rd/rasterizer_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/rasterizer_rd.h create mode 100644 servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h create mode 100644 servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/rasterizer_scene_rd.h create mode 100644 servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/rasterizer_storage_rd.h create mode 100644 servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h create mode 100644 servers/rendering/rasterizer_rd/shader_compiler_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/shader_compiler_rd.h create mode 100644 servers/rendering/rasterizer_rd/shader_rd.cpp create mode 100644 servers/rendering/rasterizer_rd/shader_rd.h create mode 100644 servers/rendering/rasterizer_rd/shaders/SCsub create mode 100644 servers/rendering/rasterizer_rd/shaders/blur.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/blur_inc.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/canvas.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/copy.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/giprobe.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/sky.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/ssao.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl create mode 100644 servers/rendering/rasterizer_rd/shaders/tonemap.glsl create mode 100644 servers/rendering/rendering_device.cpp create mode 100644 servers/rendering/rendering_device.h create mode 100644 servers/rendering/rendering_server_canvas.cpp create mode 100644 servers/rendering/rendering_server_canvas.h create mode 100644 servers/rendering/rendering_server_globals.cpp create mode 100644 servers/rendering/rendering_server_globals.h create mode 100644 servers/rendering/rendering_server_raster.cpp create mode 100644 servers/rendering/rendering_server_raster.h create mode 100644 servers/rendering/rendering_server_scene.cpp create mode 100644 servers/rendering/rendering_server_scene.h create mode 100644 servers/rendering/rendering_server_viewport.cpp create mode 100644 servers/rendering/rendering_server_viewport.h create mode 100644 servers/rendering/rendering_server_wrap_mt.cpp create mode 100644 servers/rendering/rendering_server_wrap_mt.h create mode 100644 servers/rendering/shader_language.cpp create mode 100644 servers/rendering/shader_language.h create mode 100644 servers/rendering/shader_types.cpp create mode 100644 servers/rendering/shader_types.h create mode 100644 servers/rendering_server.cpp create mode 100644 servers/rendering_server.h delete mode 100644 servers/visual/SCsub delete mode 100644 servers/visual/rasterizer.cpp delete mode 100644 servers/visual/rasterizer.h delete mode 100644 servers/visual/rasterizer_rd/SCsub delete mode 100644 servers/visual/rasterizer_rd/cubemap_coeffs.h delete mode 100644 servers/visual/rasterizer_rd/light_cluster_builder.cpp delete mode 100644 servers/visual/rasterizer_rd/light_cluster_builder.h delete mode 100644 servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/rasterizer_canvas_rd.h delete mode 100644 servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/rasterizer_effects_rd.h delete mode 100644 servers/visual/rasterizer_rd/rasterizer_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/rasterizer_rd.h delete mode 100644 servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h delete mode 100644 servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/rasterizer_scene_rd.h delete mode 100644 servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/rasterizer_storage_rd.h delete mode 100644 servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h delete mode 100644 servers/visual/rasterizer_rd/shader_compiler_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/shader_compiler_rd.h delete mode 100644 servers/visual/rasterizer_rd/shader_rd.cpp delete mode 100644 servers/visual/rasterizer_rd/shader_rd.h delete mode 100644 servers/visual/rasterizer_rd/shaders/SCsub delete mode 100644 servers/visual/rasterizer_rd/shaders/blur.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/blur_inc.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/canvas.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/canvas_uniforms_inc.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/copy.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/giprobe.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/giprobe_write.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/scene_high_end.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/sky.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/ssao.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/ssao_blur.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/ssao_minify.glsl delete mode 100644 servers/visual/rasterizer_rd/shaders/tonemap.glsl delete mode 100644 servers/visual/rendering_device.cpp delete mode 100644 servers/visual/rendering_device.h delete mode 100644 servers/visual/shader_language.cpp delete mode 100644 servers/visual/shader_language.h delete mode 100644 servers/visual/shader_types.cpp delete mode 100644 servers/visual/shader_types.h delete mode 100644 servers/visual/visual_server_canvas.cpp delete mode 100644 servers/visual/visual_server_canvas.h delete mode 100644 servers/visual/visual_server_globals.cpp delete mode 100644 servers/visual/visual_server_globals.h delete mode 100644 servers/visual/visual_server_raster.cpp delete mode 100644 servers/visual/visual_server_raster.h delete mode 100644 servers/visual/visual_server_scene.cpp delete mode 100644 servers/visual/visual_server_scene.h delete mode 100644 servers/visual/visual_server_viewport.cpp delete mode 100644 servers/visual/visual_server_viewport.h delete mode 100644 servers/visual/visual_server_wrap_mt.cpp delete mode 100644 servers/visual/visual_server_wrap_mt.h delete mode 100644 servers/visual_server.cpp delete mode 100644 servers/visual_server.h diff --git a/core/debugger/debugger_marshalls.cpp b/core/debugger/debugger_marshalls.cpp index eb3a19506a..427c005b60 100644 --- a/core/debugger/debugger_marshalls.cpp +++ b/core/debugger/debugger_marshalls.cpp @@ -317,7 +317,7 @@ bool DebuggerMarshalls::VisualProfilerFrame::deserialize(const Array &p_arr) { CHECK_SIZE(p_arr, size, "VisualProfilerFrame"); int idx = 2; areas.resize(size / 3); - VS::FrameProfileArea *w = areas.ptrw(); + RS::FrameProfileArea *w = areas.ptrw(); for (int i = 0; i < size / 3; i++) { w[i].name = p_arr[idx]; w[i].cpu_msec = p_arr[idx + 1]; diff --git a/core/debugger/debugger_marshalls.h b/core/debugger/debugger_marshalls.h index 4c15adc555..04229c0afc 100644 --- a/core/debugger/debugger_marshalls.h +++ b/core/debugger/debugger_marshalls.h @@ -32,7 +32,7 @@ #define DEBUGGER_MARSHARLLS_H #include "core/script_language.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" struct DebuggerMarshalls { @@ -165,7 +165,7 @@ struct DebuggerMarshalls { // Visual Profiler struct VisualProfilerFrame { uint64_t frame_number; - Vector areas; + Vector areas; Array serialize(); bool deserialize(const Array &p_arr); diff --git a/core/debugger/remote_debugger.cpp b/core/debugger/remote_debugger.cpp index b9db8ab1b0..66b890be23 100644 --- a/core/debugger/remote_debugger.cpp +++ b/core/debugger/remote_debugger.cpp @@ -354,18 +354,18 @@ struct RemoteDebugger::VisualProfiler { Map server_data; void toggle(bool p_enable, const Array &p_opts) { - VS::get_singleton()->set_frame_profiling_enabled(p_enable); + RS::get_singleton()->set_frame_profiling_enabled(p_enable); } void add(const Array &p_data) {} void tick(float p_frame_time, float p_idle_time, float p_physics_time, float p_physics_frame_time) { - Vector profile_areas = VS::get_singleton()->get_frame_profile(); + Vector profile_areas = RS::get_singleton()->get_frame_profile(); DebuggerMarshalls::VisualProfilerFrame frame; if (!profile_areas.size()) return; - frame.frame_number = VS::get_singleton()->get_frame_profile_frame(); + frame.frame_number = RS::get_singleton()->get_frame_profile_frame(); frame.areas.append_array(profile_areas); EngineDebugger::get_singleton()->send_message("visual:profile_frame", frame.serialize()); } @@ -404,10 +404,10 @@ void RemoteDebugger::_send_resource_usage() { DebuggerMarshalls::ResourceUsage usage; - List tinfo; - VS::get_singleton()->texture_debug_usage(&tinfo); + List tinfo; + RS::get_singleton()->texture_debug_usage(&tinfo); - for (List::Element *E = tinfo.front(); E; E = E->next()) { + for (List::Element *E = tinfo.front(); E; E = E->next()) { DebuggerMarshalls::ResourceInfo info; info.path = E->get().path; @@ -771,9 +771,9 @@ void RemoteDebugger::debug(bool p_can_continue, bool p_is_error_breakpoint) { // This is for the camera override to stay live even when the game is paused from the editor loop_time_sec = (OS::get_singleton()->get_ticks_usec() - loop_begin_usec) / 1000000.0f; - VisualServer::get_singleton()->sync(); - if (VisualServer::get_singleton()->has_changed()) { - VisualServer::get_singleton()->draw(true, loop_time_sec * Engine::get_singleton()->get_time_scale()); + RenderingServer::get_singleton()->sync(); + if (RenderingServer::get_singleton()->has_changed()) { + RenderingServer::get_singleton()->draw(true, loop_time_sec * Engine::get_singleton()->get_time_scale()); } } diff --git a/drivers/dummy/rasterizer_dummy.h b/drivers/dummy/rasterizer_dummy.h index b446828128..a503492595 100644 --- a/drivers/dummy/rasterizer_dummy.h +++ b/drivers/dummy/rasterizer_dummy.h @@ -35,8 +35,8 @@ #include "core/rid_owner.h" #include "core/self_list.h" #include "scene/resources/mesh.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" class RasterizerSceneDummy : public RasterizerScene { public: @@ -55,7 +55,7 @@ public: RID sky_create() { return RID(); } void sky_set_radiance_size(RID p_sky, int p_radiance_size) {} - void sky_set_mode(RID p_sky, VS::SkyMode p_samples) {} + void sky_set_mode(RID p_sky, RS::SkyMode p_samples) {} void sky_set_texture(RID p_sky, RID p_panorama) {} void sky_set_texture(RID p_sky, RID p_cube_map, int p_radiance_size) {} void sky_set_material(RID p_sky, RID p_material) {} @@ -64,28 +64,28 @@ public: RID environment_create() { return RID(); } - void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) {} + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) {} void environment_set_sky(RID p_env, RID p_sky) {} void environment_set_sky_custom_fov(RID p_env, float p_scale) {} void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) {} void environment_set_bg_color(RID p_env, const Color &p_color) {} void environment_set_bg_energy(RID p_env, float p_energy) {} void environment_set_canvas_max_layer(RID p_env, int p_max_layer) {} - void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) {} + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) {} // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) {} #endif - void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {} + void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) {} void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {} void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {} - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {} - virtual void environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size) {} + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) {} + virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) {} - void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {} + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) {} void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} @@ -94,13 +94,13 @@ public: void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {} bool is_environment(RID p_env) const { return false; } - VS::EnvironmentBG environment_get_background(RID p_env) const { return VS::ENV_BG_KEEP; } + RS::EnvironmentBG environment_get_background(RID p_env) const { return RS::ENV_BG_KEEP; } int environment_get_canvas_max_layer(RID p_env) const { return 0; } virtual RID camera_effects_create() { return RID(); } - virtual void camera_effects_set_dof_blur_quality(VS::DOFBlurQuality p_quality, bool p_use_jitter) {} - virtual void camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape p_shape) {} + virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) {} + virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) {} virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) {} virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) {} @@ -133,10 +133,10 @@ public: void set_scene_pass(uint64_t p_pass) {} virtual void set_time(double p_time, double p_step) {} - void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) {} + void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) {} virtual RID render_buffers_create() { return RID(); } - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) {} + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa) {} virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) {} virtual bool screen_space_roughness_limiter_is_active() const { return false; } @@ -162,7 +162,7 @@ public: struct DummySurface { uint32_t format; - VS::PrimitiveType primitive; + RS::PrimitiveType primitive; Vector array; int vertex_count; Vector index_array; @@ -175,14 +175,14 @@ public: struct DummyMesh { Vector surfaces; int blend_shape_count; - VS::BlendShapeMode blend_shape_mode; + RS::BlendShapeMode blend_shape_mode; }; mutable RID_PtrOwner texture_owner; mutable RID_PtrOwner mesh_owner; virtual RID texture_2d_create(const Ref &p_image) { return RID(); } - virtual RID texture_2d_layered_create(const Vector> &p_layers, VS::TextureLayeredType p_layered_type) { return RID(); } + virtual RID texture_2d_layered_create(const Vector> &p_layers, RS::TextureLayeredType p_layered_type) { return RID(); } virtual RID texture_3d_create(const Vector> &p_slices) { return RID(); } virtual RID texture_proxy_create(RID p_base) { return RID(); } @@ -209,11 +209,11 @@ public: virtual void texture_set_path(RID p_texture, const String &p_path) {} virtual String texture_get_path(RID p_texture) const { return String(); } - virtual void texture_set_detect_3d_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) {} - virtual void texture_set_detect_normal_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) {} - virtual void texture_set_detect_roughness_callback(RID p_texture, VS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {} + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {} + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) {} + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) {} - virtual void texture_debug_usage(List *r_info) {} + virtual void texture_debug_usage(List *r_info) {} virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) {} virtual Size2 texture_size_with_proxy(RID p_proxy) { return Size2(); } @@ -225,7 +225,7 @@ public: return texture_owner.make_rid(texture); } - void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type = VS::TEXTURE_TYPE_2D, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT) { + void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingServer::TextureType p_type = RS::TEXTURE_TYPE_2D, uint32_t p_flags = RS::TEXTURE_FLAGS_DEFAULT) { DummyTexture *t = texture_owner.getornull(p_texture); ERR_FAIL_COND(!t); t->width = p_width; @@ -278,7 +278,7 @@ public: return t->format; } - VisualServer::TextureType texture_get_type(RID p_texture) const { return VS::TEXTURE_TYPE_2D; } + RenderingServer::TextureType texture_get_type(RID p_texture) const { return RS::TEXTURE_TYPE_2D; } uint32_t texture_get_texid(RID p_texture) const { return 0; } uint32_t texture_get_width(RID p_texture) const { return 0; } uint32_t texture_get_height(RID p_texture) const { return 0; } @@ -299,13 +299,13 @@ public: void texture_set_shrink_all_x2_on_set_data(bool p_enable) {} - void texture_debug_usage(List *r_info) {} + void texture_debug_usage(List *r_info) {} RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const { return RID(); } - void texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {} - void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {} - void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) {} + void texture_set_detect_3d_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) {} + void texture_set_detect_srgb_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) {} + void texture_set_detect_normal_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) {} void textures_keep_original(bool p_enable) {} @@ -353,14 +353,14 @@ public: DummyMesh *mesh = memnew(DummyMesh); ERR_FAIL_COND_V(!mesh, RID()); mesh->blend_shape_count = 0; - mesh->blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED; + mesh->blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; return mesh_owner.make_rid(mesh); } - void mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface) {} + void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) {} #if 0 - void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector > &p_blend_shapes = Vector >(), const Vector &p_bone_aabbs = Vector()) { + void mesh_add_surface(RID p_mesh, uint32_t p_format, RS::PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector > &p_blend_shapes = Vector >(), const Vector &p_bone_aabbs = Vector()) { DummyMesh *m = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!m); @@ -390,14 +390,14 @@ public: return m->blend_shape_count; } - void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) { + void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { DummyMesh *m = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!m); m->blend_shape_mode = p_mode; } - VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const { + RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const { DummyMesh *m = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!m, VS::BLEND_SHAPE_MODE_NORMALIZED); + ERR_FAIL_COND_V(!m, RS::BLEND_SHAPE_MODE_NORMALIZED); return m->blend_shape_mode; } @@ -439,9 +439,9 @@ public: return m->surfaces[p_surface].format; } - VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { + RS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { DummyMesh *m = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!m, VS::PRIMITIVE_POINTS); + ERR_FAIL_COND_V(!m, RS::PRIMITIVE_POINTS); return m->surfaces[p_surface].primitive; } @@ -474,7 +474,7 @@ public: } #endif - VS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const { return VS::SurfaceData(); } + RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const { return RS::SurfaceData(); } int mesh_get_surface_count(RID p_mesh) const { DummyMesh *m = mesh_owner.getornull(p_mesh); ERR_FAIL_COND_V(!m, 0); @@ -491,7 +491,7 @@ public: virtual RID multimesh_create() { return RID(); } - virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) {} + virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) {} int multimesh_get_instance_count(RID p_multimesh) const { return 0; } void multimesh_set_mesh(RID p_multimesh, RID p_mesh) {} @@ -516,7 +516,7 @@ public: /* IMMEDIATE API */ RID immediate_create() { return RID(); } - void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID()) {} + void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {} void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {} void immediate_normal(RID p_immediate, const Vector3 &p_normal) {} void immediate_tangent(RID p_immediate, const Plane &p_tangent) {} @@ -543,14 +543,14 @@ public: /* Light API */ - RID light_create(VS::LightType p_type) { return RID(); } + RID light_create(RS::LightType p_type) { return RID(); } - RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); } - RID omni_light_create() { return light_create(VS::LIGHT_OMNI); } - RID spot_light_create() { return light_create(VS::LIGHT_SPOT); } + RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); } + RID omni_light_create() { return light_create(RS::LIGHT_OMNI); } + RID spot_light_create() { return light_create(RS::LIGHT_SPOT); } void light_set_color(RID p_light, const Color &p_color) {} - void light_set_param(RID p_light, VS::LightParam p_param, float p_value) {} + void light_set_param(RID p_light, RS::LightParam p_param, float p_value) {} void light_set_shadow(RID p_light, bool p_enabled) {} void light_set_shadow_color(RID p_light, const Color &p_color) {} void light_set_projector(RID p_light, RID p_texture) {} @@ -559,22 +559,22 @@ public: void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) {} void light_set_use_gi(RID p_light, bool p_enabled) {} - void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) {} + void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) {} - void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) {} + void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) {} void light_directional_set_blend_splits(RID p_light, bool p_enable) {} bool light_directional_get_blend_splits(RID p_light) const { return false; } - void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) {} - VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const { return VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; } + void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) {} + RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const { return RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; } - VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) { return VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; } - VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) { return VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; } + RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) { return RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; } + RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) { return RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; } bool light_has_shadow(RID p_light) const { return false; } - VS::LightType light_get_type(RID p_light) const { return VS::LIGHT_OMNI; } + RS::LightType light_get_type(RID p_light) const { return RS::LIGHT_OMNI; } AABB light_get_aabb(RID p_light) const { return AABB(); } - float light_get_param(RID p_light, VS::LightParam p_param) { return 0.0; } + float light_get_param(RID p_light, RS::LightParam p_param) { return 0.0; } Color light_get_color(RID p_light) { return Color(); } bool light_get_use_gi(RID p_light) { return false; } uint64_t light_get_version(RID p_light) const { return 0; } @@ -583,7 +583,7 @@ public: RID reflection_probe_create() { return RID(); } - void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) {} + void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) {} void reflection_probe_set_intensity(RID p_probe, float p_intensity) {} void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) {} void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) {} @@ -598,7 +598,7 @@ public: void reflection_probe_set_resolution(RID p_probe, int p_resolution) {} AABB reflection_probe_get_aabb(RID p_probe) const { return AABB(); } - VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return VisualServer::REFLECTION_PROBE_UPDATE_ONCE; } + RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const { return RenderingServer::REFLECTION_PROBE_UPDATE_ONCE; } uint32_t reflection_probe_get_cull_mask(RID p_probe) const { return 0; } Vector3 reflection_probe_get_extents(RID p_probe) const { return Vector3(); } Vector3 reflection_probe_get_origin_offset(RID p_probe) const { return Vector3(); } @@ -742,7 +742,7 @@ public: void particles_set_fractional_delta(RID p_particles, bool p_enable) {} void particles_restart(RID p_particles) {} - void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) {} + void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {} void particles_set_draw_passes(RID p_particles, int p_count) {} void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {} @@ -776,12 +776,12 @@ public: virtual void render_target_disable_clear_request(RID p_render_target) {} virtual void render_target_do_clear_request(RID p_render_target) {} - VS::InstanceType get_base_type(RID p_rid) const { + RS::InstanceType get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { - return VS::INSTANCE_MESH; + return RS::INSTANCE_MESH; } - return VS::INSTANCE_NONE; + return RS::INSTANCE_NONE; } bool free(RID p_rid) { @@ -803,9 +803,9 @@ public: void render_info_begin_capture() {} void render_info_end_capture() {} - int get_captured_render_info(VS::RenderInfo p_info) { return 0; } + int get_captured_render_info(RS::RenderInfo p_info) { return 0; } - int get_render_info(VS::RenderInfo p_info) { return 0; } + int get_render_info(RS::RenderInfo p_info) { return 0; } String get_video_adapter_name() const { return String(); } String get_video_adapter_vendor() const { return String(); } @@ -825,7 +825,7 @@ public: class RasterizerCanvasDummy : public RasterizerCanvas { public: - virtual TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { return 0; } + virtual TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { return 0; } virtual void free_texture_binding(TextureBindingID p_binding) {} virtual PolygonID request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()) { return 0; } @@ -841,7 +841,7 @@ public: virtual RID occluder_polygon_create() { return RID(); } virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines) {} - virtual void occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode) {} + virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) {} void draw_window_margins(int *p_margins, RID *p_margin_textures) {} diff --git a/drivers/gles2/rasterizer_canvas_gles2.cpp b/drivers/gles2/rasterizer_canvas_gles2.cpp index 5e8948e9c4..734b4463ff 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.cpp +++ b/drivers/gles2/rasterizer_canvas_gles2.cpp @@ -33,7 +33,7 @@ #include "core/os/os.h" #include "core/project_settings.h" #include "rasterizer_scene_gles2.h" -#include "servers/visual/visual_server_raster.h" +#include "servers/rendering/rendering_server_raster.h" #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf @@ -85,7 +85,7 @@ void RasterizerCanvasGLES2::_set_uniforms() { state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_COLOR, light->color * light->energy); state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_POS, light->light_shader_pos); state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_HEIGHT, light->height); - state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == VS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0); + state.canvas_shader.set_uniform(CanvasShaderGLES2::LIGHT_OUTSIDE_ALPHA, light->mode == RS::CANVAS_LIGHT_MODE_MASK ? 1.0 : 0.0); if (state.using_shadow) { RasterizerStorageGLES2::CanvasLightShadow *cls = storage->canvas_light_shadow_owner.getornull(light->shadow_buffer); @@ -152,8 +152,8 @@ void RasterizerCanvasGLES2::canvas_begin() { glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, storage->resources.white_tex); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); - glDisableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); + glDisableVertexAttribArray(RS::ARRAY_COLOR); // set up default uniforms @@ -188,7 +188,7 @@ void RasterizerCanvasGLES2::canvas_end() { glBindBuffer(GL_ARRAY_BUFFER, 0); - for (int i = 0; i < VS::ARRAY_MAX; i++) { + for (int i = 0; i < RS::ARRAY_MAX; i++) { glDisableVertexAttribArray(i); } @@ -224,7 +224,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con } else { if (texture->redraw_if_visible) { - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } texture = texture->get_ptr(); @@ -266,7 +266,7 @@ RasterizerStorageGLES2::Texture *RasterizerCanvasGLES2::_bind_canvas_texture(con } else { if (normal_map->redraw_if_visible) { //check before proxy, because this is usually used with proxies - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } normal_map = normal_map->get_ptr(); @@ -299,47 +299,47 @@ void RasterizerCanvasGLES2::_draw_polygon(const int *p_indices, int p_index_coun uint32_t buffer_ofs = 0; glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); buffer_ofs += sizeof(Vector2) * p_vertex_count; if (p_singlecolor) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); + glDisableVertexAttribArray(RS::ARRAY_COLOR); Color m = *p_colors; - glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + glVertexAttrib4f(RS::ARRAY_COLOR, m.r, m.g, m.b, m.a); } else if (!p_colors) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } else { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Color) * p_vertex_count; } if (p_uvs) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Vector2) * p_vertex_count; } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV); } if (p_weights && p_bones) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(float) * 4 * p_vertex_count, p_weights); - glEnableVertexAttribArray(VS::ARRAY_WEIGHTS); - glVertexAttribPointer(VS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_WEIGHTS); + glVertexAttribPointer(RS::ARRAY_WEIGHTS, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(float) * 4 * p_vertex_count; glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(int) * 4 * p_vertex_count, p_bones); - glEnableVertexAttribArray(VS::ARRAY_BONES); - glVertexAttribPointer(VS::ARRAY_BONES, 4, GL_UNSIGNED_INT, GL_FALSE, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_BONES); + glVertexAttribPointer(RS::ARRAY_BONES, 4, GL_UNSIGNED_INT, GL_FALSE, sizeof(int) * 4, CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(int) * 4 * p_vertex_count; } else { - glDisableVertexAttribArray(VS::ARRAY_WEIGHTS); - glDisableVertexAttribArray(VS::ARRAY_BONES); + glDisableVertexAttribArray(RS::ARRAY_WEIGHTS); + glDisableVertexAttribArray(RS::ARRAY_BONES); } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); @@ -375,30 +375,30 @@ void RasterizerCanvasGLES2::_draw_generic(GLuint p_primitive, int p_vertex_count uint32_t buffer_ofs = 0; glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); buffer_ofs += sizeof(Vector2) * p_vertex_count; if (p_singlecolor) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); + glDisableVertexAttribArray(RS::ARRAY_COLOR); Color m = *p_colors; - glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + glVertexAttrib4f(RS::ARRAY_COLOR, m.r, m.g, m.b, m.a); } else if (!p_colors) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } else { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Color) * p_vertex_count; } if (p_uvs) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV); } glDrawArrays(p_primitive, 0, p_vertex_count); @@ -417,31 +417,31 @@ void RasterizerCanvasGLES2::_draw_generic_indices(GLuint p_primitive, const int uint32_t buffer_ofs = 0; glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(Vector2) * p_vertex_count, p_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), NULL); buffer_ofs += sizeof(Vector2) * p_vertex_count; if (p_singlecolor) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); + glDisableVertexAttribArray(RS::ARRAY_COLOR); Color m = *p_colors; - glVertexAttrib4f(VS::ARRAY_COLOR, m.r, m.g, m.b, m.a); + glVertexAttrib4f(RS::ARRAY_COLOR, m.r, m.g, m.b, m.a); } else if (!p_colors) { - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } else { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Color) * p_vertex_count, p_colors); - glEnableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Color) * p_vertex_count; } if (p_uvs) { glBufferSubData(GL_ARRAY_BUFFER, buffer_ofs, sizeof(Vector2) * p_vertex_count, p_uvs); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buffer_ofs)); buffer_ofs += sizeof(Vector2) * p_vertex_count; } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV); } glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.polygon_index_buffer); @@ -514,16 +514,16 @@ void RasterizerCanvasGLES2::_draw_gui_primitive(int p_points, const Vector2 *p_v #endif glBufferSubData(GL_ARRAY_BUFFER, 0, p_points * stride * 4 * sizeof(float), buffer_data); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), NULL); if (p_colors) { - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(color_offset * sizeof(float))); - glEnableVertexAttribArray(VS::ARRAY_COLOR); + glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(color_offset * sizeof(float))); + glEnableVertexAttribArray(RS::ARRAY_COLOR); } if (p_uvs) { - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(uv_offset * sizeof(float))); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, stride * sizeof(float), CAST_INT_TO_UCHAR_PTR(uv_offset * sizeof(float))); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); } glDrawArrays(prim[p_points], 0, p_points); @@ -564,8 +564,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur _bind_canvas_texture(RID(), RID()); - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4fv(VS::ARRAY_COLOR, line->color.components); + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4fv(RS::ARRAY_COLOR, line->color.components); state.canvas_shader.set_uniform(CanvasShaderGLES2::MODELVIEW_MATRIX, state.uniforms.modelview_matrix); @@ -616,8 +616,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur Item::CommandRect *r = static_cast(command); - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4fv(VS::ARRAY_COLOR, r->modulate.components); + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4fv(RS::ARRAY_COLOR, r->modulate.components); bool can_tile = true; if (r->texture.is_valid() && r->flags & CANVAS_RECT_TILE && !storage->config.support_npot_repeat_mipmap) { @@ -696,7 +696,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur bool untile = false; - if (can_tile && r->flags & CANVAS_RECT_TILE && !(texture->flags & VS::TEXTURE_FLAG_REPEAT)) { + if (can_tile && r->flags & CANVAS_RECT_TILE && !(texture->flags & RS::TEXTURE_FLAG_REPEAT)) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); untile = true; @@ -753,7 +753,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur bool untile = false; - if (can_tile && r->flags & CANVAS_RECT_TILE && !(tex->flags & VS::TEXTURE_FLAG_REPEAT)) { + if (can_tile && r->flags & CANVAS_RECT_TILE && !(tex->flags & RS::TEXTURE_FLAG_REPEAT)) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); untile = true; @@ -816,8 +816,8 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur state.canvas_shader.use_material((void *)p_material); } - glDisableVertexAttribArray(VS::ARRAY_COLOR); - glVertexAttrib4fv(VS::ARRAY_COLOR, np->color.components); + glDisableVertexAttribArray(RS::ARRAY_COLOR); + glVertexAttrib4fv(RS::ARRAY_COLOR, np->color.components); RasterizerStorageGLES2::Texture *tex = _bind_canvas_texture(np->texture, np->normal_map); @@ -968,11 +968,11 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.ninepatch_elements); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), NULL); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), CAST_INT_TO_UCHAR_PTR((sizeof(float) * 2))); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), NULL); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(float), CAST_INT_TO_UCHAR_PTR((sizeof(float) * 2))); glDrawElements(GL_TRIANGLES, 18 * 3 - (np->draw_center ? 0 : 6), GL_UNSIGNED_BYTE, NULL); @@ -1072,18 +1072,18 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); } - for (int k = 0; k < VS::ARRAY_MAX - 1; k++) { + for (int k = 0; k < RS::ARRAY_MAX - 1; k++) { if (s->attribs[k].enabled) { glEnableVertexAttribArray(k); glVertexAttribPointer(s->attribs[k].index, s->attribs[k].size, s->attribs[k].type, s->attribs[k].normalized, s->attribs[k].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[k].offset)); } else { glDisableVertexAttribArray(k); switch (k) { - case VS::ARRAY_NORMAL: { - glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); + case RS::ARRAY_NORMAL: { + glVertexAttrib4f(RS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); } break; - case VS::ARRAY_COLOR: { - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + case RS::ARRAY_COLOR: { + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } break; default: { @@ -1099,7 +1099,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } } - for (int j = 1; j < VS::ARRAY_MAX - 1; j++) { + for (int j = 1; j < RS::ARRAY_MAX - 1; j++) { glDisableVertexAttribArray(j); } } @@ -1118,7 +1118,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur if (!mesh_data) break; - state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != VS::MULTIMESH_CUSTOM_DATA_NONE); + state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != RS::MULTIMESH_CUSTOM_DATA_NONE); state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_INSTANCING, true); state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_TEXTURE_RECT, false); @@ -1162,18 +1162,18 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); } - for (int k = 0; k < VS::ARRAY_MAX - 1; k++) { + for (int k = 0; k < RS::ARRAY_MAX - 1; k++) { if (s->attribs[k].enabled) { glEnableVertexAttribArray(k); glVertexAttribPointer(s->attribs[k].index, s->attribs[k].size, s->attribs[k].type, s->attribs[k].normalized, s->attribs[k].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[k].offset)); } else { glDisableVertexAttribArray(k); switch (k) { - case VS::ARRAY_NORMAL: { - glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); + case RS::ARRAY_NORMAL: { + glVertexAttrib4f(RS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); } break; - case VS::ARRAY_COLOR: { - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + case RS::ARRAY_COLOR: { + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } break; default: { @@ -1189,7 +1189,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 0, &buffer[0]); glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 1, &buffer[4]); - if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { + if (multi_mesh->transform_format == RS::MULTIMESH_TRANSFORM_3D) { glVertexAttrib4fv(INSTANCE_ATTRIB_BASE + 2, &buffer[8]); } else { glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 2, 0.0, 0.0, 1.0, 0.0); @@ -1197,7 +1197,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } if (multi_mesh->color_floats) { - if (multi_mesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + if (multi_mesh->color_format == RS::MULTIMESH_COLOR_8BIT) { uint8_t *color_data = (uint8_t *)(buffer + color_ofs); glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, color_data[0] / 255.0, color_data[1] / 255.0, color_data[2] / 255.0, color_data[3] / 255.0); } else { @@ -1208,7 +1208,7 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur } if (multi_mesh->custom_data_floats) { - if (multi_mesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + if (multi_mesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_8BIT) { uint8_t *custom_data = (uint8_t *)(buffer + custom_data_ofs); glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 4, custom_data[0] / 255.0, custom_data[1] / 255.0, custom_data[2] / 255.0, custom_data[3] / 255.0); } else { @@ -1301,9 +1301,9 @@ void RasterizerCanvasGLES2::_canvas_item_render_commands(Item *p_item, Item *cur if (primitive->colors.size() == 1 && primitive->points.size() > 1) { Color c = primitive->colors[0]; - glVertexAttrib4f(VS::ARRAY_COLOR, c.r, c.g, c.b, c.a); + glVertexAttrib4f(RS::ARRAY_COLOR, c.r, c.g, c.b, c.a); } else if (primitive->colors.empty()) { - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } _draw_gui_primitive(primitive->points.size(), primitive->points.ptr(), primitive->colors.ptr(), primitive->uvs.ptr()); @@ -1518,7 +1518,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons if (material_ptr) { shader_ptr = material_ptr->shader; - if (shader_ptr && shader_ptr->mode != VS::SHADER_CANVAS_ITEM) { + if (shader_ptr && shader_ptr->mode != RS::SHADER_CANVAS_ITEM) { shader_ptr = NULL; // not a canvas item shader, don't use. } } @@ -1542,7 +1542,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons if (shader_ptr != shader_cache) { if (shader_ptr->canvas_item.uses_time) { - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } state.canvas_shader.set_custom_shader(shader_ptr->custom_code_id); @@ -1582,7 +1582,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons } if (t->redraw_if_visible) { - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } t = t->get_ptr(); @@ -1682,7 +1682,7 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons Light *light = p_light; bool light_used = false; - VS::CanvasLightMode mode = VS::CANVAS_LIGHT_MODE_ADD; + RS::CanvasLightMode mode = RS::CANVAS_LIGHT_MODE_ADD; state.uniforms.final_modulate = ci->final_modulate; // remove the canvas modulate while (light) { @@ -1697,17 +1697,17 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons switch (mode) { - case VS::CANVAS_LIGHT_MODE_ADD: { + case RS::CANVAS_LIGHT_MODE_ADD: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE); } break; - case VS::CANVAS_LIGHT_MODE_SUB: { + case RS::CANVAS_LIGHT_MODE_SUB: { glBlendEquation(GL_FUNC_REVERSE_SUBTRACT); glBlendFunc(GL_SRC_ALPHA, GL_ONE); } break; - case VS::CANVAS_LIGHT_MODE_MIX: - case VS::CANVAS_LIGHT_MODE_MASK: { + case RS::CANVAS_LIGHT_MODE_MIX: + case RS::CANVAS_LIGHT_MODE_MASK: { glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -1726,12 +1726,12 @@ void RasterizerCanvasGLES2::canvas_render_items(Item *p_item_list, int p_z, cons state.canvas_shader.set_conditional(CanvasShaderGLES2::USE_SHADOWS, has_shadow); if (has_shadow) { state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_USE_GRADIENT, light->shadow_gradient_length > 0); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF3); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF5); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF7); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF9); - state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == VS::CANVAS_LIGHT_FILTER_PCF13); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_NEAREST, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_NONE); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF3, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF3); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF5, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF5); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF7, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF7); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF9, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF9); + state.canvas_shader.set_conditional(CanvasShaderGLES2::SHADOW_FILTER_PCF13, light->shadow_filter == RS::CANVAS_LIGHT_FILTER_PCF13); } state.canvas_shader.bind(); @@ -1846,7 +1846,7 @@ void RasterizerCanvasGLES2::canvas_light_shadow_buffer_update(RID p_buffer, cons glClearColor(1, 1, 1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - VS::CanvasOccluderPolygonCullMode cull = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + RS::CanvasOccluderPolygonCullMode cull = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; for (int i = 0; i < 4; i++) { @@ -1903,31 +1903,31 @@ void RasterizerCanvasGLES2::canvas_light_shadow_buffer_update(RID p_buffer, cons state.canvas_shadow_shader.set_uniform(CanvasShadowShaderGLES2::WORLD_MATRIX, instance->xform_cache); - VS::CanvasOccluderPolygonCullMode transformed_cull_cache = instance->cull_cache; + RS::CanvasOccluderPolygonCullMode transformed_cull_cache = instance->cull_cache; - if (transformed_cull_cache != VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED && + if (transformed_cull_cache != RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED && (p_light_xform.basis_determinant() * instance->xform_cache.basis_determinant()) < 0) { transformed_cull_cache = - transformed_cull_cache == VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ? - VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE : - VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE; + transformed_cull_cache == RS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE ? + RS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE : + RS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE; } if (cull != transformed_cull_cache) { cull = transformed_cull_cache; switch (cull) { - case VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { + case RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED: { glDisable(GL_CULL_FACE); } break; - case VS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { + case RS::CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE: { glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); } break; - case VS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { + case RS::CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE: { glEnable(GL_CULL_FACE); glCullFace(GL_BACK); @@ -1937,8 +1937,8 @@ void RasterizerCanvasGLES2::canvas_light_shadow_buffer_update(RID p_buffer, cons } glBindBuffer(GL_ARRAY_BUFFER, cc->vertex_id); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glVertexAttribPointer(RS::ARRAY_VERTEX, 3, GL_FLOAT, false, 0, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, cc->index_id); glDrawElements(GL_TRIANGLES, cc->len * 3, GL_UNSIGNED_SHORT, 0); @@ -1979,8 +1979,8 @@ void RasterizerCanvasGLES2::reset_canvas() { void RasterizerCanvasGLES2::_bind_quad_buffer() { glBindBuffer(GL_ARRAY_BUFFER, data.canvas_quad_vertices); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, NULL); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, 0, NULL); } void RasterizerCanvasGLES2::draw_generic_textured_rect(const Rect2 &p_rect, const Rect2 &p_src) { @@ -2022,7 +2022,7 @@ void RasterizerCanvasGLES2::draw_lens_distortion_rect(const Rect2 &p_rect, float // and cleanup glBindBuffer(GL_ARRAY_BUFFER, 0); - for (int i = 0; i < VS::ARRAY_MAX; i++) { + for (int i = 0; i < RS::ARRAY_MAX; i++) { glDisableVertexAttribArray(i); } } diff --git a/drivers/gles2/rasterizer_canvas_gles2.h b/drivers/gles2/rasterizer_canvas_gles2.h index f6ae6a60c0..4e4db98c25 100644 --- a/drivers/gles2/rasterizer_canvas_gles2.h +++ b/drivers/gles2/rasterizer_canvas_gles2.h @@ -32,7 +32,7 @@ #define RASTERIZERCANVASGLES2_H #include "rasterizer_storage_gles2.h" -#include "servers/visual/rasterizer.h" +#include "servers/rendering/rasterizer.h" #include "shaders/canvas.glsl.gen.h" #include "shaders/lens_distorted.glsl.gen.h" diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp index f14c5f9406..cc17af171e 100644 --- a/drivers/gles2/rasterizer_gles2.cpp +++ b/drivers/gles2/rasterizer_gles2.cpp @@ -263,7 +263,7 @@ void RasterizerGLES2::initialize() { #endif // GLES_OVER_GL #endif // CAN_DEBUG - print_line("OpenGL ES 2.0 Renderer: " + VisualServer::get_singleton()->get_video_adapter_name()); + print_line("OpenGL ES 2.0 Renderer: " + RenderingServer::get_singleton()->get_video_adapter_name()); storage->initialize(); canvas->initialize(); scene->initialize(); @@ -359,7 +359,7 @@ void RasterizerGLES2::set_boot_image(const Ref &p_image, const Color &p_c canvas->canvas_begin(); RID texture = storage->texture_create(); - storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), VS::TEXTURE_TYPE_2D, p_use_filter ? VS::TEXTURE_FLAG_FILTER : 0); + storage->texture_allocate(texture, p_image->get_width(), p_image->get_height(), 0, p_image->get_format(), RS::TEXTURE_TYPE_2D, p_use_filter ? RS::TEXTURE_FLAG_FILTER : 0); storage->texture_set_data(texture, p_image); Rect2 imgrect(0, 0, p_image->get_width(), p_image->get_height()); diff --git a/drivers/gles2/rasterizer_gles2.h b/drivers/gles2/rasterizer_gles2.h index 9a5501f13d..027a634ae8 100644 --- a/drivers/gles2/rasterizer_gles2.h +++ b/drivers/gles2/rasterizer_gles2.h @@ -34,7 +34,7 @@ #include "rasterizer_canvas_gles2.h" #include "rasterizer_scene_gles2.h" #include "rasterizer_storage_gles2.h" -#include "servers/visual/rasterizer.h" +#include "servers/rendering/rasterizer.h" class RasterizerGLES2 : public Rasterizer { diff --git a/drivers/gles2/rasterizer_scene_gles2.cpp b/drivers/gles2/rasterizer_scene_gles2.cpp index 8872dde9fc..4bb8d5a16d 100644 --- a/drivers/gles2/rasterizer_scene_gles2.cpp +++ b/drivers/gles2/rasterizer_scene_gles2.cpp @@ -37,7 +37,7 @@ #include "core/vmap.h" #include "rasterizer_canvas_gles2.h" #include "servers/camera/camera_feed.h" -#include "servers/visual/visual_server_raster.h" +#include "servers/rendering/rendering_server_raster.h" #ifndef GLES_OVER_GL #define glClearDepth glClearDepthf @@ -456,10 +456,10 @@ int RasterizerSceneGLES2::get_directional_light_shadow_size(RID p_light_intance) ERR_FAIL_COND_V(!light_instance, 0); switch (light_instance->light_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: break; //none - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: shadow_size /= 2; break; } @@ -525,7 +525,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_needs_redraw(RID p_instance const ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); ERR_FAIL_COND_V(!rpi, false); - bool need_redraw = rpi->probe_ptr->resolution != rpi->current_resolution || rpi->dirty || rpi->probe_ptr->update_mode == VS::REFLECTION_PROBE_UPDATE_ALWAYS; + bool need_redraw = rpi->probe_ptr->resolution != rpi->current_resolution || rpi->dirty || rpi->probe_ptr->update_mode == RS::REFLECTION_PROBE_UPDATE_ALWAYS; rpi->dirty = false; return need_redraw; } @@ -610,7 +610,7 @@ bool RasterizerSceneGLES2::reflection_probe_instance_postprocess_step(RID p_inst glDisable(GL_BLEND); glDepthMask(GL_FALSE); - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + for (int i = 0; i < RS::ARRAY_MAX - 1; i++) { glDisableVertexAttribArray(i); } } @@ -690,7 +690,7 @@ RID RasterizerSceneGLES2::environment_create() { return environment_owner.make_rid(env); } -void RasterizerSceneGLES2::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) { +void RasterizerSceneGLES2::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -755,7 +755,7 @@ void RasterizerSceneGLES2::environment_set_camera_feed_id(RID p_env, int p_camer env->camera_feed_id = p_camera_feed_id; } -void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { +void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, RS::EnvironmentDOFBlurQuality p_quality) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -767,7 +767,7 @@ void RasterizerSceneGLES2::environment_set_dof_blur_far(RID p_env, bool p_enable env->dof_blur_far_quality = p_quality; } -void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality) { +void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, RS::EnvironmentDOFBlurQuality p_quality) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -779,7 +779,7 @@ void RasterizerSceneGLES2::environment_set_dof_blur_near(RID p_env, bool p_enabl env->dof_blur_near_quality = p_quality; } -void RasterizerSceneGLES2::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { +void RasterizerSceneGLES2::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); @@ -806,12 +806,12 @@ void RasterizerSceneGLES2::environment_set_ssr(RID p_env, bool p_enable, int p_m ERR_FAIL_COND(!env); } -void RasterizerSceneGLES2::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VisualServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { +void RasterizerSceneGLES2::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, RS::EnvironmentSSAOQuality p_quality, RenderingServer::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); } -void RasterizerSceneGLES2::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { +void RasterizerSceneGLES2::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { Environment *env = environment_owner.getornull(p_env); ERR_FAIL_COND(!env); } @@ -866,9 +866,9 @@ bool RasterizerSceneGLES2::is_environment(RID p_env) { return environment_owner.owns(p_env); } -VS::EnvironmentBG RasterizerSceneGLES2::environment_get_background(RID p_env) { +RS::EnvironmentBG RasterizerSceneGLES2::environment_get_background(RID p_env) { const Environment *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); + ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX); return env->bg_mode; } @@ -914,7 +914,7 @@ void RasterizerSceneGLES2::light_instance_set_shadow_transform(RID p_light_insta LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); ERR_FAIL_COND(!light_instance); - if (light_instance->light_ptr->type != VS::LIGHT_DIRECTIONAL) { + if (light_instance->light_ptr->type != RS::LIGHT_DIRECTIONAL) { p_pass = 0; } @@ -1022,7 +1022,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G if (!p_material->shader->spatial.uses_alpha_scissor && !p_material->shader->spatial.writes_modelview_or_projection && !p_material->shader->spatial.uses_vertex && !p_material->shader->spatial.uses_discard && p_material->shader->spatial.depth_draw_mode != RasterizerStorageGLES2::Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS) { //shader does not use discard and does not write a vertex position, use generic material - if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { + if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { p_material = storage->material_owner.getornull(!p_shadow_pass && p_material->shader->spatial.uses_world_coordinates ? default_worldcoord_material_twosided : default_material_twosided); mirror = false; } else { @@ -1048,7 +1048,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G e->use_accum = false; e->light_index = RenderList::MAX_LIGHTS; e->use_accum_ptr = &e->use_accum; - e->instancing = (e->instance->base_type == VS::INSTANCE_MULTIMESH) ? 1 : 0; + e->instancing = (e->instance->base_type == RS::INSTANCE_MULTIMESH) ? 1 : 0; e->front_facing = false; if (e->geometry->last_pass != render_pass) { @@ -1162,7 +1162,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G //directional sort key e->light_type1 = 1; - e->light_type2 = li->light_ptr->type == VisualServer::LIGHT_OMNI ? 0 : 1; + e->light_type2 = li->light_ptr->type == RenderingServer::LIGHT_OMNI ? 0 : 1; e->light_index = li->light_index; copy = true; @@ -1181,7 +1181,7 @@ void RasterizerSceneGLES2::_add_geometry_with_material(RasterizerStorageGLES2::G // do not add anything here, as lights are duplicated elements.. if (p_material->shader->spatial.uses_time) { - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } } @@ -1224,7 +1224,7 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p switch (instance->base_type) { - case VS::INSTANCE_MESH: { + case RS::INSTANCE_MESH: { RasterizerStorageGLES2::Mesh *mesh = storage->mesh_owner.getornull(instance->base); ERR_CONTINUE(!mesh); @@ -1241,7 +1241,7 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p } break; - case VS::INSTANCE_MULTIMESH: { + case RS::INSTANCE_MULTIMESH: { RasterizerStorageGLES2::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(instance->base); ERR_CONTINUE(!multi_mesh); @@ -1260,7 +1260,7 @@ void RasterizerSceneGLES2::_fill_render_list(InstanceBase **p_cull_result, int p } } break; - case VS::INSTANCE_IMMEDIATE: { + case RS::INSTANCE_IMMEDIATE: { RasterizerStorageGLES2::Immediate *im = storage->immediate_owner.getornull(instance->base); ERR_CONTINUE(!im); @@ -1426,7 +1426,7 @@ bool RasterizerSceneGLES2::_setup_material(RasterizerStorageGLES2::Material *p_m } if (t->redraw_if_visible) { //must check before proxy because this is often used with proxies - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } t = t->get_ptr(); @@ -1459,7 +1459,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste switch (p_element->instance->base_type) { - case VS::INSTANCE_MESH: { + case RS::INSTANCE_MESH: { RasterizerStorageGLES2::Surface *s = static_cast(p_element->geometry); glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id); @@ -1468,18 +1468,18 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); } - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + for (int i = 0; i < RS::ARRAY_MAX - 1; i++) { if (s->attribs[i].enabled) { glEnableVertexAttribArray(i); glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[i].offset)); } else { glDisableVertexAttribArray(i); switch (i) { - case VS::ARRAY_NORMAL: { - glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); + case RS::ARRAY_NORMAL: { + glVertexAttrib4f(RS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); } break; - case VS::ARRAY_COLOR: { - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + case RS::ARRAY_COLOR: { + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } break; default: { @@ -1502,7 +1502,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste Vector &transform_buffer = storage->resources.skeleton_transform_cpu_buffer; - if (!s->attribs[VS::ARRAY_BONES].enabled || !s->attribs[VS::ARRAY_WEIGHTS].enabled) { + if (!s->attribs[RS::ARRAY_BONES].enabled || !s->attribs[RS::ARRAY_WEIGHTS].enabled) { break; // the whole instance has a skeleton, but this surface is not affected by it. } @@ -1511,10 +1511,10 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste transform_buffer.resize(s->array_len * 12); } - const size_t bones_offset = s->attribs[VS::ARRAY_BONES].offset; - const size_t bones_stride = s->attribs[VS::ARRAY_BONES].stride; - const size_t bone_weight_offset = s->attribs[VS::ARRAY_WEIGHTS].offset; - const size_t bone_weight_stride = s->attribs[VS::ARRAY_WEIGHTS].stride; + const size_t bones_offset = s->attribs[RS::ARRAY_BONES].offset; + const size_t bones_stride = s->attribs[RS::ARRAY_BONES].stride; + const size_t bone_weight_offset = s->attribs[RS::ARRAY_WEIGHTS].offset; + const size_t bone_weight_stride = s->attribs[RS::ARRAY_WEIGHTS].stride; { float *write = transform_buffer.ptrw(); @@ -1530,7 +1530,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste size_t bones[4]; float bone_weight[4]; - if (s->attribs[VS::ARRAY_BONES].type == GL_UNSIGNED_BYTE) { + if (s->attribs[RS::ARRAY_BONES].type == GL_UNSIGNED_BYTE) { // read as byte const uint8_t *bones_ptr = vertex_data + bones_offset + (i * bones_stride); bones[0] = bones_ptr[0]; @@ -1546,7 +1546,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste bones[3] = bones_ptr[3]; } - if (s->attribs[VS::ARRAY_WEIGHTS].type == GL_FLOAT) { + if (s->attribs[RS::ARRAY_WEIGHTS].type == GL_FLOAT) { // read as float const float *weight_ptr = (const float *)(vertex_data + bone_weight_offset + (i * bone_weight_stride)); bone_weight[0] = weight_ptr[0]; @@ -1621,7 +1621,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste } break; - case VS::INSTANCE_MULTIMESH: { + case RS::INSTANCE_MULTIMESH: { RasterizerStorageGLES2::Surface *s = static_cast(p_element->geometry); glBindBuffer(GL_ARRAY_BUFFER, s->vertex_id); @@ -1630,18 +1630,18 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, s->index_id); } - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + for (int i = 0; i < RS::ARRAY_MAX - 1; i++) { if (s->attribs[i].enabled) { glEnableVertexAttribArray(i); glVertexAttribPointer(s->attribs[i].index, s->attribs[i].size, s->attribs[i].type, s->attribs[i].normalized, s->attribs[i].stride, CAST_INT_TO_UCHAR_PTR(s->attribs[i].offset)); } else { glDisableVertexAttribArray(i); switch (i) { - case VS::ARRAY_NORMAL: { - glVertexAttrib4f(VS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); + case RS::ARRAY_NORMAL: { + glVertexAttrib4f(RS::ARRAY_NORMAL, 0.0, 0.0, 1, 1); } break; - case VS::ARRAY_COLOR: { - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + case RS::ARRAY_COLOR: { + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); } break; default: { @@ -1662,7 +1662,7 @@ void RasterizerSceneGLES2::_setup_geometry(RenderList::Element *p_element, Raste } break; - case VS::INSTANCE_IMMEDIATE: { + case RS::INSTANCE_IMMEDIATE: { } break; default: { @@ -1674,7 +1674,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { switch (p_element->instance->base_type) { - case VS::INSTANCE_MESH: { + case RS::INSTANCE_MESH: { RasterizerStorageGLES2::Surface *s = static_cast(p_element->geometry); @@ -1688,22 +1688,22 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { storage->info.render.vertices_count += s->array_len; } /* - if (p_element->instance->skeleton.is_valid() && s->attribs[VS::ARRAY_BONES].enabled && s->attribs[VS::ARRAY_WEIGHTS].enabled) { + if (p_element->instance->skeleton.is_valid() && s->attribs[RS::ARRAY_BONES].enabled && s->attribs[RS::ARRAY_WEIGHTS].enabled) { //clean up after skeleton glBindBuffer(GL_ARRAY_BUFFER, storage->resources.skeleton_transform_buffer); - glDisableVertexAttribArray(VS::ARRAY_MAX + 0); - glDisableVertexAttribArray(VS::ARRAY_MAX + 1); - glDisableVertexAttribArray(VS::ARRAY_MAX + 2); + glDisableVertexAttribArray(RS::ARRAY_MAX + 0); + glDisableVertexAttribArray(RS::ARRAY_MAX + 1); + glDisableVertexAttribArray(RS::ARRAY_MAX + 2); - glVertexAttrib4f(VS::ARRAY_MAX + 0, 1, 0, 0, 0); - glVertexAttrib4f(VS::ARRAY_MAX + 1, 0, 1, 0, 0); - glVertexAttrib4f(VS::ARRAY_MAX + 2, 0, 0, 1, 0); + glVertexAttrib4f(RS::ARRAY_MAX + 0, 1, 0, 0, 0); + glVertexAttrib4f(RS::ARRAY_MAX + 1, 0, 1, 0, 0); + glVertexAttrib4f(RS::ARRAY_MAX + 2, 0, 0, 1, 0); } */ } break; - case VS::INSTANCE_MULTIMESH: { + case RS::INSTANCE_MULTIMESH: { RasterizerStorageGLES2::MultiMesh *multi_mesh = static_cast(p_element->owner); RasterizerStorageGLES2::Surface *s = static_cast(p_element->geometry); @@ -1734,7 +1734,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } if (multi_mesh->color_floats) { - if (multi_mesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + if (multi_mesh->color_format == RS::MULTIMESH_COLOR_8BIT) { uint8_t *color_data = (uint8_t *)(buffer + color_ofs); glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 3, color_data[0] / 255.0, color_data[1] / 255.0, color_data[2] / 255.0, color_data[3] / 255.0); } else { @@ -1745,7 +1745,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } if (multi_mesh->custom_data_floats) { - if (multi_mesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + if (multi_mesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_8BIT) { uint8_t *custom_data = (uint8_t *)(buffer + custom_data_ofs); glVertexAttrib4f(INSTANCE_ATTRIB_BASE + 4, custom_data[0] / 255.0, custom_data[1] / 255.0, custom_data[2] / 255.0, custom_data[3] / 255.0); } else { @@ -1764,7 +1764,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } break; - case VS::INSTANCE_IMMEDIATE: { + case RS::INSTANCE_IMMEDIATE: { const RasterizerStorageGLES2::Immediate *im = static_cast(p_element->geometry); if (im->building) { @@ -1792,7 +1792,7 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { RasterizerStorageGLES2::Texture *t = storage->texture_owner.getornull(c.texture); if (t->redraw_if_visible) { - VisualServerRaster::redraw_request(); + RenderingServerRaster::redraw_request(); } t = t->get_ptr(); @@ -1816,53 +1816,53 @@ void RasterizerSceneGLES2::_render_geometry(RenderList::Element *p_element) { } if (!c.normals.empty()) { - glEnableVertexAttribArray(VS::ARRAY_NORMAL); + glEnableVertexAttribArray(RS::ARRAY_NORMAL); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.normals.ptr()); - glVertexAttribPointer(VS::ARRAY_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); + glVertexAttribPointer(RS::ARRAY_NORMAL, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector3) * vertices; } else { - glDisableVertexAttribArray(VS::ARRAY_NORMAL); + glDisableVertexAttribArray(RS::ARRAY_NORMAL); } if (!c.tangents.empty()) { - glEnableVertexAttribArray(VS::ARRAY_TANGENT); + glEnableVertexAttribArray(RS::ARRAY_TANGENT); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Plane) * vertices, c.tangents.ptr()); - glVertexAttribPointer(VS::ARRAY_TANGENT, 4, GL_FLOAT, GL_FALSE, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs)); + glVertexAttribPointer(RS::ARRAY_TANGENT, 4, GL_FLOAT, GL_FALSE, sizeof(Plane), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Plane) * vertices; } else { - glDisableVertexAttribArray(VS::ARRAY_TANGENT); + glDisableVertexAttribArray(RS::ARRAY_TANGENT); } if (!c.colors.empty()) { - glEnableVertexAttribArray(VS::ARRAY_COLOR); + glEnableVertexAttribArray(RS::ARRAY_COLOR); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Color) * vertices, c.colors.ptr()); - glVertexAttribPointer(VS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs)); + glVertexAttribPointer(RS::ARRAY_COLOR, 4, GL_FLOAT, GL_FALSE, sizeof(Color), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Color) * vertices; } else { - glDisableVertexAttribArray(VS::ARRAY_COLOR); + glDisableVertexAttribArray(RS::ARRAY_COLOR); } if (!c.uvs.empty()) { - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uvs.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector2) * vertices; } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV); } if (!c.uv2s.empty()) { - glEnableVertexAttribArray(VS::ARRAY_TEX_UV2); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV2); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector2) * vertices, c.uv2s.ptr()); - glVertexAttribPointer(VS::ARRAY_TEX_UV2, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); + glVertexAttribPointer(RS::ARRAY_TEX_UV2, 2, GL_FLOAT, GL_FALSE, sizeof(Vector2), CAST_INT_TO_UCHAR_PTR(buf_ofs)); buf_ofs += sizeof(Vector2) * vertices; } else { - glDisableVertexAttribArray(VS::ARRAY_TEX_UV2); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV2); } - glEnableVertexAttribArray(VS::ARRAY_VERTEX); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); glBufferSubData(GL_ARRAY_BUFFER, buf_ofs, sizeof(Vector3) * vertices, c.vertices.ptr()); - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); + glVertexAttribPointer(RS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3), CAST_INT_TO_UCHAR_PTR(buf_ofs)); glDrawArrays(gl_primitive[c.primitive], 0, c.vertices.size()); } @@ -1901,18 +1901,18 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::USE_LIGHTING, true); switch (p_light->light_ptr->type) { - case VS::LIGHT_DIRECTIONAL: { + case RS::LIGHT_DIRECTIONAL: { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_DIRECTIONAL, true); switch (p_light->light_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { //no need } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM2, true); } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_USE_PSSM4, true); } break; } @@ -1931,7 +1931,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas } } break; - case VS::LIGHT_OMNI: { + case RS::LIGHT_OMNI: { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_OMNI, true); if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { @@ -1946,7 +1946,7 @@ void RasterizerSceneGLES2::_setup_light_type(LightInstance *p_light, ShadowAtlas state.scene_shader.set_conditional(SceneShaderGLES2::SHADOW_MODE_PCF_13, shadow_filter_mode == SHADOW_FILTER_PCF13); } } break; - case VS::LIGHT_SPOT: { + case RS::LIGHT_SPOT: { state.scene_shader.set_conditional(SceneShaderGLES2::LIGHT_MODE_SPOT, true); if (!state.render_no_shadows && shadow_atlas && p_light->light_ptr->shadow) { @@ -1969,8 +1969,8 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado RasterizerStorageGLES2::Light *light_ptr = light->light_ptr; //common parameters - float energy = light_ptr->param[VS::LIGHT_PARAM_ENERGY]; - float specular = light_ptr->param[VS::LIGHT_PARAM_SPECULAR]; + float energy = light_ptr->param[RS::LIGHT_PARAM_ENERGY]; + float specular = light_ptr->param[RS::LIGHT_PARAM_SPECULAR]; float sign = (light_ptr->negative && !accum_pass) ? -1 : 1; //inverse color for base pass lights only state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPECULAR, specular); @@ -1982,7 +1982,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado //specific parameters switch (light_ptr->type) { - case VS::LIGHT_DIRECTIONAL: { + case RS::LIGHT_DIRECTIONAL: { //not using inverse for performance, view should be normalized anyway Vector3 direction = p_view_transform.basis.xform_inv(light->transform.basis.xform(Vector3(0, 0, -1))).normalized(); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction); @@ -1995,15 +1995,15 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado Color split_offsets; switch (light_ptr->directional_shadow_mode) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: { shadow_count = 1; } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: { shadow_count = 2; } break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: { shadow_count = 4; } break; } @@ -2015,7 +2015,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado uint32_t width = light->directional_rect.size.x; uint32_t height = light->directional_rect.size.y; - if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + if (light_ptr->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { width /= 2; height /= 2; @@ -2029,7 +2029,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado y += height; } - } else if (light_ptr->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + } else if (light_ptr->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { height /= 2; @@ -2067,16 +2067,16 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SHADOW_MATRIX4, matrices[3]); } } break; - case VS::LIGHT_OMNI: { + case RS::LIGHT_OMNI: { Vector3 position = p_view_transform.xform_inv(light->transform.origin); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_POSITION, position); - float range = light_ptr->param[VS::LIGHT_PARAM_RANGE]; + float range = light_ptr->param[RS::LIGHT_PARAM_RANGE]; state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_RANGE, range); - float attenuation = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; + float attenuation = light_ptr->param[RS::LIGHT_PARAM_ATTENUATION]; state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation); if (!state.render_no_shadows && light_ptr->shadow && shadow_atlas && shadow_atlas->shadow_owners.has(light->self)) { @@ -2101,7 +2101,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado uint32_t width = shadow_size; uint32_t height = shadow_size; - if (light->light_ptr->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { + if (light->light_ptr->omni_shadow_detail == RS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { height /= 2; } else { width /= 2; @@ -2121,7 +2121,7 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado } } break; - case VS::LIGHT_SPOT: { + case RS::LIGHT_SPOT: { Vector3 position = p_view_transform.xform_inv(light->transform.origin); @@ -2129,10 +2129,10 @@ void RasterizerSceneGLES2::_setup_light(LightInstance *light, ShadowAtlas *shado Vector3 direction = p_view_transform.inverse().basis.xform(light->transform.basis.xform(Vector3(0, 0, -1))).normalized(); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_DIRECTION, direction); - float attenuation = light_ptr->param[VS::LIGHT_PARAM_ATTENUATION]; - float range = light_ptr->param[VS::LIGHT_PARAM_RANGE]; - float spot_attenuation = light_ptr->param[VS::LIGHT_PARAM_SPOT_ATTENUATION]; - float angle = light_ptr->param[VS::LIGHT_PARAM_SPOT_ANGLE]; + float attenuation = light_ptr->param[RS::LIGHT_PARAM_ATTENUATION]; + float range = light_ptr->param[RS::LIGHT_PARAM_RANGE]; + float spot_attenuation = light_ptr->param[RS::LIGHT_PARAM_SPOT_ATTENUATION]; + float angle = light_ptr->param[RS::LIGHT_PARAM_SPOT_ANGLE]; angle = Math::cos(Math::deg2rad(angle)); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_ATTENUATION, attenuation); state.scene_shader.set_uniform(SceneShaderGLES2::LIGHT_SPOT_ATTENUATION, spot_attenuation); @@ -2490,7 +2490,7 @@ void RasterizerSceneGLES2::_render_render_list(RenderList::Element **p_elements, rebind = true; } - bool instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH; + bool instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH; if (instancing != prev_instancing) { @@ -2726,10 +2726,10 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C glBufferData(GL_ARRAY_BUFFER, sizeof(Vector3) * 8, vertices, GL_DYNAMIC_DRAW); // bind sky vertex array.... - glVertexAttribPointer(VS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, CAST_INT_TO_UCHAR_PTR(sizeof(Vector3))); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glVertexAttribPointer(RS::ARRAY_VERTEX, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, 0); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 3, GL_FLOAT, GL_FALSE, sizeof(Vector3) * 2, CAST_INT_TO_UCHAR_PTR(sizeof(Vector3))); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_ASYM_PANO, asymmetrical); storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_PANORAMA, !asymmetrical); @@ -2752,8 +2752,8 @@ void RasterizerSceneGLES2::_draw_sky(RasterizerStorageGLES2::Sky *p_sky, const C glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(VS::ARRAY_VERTEX); - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glDisableVertexAttribArray(RS::ARRAY_VERTEX); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV); glBindBuffer(GL_ARRAY_BUFFER, 0); storage->shaders.copy.set_conditional(CopyShaderGLES2::USE_ASYM_PANO, false); @@ -2845,9 +2845,9 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::USE_ORTHOGONAL_PROJECTION, p_cam_projection.is_orthogonal()); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_FAR_BLUR, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_LOW); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_far_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_far_quality == RS::ENV_DOF_BLUR_QUALITY_LOW); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_far_quality == RS::ENV_DOF_BLUR_QUALITY_MEDIUM); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_far_quality == RS::ENV_DOF_BLUR_QUALITY_HIGH); state.effect_blur_shader.bind(); int qsteps[3] = { 4, 10, 20 }; @@ -2911,9 +2911,9 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_BLUR, true); state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_NEAR_FIRST_TAP, true); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_LOW); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_MEDIUM); - state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_near_quality == VS::ENV_DOF_BLUR_QUALITY_HIGH); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_LOW, env->dof_blur_near_quality == RS::ENV_DOF_BLUR_QUALITY_LOW); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_MEDIUM, env->dof_blur_near_quality == RS::ENV_DOF_BLUR_QUALITY_MEDIUM); + state.effect_blur_shader.set_conditional(EffectBlurShaderGLES2::DOF_QUALITY_HIGH, env->dof_blur_near_quality == RS::ENV_DOF_BLUR_QUALITY_HIGH); state.effect_blur_shader.bind(); int qsteps[3] = { 4, 10, 20 }; @@ -3003,7 +3003,7 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p if (env->glow_enabled) { - for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) { + for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { if (env->glow_levels & (1 << i)) { if (i >= storage->frame.current_rt->mip_maps[1].sizes.size()) { @@ -3156,9 +3156,9 @@ void RasterizerSceneGLES2::_post_process(Environment *env, const CameraMatrix &p } } - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SCREEN, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_SCREEN); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SOFTLIGHT, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_SOFTLIGHT); - state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_REPLACE, env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_REPLACE); + state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SCREEN, env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_SCREEN); + state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_SOFTLIGHT, env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT); + state.tonemap_shader.set_conditional(TonemapShaderGLES2::USE_GLOW_REPLACE, env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_REPLACE); } //Adjustments @@ -3288,7 +3288,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const LightInstance *light = light_instance_owner.getornull(light_rid); - if (light->light_ptr->type == VS::LIGHT_DIRECTIONAL) { + if (light->light_ptr->type == RS::LIGHT_DIRECTIONAL) { render_directional_lights++; //as going in reverse, directional lights are always first anyway } @@ -3322,7 +3322,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const reflection_probe_count = 0; } - if (env && env->bg_mode == VS::ENV_BG_CANVAS) { + if (env && env->bg_mode == RS::ENV_BG_CANVAS) { // If using canvas background, copy 2d to screen copy texture // TODO: When GLES2 renders to current_rt->mip_maps[], this copy will no longer be needed _copy_texture_to_buffer(storage->frame.current_rt->color, storage->frame.current_rt->copy_screen_effect.fbo); @@ -3358,22 +3358,22 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (storage->frame.current_rt && storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT]) { clear_color = Color(0, 0, 0, 0); storage->frame.clear_request = false; - } else if (!env || env->bg_mode == VS::ENV_BG_CLEAR_COLOR || env->bg_mode == VS::ENV_BG_SKY) { + } else if (!env || env->bg_mode == RS::ENV_BG_CLEAR_COLOR || env->bg_mode == RS::ENV_BG_SKY) { if (storage->frame.clear_request) { clear_color = storage->frame.clear_request_color; storage->frame.clear_request = false; } - } else if (env->bg_mode == VS::ENV_BG_CANVAS || env->bg_mode == VS::ENV_BG_COLOR || env->bg_mode == VS::ENV_BG_COLOR_SKY) { + } else if (env->bg_mode == RS::ENV_BG_CANVAS || env->bg_mode == RS::ENV_BG_COLOR || env->bg_mode == RS::ENV_BG_COLOR_SKY) { clear_color = env->bg_color; storage->frame.clear_request = false; - } else if (env->bg_mode == VS::ENV_BG_CAMERA_FEED) { + } else if (env->bg_mode == RS::ENV_BG_CAMERA_FEED) { feed = CameraServer::get_singleton()->get_feed_by_id(env->camera_feed_id); storage->frame.clear_request = false; } else { storage->frame.clear_request = false; } - if (!env || env->bg_mode != VS::ENV_BG_KEEP) { + if (!env || env->bg_mode != RS::ENV_BG_KEEP) { glClearColor(clear_color.r, clear_color.g, clear_color.b, clear_color.a); glClear(GL_COLOR_BUFFER_BIT); } @@ -3385,7 +3385,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const glDisable(GL_SCISSOR_TEST); } - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -3396,15 +3396,15 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (env) { switch (env->bg_mode) { - case VS::ENV_BG_COLOR_SKY: - case VS::ENV_BG_SKY: { + case RS::ENV_BG_COLOR_SKY: + case RS::ENV_BG_SKY: { sky = storage->sky_owner.getornull(env->sky); if (sky) { env_radiance_tex = sky->radiance; } } break; - case VS::ENV_BG_CAMERA_FEED: { + case RS::ENV_BG_CAMERA_FEED: { if (feed.is_valid() && (feed->get_base_width() > 0) && (feed->get_base_height() > 0)) { // copy our camera feed to our background @@ -3419,12 +3419,12 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const if (feed->get_datatype() == CameraFeed::FEED_RGB) { RID camera_RGBA = feed->get_texture(CameraServer::FEED_RGBA_IMAGE); - VS::get_singleton()->texture_bind(camera_RGBA, 0); + RS::get_singleton()->texture_bind(camera_RGBA, 0); } else if (feed->get_datatype() == CameraFeed::FEED_YCBCR) { RID camera_YCbCr = feed->get_texture(CameraServer::FEED_YCBCR_IMAGE); - VS::get_singleton()->texture_bind(camera_YCbCr, 0); + RS::get_singleton()->texture_bind(camera_YCbCr, 0); storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); @@ -3432,8 +3432,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const RID camera_Y = feed->get_texture(CameraServer::FEED_Y_IMAGE); RID camera_CbCr = feed->get_texture(CameraServer::FEED_CBCR_IMAGE); - VS::get_singleton()->texture_bind(camera_Y, 0); - VS::get_singleton()->texture_bind(camera_CbCr, 1); + RS::get_singleton()->texture_bind(camera_Y, 0); + RS::get_singleton()->texture_bind(camera_CbCr, 1); storage->shaders.copy.set_conditional(CopyShaderGLES2::SEP_CBCR_TEXTURE, true); storage->shaders.copy.set_conditional(CopyShaderGLES2::YCBCR_TO_RGB, true); @@ -3444,8 +3444,8 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const storage->bind_quad_array(); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); - glDisableVertexAttribArray(VS::ARRAY_VERTEX); - glDisableVertexAttribArray(VS::ARRAY_TEX_UV); + glDisableVertexAttribArray(RS::ARRAY_VERTEX); + glDisableVertexAttribArray(RS::ARRAY_TEX_UV); glBindBuffer(GL_ARRAY_BUFFER, 0); // turn off everything used @@ -3464,7 +3464,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const clear_color = Color(0.0, 1.0, 0.0, 1.0); } } break; - case VS::ENV_BG_CANVAS: { + case RS::ENV_BG_CANVAS: { // use screen copy as background _copy_texture_to_buffer(storage->frame.current_rt->copy_screen_effect.color, current_fb); } break; @@ -3484,7 +3484,7 @@ void RasterizerSceneGLES2::render_scene(const Transform &p_cam_transform, const _render_render_list(render_list.elements, render_list.element_count, cam_transform, p_cam_projection, p_shadow_atlas, env, env_radiance_tex, 0.0, 0.0, reverse_cull, false, false); // then draw the sky after - if (env && env->bg_mode == VS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) { + if (env && env->bg_mode == RS::ENV_BG_SKY && (!storage->frame.current_rt || !storage->frame.current_rt->flags[RasterizerStorage::RENDER_TARGET_TRANSPARENT])) { if (sky && sky->panorama.is_valid()) { _draw_sky(sky, p_cam_projection, cam_transform, false, env->sky_custom_fov, env->bg_energy, env->sky_orientation); @@ -3616,7 +3616,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ // TODO directional light - if (light->type == VS::LIGHT_DIRECTIONAL) { + if (light->type == RS::LIGHT_DIRECTIONAL) { // set pssm stuff // TODO set this only when changed @@ -3651,7 +3651,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ width = light_instance->directional_rect.size.width; height = light_instance->directional_rect.size.height; - if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + if (light->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { width /= 2; height /= 2; @@ -3665,7 +3665,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ y += height; } - } else if (light->directional_shadow_mode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + } else if (light->directional_shadow_mode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { height /= 2; @@ -3676,10 +3676,10 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ } } - float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]); - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult; - normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult; + float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, light->param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE]); + zfar = light->param[RS::LIGHT_PARAM_RANGE]; + bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS] * bias_mult; + normal_bias = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] * bias_mult; fbo = directional_shadow.fbo; } else { @@ -3708,9 +3708,9 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ width = shadow_size; height = shadow_size; - if (light->type == VS::LIGHT_OMNI) { + if (light->type == RS::LIGHT_OMNI) { // cubemap only - if (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) { + if (light->omni_shadow_mode == RS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) { int cubemap_index = shadow_cubemaps.size() - 1; // find an appropriate cubemap to render to @@ -3727,7 +3727,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ light_transform = light_instance->shadow_transform[0].transform; custom_vp_size = shadow_cubemaps[cubemap_index].size; - zfar = light->param[VS::LIGHT_PARAM_RANGE]; + zfar = light->param[RS::LIGHT_PARAM_RANGE]; current_cubemap = cubemap_index; } else { @@ -3736,7 +3736,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ light_projection = light_instance->shadow_transform[0].camera; light_transform = light_instance->shadow_transform[0].transform; - if (light->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { + if (light->omni_shadow_detail == RS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { height /= 2; y += p_pass * height; @@ -3747,22 +3747,22 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ state.dual_parbolloid_direction = p_pass == 0 ? 1.0 : -1.0; flip_facing = (p_pass == 1); - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; + zfar = light->param[RS::LIGHT_PARAM_RANGE]; + bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS]; state.dual_parbolloid_zfar = zfar; state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, true); } - } else if (light->type == VS::LIGHT_SPOT) { + } else if (light->type == RS::LIGHT_SPOT) { light_projection = light_instance->shadow_transform[0].camera; light_transform = light_instance->shadow_transform[0].transform; flip_facing = false; - zfar = light->param[VS::LIGHT_PARAM_RANGE]; - bias = light->param[VS::LIGHT_PARAM_SHADOW_BIAS]; - normal_bias = light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]; + zfar = light->param[RS::LIGHT_PARAM_RANGE]; + bias = light->param[RS::LIGHT_PARAM_SHADOW_BIAS]; + normal_bias = light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS]; } } @@ -3812,7 +3812,7 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ state.scene_shader.set_conditional(SceneShaderGLES2::RENDER_DEPTH_DUAL_PARABOLOID, false); // convert cubemap to dual paraboloid if needed - if (light->type == VS::LIGHT_OMNI && (light->omni_shadow_mode == VS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) && p_pass == 5) { + if (light->type == RS::LIGHT_OMNI && (light->omni_shadow_mode == RS::LIGHT_OMNI_SHADOW_CUBE && storage->config.support_shadow_cubemaps) && p_pass == 5) { ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); glBindFramebuffer(GL_FRAMEBUFFER, shadow_atlas->fbo); @@ -3827,14 +3827,14 @@ void RasterizerSceneGLES2::render_shadow(RID p_light, RID p_shadow_atlas, int p_ state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_FLIP, i == 1); state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_NEAR, light_projection.get_z_near()); state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::Z_FAR, light_projection.get_z_far()); - state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::BIAS, light->param[VS::LIGHT_PARAM_SHADOW_BIAS]); + state.cube_to_dp_shader.set_uniform(CubeToDpShaderGLES2::BIAS, light->param[RS::LIGHT_PARAM_SHADOW_BIAS]); uint32_t local_width = width; uint32_t local_height = height; uint32_t local_x = x; uint32_t local_y = y; - if (light->omni_shadow_detail == VS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { + if (light->omni_shadow_detail == RS::LIGHT_OMNI_SHADOW_DETAIL_HORIZONTAL) { local_height /= 2; local_y += i * local_height; } else { @@ -3922,7 +3922,7 @@ bool RasterizerSceneGLES2::free(RID p_rid) { return true; } -void RasterizerSceneGLES2::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { +void RasterizerSceneGLES2::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) { } void RasterizerSceneGLES2::initialize() { diff --git a/drivers/gles2/rasterizer_scene_gles2.h b/drivers/gles2/rasterizer_scene_gles2.h index 174cdd8e2e..6d0a5a45ca 100644 --- a/drivers/gles2/rasterizer_scene_gles2.h +++ b/drivers/gles2/rasterizer_scene_gles2.h @@ -236,7 +236,7 @@ public: /* ENVIRONMENT API */ struct Environment { - VS::EnvironmentBG bg_mode; + RS::EnvironmentBG bg_mode; RID sky; float sky_custom_fov; @@ -259,7 +259,7 @@ public: float glow_intensity; float glow_strength; float glow_bloom; - VS::EnvironmentGlowBlendMode glow_blend_mode; + RS::EnvironmentGlowBlendMode glow_blend_mode; float glow_hdr_bleed_threshold; float glow_hdr_bleed_scale; float glow_hdr_luminance_cap; @@ -269,13 +269,13 @@ public: float dof_blur_far_distance; float dof_blur_far_transition; float dof_blur_far_amount; - VS::EnvironmentDOFBlurQuality dof_blur_far_quality; + RS::EnvironmentDOFBlurQuality dof_blur_far_quality; bool dof_blur_near_enabled; float dof_blur_near_distance; float dof_blur_near_transition; float dof_blur_near_amount; - VS::EnvironmentDOFBlurQuality dof_blur_near_quality; + RS::EnvironmentDOFBlurQuality dof_blur_near_quality; bool adjustments_enabled; float adjustments_brightness; @@ -300,7 +300,7 @@ public: float fog_height_curve; Environment() : - bg_mode(VS::ENV_BG_CLEAR_COLOR), + bg_mode(RS::ENV_BG_CLEAR_COLOR), sky_custom_fov(0.0), bg_energy(1.0), sky_ambient(0), @@ -313,7 +313,7 @@ public: glow_intensity(0.8), glow_strength(1.0), glow_bloom(0.0), - glow_blend_mode(VS::ENV_GLOW_BLEND_MODE_SOFTLIGHT), + glow_blend_mode(RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT), glow_hdr_bleed_threshold(1.0), glow_hdr_bleed_scale(2.0), glow_hdr_luminance_cap(12.0), @@ -322,12 +322,12 @@ public: dof_blur_far_distance(10), dof_blur_far_transition(5), dof_blur_far_amount(0.1), - dof_blur_far_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM), + dof_blur_far_quality(RS::ENV_DOF_BLUR_QUALITY_MEDIUM), dof_blur_near_enabled(false), dof_blur_near_distance(2), dof_blur_near_transition(1), dof_blur_near_amount(0.1), - dof_blur_near_quality(VS::ENV_DOF_BLUR_QUALITY_MEDIUM), + dof_blur_near_quality(RS::ENV_DOF_BLUR_QUALITY_MEDIUM), adjustments_enabled(false), adjustments_brightness(1.0), adjustments_contrast(1.0), @@ -353,7 +353,7 @@ public: virtual RID environment_create(); - virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); + virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg); virtual void environment_set_sky(RID p_env, RID p_sky); virtual void environment_set_sky_custom_fov(RID p_env, float p_scale); virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); @@ -363,15 +363,15 @@ public: virtual void environment_set_ambient_light(RID p_env, const Color &p_color, float p_energy = 1.0, float p_sky_contribution = 0.0); virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id); - virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); - virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, VS::EnvironmentDOFBlurQuality p_quality); - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); + virtual void environment_set_dof_blur_near(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, RS::EnvironmentDOFBlurQuality p_quality); + virtual void environment_set_dof_blur_far(RID p_env, bool p_enable, float p_distance, float p_transition, float p_amount, RS::EnvironmentDOFBlurQuality p_quality); + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture); virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness); - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_radius2, float p_intensity2, float p_bias, float p_light_affect, float p_ao_channel_affect, const Color &p_color, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); - virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); + virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp); @@ -381,7 +381,7 @@ public: virtual bool is_environment(RID p_env); - virtual VS::EnvironmentBG environment_get_background(RID p_env); + virtual RS::EnvironmentBG environment_get_background(RID p_env); virtual int environment_get_canvas_max_layer(RID p_env); /* LIGHT INSTANCE */ @@ -650,7 +650,7 @@ public: virtual bool free(RID p_rid); virtual void set_scene_pass(uint64_t p_pass); - virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw); + virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw); void iteration(); void initialize(); diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index f76c7da8e1..4337d2a833 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -34,7 +34,7 @@ #include "core/project_settings.h" #include "rasterizer_canvas_gles2.h" #include "rasterizer_scene_gles2.h" -#include "servers/visual/shader_language.h" +#include "servers/rendering/shader_language.h" GLuint RasterizerStorageGLES2::system_fbo = 0; @@ -127,11 +127,11 @@ PFNGLCOMPRESSEDTEXSUBIMAGE3DOESPROC glCompressedTexSubImage3DOES; void RasterizerStorageGLES2::bind_quad_array() const { glBindBuffer(GL_ARRAY_BUFFER, resources.quadie); - glVertexAttribPointer(VS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); - glVertexAttribPointer(VS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); + glVertexAttribPointer(RS::ARRAY_VERTEX, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, 0); + glVertexAttribPointer(RS::ARRAY_TEX_UV, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 4, CAST_INT_TO_UCHAR_PTR(8)); - glEnableVertexAttribArray(VS::ARRAY_VERTEX); - glEnableVertexAttribArray(VS::ARRAY_TEX_UV); + glEnableVertexAttribArray(RS::ARRAY_VERTEX); + glEnableVertexAttribArray(RS::ARRAY_TEX_UV); } Ref RasterizerStorageGLES2::_get_gl_image_and_format(const Ref &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const { @@ -549,15 +549,15 @@ RID RasterizerStorageGLES2::texture_create() { return texture_owner.make_rid(texture); } -void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VisualServer::TextureType p_type, uint32_t p_flags) { +void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RenderingServer::TextureType p_type, uint32_t p_flags) { GLenum format; GLenum internal_format; GLenum type; bool compressed = false; - if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { - p_flags &= ~VS::TEXTURE_FLAG_MIPMAPS; // no mipies for video + if (p_flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING) { + p_flags &= ~RS::TEXTURE_FLAG_MIPMAPS; // no mipies for video } Texture *texture = texture_owner.getornull(p_texture); @@ -570,15 +570,15 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ texture->type = p_type; switch (p_type) { - case VS::TEXTURE_TYPE_2D: { + case RS::TEXTURE_TYPE_2D: { texture->target = GL_TEXTURE_2D; texture->images.resize(1); } break; - case VS::TEXTURE_TYPE_CUBEMAP: { + case RS::TEXTURE_TYPE_CUBEMAP: { texture->target = GL_TEXTURE_CUBE_MAP; texture->images.resize(6); } break; - case VS::TEXTURE_TYPE_2D_ARRAY: { + case RS::TEXTURE_TYPE_2D_ARRAY: { if (config.texture_array_supported) { texture->target = GL_TEXTURE_2D_ARRAY; texture->images.resize(p_depth_3d); @@ -587,7 +587,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ return; } } break; - case VS::TEXTURE_TYPE_3D: { + case RS::TEXTURE_TYPE_3D: { if (config.texture_3d_supported) { texture->target = GL_TEXTURE_3D; texture->images.resize(p_depth_3d); @@ -611,12 +611,12 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ bool is_po2 = p_width == po2_width && p_height == po2_height; - if (!is_po2 && (p_flags & VS::TEXTURE_FLAG_REPEAT || p_flags & VS::TEXTURE_FLAG_MIPMAPS)) { + if (!is_po2 && (p_flags & RS::TEXTURE_FLAG_REPEAT || p_flags & RS::TEXTURE_FLAG_MIPMAPS)) { - if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + if (p_flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING) { //not supported ERR_PRINT("Streaming texture for non power of 2 or has mipmaps on this hardware: " + texture->path + "'. Mipmaps and repeat disabled."); - texture->flags &= ~(VS::TEXTURE_FLAG_REPEAT | VS::TEXTURE_FLAG_MIPMAPS); + texture->flags &= ~(RS::TEXTURE_FLAG_REPEAT | RS::TEXTURE_FLAG_MIPMAPS); } else { texture->alloc_height = po2_height; texture->alloc_width = po2_width; @@ -640,7 +640,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ glBindTexture(texture->target, texture->tex_id); #if defined(GLES_OVER_GL) || defined(ANDROID_ENABLED) - if ((p_type == VS::TEXTURE_TYPE_3D && config.texture_3d_supported) || (p_type == VS::TEXTURE_TYPE_2D_ARRAY && config.texture_array_supported)) { + if ((p_type == RS::TEXTURE_TYPE_3D && config.texture_3d_supported) || (p_type == RS::TEXTURE_TYPE_2D_ARRAY && config.texture_array_supported)) { int width = p_width; int height = p_height; @@ -648,7 +648,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ int mipmaps = 0; - while (width > 0 || height > 0 || (p_type == VS::TEXTURE_TYPE_3D && depth > 0)) { + while (width > 0 || height > 0 || (p_type == RS::TEXTURE_TYPE_3D && depth > 0)) { width = MAX(1, width); height = MAX(1, height); depth = MAX(1, depth); @@ -658,13 +658,13 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ width /= 2; height /= 2; - if (p_type == VS::TEXTURE_TYPE_3D) { + if (p_type == RS::TEXTURE_TYPE_3D) { depth /= 2; } mipmaps++; - if (!(p_flags & VS::TEXTURE_FLAG_MIPMAPS)) + if (!(p_flags & RS::TEXTURE_FLAG_MIPMAPS)) break; } #ifdef GLES_OVER_GL @@ -674,7 +674,7 @@ void RasterizerStorageGLES2::texture_allocate(RID p_texture, int p_width, int p_ } else #endif - if (p_flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + if (p_flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING) { //prealloc if video glTexImage2D(texture->target, 0, internal_format, texture->alloc_width, texture->alloc_height, 0, format, type, NULL); } @@ -686,7 +686,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); - if ((texture->type == VS::TEXTURE_TYPE_2D_ARRAY && !config.texture_array_supported) || (texture->type == VS::TEXTURE_TYPE_3D && !config.texture_3d_supported)) { + if ((texture->type == RS::TEXTURE_TYPE_2D_ARRAY && !config.texture_array_supported) || (texture->type == RS::TEXTURE_TYPE_3D && !config.texture_3d_supported)) { return; } ERR_FAIL_COND(!texture->active); @@ -699,7 +699,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p GLenum internal_format; bool compressed = false; - if (config.keep_original_textures && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + if (config.keep_original_textures && !(texture->flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING)) { texture->images.write[p_layer] = p_image; } @@ -717,7 +717,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p img->resize_to_po2(false); } - if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING)) { + if (config.shrink_textures_x2 && (p_image->has_mipmaps() || !p_image->is_compressed()) && !(texture->flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING)) { texture->alloc_height = MAX(1, texture->alloc_height / 2); texture->alloc_width = MAX(1, texture->alloc_width / 2); @@ -734,17 +734,17 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p GLenum blit_target = GL_TEXTURE_2D; switch (texture->type) { - case VS::TEXTURE_TYPE_2D: { + case RS::TEXTURE_TYPE_2D: { blit_target = GL_TEXTURE_2D; } break; - case VS::TEXTURE_TYPE_CUBEMAP: { + case RS::TEXTURE_TYPE_CUBEMAP: { ERR_FAIL_INDEX(p_layer, 6); blit_target = _cube_side_enum[p_layer]; } break; - case VS::TEXTURE_TYPE_2D_ARRAY: { + case RS::TEXTURE_TYPE_2D_ARRAY: { blit_target = GL_TEXTURE_2D_ARRAY; } break; - case VS::TEXTURE_TYPE_3D: { + case RS::TEXTURE_TYPE_3D: { blit_target = GL_TEXTURE_3D; } break; } @@ -758,17 +758,17 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p texture->ignore_mipmaps = compressed && !img->has_mipmaps(); - if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) + if ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); else { - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + if (texture->flags & RS::TEXTURE_FLAG_FILTER) { glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + if (texture->flags & RS::TEXTURE_FLAG_FILTER) { glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering @@ -777,9 +777,9 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // raw Filtering } - if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { + if (((texture->flags & RS::TEXTURE_FLAG_REPEAT) || (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { - if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) { + if (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); } else { @@ -793,7 +793,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - int mipmaps = ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; + int mipmaps = ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && img->has_mipmaps()) ? img->get_mipmap_count() + 1 : 1; int w = img->get_width(); int h = img->get_height(); @@ -804,7 +804,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p int size, ofs; img->get_mipmap_offset_and_size(i, ofs, size); - if (texture->type == VS::TEXTURE_TYPE_2D || texture->type == VS::TEXTURE_TYPE_CUBEMAP) { + if (texture->type == RS::TEXTURE_TYPE_2D || texture->type == RS::TEXTURE_TYPE_CUBEMAP) { if (compressed) { glPixelStorei(GL_UNPACK_ALIGNMENT, 4); @@ -816,7 +816,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p } else { glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - if (texture->flags & VS::TEXTURE_FLAG_USED_FOR_STREAMING) { + if (texture->flags & RS::TEXTURE_FLAG_USED_FOR_STREAMING) { glTexSubImage2D(blit_target, i, 0, 0, w, h, format, type, &read[ofs]); } else { glTexImage2D(blit_target, i, internal_format, w, h, 0, format, type, &read[ofs]); @@ -854,7 +854,7 @@ void RasterizerStorageGLES2::texture_set_data(RID p_texture, const Ref &p texture->stored_cube_sides |= (1 << p_layer); - if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != VS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) { + if ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && mipmaps == 1 && !texture->ignore_mipmaps && (texture->type != RS::TEXTURE_TYPE_CUBEMAP || texture->stored_cube_sides == (1 << 6) - 1)) { //generate mipmaps if they were requested and the image does not contain them glGenerateMipmap(texture->target); } @@ -875,7 +875,7 @@ Ref RasterizerStorageGLES2::texture_get_data(RID p_texture, int p_layer) ERR_FAIL_COND_V(!texture->active, Ref()); ERR_FAIL_COND_V(texture->data_size == 0 && !texture->render_target, Ref()); - if (texture->type == VS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { + if (texture->type == RS::TEXTURE_TYPE_CUBEMAP && p_layer < 6 && p_layer >= 0 && !texture->images[p_layer].is_null()) { return texture->images[p_layer]; } @@ -997,16 +997,16 @@ void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); - bool had_mipmaps = texture->flags & VS::TEXTURE_FLAG_MIPMAPS; + bool had_mipmaps = texture->flags & RS::TEXTURE_FLAG_MIPMAPS; texture->flags = p_flags; glActiveTexture(GL_TEXTURE0); glBindTexture(texture->target, texture->tex_id); - if (((texture->flags & VS::TEXTURE_FLAG_REPEAT) || (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { + if (((texture->flags & RS::TEXTURE_FLAG_REPEAT) || (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT)) && texture->target != GL_TEXTURE_CUBE_MAP) { - if (texture->flags & VS::TEXTURE_FLAG_MIRRORED_REPEAT) { + if (texture->flags & RS::TEXTURE_FLAG_MIRRORED_REPEAT) { glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); } else { @@ -1019,21 +1019,21 @@ void RasterizerStorageGLES2::texture_set_flags(RID p_texture, uint32_t p_flags) glTexParameterf(texture->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } - if ((texture->flags & VS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { + if ((texture->flags & RS::TEXTURE_FLAG_MIPMAPS) && !texture->ignore_mipmaps) { if (!had_mipmaps && texture->mipmaps == 1) { glGenerateMipmap(texture->target); } glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, config.use_fast_texture_filter ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR_MIPMAP_LINEAR); } else { - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + if (texture->flags & RS::TEXTURE_FLAG_FILTER) { glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } else { glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); } } - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + if (texture->flags & RS::TEXTURE_FLAG_FILTER) { glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Linear Filtering @@ -1059,10 +1059,10 @@ Image::Format RasterizerStorageGLES2::texture_get_format(RID p_texture) const { return texture->format; } -VisualServer::TextureType RasterizerStorageGLES2::texture_get_type(RID p_texture) const { +RenderingServer::TextureType RasterizerStorageGLES2::texture_get_type(RID p_texture) const { Texture *texture = texture_owner.getornull(p_texture); - ERR_FAIL_COND_V(!texture, VS::TEXTURE_TYPE_2D); + ERR_FAIL_COND_V(!texture, RS::TEXTURE_TYPE_2D); return texture->type; } @@ -1135,7 +1135,7 @@ String RasterizerStorageGLES2::texture_get_path(RID p_texture) const { return texture->path; } -void RasterizerStorageGLES2::texture_debug_usage(List *r_info) { +void RasterizerStorageGLES2::texture_debug_usage(List *r_info) { List textures; texture_owner.get_owned_list(&textures); @@ -1144,7 +1144,7 @@ void RasterizerStorageGLES2::texture_debug_usage(List *r_info) Texture *t = texture_owner.getornull(E->get()); if (!t) continue; - VS::TextureInfo tinfo; + RS::TextureInfo tinfo; tinfo.path = t->path; tinfo.format = t->format; tinfo.width = t->alloc_width; @@ -1200,7 +1200,7 @@ void RasterizerStorageGLES2::texture_set_force_redraw_if_visible(RID p_texture, texture->redraw_if_visible = p_enable; } -void RasterizerStorageGLES2::texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) { +void RasterizerStorageGLES2::texture_set_detect_3d_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) { Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); @@ -1208,7 +1208,7 @@ void RasterizerStorageGLES2::texture_set_detect_3d_callback(RID p_texture, Visua texture->detect_3d_ud = p_userdata; } -void RasterizerStorageGLES2::texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) { +void RasterizerStorageGLES2::texture_set_detect_srgb_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) { Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); @@ -1216,7 +1216,7 @@ void RasterizerStorageGLES2::texture_set_detect_srgb_callback(RID p_texture, Vis texture->detect_srgb_ud = p_userdata; } -void RasterizerStorageGLES2::texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata) { +void RasterizerStorageGLES2::texture_set_detect_normal_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata) { Texture *texture = texture_owner.getornull(p_texture); ERR_FAIL_COND(!texture); @@ -1265,7 +1265,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra glDisable(GL_SCISSOR_TEST); glDisable(GL_BLEND); - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + for (int i = 0; i < RS::ARRAY_MAX - 1; i++) { glDisableVertexAttribArray(i); } } @@ -1397,7 +1397,7 @@ void RasterizerStorageGLES2::sky_set_texture(RID p_sky, RID p_panorama, int p_ra RID RasterizerStorageGLES2::shader_create() { Shader *shader = memnew(Shader); - shader->mode = VS::SHADER_SPATIAL; + shader->mode = RS::SHADER_SPATIAL; shader->shader = &scene->state.scene_shader; RID rid = shader_owner.make_rid(shader); _shader_make_dirty(shader); @@ -1421,16 +1421,16 @@ void RasterizerStorageGLES2::shader_set_code(RID p_shader, const String &p_code) shader->code = p_code; String mode_string = ShaderLanguage::get_shader_type(p_code); - VS::ShaderMode mode; + RS::ShaderMode mode; if (mode_string == "canvas_item") - mode = VS::SHADER_CANVAS_ITEM; + mode = RS::SHADER_CANVAS_ITEM; else if (mode_string == "particles") - mode = VS::SHADER_PARTICLES; + mode = RS::SHADER_PARTICLES; else if (mode_string == "sky") - mode = VS::SHADER_SKY; + mode = RS::SHADER_SKY; else - mode = VS::SHADER_SPATIAL; + mode = RS::SHADER_SPATIAL; if (shader->custom_code_id && mode != shader->mode) { shader->shader->free_custom_shader(shader->custom_code_id); @@ -1440,10 +1440,10 @@ void RasterizerStorageGLES2::shader_set_code(RID p_shader, const String &p_code) shader->mode = mode; // TODO handle all shader types - if (mode == VS::SHADER_CANVAS_ITEM) { + if (mode == RS::SHADER_CANVAS_ITEM) { shader->shader = &canvas->state.canvas_shader; - } else if (mode == VS::SHADER_SPATIAL) { + } else if (mode == RS::SHADER_SPATIAL) { shader->shader = &scene->state.scene_shader; } else { return; @@ -1481,7 +1481,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { switch (p_shader->mode) { - case VS::SHADER_CANVAS_ITEM: { + case RS::SHADER_CANVAS_ITEM: { p_shader->canvas_item.light_mode = Shader::CanvasItem::LIGHT_MODE_NORMAL; p_shader->canvas_item.blend_mode = Shader::CanvasItem::BLEND_MODE_MIX; @@ -1508,7 +1508,7 @@ void RasterizerStorageGLES2::_update_shader(Shader *p_shader) const { actions->uniforms = &p_shader->uniforms; } break; - case VS::SHADER_SPATIAL: { + case RS::SHADER_SPATIAL: { p_shader->spatial.blend_mode = Shader::Spatial::BLEND_MODE_MIX; p_shader->spatial.depth_draw_mode = Shader::Spatial::DEPTH_DRAW_OPAQUE; p_shader->spatial.cull_mode = Shader::Spatial::CULL_MODE_BACK; @@ -1949,8 +1949,8 @@ void RasterizerStorageGLES2::material_remove_instance_owner(RID p_material, Rast } void RasterizerStorageGLES2::material_set_render_priority(RID p_material, int priority) { - ERR_FAIL_COND(priority < VS::MATERIAL_RENDER_PRIORITY_MIN); - ERR_FAIL_COND(priority > VS::MATERIAL_RENDER_PRIORITY_MAX); + ERR_FAIL_COND(priority < RS::MATERIAL_RENDER_PRIORITY_MIN); + ERR_FAIL_COND(priority > RS::MATERIAL_RENDER_PRIORITY_MAX); Material *material = material_owner.getornull(p_material); ERR_FAIL_COND(!material); @@ -1975,7 +1975,7 @@ void RasterizerStorageGLES2::_update_material(Material *p_material) { bool can_cast_shadow = false; bool is_animated = false; - if (p_material->shader && p_material->shader->mode == VS::SHADER_SPATIAL) { + if (p_material->shader && p_material->shader->mode == RS::SHADER_SPATIAL) { if (p_material->shader->spatial.blend_mode == Shader::Spatial::BLEND_MODE_MIX && (!p_material->shader->spatial.uses_alpha || p_material->shader->spatial.depth_draw_mode == Shader::Spatial::DEPTH_DRAW_ALPHA_PREPASS)) { @@ -2087,14 +2087,14 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ uint32_t p_format = format; - static int src_size[VS::ARRAY_MAX]; - static int dst_size[VS::ARRAY_MAX]; - static int to_convert[VS::ARRAY_MAX]; + static int src_size[RS::ARRAY_MAX]; + static int dst_size[RS::ARRAY_MAX]; + static int to_convert[RS::ARRAY_MAX]; int src_stride = 0; int dst_stride = 0; - for (int i = 0; i < VS::ARRAY_MAX; i++) { + for (int i = 0; i < RS::ARRAY_MAX; i++) { to_convert[i] = 0; if (!(p_format & (1 << i))) { @@ -2105,11 +2105,11 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ switch (i) { - case VS::ARRAY_VERTEX: { + case RS::ARRAY_VERTEX: { - if (p_format & VS::ARRAY_COMPRESS_VERTEX) { + if (p_format & RS::ARRAY_COMPRESS_VERTEX) { - if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { + if (p_format & RS::ARRAY_FLAG_USE_2D_VERTICES) { src_size[i] = 4; dst_size[i] = 8; to_convert[i] = 2; @@ -2119,10 +2119,10 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ to_convert[i] = 3; } - format &= ~VS::ARRAY_COMPRESS_VERTEX; + format &= ~RS::ARRAY_COMPRESS_VERTEX; } else { - if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { + if (p_format & RS::ARRAY_FLAG_USE_2D_VERTICES) { src_size[i] = 8; dst_size[i] = 8; } else { @@ -2132,9 +2132,9 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ } } break; - case VS::ARRAY_NORMAL: { + case RS::ARRAY_NORMAL: { - if (p_format & VS::ARRAY_COMPRESS_NORMAL) { + if (p_format & RS::ARRAY_COMPRESS_NORMAL) { src_size[i] = 4; dst_size[i] = 4; } else { @@ -2143,9 +2143,9 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ } } break; - case VS::ARRAY_TANGENT: { + case RS::ARRAY_TANGENT: { - if (p_format & VS::ARRAY_COMPRESS_TANGENT) { + if (p_format & RS::ARRAY_COMPRESS_TANGENT) { src_size[i] = 4; dst_size[i] = 4; } else { @@ -2154,9 +2154,9 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ } } break; - case VS::ARRAY_COLOR: { + case RS::ARRAY_COLOR: { - if (p_format & VS::ARRAY_COMPRESS_COLOR) { + if (p_format & RS::ARRAY_COMPRESS_COLOR) { src_size[i] = 4; dst_size[i] = 4; } else { @@ -2165,12 +2165,12 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ } } break; - case VS::ARRAY_TEX_UV: { + case RS::ARRAY_TEX_UV: { - if (p_format & VS::ARRAY_COMPRESS_TEX_UV) { + if (p_format & RS::ARRAY_COMPRESS_TEX_UV) { src_size[i] = 4; to_convert[i] = 2; - format &= ~VS::ARRAY_COMPRESS_TEX_UV; + format &= ~RS::ARRAY_COMPRESS_TEX_UV; } else { src_size[i] = 8; } @@ -2178,12 +2178,12 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ dst_size[i] = 8; } break; - case VS::ARRAY_TEX_UV2: { + case RS::ARRAY_TEX_UV2: { - if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) { + if (p_format & RS::ARRAY_COMPRESS_TEX_UV2) { src_size[i] = 4; to_convert[i] = 2; - format &= ~VS::ARRAY_COMPRESS_TEX_UV2; + format &= ~RS::ARRAY_COMPRESS_TEX_UV2; } else { src_size[i] = 8; } @@ -2191,9 +2191,9 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ dst_size[i] = 8; } break; - case VS::ARRAY_BONES: { + case RS::ARRAY_BONES: { - if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) { + if (p_format & RS::ARRAY_FLAG_USE_16_BIT_BONES) { src_size[i] = 8; dst_size[i] = 8; } else { @@ -2202,9 +2202,9 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ } } break; - case VS::ARRAY_WEIGHTS: { + case RS::ARRAY_WEIGHTS: { - if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) { + if (p_format & RS::ARRAY_COMPRESS_WEIGHTS) { src_size[i] = 8; dst_size[i] = 8; } else { @@ -2213,7 +2213,7 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ } } break; - case VS::ARRAY_INDEX: { + case RS::ARRAY_INDEX: { src_size[i] = 0; dst_size[i] = 0; @@ -2234,7 +2234,7 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ int src_offset = 0; int dst_offset = 0; - for (int i = 0; i < VS::ARRAY_MAX; i++) { + for (int i = 0; i < RS::ARRAY_MAX; i++) { if (src_size[i] == 0) { continue; //no go @@ -2272,27 +2272,27 @@ static Vector _unpack_half_floats(const Vector &array, uint32_ return ret; } -void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes, const Vector &p_bone_aabbs) { +void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, RS::PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes, const Vector &p_bone_aabbs) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); - ERR_FAIL_COND(!(p_format & VS::ARRAY_FORMAT_VERTEX)); + ERR_FAIL_COND(!(p_format & RS::ARRAY_FORMAT_VERTEX)); //must have index and bones, both. { - uint32_t bones_weight = VS::ARRAY_FORMAT_BONES | VS::ARRAY_FORMAT_WEIGHTS; + uint32_t bones_weight = RS::ARRAY_FORMAT_BONES | RS::ARRAY_FORMAT_WEIGHTS; ERR_FAIL_COND_MSG((p_format & bones_weight) && (p_format & bones_weight) != bones_weight, "Array must have both bones and weights in format or none."); } //bool has_morph = p_blend_shapes.size(); - Surface::Attrib attribs[VS::ARRAY_MAX]; + Surface::Attrib attribs[RS::ARRAY_MAX]; int stride = 0; bool uses_half_float = false; - for (int i = 0; i < VS::ARRAY_MAX; i++) { + for (int i = 0; i < RS::ARRAY_MAX; i++) { attribs[i].index = i; @@ -2308,15 +2308,15 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: switch (i) { - case VS::ARRAY_VERTEX: { + case RS::ARRAY_VERTEX: { - if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { + if (p_format & RS::ARRAY_FLAG_USE_2D_VERTICES) { attribs[i].size = 2; } else { - attribs[i].size = (p_format & VS::ARRAY_COMPRESS_VERTEX) ? 4 : 3; + attribs[i].size = (p_format & RS::ARRAY_COMPRESS_VERTEX) ? 4 : 3; } - if (p_format & VS::ARRAY_COMPRESS_VERTEX) { + if (p_format & RS::ARRAY_COMPRESS_VERTEX) { attribs[i].type = _GL_HALF_FLOAT_OES; stride += attribs[i].size * 2; uses_half_float = true; @@ -2328,11 +2328,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: attribs[i].normalized = GL_FALSE; } break; - case VS::ARRAY_NORMAL: { + case RS::ARRAY_NORMAL: { attribs[i].size = 3; - if (p_format & VS::ARRAY_COMPRESS_NORMAL) { + if (p_format & RS::ARRAY_COMPRESS_NORMAL) { attribs[i].type = GL_BYTE; stride += 4; //pad extra byte attribs[i].normalized = GL_TRUE; @@ -2343,11 +2343,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } } break; - case VS::ARRAY_TANGENT: { + case RS::ARRAY_TANGENT: { attribs[i].size = 4; - if (p_format & VS::ARRAY_COMPRESS_TANGENT) { + if (p_format & RS::ARRAY_COMPRESS_TANGENT) { attribs[i].type = GL_BYTE; stride += 4; attribs[i].normalized = GL_TRUE; @@ -2358,11 +2358,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } } break; - case VS::ARRAY_COLOR: { + case RS::ARRAY_COLOR: { attribs[i].size = 4; - if (p_format & VS::ARRAY_COMPRESS_COLOR) { + if (p_format & RS::ARRAY_COMPRESS_COLOR) { attribs[i].type = GL_UNSIGNED_BYTE; stride += 4; attribs[i].normalized = GL_TRUE; @@ -2373,11 +2373,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } } break; - case VS::ARRAY_TEX_UV: { + case RS::ARRAY_TEX_UV: { attribs[i].size = 2; - if (p_format & VS::ARRAY_COMPRESS_TEX_UV) { + if (p_format & RS::ARRAY_COMPRESS_TEX_UV) { attribs[i].type = _GL_HALF_FLOAT_OES; stride += 4; uses_half_float = true; @@ -2389,11 +2389,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: attribs[i].normalized = GL_FALSE; } break; - case VS::ARRAY_TEX_UV2: { + case RS::ARRAY_TEX_UV2: { attribs[i].size = 2; - if (p_format & VS::ARRAY_COMPRESS_TEX_UV2) { + if (p_format & RS::ARRAY_COMPRESS_TEX_UV2) { attribs[i].type = _GL_HALF_FLOAT_OES; stride += 4; uses_half_float = true; @@ -2404,11 +2404,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: attribs[i].normalized = GL_FALSE; } break; - case VS::ARRAY_BONES: { + case RS::ARRAY_BONES: { attribs[i].size = 4; - if (p_format & VS::ARRAY_FLAG_USE_16_BIT_BONES) { + if (p_format & RS::ARRAY_FLAG_USE_16_BIT_BONES) { attribs[i].type = GL_UNSIGNED_SHORT; stride += 8; } else { @@ -2420,11 +2420,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: attribs[i].integer = true; } break; - case VS::ARRAY_WEIGHTS: { + case RS::ARRAY_WEIGHTS: { attribs[i].size = 4; - if (p_format & VS::ARRAY_COMPRESS_WEIGHTS) { + if (p_format & RS::ARRAY_COMPRESS_WEIGHTS) { attribs[i].type = GL_UNSIGNED_SHORT; stride += 8; @@ -2436,7 +2436,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } } break; - case VS::ARRAY_INDEX: { + case RS::ARRAY_INDEX: { attribs[i].size = 1; @@ -2454,7 +2454,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: } } - for (int i = 0; i < VS::ARRAY_MAX - 1; i++) { + for (int i = 0; i < RS::ARRAY_MAX - 1; i++) { attribs[i].stride = stride; } @@ -2500,9 +2500,9 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: return; //do not go any further, above function used unpacked stuff will be used instead. } - if (p_format & VS::ARRAY_FORMAT_INDEX) { + if (p_format & RS::ARRAY_FORMAT_INDEX) { - index_array_size = attribs[VS::ARRAY_INDEX].stride * p_index_count; + index_array_size = attribs[RS::ARRAY_INDEX].stride * p_index_count; } ERR_FAIL_COND(p_index_array.size() != index_array_size); @@ -2545,7 +2545,7 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: surface->skeleton_bone_used.write[i] = !(surface->skeleton_bone_aabb[i].size.x < 0 || surface->skeleton_bone_aabb[i].size.y < 0 || surface->skeleton_bone_aabb[i].size.z < 0); } - for (int i = 0; i < VS::ARRAY_MAX; i++) { + for (int i = 0; i < RS::ARRAY_MAX; i++) { surface->attribs[i] = attribs[i]; } @@ -2555,11 +2555,11 @@ void RasterizerStorageGLES2::mesh_add_surface(RID p_mesh, uint32_t p_format, VS: glGenBuffers(1, &surface->vertex_id); glBindBuffer(GL_ARRAY_BUFFER, surface->vertex_id); - glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), (p_format & VS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); + glBufferData(GL_ARRAY_BUFFER, array_size, vr.ptr(), (p_format & RS::ARRAY_FLAG_USE_DYNAMIC_UPDATE) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW); glBindBuffer(GL_ARRAY_BUFFER, 0); - if (p_format & VS::ARRAY_FORMAT_INDEX) { + if (p_format & RS::ARRAY_FORMAT_INDEX) { const uint8_t *ir = p_index_array.ptr(); glGenBuffers(1, &surface->index_id); @@ -2616,16 +2616,16 @@ int RasterizerStorageGLES2::mesh_get_blend_shape_count(RID p_mesh) const { return mesh->blend_shape_count; } -void RasterizerStorageGLES2::mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) { +void RasterizerStorageGLES2::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { Mesh *mesh = mesh_owner.getornull(p_mesh); ERR_FAIL_COND(!mesh); mesh->blend_shape_mode = p_mode; } -VS::BlendShapeMode RasterizerStorageGLES2::mesh_get_blend_shape_mode(RID p_mesh) const { +RS::BlendShapeMode RasterizerStorageGLES2::mesh_get_blend_shape_mode(RID p_mesh) const { const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::BLEND_SHAPE_MODE_NORMALIZED); + ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); return mesh->blend_shape_mode; } @@ -2723,10 +2723,10 @@ uint32_t RasterizerStorageGLES2::mesh_surface_get_format(RID p_mesh, int p_surfa return mesh->surfaces[p_surface]->format; } -VS::PrimitiveType RasterizerStorageGLES2::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { +RS::PrimitiveType RasterizerStorageGLES2::mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const { const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::PRIMITIVE_MAX); - ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), VS::PRIMITIVE_MAX); + ERR_FAIL_COND_V(!mesh, RS::PRIMITIVE_MAX); + ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), RS::PRIMITIVE_MAX); return mesh->surfaces[p_surface]->primitive; } @@ -2827,7 +2827,7 @@ AABB RasterizerStorageGLES2::mesh_get_aabb(RID p_mesh, RID p_skeleton) const { for (int i = 0; i < mesh->surfaces.size(); i++) { AABB laabb; - if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->skeleton_bone_aabb.size()) { + if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->skeleton_bone_aabb.size()) { int bs = mesh->surfaces[i]->skeleton_bone_aabb.size(); const AABB *skbones = mesh->surfaces[i]->skeleton_bone_aabb.ptr(); @@ -2939,7 +2939,7 @@ RID RasterizerStorageGLES2::multimesh_create() { return multimesh_owner.make_rid(multimesh); } -void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data) { +void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, RS::MultimeshColorFormat p_color_format, RS::MultimeshCustomDataFormat p_data) { MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); @@ -2957,23 +2957,23 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances multimesh->data.resize(0); } - if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { + if (multimesh->transform_format == RS::MULTIMESH_TRANSFORM_2D) { multimesh->xform_floats = 8; } else { multimesh->xform_floats = 12; } - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + if (multimesh->color_format == RS::MULTIMESH_COLOR_8BIT) { multimesh->color_floats = 1; - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { + } else if (multimesh->color_format == RS::MULTIMESH_COLOR_FLOAT) { multimesh->color_floats = 4; } else { multimesh->color_floats = 0; } - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_8BIT) { multimesh->custom_data_floats = 1; - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { + } else if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_FLOAT) { multimesh->custom_data_floats = 4; } else { multimesh->custom_data_floats = 0; @@ -2987,7 +2987,7 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances int color_from = 0; int custom_data_from = 0; - if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { + if (multimesh->transform_format == RS::MULTIMESH_TRANSFORM_2D) { multimesh->data.write[i + 0] = 1.0; multimesh->data.write[i + 1] = 0.0; multimesh->data.write[i + 2] = 0.0; @@ -3015,7 +3015,7 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances custom_data_from = 12; } - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + if (multimesh->color_format == RS::MULTIMESH_COLOR_8BIT) { union { uint32_t colu; float colf; @@ -3024,7 +3024,7 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances cu.colu = 0xFFFFFFFF; multimesh->data.write[i + color_from + 0] = cu.colf; custom_data_from = color_from + 1; - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { + } else if (multimesh->color_format == RS::MULTIMESH_COLOR_FLOAT) { multimesh->data.write[i + color_from + 0] = 1.0; multimesh->data.write[i + color_from + 1] = 1.0; multimesh->data.write[i + color_from + 2] = 1.0; @@ -3032,7 +3032,7 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances custom_data_from = color_from + 4; } - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_8BIT) { union { uint32_t colu; float colf; @@ -3040,7 +3040,7 @@ void RasterizerStorageGLES2::multimesh_allocate(RID p_multimesh, int p_instances cu.colu = 0; multimesh->data.write[i + custom_data_from + 0] = cu.colf; - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { + } else if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_FLOAT) { multimesh->data.write[i + custom_data_from + 0] = 0.0; multimesh->data.write[i + custom_data_from + 1] = 0.0; multimesh->data.write[i + custom_data_from + 2] = 0.0; @@ -3094,7 +3094,7 @@ void RasterizerStorageGLES2::multimesh_instance_set_transform(RID p_multimesh, i MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D); + ERR_FAIL_COND(multimesh->transform_format == RS::MULTIMESH_TRANSFORM_2D); int stride = multimesh->color_floats + multimesh->custom_data_floats + multimesh->xform_floats; @@ -3125,7 +3125,7 @@ void RasterizerStorageGLES2::multimesh_instance_set_transform_2d(RID p_multimesh MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D); + ERR_FAIL_COND(multimesh->transform_format == RS::MULTIMESH_TRANSFORM_3D); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index]; @@ -3151,13 +3151,13 @@ void RasterizerStorageGLES2::multimesh_instance_set_color(RID p_multimesh, int p MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->color_format == VS::MULTIMESH_COLOR_NONE); - ERR_FAIL_INDEX(multimesh->color_format, VS::MULTIMESH_COLOR_MAX); + ERR_FAIL_COND(multimesh->color_format == RS::MULTIMESH_COLOR_NONE); + ERR_FAIL_INDEX(multimesh->color_format, RS::MULTIMESH_COLOR_MAX); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats]; - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + if (multimesh->color_format == RS::MULTIMESH_COLOR_8BIT) { uint8_t *data8 = (uint8_t *)dataptr; data8[0] = CLAMP(p_color.r * 255.0, 0, 255); @@ -3165,7 +3165,7 @@ void RasterizerStorageGLES2::multimesh_instance_set_color(RID p_multimesh, int p data8[2] = CLAMP(p_color.b * 255.0, 0, 255); data8[3] = CLAMP(p_color.a * 255.0, 0, 255); - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { + } else if (multimesh->color_format == RS::MULTIMESH_COLOR_FLOAT) { dataptr[0] = p_color.r; dataptr[1] = p_color.g; dataptr[2] = p_color.b; @@ -3184,13 +3184,13 @@ void RasterizerStorageGLES2::multimesh_instance_set_custom_data(RID p_multimesh, MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND(!multimesh); ERR_FAIL_INDEX(p_index, multimesh->size); - ERR_FAIL_COND(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE); - ERR_FAIL_INDEX(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX); + ERR_FAIL_COND(multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_NONE); + ERR_FAIL_INDEX(multimesh->custom_data_format, RS::MULTIMESH_CUSTOM_DATA_MAX); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats]; - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_8BIT) { uint8_t *data8 = (uint8_t *)dataptr; data8[0] = CLAMP(p_custom_data.r * 255.0, 0, 255); @@ -3198,7 +3198,7 @@ void RasterizerStorageGLES2::multimesh_instance_set_custom_data(RID p_multimesh, data8[2] = CLAMP(p_custom_data.b * 255.0, 0, 255); data8[3] = CLAMP(p_custom_data.a * 255.0, 0, 255); - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { + } else if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_FLOAT) { dataptr[0] = p_custom_data.r; dataptr[1] = p_custom_data.g; dataptr[2] = p_custom_data.b; @@ -3224,7 +3224,7 @@ Transform RasterizerStorageGLES2::multimesh_instance_get_transform(RID p_multime MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Transform()); ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform()); - ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D, Transform()); + ERR_FAIL_COND_V(multimesh->transform_format == RS::MULTIMESH_TRANSFORM_2D, Transform()); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index]; @@ -3251,7 +3251,7 @@ Transform2D RasterizerStorageGLES2::multimesh_instance_get_transform_2d(RID p_mu MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Transform2D()); ERR_FAIL_INDEX_V(p_index, multimesh->size, Transform2D()); - ERR_FAIL_COND_V(multimesh->transform_format == VS::MULTIMESH_TRANSFORM_3D, Transform2D()); + ERR_FAIL_COND_V(multimesh->transform_format == RS::MULTIMESH_TRANSFORM_3D, Transform2D()); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index]; @@ -3272,13 +3272,13 @@ Color RasterizerStorageGLES2::multimesh_instance_get_color(RID p_multimesh, int MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->size, Color()); - ERR_FAIL_COND_V(multimesh->color_format == VS::MULTIMESH_COLOR_NONE, Color()); - ERR_FAIL_INDEX_V(multimesh->color_format, VS::MULTIMESH_COLOR_MAX, Color()); + ERR_FAIL_COND_V(multimesh->color_format == RS::MULTIMESH_COLOR_NONE, Color()); + ERR_FAIL_INDEX_V(multimesh->color_format, RS::MULTIMESH_COLOR_MAX, Color()); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats]; - if (multimesh->color_format == VS::MULTIMESH_COLOR_8BIT) { + if (multimesh->color_format == RS::MULTIMESH_COLOR_8BIT) { union { uint32_t colu; float colf; @@ -3288,7 +3288,7 @@ Color RasterizerStorageGLES2::multimesh_instance_get_color(RID p_multimesh, int return Color::hex(BSWAP32(cu.colu)); - } else if (multimesh->color_format == VS::MULTIMESH_COLOR_FLOAT) { + } else if (multimesh->color_format == RS::MULTIMESH_COLOR_FLOAT) { Color c; c.r = dataptr[0]; c.g = dataptr[1]; @@ -3305,13 +3305,13 @@ Color RasterizerStorageGLES2::multimesh_instance_get_custom_data(RID p_multimesh MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); ERR_FAIL_COND_V(!multimesh, Color()); ERR_FAIL_INDEX_V(p_index, multimesh->size, Color()); - ERR_FAIL_COND_V(multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_NONE, Color()); - ERR_FAIL_INDEX_V(multimesh->custom_data_format, VS::MULTIMESH_CUSTOM_DATA_MAX, Color()); + ERR_FAIL_COND_V(multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_NONE, Color()); + ERR_FAIL_INDEX_V(multimesh->custom_data_format, RS::MULTIMESH_CUSTOM_DATA_MAX, Color()); int stride = multimesh->color_floats + multimesh->xform_floats + multimesh->custom_data_floats; float *dataptr = &multimesh->data.write[stride * p_index + multimesh->xform_floats + multimesh->color_floats]; - if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_8BIT) { + if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_8BIT) { union { uint32_t colu; float colf; @@ -3321,7 +3321,7 @@ Color RasterizerStorageGLES2::multimesh_instance_get_custom_data(RID p_multimesh return Color::hex(BSWAP32(cu.colu)); - } else if (multimesh->custom_data_format == VS::MULTIMESH_CUSTOM_DATA_FLOAT) { + } else if (multimesh->custom_data_format == RS::MULTIMESH_CUSTOM_DATA_FLOAT) { Color c; c.r = dataptr[0]; c.g = dataptr[1]; @@ -3400,7 +3400,7 @@ void RasterizerStorageGLES2::update_dirty_multimeshes() { AABB aabb; - if (multimesh->transform_format == VS::MULTIMESH_TRANSFORM_2D) { + if (multimesh->transform_format == RS::MULTIMESH_TRANSFORM_2D) { for (int i = 0; i < count; i += stride) { @@ -3472,7 +3472,7 @@ RID RasterizerStorageGLES2::immediate_create() { return immediate_owner.make_rid(im); } -void RasterizerStorageGLES2::immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture) { +void RasterizerStorageGLES2::immediate_begin(RID p_immediate, RS::PrimitiveType p_primitive, RID p_texture) { Immediate *im = immediate_owner.getornull(p_immediate); ERR_FAIL_COND(!im); ERR_FAIL_COND(im->building); @@ -3499,17 +3499,17 @@ void RasterizerStorageGLES2::immediate_vertex(RID p_immediate, const Vector3 &p_ im->aabb.expand_to(p_vertex); } - if (im->mask & VS::ARRAY_FORMAT_NORMAL) + if (im->mask & RS::ARRAY_FORMAT_NORMAL) c->normals.push_back(chunk_normal); - if (im->mask & VS::ARRAY_FORMAT_TANGENT) + if (im->mask & RS::ARRAY_FORMAT_TANGENT) c->tangents.push_back(chunk_tangent); - if (im->mask & VS::ARRAY_FORMAT_COLOR) + if (im->mask & RS::ARRAY_FORMAT_COLOR) c->colors.push_back(chunk_color); - if (im->mask & VS::ARRAY_FORMAT_TEX_UV) + if (im->mask & RS::ARRAY_FORMAT_TEX_UV) c->uvs.push_back(chunk_uv); - if (im->mask & VS::ARRAY_FORMAT_TEX_UV2) + if (im->mask & RS::ARRAY_FORMAT_TEX_UV2) c->uv2s.push_back(chunk_uv2); - im->mask |= VS::ARRAY_FORMAT_VERTEX; + im->mask |= RS::ARRAY_FORMAT_VERTEX; c->vertices.push_back(p_vertex); } @@ -3518,7 +3518,7 @@ void RasterizerStorageGLES2::immediate_normal(RID p_immediate, const Vector3 &p_ ERR_FAIL_COND(!im); ERR_FAIL_COND(!im->building); - im->mask |= VS::ARRAY_FORMAT_NORMAL; + im->mask |= RS::ARRAY_FORMAT_NORMAL; chunk_normal = p_normal; } @@ -3527,7 +3527,7 @@ void RasterizerStorageGLES2::immediate_tangent(RID p_immediate, const Plane &p_t ERR_FAIL_COND(!im); ERR_FAIL_COND(!im->building); - im->mask |= VS::ARRAY_FORMAT_TANGENT; + im->mask |= RS::ARRAY_FORMAT_TANGENT; chunk_tangent = p_tangent; } @@ -3536,7 +3536,7 @@ void RasterizerStorageGLES2::immediate_color(RID p_immediate, const Color &p_col ERR_FAIL_COND(!im); ERR_FAIL_COND(!im->building); - im->mask |= VS::ARRAY_FORMAT_COLOR; + im->mask |= RS::ARRAY_FORMAT_COLOR; chunk_color = p_color; } @@ -3545,7 +3545,7 @@ void RasterizerStorageGLES2::immediate_uv(RID p_immediate, const Vector2 &tex_uv ERR_FAIL_COND(!im); ERR_FAIL_COND(!im->building); - im->mask |= VS::ARRAY_FORMAT_TEX_UV; + im->mask |= RS::ARRAY_FORMAT_TEX_UV; chunk_uv = tex_uv; } @@ -3554,7 +3554,7 @@ void RasterizerStorageGLES2::immediate_uv2(RID p_immediate, const Vector2 &tex_u ERR_FAIL_COND(!im); ERR_FAIL_COND(!im->building); - im->mask |= VS::ARRAY_FORMAT_TEX_UV2; + im->mask |= RS::ARRAY_FORMAT_TEX_UV2; chunk_uv2 = tex_uv; } @@ -3812,34 +3812,34 @@ void RasterizerStorageGLES2::update_dirty_skeletons() { /* Light API */ -RID RasterizerStorageGLES2::light_create(VS::LightType p_type) { +RID RasterizerStorageGLES2::light_create(RS::LightType p_type) { Light *light = memnew(Light); light->type = p_type; - light->param[VS::LIGHT_PARAM_ENERGY] = 1.0; - light->param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0; - light->param[VS::LIGHT_PARAM_SPECULAR] = 0.5; - light->param[VS::LIGHT_PARAM_RANGE] = 1.0; - light->param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45; - light->param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45; - light->param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; - light->param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; - light->param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1; - light->param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1; + light->param[RS::LIGHT_PARAM_ENERGY] = 1.0; + light->param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0; + light->param[RS::LIGHT_PARAM_SPECULAR] = 0.5; + light->param[RS::LIGHT_PARAM_RANGE] = 1.0; + light->param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45; + light->param[RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45; + light->param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; + light->param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; + light->param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; + light->param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; + light->param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1; + light->param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1; light->color = Color(1, 1, 1, 1); light->shadow = false; light->negative = false; light->cull_mask = 0xFFFFFFFF; - light->directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; - light->omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; - light->omni_shadow_detail = VS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL; + light->directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + light->omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; + light->omni_shadow_detail = RS::LIGHT_OMNI_SHADOW_DETAIL_VERTICAL; light->directional_blend_splits = false; - light->directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; + light->directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; light->reverse_cull = false; light->use_gi = true; light->version = 0; @@ -3854,20 +3854,20 @@ void RasterizerStorageGLES2::light_set_color(RID p_light, const Color &p_color) light->color = p_color; } -void RasterizerStorageGLES2::light_set_param(RID p_light, VS::LightParam p_param, float p_value) { +void RasterizerStorageGLES2::light_set_param(RID p_light, RS::LightParam p_param, float p_value) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); - ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX); + ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX); switch (p_param) { - case VS::LIGHT_PARAM_RANGE: - case VS::LIGHT_PARAM_SPOT_ANGLE: - case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: - case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: - case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: - case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: - case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: - case VS::LIGHT_PARAM_SHADOW_BIAS: { + case RS::LIGHT_PARAM_RANGE: + case RS::LIGHT_PARAM_SPOT_ANGLE: + case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: + case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: + case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: + case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: + case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: + case RS::LIGHT_PARAM_SHADOW_BIAS: { light->version++; light->instance_change_notify(true, false); } break; @@ -3939,7 +3939,7 @@ void RasterizerStorageGLES2::light_set_use_gi(RID p_light, bool p_enabled) { light->instance_change_notify(true, false); } -void RasterizerStorageGLES2::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { +void RasterizerStorageGLES2::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); @@ -3949,14 +3949,14 @@ void RasterizerStorageGLES2::light_omni_set_shadow_mode(RID p_light, VS::LightOm light->instance_change_notify(true, false); } -VS::LightOmniShadowMode RasterizerStorageGLES2::light_omni_get_shadow_mode(RID p_light) { +RS::LightOmniShadowMode RasterizerStorageGLES2::light_omni_get_shadow_mode(RID p_light) { Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE); + ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE); return light->omni_shadow_mode; } -void RasterizerStorageGLES2::light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail) { +void RasterizerStorageGLES2::light_omni_set_shadow_detail(RID p_light, RS::LightOmniShadowDetail p_detail) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); @@ -3966,7 +3966,7 @@ void RasterizerStorageGLES2::light_omni_set_shadow_detail(RID p_light, VS::Light light->instance_change_notify(true, false); } -void RasterizerStorageGLES2::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) { +void RasterizerStorageGLES2::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); @@ -3992,37 +3992,37 @@ bool RasterizerStorageGLES2::light_directional_get_blend_splits(RID p_light) con return light->directional_blend_splits; } -VS::LightDirectionalShadowMode RasterizerStorageGLES2::light_directional_get_shadow_mode(RID p_light) { +RS::LightDirectionalShadowMode RasterizerStorageGLES2::light_directional_get_shadow_mode(RID p_light) { Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); return light->directional_shadow_mode; } -void RasterizerStorageGLES2::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) { +void RasterizerStorageGLES2::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND(!light); light->directional_range_mode = p_range_mode; } -VS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES2::light_directional_get_shadow_depth_range_mode(RID p_light) const { +RS::LightDirectionalShadowDepthRangeMode RasterizerStorageGLES2::light_directional_get_shadow_depth_range_mode(RID p_light) const { Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); return light->directional_range_mode; } -VS::LightType RasterizerStorageGLES2::light_get_type(RID p_light) const { +RS::LightType RasterizerStorageGLES2::light_get_type(RID p_light) const { Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); return light->type; } -float RasterizerStorageGLES2::light_get_param(RID p_light, VS::LightParam p_param) { +float RasterizerStorageGLES2::light_get_param(RID p_light, RS::LightParam p_param) { Light *light = light_owner.getornull(p_light); ERR_FAIL_COND_V(!light, 0.0); - ERR_FAIL_INDEX_V(p_param, VS::LIGHT_PARAM_MAX, 0.0); + ERR_FAIL_INDEX_V(p_param, RS::LIGHT_PARAM_MAX, 0.0); return light->param[p_param]; } @@ -4061,18 +4061,18 @@ AABB RasterizerStorageGLES2::light_get_aabb(RID p_light) const { switch (light->type) { - case VS::LIGHT_SPOT: { - float len = light->param[VS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len; + case RS::LIGHT_SPOT: { + float len = light->param[RS::LIGHT_PARAM_RANGE]; + float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); }; - case VS::LIGHT_OMNI: { - float r = light->param[VS::LIGHT_PARAM_RANGE]; + case RS::LIGHT_OMNI: { + float r = light->param[RS::LIGHT_PARAM_RANGE]; return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); }; - case VS::LIGHT_DIRECTIONAL: { + case RS::LIGHT_DIRECTIONAL: { return AABB(); }; } @@ -4097,13 +4097,13 @@ RID RasterizerStorageGLES2::reflection_probe_create() { reflection_probe->box_projection = false; reflection_probe->enable_shadows = false; reflection_probe->cull_mask = (1 << 20) - 1; - reflection_probe->update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE; + reflection_probe->update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; reflection_probe->resolution = 128; return reflection_probe_owner.make_rid(reflection_probe); } -void RasterizerStorageGLES2::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) { +void RasterizerStorageGLES2::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); ERR_FAIL_COND(!reflection_probe); @@ -4220,10 +4220,10 @@ AABB RasterizerStorageGLES2::reflection_probe_get_aabb(RID p_probe) const { return aabb; } -VS::ReflectionProbeUpdateMode RasterizerStorageGLES2::reflection_probe_get_update_mode(RID p_probe) const { +RS::ReflectionProbeUpdateMode RasterizerStorageGLES2::reflection_probe_get_update_mode(RID p_probe) const { const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS); + ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS); return reflection_probe->update_mode; } @@ -4518,7 +4518,7 @@ void RasterizerStorageGLES2::particles_set_fractional_delta(RID p_particles, boo void RasterizerStorageGLES2::particles_set_process_material(RID p_particles, RID p_material) { } -void RasterizerStorageGLES2::particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) { +void RasterizerStorageGLES2::particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) { } void RasterizerStorageGLES2::particles_set_draw_passes(RID p_particles, int p_passes) { @@ -4581,35 +4581,35 @@ void RasterizerStorageGLES2::instance_add_dependency(RID p_base, RasterizerScene Instantiable *inst = NULL; switch (p_instance->base_type) { - case VS::INSTANCE_MESH: { + case RS::INSTANCE_MESH: { inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - case VS::INSTANCE_MULTIMESH: { + case RS::INSTANCE_MULTIMESH: { inst = multimesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - case VS::INSTANCE_IMMEDIATE: { + case RS::INSTANCE_IMMEDIATE: { inst = immediate_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - /*case VS::INSTANCE_PARTICLES: { + /*case RS::INSTANCE_PARTICLES: { inst = particles_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break;*/ - case VS::INSTANCE_REFLECTION_PROBE: { + case RS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - case VS::INSTANCE_LIGHT: { + case RS::INSTANCE_LIGHT: { inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - /*case VS::INSTANCE_GI_PROBE: { + /*case RS::INSTANCE_GI_PROBE: { inst = gi_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break;*/ - case VS::INSTANCE_LIGHTMAP_CAPTURE: { + case RS::INSTANCE_LIGHTMAP_CAPTURE: { inst = lightmap_capture_data_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; @@ -4626,35 +4626,35 @@ void RasterizerStorageGLES2::instance_remove_dependency(RID p_base, RasterizerSc Instantiable *inst = NULL; switch (p_instance->base_type) { - case VS::INSTANCE_MESH: { + case RS::INSTANCE_MESH: { inst = mesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - case VS::INSTANCE_MULTIMESH: { + case RS::INSTANCE_MULTIMESH: { inst = multimesh_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - case VS::INSTANCE_IMMEDIATE: { + case RS::INSTANCE_IMMEDIATE: { inst = immediate_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - /*case VS::INSTANCE_PARTICLES: { + /*case RS::INSTANCE_PARTICLES: { inst = particles_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break;*/ - case VS::INSTANCE_REFLECTION_PROBE: { + case RS::INSTANCE_REFLECTION_PROBE: { inst = reflection_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - case VS::INSTANCE_LIGHT: { + case RS::INSTANCE_LIGHT: { inst = light_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; - /*case VS::INSTANCE_GI_PROBE: { + /*case RS::INSTANCE_GI_PROBE: { inst = gi_probe_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; */ - case VS::INSTANCE_LIGHTMAP_CAPTURE: { + case RS::INSTANCE_LIGHTMAP_CAPTURE: { inst = lightmap_capture_data_owner.getornull(p_base); ERR_FAIL_COND(!inst); } break; @@ -4723,7 +4723,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { glTexImage2D(GL_TEXTURE_2D, 0, color_internal_format, rt->width, rt->height, 0, color_format, color_type, NULL); - if (texture->flags & VS::TEXTURE_FLAG_FILTER) { + if (texture->flags & RS::TEXTURE_FLAG_FILTER) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); @@ -4805,7 +4805,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { /* For MSAA */ #ifndef JAVASCRIPT_ENABLED - if (rt->msaa >= VS::VIEWPORT_MSAA_2X && rt->msaa <= VS::VIEWPORT_MSAA_16X && config.multisample_supported) { + if (rt->msaa >= RS::VIEWPORT_MSAA_2X && rt->msaa <= RS::VIEWPORT_MSAA_16X && config.multisample_supported) { rt->multisample_active = true; @@ -5134,7 +5134,7 @@ RID RasterizerStorageGLES2::render_target_create() { Texture *t = memnew(Texture); - t->type = VS::TEXTURE_TYPE_2D; + t->type = RS::TEXTURE_TYPE_2D; t->flags = 0; t->width = 0; t->height = 0; @@ -5235,7 +5235,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar // allocate a texture t = memnew(Texture); - t->type = VS::TEXTURE_TYPE_2D; + t->type = RS::TEXTURE_TYPE_2D; t->flags = 0; t->width = 0; t->height = 0; @@ -5278,7 +5278,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar // Switch our texture on our frame buffer #if ANDROID_ENABLED - if (rt->msaa >= VS::VIEWPORT_MSAA_EXT_2X && rt->msaa <= VS::VIEWPORT_MSAA_EXT_4X) { + if (rt->msaa >= RS::VIEWPORT_MSAA_EXT_2X && rt->msaa <= RS::VIEWPORT_MSAA_EXT_4X) { // This code only applies to the Oculus Go and Oculus Quest. Due to the the tiled nature // of the GPU we can do a single render pass by rendering directly into our texture chains // texture and apply MSAA as we render. @@ -5287,7 +5287,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar // the normal MSAA modes need to be used to enable our two pass approach static const int msaa_value[] = { 2, 4 }; - int msaa = msaa_value[rt->msaa - VS::VIEWPORT_MSAA_EXT_2X]; + int msaa = msaa_value[rt->msaa - RS::VIEWPORT_MSAA_EXT_2X]; if (rt->external.depth == 0) { // create a multisample depth buffer, we're not reusing Godots because Godot's didn't get created.. @@ -5370,7 +5370,7 @@ void RasterizerStorageGLES2::render_target_set_as_unused(RID p_render_target) { rt->used_in_frame = false; } -void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa) { +void RasterizerStorageGLES2::render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa) { RenderTarget *rt = render_target_owner.getornull(p_render_target); ERR_FAIL_COND(!rt); @@ -5544,22 +5544,22 @@ void RasterizerStorageGLES2::canvas_light_occluder_set_polylines(RID p_occluder, } } -VS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const { +RS::InstanceType RasterizerStorageGLES2::get_base_type(RID p_rid) const { if (mesh_owner.owns(p_rid)) { - return VS::INSTANCE_MESH; + return RS::INSTANCE_MESH; } else if (light_owner.owns(p_rid)) { - return VS::INSTANCE_LIGHT; + return RS::INSTANCE_LIGHT; } else if (multimesh_owner.owns(p_rid)) { - return VS::INSTANCE_MULTIMESH; + return RS::INSTANCE_MULTIMESH; } else if (immediate_owner.owns(p_rid)) { - return VS::INSTANCE_IMMEDIATE; + return RS::INSTANCE_IMMEDIATE; } else if (reflection_probe_owner.owns(p_rid)) { - return VS::INSTANCE_REFLECTION_PROBE; + return RS::INSTANCE_REFLECTION_PROBE; } else if (lightmap_capture_data_owner.owns(p_rid)) { - return VS::INSTANCE_LIGHTMAP_CAPTURE; + return RS::INSTANCE_LIGHTMAP_CAPTURE; } else { - return VS::INSTANCE_NONE; + return RS::INSTANCE_NONE; } } @@ -5710,7 +5710,7 @@ bool RasterizerStorageGLES2::free(RID p_rid) { } } - multimesh_allocate(p_rid, 0, VS::MULTIMESH_TRANSFORM_3D, VS::MULTIMESH_COLOR_NONE); + multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_3D, RS::MULTIMESH_COLOR_NONE); update_dirty_multimeshes(); @@ -5817,25 +5817,25 @@ void RasterizerStorageGLES2::render_info_end_capture() { info.snap.vertices_count = info.render.vertices_count - info.snap.vertices_count; } -int RasterizerStorageGLES2::get_captured_render_info(VS::RenderInfo p_info) { +int RasterizerStorageGLES2::get_captured_render_info(RS::RenderInfo p_info) { switch (p_info) { - case VS::INFO_OBJECTS_IN_FRAME: { + case RS::INFO_OBJECTS_IN_FRAME: { return info.snap.object_count; } break; - case VS::INFO_VERTICES_IN_FRAME: { + case RS::INFO_VERTICES_IN_FRAME: { return info.snap.vertices_count; } break; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: { + case RS::INFO_MATERIAL_CHANGES_IN_FRAME: { return info.snap.material_switch_count; } break; - case VS::INFO_SHADER_CHANGES_IN_FRAME: { + case RS::INFO_SHADER_CHANGES_IN_FRAME: { return info.snap.shader_rebind_count; } break; - case VS::INFO_SURFACE_CHANGES_IN_FRAME: { + case RS::INFO_SURFACE_CHANGES_IN_FRAME: { return info.snap.surface_switch_count; } break; - case VS::INFO_DRAW_CALLS_IN_FRAME: { + case RS::INFO_DRAW_CALLS_IN_FRAME: { return info.snap.draw_call_count; } break; default: { @@ -5844,27 +5844,27 @@ int RasterizerStorageGLES2::get_captured_render_info(VS::RenderInfo p_info) { } } -int RasterizerStorageGLES2::get_render_info(VS::RenderInfo p_info) { +int RasterizerStorageGLES2::get_render_info(RS::RenderInfo p_info) { switch (p_info) { - case VS::INFO_OBJECTS_IN_FRAME: + case RS::INFO_OBJECTS_IN_FRAME: return info.render_final.object_count; - case VS::INFO_VERTICES_IN_FRAME: + case RS::INFO_VERTICES_IN_FRAME: return info.render_final.vertices_count; - case VS::INFO_MATERIAL_CHANGES_IN_FRAME: + case RS::INFO_MATERIAL_CHANGES_IN_FRAME: return info.render_final.material_switch_count; - case VS::INFO_SHADER_CHANGES_IN_FRAME: + case RS::INFO_SHADER_CHANGES_IN_FRAME: return info.render_final.shader_rebind_count; - case VS::INFO_SURFACE_CHANGES_IN_FRAME: + case RS::INFO_SURFACE_CHANGES_IN_FRAME: return info.render_final.surface_switch_count; - case VS::INFO_DRAW_CALLS_IN_FRAME: + case RS::INFO_DRAW_CALLS_IN_FRAME: return info.render_final.draw_call_count; - case VS::INFO_USAGE_VIDEO_MEM_TOTAL: + case RS::INFO_USAGE_VIDEO_MEM_TOTAL: return 0; //no idea - case VS::INFO_VIDEO_MEM_USED: + case RS::INFO_VIDEO_MEM_USED: return info.vertex_mem + info.texture_mem; - case VS::INFO_TEXTURE_MEM_USED: + case RS::INFO_TEXTURE_MEM_USED: return info.texture_mem; - case VS::INFO_VERTEX_MEM_USED: + case RS::INFO_VERTEX_MEM_USED: return info.vertex_mem; default: return 0; //no idea either diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 86965730e0..f8b8b824bd 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -32,8 +32,8 @@ #define RASTERIZERSTORAGEGLES2_H #include "core/self_list.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/shader_language.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering/shader_language.h" #include "shader_compiler_gles2.h" #include "shader_gles2.h" @@ -249,7 +249,7 @@ public: int width, height, depth; int alloc_width, alloc_height; Image::Format format; - VS::TextureType type; + RS::TextureType type; GLenum target; GLenum gl_format_cache; @@ -279,13 +279,13 @@ public: bool redraw_if_visible; - VisualServer::TextureDetectCallback detect_3d; + RenderingServer::TextureDetectCallback detect_3d; void *detect_3d_ud; - VisualServer::TextureDetectCallback detect_srgb; + RenderingServer::TextureDetectCallback detect_srgb; void *detect_srgb_ud; - VisualServer::TextureDetectCallback detect_normal; + RenderingServer::TextureDetectCallback detect_normal; void *detect_normal_ud; Texture() : @@ -296,7 +296,7 @@ public: alloc_width(0), alloc_height(0), format(Image::FORMAT_L8), - type(VS::TEXTURE_TYPE_2D), + type(RS::TEXTURE_TYPE_2D), target(0), data_size(0), total_data_size(0), @@ -345,14 +345,14 @@ public: Ref _get_gl_image_and_format(const Ref &p_image, Image::Format p_format, uint32_t p_flags, Image::Format &r_real_format, GLenum &r_gl_format, GLenum &r_gl_internal_format, GLenum &r_gl_type, bool &r_compressed, bool p_force_decompress) const; virtual RID texture_create(); - virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, VS::TextureType p_type, uint32_t p_flags = VS::TEXTURE_FLAGS_DEFAULT); + virtual void texture_allocate(RID p_texture, int p_width, int p_height, int p_depth_3d, Image::Format p_format, RS::TextureType p_type, uint32_t p_flags = RS::TEXTURE_FLAGS_DEFAULT); virtual void texture_set_data(RID p_texture, const Ref &p_image, int p_layer = 0); virtual void texture_set_data_partial(RID p_texture, const Ref &p_image, int src_x, int src_y, int src_w, int src_h, int dst_x, int dst_y, int p_dst_mip, int p_layer = 0); virtual Ref texture_get_data(RID p_texture, int p_layer = 0) const; virtual void texture_set_flags(RID p_texture, uint32_t p_flags); virtual uint32_t texture_get_flags(RID p_texture) const; virtual Image::Format texture_get_format(RID p_texture) const; - virtual VS::TextureType texture_get_type(RID p_texture) const; + virtual RS::TextureType texture_get_type(RID p_texture) const; virtual uint32_t texture_get_texid(RID p_texture) const; virtual uint32_t texture_get_width(RID p_texture) const; virtual uint32_t texture_get_height(RID p_texture) const; @@ -365,7 +365,7 @@ public: virtual void texture_set_shrink_all_x2_on_set_data(bool p_enable); - virtual void texture_debug_usage(List *r_info); + virtual void texture_debug_usage(List *r_info); virtual RID texture_create_radiance_cubemap(RID p_source, int p_resolution = -1) const; @@ -374,9 +374,9 @@ public: virtual void texture_set_proxy(RID p_texture, RID p_proxy); virtual Size2 texture_size_with_proxy(RID p_texture) const; - virtual void texture_set_detect_3d_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_srgb_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, VisualServer::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_3d_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_srgb_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_normal_callback(RID p_texture, RenderingServer::TextureDetectCallback p_callback, void *p_userdata); virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); @@ -402,7 +402,7 @@ public: RID self; - VS::ShaderMode mode; + RS::ShaderMode mode; ShaderGLES2 *shader; String code; SelfList::List materials; @@ -617,7 +617,7 @@ public: uint32_t offset; }; - Attrib attribs[VS::ARRAY_MAX]; + Attrib attribs[RS::ARRAY_MAX]; Mesh *mesh; uint32_t format; @@ -641,7 +641,7 @@ public: int array_byte_size; int index_array_byte_size; - VS::PrimitiveType primitive; + RS::PrimitiveType primitive; Vector skeleton_bone_aabb; Vector skeleton_bone_used; @@ -660,7 +660,7 @@ public: index_array_len(0), array_byte_size(0), index_array_byte_size(0), - primitive(VS::PRIMITIVE_POINTS), + primitive(RS::PRIMITIVE_POINTS), active(false), total_data_size(0) { } @@ -675,7 +675,7 @@ public: Vector surfaces; int blend_shape_count; - VS::BlendShapeMode blend_shape_mode; + RS::BlendShapeMode blend_shape_mode; AABB custom_aabb; @@ -694,7 +694,7 @@ public: Mesh() : blend_shape_count(0), - blend_shape_mode(VS::BLEND_SHAPE_MODE_NORMALIZED) { + blend_shape_mode(RS::BLEND_SHAPE_MODE_NORMALIZED) { } }; @@ -702,13 +702,13 @@ public: virtual RID mesh_create(); - virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, VS::PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes = Vector>(), const Vector &p_bone_aabbs = Vector()); + virtual void mesh_add_surface(RID p_mesh, uint32_t p_format, RS::PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes = Vector>(), const Vector &p_bone_aabbs = Vector()); virtual void mesh_set_blend_shape_count(RID p_mesh, int p_amount); virtual int mesh_get_blend_shape_count(RID p_mesh) const; - virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode); - virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode); + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data); @@ -722,7 +722,7 @@ public: virtual Vector mesh_surface_get_index_array(RID p_mesh, int p_surface) const; virtual uint32_t mesh_surface_get_format(RID p_mesh, int p_surface) const; - virtual VS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; + virtual RS::PrimitiveType mesh_surface_get_primitive_type(RID p_mesh, int p_surface) const; virtual AABB mesh_surface_get_aabb(RID p_mesh, int p_surface) const; virtual Vector> mesh_surface_get_blend_shapes(RID p_mesh, int p_surface) const; @@ -744,9 +744,9 @@ public: RID mesh; int size; - VS::MultimeshTransformFormat transform_format; - VS::MultimeshColorFormat color_format; - VS::MultimeshCustomDataFormat custom_data_format; + RS::MultimeshTransformFormat transform_format; + RS::MultimeshColorFormat color_format; + RS::MultimeshCustomDataFormat custom_data_format; Vector data; @@ -766,9 +766,9 @@ public: MultiMesh() : size(0), - transform_format(VS::MULTIMESH_TRANSFORM_2D), - color_format(VS::MULTIMESH_COLOR_NONE), - custom_data_format(VS::MULTIMESH_CUSTOM_DATA_NONE), + transform_format(RS::MULTIMESH_TRANSFORM_2D), + color_format(RS::MULTIMESH_COLOR_NONE), + custom_data_format(RS::MULTIMESH_CUSTOM_DATA_NONE), update_list(this), mesh_list(this), visible_instances(-1), @@ -786,7 +786,7 @@ public: virtual RID multimesh_create(); - virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, VS::MultimeshColorFormat p_color_format, VS::MultimeshCustomDataFormat p_data = VS::MULTIMESH_CUSTOM_DATA_NONE); + virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, RS::MultimeshColorFormat p_color_format, RS::MultimeshCustomDataFormat p_data = RS::MULTIMESH_CUSTOM_DATA_NONE); virtual int multimesh_get_instance_count(RID p_multimesh) const; virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh); @@ -817,7 +817,7 @@ public: struct Chunk { RID texture; - VS::PrimitiveType primitive; + RS::PrimitiveType primitive; Vector vertices; Vector normals; Vector tangents; @@ -846,7 +846,7 @@ public: mutable RID_PtrOwner immediate_owner; virtual RID immediate_create(); - virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_primitive, RID p_texture = RID()); + virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_primitive, RID p_texture = RID()); virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex); virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal); virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent); @@ -906,8 +906,8 @@ public: /* Light API */ struct Light : Instantiable { - VS::LightType type; - float param[VS::LIGHT_PARAM_MAX]; + RS::LightType type; + float param[RS::LIGHT_PARAM_MAX]; Color color; Color shadow_color; @@ -921,11 +921,11 @@ public: uint32_t cull_mask; - VS::LightOmniShadowMode omni_shadow_mode; - VS::LightOmniShadowDetail omni_shadow_detail; + RS::LightOmniShadowMode omni_shadow_mode; + RS::LightOmniShadowDetail omni_shadow_detail; - VS::LightDirectionalShadowMode directional_shadow_mode; - VS::LightDirectionalShadowDepthRangeMode directional_range_mode; + RS::LightDirectionalShadowMode directional_shadow_mode; + RS::LightDirectionalShadowDepthRangeMode directional_range_mode; bool directional_blend_splits; @@ -934,10 +934,10 @@ public: mutable RID_PtrOwner light_owner; - virtual RID light_create(VS::LightType p_type); + virtual RID light_create(RS::LightType p_type); virtual void light_set_color(RID p_light, const Color &p_color); - virtual void light_set_param(RID p_light, VS::LightParam p_param, float p_value); + virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value); virtual void light_set_shadow(RID p_light, bool p_enabled); virtual void light_set_shadow_color(RID p_light, const Color &p_color); virtual void light_set_projector(RID p_light, RID p_texture); @@ -946,23 +946,23 @@ public: virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); virtual void light_set_use_gi(RID p_light, bool p_enabled); - virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode); - virtual void light_omni_set_shadow_detail(RID p_light, VS::LightOmniShadowDetail p_detail); + virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode); + virtual void light_omni_set_shadow_detail(RID p_light, RS::LightOmniShadowDetail p_detail); - virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode); + virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode); virtual void light_directional_set_blend_splits(RID p_light, bool p_enable); virtual bool light_directional_get_blend_splits(RID p_light) const; - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); + virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); + virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); - virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode); - virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode); + virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; virtual bool light_has_shadow(RID p_light) const; - virtual VS::LightType light_get_type(RID p_light) const; - virtual float light_get_param(RID p_light, VS::LightParam p_param); + virtual RS::LightType light_get_type(RID p_light) const; + virtual float light_get_param(RID p_light, RS::LightParam p_param); virtual Color light_get_color(RID p_light); virtual bool light_get_use_gi(RID p_light); @@ -973,7 +973,7 @@ public: struct ReflectionProbe : Instantiable { - VS::ReflectionProbeUpdateMode update_mode; + RS::ReflectionProbeUpdateMode update_mode; float intensity; Color interior_ambient; float interior_ambient_energy; @@ -992,7 +992,7 @@ public: virtual RID reflection_probe_create(); - virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode); + virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode); virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity); virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient); virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); @@ -1007,7 +1007,7 @@ public: virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution); virtual AABB reflection_probe_get_aabb(RID p_probe) const; - virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; + virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const; virtual int reflection_probe_get_resolution(RID p_probe) const; @@ -1111,7 +1111,7 @@ public: virtual void particles_set_fractional_delta(RID p_particles, bool p_enable); virtual void particles_restart(RID p_particles); - virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order); + virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order); virtual void particles_set_draw_passes(RID p_particles, int p_passes); virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh); @@ -1203,7 +1203,7 @@ public: bool flags[RENDER_TARGET_FLAG_MAX]; bool used_in_frame; - VS::ViewportMSAA msaa; + RS::ViewportMSAA msaa; RID texture; @@ -1223,7 +1223,7 @@ public: width(0), height(0), used_in_frame(false), - msaa(VS::VIEWPORT_MSAA_DISABLED), + msaa(RS::VIEWPORT_MSAA_DISABLED), used_dof_blur_near(false), mip_maps_allocated(false) { for (int i = 0; i < RENDER_TARGET_FLAG_MAX; ++i) { @@ -1247,7 +1247,7 @@ public: virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); virtual bool render_target_was_used(RID p_render_target); virtual void render_target_set_as_unused(RID p_render_target); - virtual void render_target_set_msaa(RID p_render_target, VS::ViewportMSAA p_msaa); + virtual void render_target_set_msaa(RID p_render_target, RS::ViewportMSAA p_msaa); /* CANVAS SHADOW */ @@ -1279,7 +1279,7 @@ public: virtual RID canvas_light_occluder_create(); virtual void canvas_light_occluder_set_polylines(RID p_occluder, const Vector &p_lines); - virtual VS::InstanceType get_base_type(RID p_rid) const; + virtual RS::InstanceType get_base_type(RID p_rid) const; virtual bool free(RID p_rid); @@ -1309,9 +1309,9 @@ public: virtual void render_info_begin_capture(); virtual void render_info_end_capture(); - virtual int get_captured_render_info(VS::RenderInfo p_info); + virtual int get_captured_render_info(RS::RenderInfo p_info); - virtual int get_render_info(VS::RenderInfo p_info); + virtual int get_render_info(RS::RenderInfo p_info); virtual String get_video_adapter_name() const; virtual String get_video_adapter_vendor() const; diff --git a/drivers/gles2/shader_compiler_gles2.cpp b/drivers/gles2/shader_compiler_gles2.cpp index 620fcdbdca..d626263431 100644 --- a/drivers/gles2/shader_compiler_gles2.cpp +++ b/drivers/gles2/shader_compiler_gles2.cpp @@ -934,7 +934,7 @@ String ShaderCompilerGLES2::_dump_node_code(SL::Node *p_node, int p_level, Gener return code.as_string(); } -Error ShaderCompilerGLES2::compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { +Error ShaderCompilerGLES2::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types()); @@ -975,210 +975,210 @@ ShaderCompilerGLES2::ShaderCompilerGLES2() { /** CANVAS ITEM SHADER **/ - actions[VS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy"; - actions[VS::SHADER_CANVAS_ITEM].renames["UV"] = "uv"; - actions[VS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "point_size"; - - actions[VS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix"; - actions[VS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[VS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] = "extra_matrix_instance"; - actions[VS::SHADER_CANVAS_ITEM].renames["TIME"] = "time"; - actions[VS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass"; - actions[VS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; - - actions[VS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; - actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; - actions[VS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv"; - actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; - actions[VS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[VS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord"; - - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; - actions[VS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; - actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; - actions[VS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec"; - - actions[VS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].renames["VERTEX"] = "outvec.xy"; + actions[RS::SHADER_CANVAS_ITEM].renames["UV"] = "uv"; + actions[RS::SHADER_CANVAS_ITEM].renames["POINT_SIZE"] = "point_size"; + + actions[RS::SHADER_CANVAS_ITEM].renames["WORLD_MATRIX"] = "modelview_matrix"; + actions[RS::SHADER_CANVAS_ITEM].renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions[RS::SHADER_CANVAS_ITEM].renames["EXTRA_MATRIX"] = "extra_matrix_instance"; + actions[RS::SHADER_CANVAS_ITEM].renames["TIME"] = "time"; + actions[RS::SHADER_CANVAS_ITEM].renames["AT_LIGHT_PASS"] = "at_light_pass"; + actions[RS::SHADER_CANVAS_ITEM].renames["INSTANCE_CUSTOM"] = "instance_custom"; + + actions[RS::SHADER_CANVAS_ITEM].renames["COLOR"] = "color"; + actions[RS::SHADER_CANVAS_ITEM].renames["NORMAL"] = "normal"; + actions[RS::SHADER_CANVAS_ITEM].renames["NORMALMAP"] = "normal_map"; + actions[RS::SHADER_CANVAS_ITEM].renames["NORMALMAP_DEPTH"] = "normal_depth"; + actions[RS::SHADER_CANVAS_ITEM].renames["TEXTURE"] = "color_texture"; + actions[RS::SHADER_CANVAS_ITEM].renames["TEXTURE_PIXEL_SIZE"] = "color_texpixel_size"; + actions[RS::SHADER_CANVAS_ITEM].renames["NORMAL_TEXTURE"] = "normal_texture"; + actions[RS::SHADER_CANVAS_ITEM].renames["SCREEN_UV"] = "screen_uv"; + actions[RS::SHADER_CANVAS_ITEM].renames["SCREEN_TEXTURE"] = "screen_texture"; + actions[RS::SHADER_CANVAS_ITEM].renames["SCREEN_PIXEL_SIZE"] = "screen_pixel_size"; + actions[RS::SHADER_CANVAS_ITEM].renames["FRAGCOORD"] = "gl_FragCoord"; + actions[RS::SHADER_CANVAS_ITEM].renames["POINT_COORD"] = "gl_PointCoord"; + + actions[RS::SHADER_CANVAS_ITEM].renames["LIGHT_VEC"] = "light_vec"; + actions[RS::SHADER_CANVAS_ITEM].renames["LIGHT_HEIGHT"] = "light_height"; + actions[RS::SHADER_CANVAS_ITEM].renames["LIGHT_COLOR"] = "light_color"; + actions[RS::SHADER_CANVAS_ITEM].renames["LIGHT_UV"] = "light_uv"; + actions[RS::SHADER_CANVAS_ITEM].renames["LIGHT"] = "light"; + actions[RS::SHADER_CANVAS_ITEM].renames["SHADOW_COLOR"] = "shadow_color"; + actions[RS::SHADER_CANVAS_ITEM].renames["SHADOW_VEC"] = "shadow_vec"; + + actions[RS::SHADER_CANVAS_ITEM].usage_defines["COLOR"] = "#define COLOR_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["NORMAL"] = "#define NORMAL_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions[RS::SHADER_CANVAS_ITEM].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["SHADOW_VEC"] = "#define SHADOW_VEC_USED\n"; // Ported from GLES3 - actions[VS::SHADER_CANVAS_ITEM].usage_defines["sinh"] = "#define SINH_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["cosh"] = "#define COSH_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["tanh"] = "#define TANH_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["asinh"] = "#define ASINH_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["acosh"] = "#define ACOSH_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["atanh"] = "#define ATANH_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["determinant"] = "#define DETERMINANT_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["transpose"] = "#define TRANSPOSE_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["outerProduct"] = "#define OUTER_PRODUCT_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["round"] = "#define ROUND_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["roundEven"] = "#define ROUND_EVEN_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["inverse"] = "#define INVERSE_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["isinf"] = "#define IS_INF_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["isnan"] = "#define IS_NAN_USED\n"; - actions[VS::SHADER_CANVAS_ITEM].usage_defines["trunc"] = "#define TRUNC_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["sinh"] = "#define SINH_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["cosh"] = "#define COSH_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["tanh"] = "#define TANH_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["asinh"] = "#define ASINH_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["acosh"] = "#define ACOSH_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["atanh"] = "#define ATANH_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["determinant"] = "#define DETERMINANT_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["transpose"] = "#define TRANSPOSE_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["outerProduct"] = "#define OUTER_PRODUCT_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["round"] = "#define ROUND_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["roundEven"] = "#define ROUND_EVEN_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["inverse"] = "#define INVERSE_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["isinf"] = "#define IS_INF_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["isnan"] = "#define IS_NAN_USED\n"; + actions[RS::SHADER_CANVAS_ITEM].usage_defines["trunc"] = "#define TRUNC_USED\n"; /** SPATIAL SHADER **/ - actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; - actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; - actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; - actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "projection_inverse_matrix"; - actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; - - actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; - actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; - actions[VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; - actions[VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; - actions[VS::SHADER_SPATIAL].renames["POSITION"] = "position"; - actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; - actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; - actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; - actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "point_size"; + actions[RS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; + actions[RS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; + actions[RS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; + actions[RS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions[RS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "projection_inverse_matrix"; + actions[RS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; + + actions[RS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; + actions[RS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; + actions[RS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; + actions[RS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; + actions[RS::SHADER_SPATIAL].renames["POSITION"] = "position"; + actions[RS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; + actions[RS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; + actions[RS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; + actions[RS::SHADER_SPATIAL].renames["POINT_SIZE"] = "point_size"; // gl_InstanceID is not available in OpenGL ES 2.0 - actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0"; + actions[RS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "0"; //builtins - actions[VS::SHADER_SPATIAL].renames["TIME"] = "time"; - actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; - - actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; - actions[VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; - actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; - actions[VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; - actions[VS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; - actions[VS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; - actions[VS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; - actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; - actions[VS::SHADER_SPATIAL].renames["RIM"] = "rim"; - actions[VS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; - actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; - actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; - actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; - actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; - actions[VS::SHADER_SPATIAL].renames["AO"] = "ao"; - actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; - actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; - actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; - actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_texture"; + actions[RS::SHADER_SPATIAL].renames["TIME"] = "time"; + actions[RS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; + + actions[RS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; + actions[RS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; + actions[RS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; + actions[RS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; + actions[RS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; + actions[RS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; + actions[RS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; + actions[RS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; + actions[RS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; + actions[RS::SHADER_SPATIAL].renames["RIM"] = "rim"; + actions[RS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; + actions[RS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; + actions[RS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions[RS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; + actions[RS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; + actions[RS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; + actions[RS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; + actions[RS::SHADER_SPATIAL].renames["AO"] = "ao"; + actions[RS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; + actions[RS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; + actions[RS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; + actions[RS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; + actions[RS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; + actions[RS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; + actions[RS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_texture"; // Defined in GLES3, but not available in GLES2 - //actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; - actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; - actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + //actions[RS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; + actions[RS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; + actions[RS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; //for light - actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view"; - actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; - actions[VS::SHADER_SPATIAL].renames["LIGHT"] = "light"; - actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; - actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; - - actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; - actions[VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; - actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; - actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; - actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; - actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions[VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; - actions[VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; - actions[VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; - actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["DEPTH_TEXTURE"] = "#define DEPTH_TEXTURE_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions[RS::SHADER_SPATIAL].renames["VIEW"] = "view"; + actions[RS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; + actions[RS::SHADER_SPATIAL].renames["LIGHT"] = "light"; + actions[RS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; + actions[RS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; + actions[RS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; + + actions[RS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; + actions[RS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; + actions[RS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; + actions[RS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; + actions[RS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions[RS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; + actions[RS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; + actions[RS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; + actions[RS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; + actions[RS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; + actions[RS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; + actions[RS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; + + actions[RS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; + actions[RS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["DEPTH_TEXTURE"] = "#define DEPTH_TEXTURE_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + + actions[RS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions[RS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; // Ported from GLES3 - actions[VS::SHADER_SPATIAL].usage_defines["sinh"] = "#define SINH_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["cosh"] = "#define COSH_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["tanh"] = "#define TANH_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["asinh"] = "#define ASINH_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["acosh"] = "#define ACOSH_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["atanh"] = "#define ATANH_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["determinant"] = "#define DETERMINANT_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["transpose"] = "#define TRANSPOSE_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["outerProduct"] = "#define OUTER_PRODUCT_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["round"] = "#define ROUND_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["roundEven"] = "#define ROUND_EVEN_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["inverse"] = "#define INVERSE_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["isinf"] = "#define IS_INF_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["isnan"] = "#define IS_NAN_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["trunc"] = "#define TRUNC_USED\n"; - - actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["sinh"] = "#define SINH_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["cosh"] = "#define COSH_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["tanh"] = "#define TANH_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["asinh"] = "#define ASINH_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["acosh"] = "#define ACOSH_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["atanh"] = "#define ATANH_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["determinant"] = "#define DETERMINANT_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["transpose"] = "#define TRANSPOSE_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["outerProduct"] = "#define OUTER_PRODUCT_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["round"] = "#define ROUND_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["roundEven"] = "#define ROUND_EVEN_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["inverse"] = "#define INVERSE_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["isinf"] = "#define IS_INF_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["isnan"] = "#define IS_NAN_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["trunc"] = "#define TRUNC_USED\n"; + + actions[RS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; // Defined in GLES3, could be implemented in GLES2 too if there's a need for it - //actions[VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; + //actions[RS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; // Defined in GLES3, might not be possible in GLES2 as gl_FrontFacing is not available - //actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - //actions[VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; + //actions[RS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; + //actions[RS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); if (!force_lambert) { - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; } - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx"); if (!force_blinn) { - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; } else { - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; } - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; // No defines for particle shaders in GLES2, there are no GPU particles diff --git a/drivers/gles2/shader_compiler_gles2.h b/drivers/gles2/shader_compiler_gles2.h index dd10a27c0d..757dcdd4f2 100644 --- a/drivers/gles2/shader_compiler_gles2.h +++ b/drivers/gles2/shader_compiler_gles2.h @@ -33,9 +33,9 @@ #include "core/pair.h" #include "core/string_builder.h" -#include "servers/visual/shader_language.h" -#include "servers/visual/shader_types.h" -#include "servers/visual_server.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering/shader_types.h" +#include "servers/rendering_server.h" class ShaderCompilerGLES2 { public: @@ -91,10 +91,10 @@ private: Set used_rmode_defines; Set internal_functions; - DefaultIdentifierActions actions[VS::SHADER_MAX]; + DefaultIdentifierActions actions[RS::SHADER_MAX]; public: - Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); + Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); ShaderCompilerGLES2(); }; diff --git a/drivers/gles2/shader_gles2.h b/drivers/gles2/shader_gles2.h index d5e8159479..54858becb6 100644 --- a/drivers/gles2/shader_gles2.h +++ b/drivers/gles2/shader_gles2.h @@ -44,7 +44,7 @@ #include "core/math/camera_matrix.h" #include "core/pair.h" #include "core/variant.h" -#include "servers/visual/shader_language.h" +#include "servers/rendering/shader_language.h" #include diff --git a/drivers/gles2/shaders/blend_shape.glsl b/drivers/gles2/shaders/blend_shape.glsl index a1e954e33d..0d0b3e24e4 100644 --- a/drivers/gles2/shaders/blend_shape.glsl +++ b/drivers/gles2/shaders/blend_shape.glsl @@ -2,7 +2,7 @@ [vertex] /* -from VisualServer: +from RenderingServer: ARRAY_VERTEX=0, ARRAY_NORMAL=1, diff --git a/drivers/unix/os_unix.cpp b/drivers/unix/os_unix.cpp index 458488f3e9..76a89b2bb4 100644 --- a/drivers/unix/os_unix.cpp +++ b/drivers/unix/os_unix.cpp @@ -41,7 +41,7 @@ #include "drivers/unix/net_socket_posix.h" #include "drivers/unix/rw_lock_posix.h" #include "drivers/unix/thread_posix.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #ifdef __APPLE__ #include diff --git a/drivers/vulkan/rendering_device_vulkan.h b/drivers/vulkan/rendering_device_vulkan.h index 7f1697b2b5..f7ae9c28ea 100644 --- a/drivers/vulkan/rendering_device_vulkan.h +++ b/drivers/vulkan/rendering_device_vulkan.h @@ -34,7 +34,7 @@ #include "core/oa_hash_map.h" #include "core/os/thread_safe.h" #include "core/rid_owner.h" -#include "servers/visual/rendering_device.h" +#include "servers/rendering/rendering_device.h" #ifdef DEBUG_ENABLED #define _DEBUG diff --git a/editor/animation_track_editor_plugins.cpp b/editor/animation_track_editor_plugins.cpp index ea0d7511fe..4467366c3f 100644 --- a/editor/animation_track_editor_plugins.cpp +++ b/editor/animation_track_editor_plugins.cpp @@ -303,7 +303,7 @@ void AnimationTrackEditAudio::draw_key(int p_index, float p_pixels_sec, int p_x, Vector color; color.push_back(Color(0.75, 0.75, 0.75)); - VS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color); + RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color); if (p_selected) { Color accent = get_theme_color("accent_color", "Editor"); @@ -673,7 +673,7 @@ void AnimationTrackEditSubAnim::draw_key(int p_index, float p_pixels_sec, int p_ } if (lines.size() > 2) { - VS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, colorv); + RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, colorv); } int limit = to_x - from_x - 4; @@ -926,7 +926,7 @@ void AnimationTrackEditTypeAudio::draw_key(int p_index, float p_pixels_sec, int Vector color; color.push_back(Color(0.75, 0.75, 0.75)); - VS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color); + RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, color); Color cut_color = get_theme_color("accent_color", "Editor"); cut_color.a = 0.7; @@ -1255,7 +1255,7 @@ void AnimationTrackEditTypeAnimation::draw_key(int p_index, float p_pixels_sec, } if (lines.size() > 2) { - VS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, colorv); + RS::get_singleton()->canvas_item_add_multiline(get_canvas_item(), lines, colorv); } int limit = to_x - from_x - 4; diff --git a/editor/editor_inspector.cpp b/editor/editor_inspector.cpp index 181811207c..013ba88c30 100644 --- a/editor/editor_inspector.cpp +++ b/editor/editor_inspector.cpp @@ -1569,7 +1569,7 @@ void EditorInspector::update_tree() { } else if (!(p.usage & PROPERTY_USAGE_EDITOR) || _is_property_disabled_by_feature_profile(p.name)) continue; - if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && VS::get_singleton()->is_low_end()) + if (p.usage & PROPERTY_USAGE_HIGH_END_GFX && RS::get_singleton()->is_low_end()) continue; //do not show this property in low end gfx if (p.name == "script" && (hide_script || bool(object->call("_hide_script_from_inspector")))) { diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 6b332ca300..2ba67ae879 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -61,9 +61,9 @@ #include "scene/gui/texture_progress.h" #include "scene/gui/tool_button.h" #include "scene/resources/packed_scene.h" -#include "servers/navigation_2d_server.h" -#include "servers/navigation_server.h" -#include "servers/physics_2d_server.h" +#include "servers/navigation_server_2d.h" +#include "servers/navigation_server_3d.h" +#include "servers/physics_server_2d.h" #include "editor/audio_stream_preview.h" #include "editor/debugger/editor_debugger_node.h" @@ -358,13 +358,13 @@ void EditorNode::_notification(int p_what) { scene_root->set_default_canvas_item_texture_repeat(tr); } - VS::DOFBokehShape dof_shape = VS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape"))); - VS::get_singleton()->camera_effects_set_dof_blur_bokeh_shape(dof_shape); - VS::DOFBlurQuality dof_quality = VS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))); + RS::DOFBokehShape dof_shape = RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape"))); + RS::get_singleton()->camera_effects_set_dof_blur_bokeh_shape(dof_shape); + RS::DOFBlurQuality dof_quality = RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))); bool dof_jitter = GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter"); - VS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter); - VS::get_singleton()->environment_set_ssao_quality(VS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); - VS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter"), GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve")); + RS::get_singleton()->camera_effects_set_dof_blur_quality(dof_quality, dof_jitter); + RS::get_singleton()->environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); + RS::get_singleton()->screen_space_roughness_limiter_set_active(GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter"), GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve")); } ResourceImporterTexture::get_singleton()->update_imports(); @@ -404,9 +404,9 @@ void EditorNode::_notification(int p_what) { _initializing_addons = false; } - VisualServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true); - VisualServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true); - VisualServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_hide_scenario(get_scene_root()->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_hide_canvas(get_scene_root()->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_disable_environment(get_viewport()->get_viewport_rid(), true); feature_profile_manager->notify_changed(); @@ -5530,12 +5530,12 @@ EditorNode::EditorNode() { InputFilter::get_singleton()->set_use_accumulated_input(true); Resource::_get_local_scene_func = _resource_get_edited_scene; - VisualServer::get_singleton()->set_debug_generate_wireframes(true); + RenderingServer::get_singleton()->set_debug_generate_wireframes(true); - NavigationServer::get_singleton()->set_active(false); // no nav by default if editor + NavigationServer3D::get_singleton()->set_active(false); // no nav by default if editor - PhysicsServer::get_singleton()->set_active(false); // no physics by default if editor - Physics2DServer::get_singleton()->set_active(false); // no physics by default if editor + PhysicsServer3D::get_singleton()->set_active(false); // no physics by default if editor + PhysicsServer2D::get_singleton()->set_active(false); // no physics by default if editor ScriptServer::set_scripting_enabled(false); // no scripting by default if editor EditorHelp::generate_doc(); //before any editor classes are created @@ -6011,7 +6011,7 @@ EditorNode::EditorNode() { scene_root = memnew(SubViewport); //scene_root->set_usage(Viewport::USAGE_2D); canvas BG mode prevents usage of this as 2D - VisualServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_hide_scenario(scene_root->get_viewport_rid(), true); scene_root->set_disable_input(true); scene_root->set_as_audio_listener_2d(true); diff --git a/editor/editor_plugin.cpp b/editor/editor_plugin.cpp index 2cafbe3cca..8faaabc1fb 100644 --- a/editor/editor_plugin.cpp +++ b/editor/editor_plugin.cpp @@ -41,7 +41,7 @@ #include "plugins/node_3d_editor_plugin.h" #include "scene/3d/camera_3d.h" #include "scene/gui/popup_menu.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" Array EditorInterface::_make_mesh_previews(const Array &p_meshes, int p_preview_size) { @@ -64,25 +64,25 @@ Vector> EditorInterface::make_mesh_previews(const Vectorscenario_create(); + RID scenario = RS::get_singleton()->scenario_create(); - RID viewport = VS::get_singleton()->viewport_create(); - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ALWAYS); - VS::get_singleton()->viewport_set_scenario(viewport, scenario); - VS::get_singleton()->viewport_set_size(viewport, size, size); - VS::get_singleton()->viewport_set_transparent_background(viewport, true); - VS::get_singleton()->viewport_set_active(viewport, true); - RID viewport_texture = VS::get_singleton()->viewport_get_texture(viewport); + RID viewport = RS::get_singleton()->viewport_create(); + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ALWAYS); + RS::get_singleton()->viewport_set_scenario(viewport, scenario); + RS::get_singleton()->viewport_set_size(viewport, size, size); + RS::get_singleton()->viewport_set_transparent_background(viewport, true); + RS::get_singleton()->viewport_set_active(viewport, true); + RID viewport_texture = RS::get_singleton()->viewport_get_texture(viewport); - RID camera = VS::get_singleton()->camera_create(); - VS::get_singleton()->viewport_attach_camera(viewport, camera); + RID camera = RS::get_singleton()->camera_create(); + RS::get_singleton()->viewport_attach_camera(viewport, camera); - RID light = VS::get_singleton()->directional_light_create(); - RID light_instance = VS::get_singleton()->instance_create2(light, scenario); + RID light = RS::get_singleton()->directional_light_create(); + RID light_instance = RS::get_singleton()->instance_create2(light, scenario); - RID light2 = VS::get_singleton()->directional_light_create(); - VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); - RID light_instance2 = VS::get_singleton()->instance_create2(light2, scenario); + RID light2 = RS::get_singleton()->directional_light_create(); + RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); + RID light_instance2 = RS::get_singleton()->instance_create2(light2, scenario); EditorProgress ep("mlib", TTR("Creating Mesh Previews"), p_meshes.size()); @@ -101,8 +101,8 @@ Vector> EditorInterface::make_mesh_previews(const Vectorinstance_create2(mesh->get_rid(), scenario); - VS::get_singleton()->instance_set_transform(inst, mesh_xform); + RID inst = RS::get_singleton()->instance_create2(mesh->get_rid(), scenario); + RS::get_singleton()->instance_set_transform(inst, mesh_xform); AABB aabb = mesh->get_aabb(); Vector3 ofs = aabb.position + aabb.size * 0.5; @@ -121,32 +121,32 @@ Vector> EditorInterface::make_mesh_previews(const Vectorcamera_set_transform(camera, xform * Transform(Basis(), Vector3(0, 0, 3))); - VS::get_singleton()->camera_set_orthogonal(camera, m * 2, 0.01, 1000.0); + RS::get_singleton()->camera_set_transform(camera, xform * Transform(Basis(), Vector3(0, 0, 3))); + RS::get_singleton()->camera_set_orthogonal(camera, m * 2, 0.01, 1000.0); - VS::get_singleton()->instance_set_transform(light_instance, xform * Transform().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0))); - VS::get_singleton()->instance_set_transform(light_instance2, xform * Transform().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0))); + RS::get_singleton()->instance_set_transform(light_instance, xform * Transform().looking_at(Vector3(-2, -1, -1), Vector3(0, 1, 0))); + RS::get_singleton()->instance_set_transform(light_instance2, xform * Transform().looking_at(Vector3(+1, -1, -2), Vector3(0, 1, 0))); ep.step(TTR("Thumbnail..."), i); Main::iteration(); Main::iteration(); - Ref img = VS::get_singleton()->texture_2d_get(viewport_texture); + Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); ERR_CONTINUE(!img.is_valid() || img->empty()); Ref it(memnew(ImageTexture)); it->create_from_image(img); - VS::get_singleton()->free(inst); + RS::get_singleton()->free(inst); textures.push_back(it); } - VS::get_singleton()->free(viewport); - VS::get_singleton()->free(light); - VS::get_singleton()->free(light_instance); - VS::get_singleton()->free(light2); - VS::get_singleton()->free(light_instance2); - VS::get_singleton()->free(camera); - VS::get_singleton()->free(scenario); + RS::get_singleton()->free(viewport); + RS::get_singleton()->free(light); + RS::get_singleton()->free(light_instance); + RS::get_singleton()->free(light2); + RS::get_singleton()->free(light_instance2); + RS::get_singleton()->free(camera); + RS::get_singleton()->free(scenario); return textures; } diff --git a/editor/editor_resource_preview.cpp b/editor/editor_resource_preview.cpp index 398850f2d6..4db8fb98f1 100644 --- a/editor/editor_resource_preview.cpp +++ b/editor/editor_resource_preview.cpp @@ -465,7 +465,7 @@ void EditorResourcePreview::stop() { preview_sem.post(); while (!exited) { OS::get_singleton()->delay_usec(10000); - VisualServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server + RenderingServer::get_singleton()->sync(); //sync pending stuff, as thread may be blocked on visual server } Thread::wait_to_finish(thread); memdelete(thread); diff --git a/editor/import/editor_import_collada.cpp b/editor/import/editor_import_collada.cpp index e67dd37b88..6c089d7020 100644 --- a/editor/import/editor_import_collada.cpp +++ b/editor/import/editor_import_collada.cpp @@ -922,10 +922,10 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref &p_me if (has_weights) { Vector weights; Vector bones; - weights.resize(VS::ARRAY_WEIGHTS_SIZE); - bones.resize(VS::ARRAY_WEIGHTS_SIZE); + weights.resize(RS::ARRAY_WEIGHTS_SIZE); + bones.resize(RS::ARRAY_WEIGHTS_SIZE); //float sum=0.0; - for (int l = 0; l < VS::ARRAY_WEIGHTS_SIZE; l++) { + for (int l = 0; l < RS::ARRAY_WEIGHTS_SIZE; l++) { if (l < vertex_array[k].weights.size()) { weights.write[l] = vertex_array[k].weights[l].weight; bones.write[l] = vertex_array[k].weights[l].bone_idx; @@ -963,7 +963,7 @@ Error ColladaImport::_create_mesh_surfaces(bool p_optimize, Ref &p_me //////////////////////////// Array d = surftool->commit_to_arrays(); - d.resize(VS::ARRAY_MAX); + d.resize(RS::ARRAY_MAX); Array mr; diff --git a/editor/import/resource_importer_texture.cpp b/editor/import/resource_importer_texture.cpp index 0090d30b9c..c218697423 100644 --- a/editor/import/resource_importer_texture.cpp +++ b/editor/import/resource_importer_texture.cpp @@ -36,7 +36,7 @@ #include "editor/editor_file_system.h" #include "editor/editor_node.h" -void ResourceImporterTexture::_texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, VS::TextureDetectRoughnessChannel p_channel) { +void ResourceImporterTexture::_texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_channel) { MutexLock lock(singleton->mutex); diff --git a/editor/import/resource_importer_texture.h b/editor/import/resource_importer_texture.h index ed0fe1be89..5f5fb75585 100644 --- a/editor/import/resource_importer_texture.h +++ b/editor/import/resource_importer_texture.h @@ -35,7 +35,7 @@ #include "core/io/resource_importer.h" #include "core/os/file_access.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class StreamTexture; @@ -63,16 +63,16 @@ protected: int flags; String normal_path_for_roughness; - VS::TextureDetectRoughnessChannel channel_for_roughness; + RS::TextureDetectRoughnessChannel channel_for_roughness; MakeInfo() { flags = 0; - channel_for_roughness = VS::TEXTURE_DETECT_ROUGNHESS_R; + channel_for_roughness = RS::TEXTURE_DETECT_ROUGNHESS_R; } }; Map make_flags; - static void _texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, VisualServer::TextureDetectRoughnessChannel p_channel); + static void _texture_reimport_roughness(const Ref &p_tex, const String &p_normal_path, RenderingServer::TextureDetectRoughnessChannel p_channel); static void _texture_reimport_3d(const Ref &p_tex); static void _texture_reimport_normal(const Ref &p_tex); diff --git a/editor/node_3d_editor_gizmos.cpp b/editor/node_3d_editor_gizmos.cpp index 67f0d991bd..40c17a9fc3 100644 --- a/editor/node_3d_editor_gizmos.cpp +++ b/editor/node_3d_editor_gizmos.cpp @@ -86,7 +86,7 @@ void EditorNode3DGizmo::clear() { for (int i = 0; i < instances.size(); i++) { if (instances[i].instance.is_valid()) - VS::get_singleton()->free(instances[i].instance); + RS::get_singleton()->free(instances[i].instance); } billboard_handle = false; @@ -168,16 +168,16 @@ void EditorNode3DGizmo::set_spatial_node(Node3D *p_node) { void EditorNode3DGizmo::Instance::create_instance(Node3D *p_base, bool p_hidden) { - instance = VS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); - VS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id()); + instance = RS::get_singleton()->instance_create2(mesh->get_rid(), p_base->get_world()->get_scenario()); + RS::get_singleton()->instance_attach_object_instance_id(instance, p_base->get_instance_id()); if (skin_reference.is_valid()) { - VS::get_singleton()->instance_attach_skeleton(instance, skin_reference->get_skeleton()); + RS::get_singleton()->instance_attach_skeleton(instance, skin_reference->get_skeleton()); } if (extra_margin) - VS::get_singleton()->instance_set_extra_visibility_margin(instance, 1); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, VS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_extra_visibility_margin(instance, 1); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(instance, RS::SHADOW_CASTING_SETTING_OFF); int layer = p_hidden ? 0 : 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER; - VS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26 + RS::get_singleton()->instance_set_layer_mask(instance, layer); //gizmos are 26 } void EditorNode3DGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, const Ref &p_skin_reference, const Ref &p_material) { @@ -191,9 +191,9 @@ void EditorNode3DGizmo::add_mesh(const Ref &p_mesh, bool p_billboard, ins.material = p_material; if (valid) { ins.create_instance(spatial_node, hidden); - VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); + RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); if (ins.material.is_valid()) { - VS::get_singleton()->instance_geometry_set_material_override(ins.instance, p_material->get_rid()); + RS::get_singleton()->instance_geometry_set_material_override(ins.instance, p_material->get_rid()); } } @@ -246,7 +246,7 @@ void EditorNode3DGizmo::add_lines(const Vector &p_lines, const Refinstance_set_transform(ins.instance, spatial_node->get_global_transform()); + RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } instances.push_back(ins); @@ -310,7 +310,7 @@ void EditorNode3DGizmo::add_unscaled_billboard(const Ref &p_material, ins.billboard = true; if (valid) { ins.create_instance(spatial_node, hidden); - VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); + RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } selectable_icon_size = p_scale; @@ -346,8 +346,8 @@ void EditorNode3DGizmo::add_handles(const Vector &p_handles, const Ref< Ref mesh = memnew(ArrayMesh); Array a; - a.resize(VS::ARRAY_MAX); - a[VS::ARRAY_VERTEX] = p_handles; + a.resize(RS::ARRAY_MAX); + a[RS::ARRAY_VERTEX] = p_handles; Vector colors; { colors.resize(p_handles.size()); @@ -364,7 +364,7 @@ void EditorNode3DGizmo::add_handles(const Vector &p_handles, const Ref< w[i] = col; } } - a[VS::ARRAY_COLOR] = colors; + a[RS::ARRAY_COLOR] = colors; mesh->add_surface_from_arrays(Mesh::PRIMITIVE_POINTS, a); mesh->surface_set_material(0, p_material); @@ -384,7 +384,7 @@ void EditorNode3DGizmo::add_handles(const Vector &p_handles, const Ref< ins.extra_margin = true; if (valid) { ins.create_instance(spatial_node, hidden); - VS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); + RS::get_singleton()->instance_set_transform(ins.instance, spatial_node->get_global_transform()); } instances.push_back(ins); if (!p_secondary) { @@ -410,14 +410,14 @@ void EditorNode3DGizmo::add_solid_box(Ref &p_material, Vector3 p_size, cubem.set_size(p_size); Array arrays = cubem.surface_get_arrays(0); - PackedVector3Array vertex = arrays[VS::ARRAY_VERTEX]; + PackedVector3Array vertex = arrays[RS::ARRAY_VERTEX]; Vector3 *w = vertex.ptrw(); for (int i = 0; i < vertex.size(); ++i) { w[i] += p_position; } - arrays[VS::ARRAY_VERTEX] = vertex; + arrays[RS::ARRAY_VERTEX] = vertex; Ref m = memnew(ArrayMesh); m->add_surface_from_arrays(cubem.surface_get_primitive_type(0), arrays); @@ -708,7 +708,7 @@ void EditorNode3DGizmo::transform() { ERR_FAIL_COND(!spatial_node); ERR_FAIL_COND(!valid); for (int i = 0; i < instances.size(); i++) { - VS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform()); + RS::get_singleton()->instance_set_transform(instances[i].instance, spatial_node->get_global_transform()); } } @@ -720,7 +720,7 @@ void EditorNode3DGizmo::free() { for (int i = 0; i < instances.size(); i++) { if (instances[i].instance.is_valid()) - VS::get_singleton()->free(instances[i].instance); + RS::get_singleton()->free(instances[i].instance); instances.write[i].instance = RID(); } @@ -733,7 +733,7 @@ void EditorNode3DGizmo::set_hidden(bool p_hidden) { hidden = p_hidden; int layer = hidden ? 0 : 1 << Node3DEditorViewport::GIZMO_EDIT_LAYER; for (int i = 0; i < instances.size(); ++i) { - VS::get_singleton()->instance_set_layer_mask(instances[i].instance, layer); + RS::get_singleton()->instance_set_layer_mask(instances[i].instance, layer); } } @@ -1585,7 +1585,7 @@ Position3DNode3DGizmoPlugin::Position3DNode3DGizmoPlugin() { mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); Array d; - d.resize(VS::ARRAY_MAX); + d.resize(RS::ARRAY_MAX); d[Mesh::ARRAY_VERTEX] = cursor_points; d[Mesh::ARRAY_COLOR] = cursor_colors; pos3d_mesh->add_surface_from_arrays(Mesh::PRIMITIVE_LINES, d); diff --git a/editor/plugins/animation_player_editor_plugin.cpp b/editor/plugins/animation_player_editor_plugin.cpp index 41af2ab0cc..0b0f93bcb5 100644 --- a/editor/plugins/animation_player_editor_plugin.cpp +++ b/editor/plugins/animation_player_editor_plugin.cpp @@ -41,7 +41,7 @@ #include "editor/plugins/canvas_item_editor_plugin.h" // For onion skinning. #include "editor/plugins/node_3d_editor_plugin.h" // For onion skinning. #include "scene/main/window.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void AnimationPlayerEditor::_node_removed(Node *p_node) { @@ -947,8 +947,8 @@ void AnimationPlayerEditor::forward_canvas_force_draw_over_viewport(Control *p_o alpha += alpha_step; if (onion.captures_valid[cidx]) { - VS::get_singleton()->canvas_item_add_texture_rect_region( - ci, dst_rect, VS::get_singleton()->viewport_get_texture(onion.captures[cidx]), src_rect, Color(1, 1, 1, alpha)); + RS::get_singleton()->canvas_item_add_texture_rect_region( + ci, dst_rect, RS::get_singleton()->viewport_get_texture(onion.captures[cidx]), src_rect, Color(1, 1, 1, alpha)); } cidx++; @@ -961,8 +961,8 @@ void AnimationPlayerEditor::forward_canvas_force_draw_over_viewport(Control *p_o alpha -= alpha_step; if (onion.captures_valid[cidx]) { - VS::get_singleton()->canvas_item_add_texture_rect_region( - ci, dst_rect, VS::get_singleton()->viewport_get_texture(onion.captures[cidx]), src_rect, Color(1, 1, 1, alpha)); + RS::get_singleton()->canvas_item_add_texture_rect_region( + ci, dst_rect, RS::get_singleton()->viewport_get_texture(onion.captures[cidx]), src_rect, Color(1, 1, 1, alpha)); } cidx++; @@ -1318,17 +1318,17 @@ void AnimationPlayerEditor::_allocate_onion_layers() { bool is_present = onion.differences_only && i == captures - 1; // Each capture is a viewport with a canvas item attached that renders a full-size rect with the contents of the main viewport. - onion.captures.write[i] = VS::get_singleton()->viewport_create(); + onion.captures.write[i] = RS::get_singleton()->viewport_create(); - VS::get_singleton()->viewport_set_size(onion.captures[i], capture_size.width, capture_size.height); - VS::get_singleton()->viewport_set_update_mode(onion.captures[i], VS::VIEWPORT_UPDATE_ALWAYS); - VS::get_singleton()->viewport_set_transparent_background(onion.captures[i], !is_present); - VS::get_singleton()->viewport_attach_canvas(onion.captures[i], onion.capture.canvas); + RS::get_singleton()->viewport_set_size(onion.captures[i], capture_size.width, capture_size.height); + RS::get_singleton()->viewport_set_update_mode(onion.captures[i], RS::VIEWPORT_UPDATE_ALWAYS); + RS::get_singleton()->viewport_set_transparent_background(onion.captures[i], !is_present); + RS::get_singleton()->viewport_attach_canvas(onion.captures[i], onion.capture.canvas); } // Reset the capture canvas item to the current root viewport texture (defensive). - VS::get_singleton()->canvas_item_clear(onion.capture.canvas_item); - VS::get_singleton()->canvas_item_add_texture_rect(onion.capture.canvas_item, Rect2(Point2(), capture_size), get_tree()->get_root()->get_texture()->get_rid()); + RS::get_singleton()->canvas_item_clear(onion.capture.canvas_item); + RS::get_singleton()->canvas_item_add_texture_rect(onion.capture.canvas_item, Rect2(Point2(), capture_size), get_tree()->get_root()->get_texture()->get_rid()); onion.capture_size = capture_size; } @@ -1337,7 +1337,7 @@ void AnimationPlayerEditor::_free_onion_layers() { for (int i = 0; i < onion.captures.size(); i++) { if (onion.captures[i].is_valid()) { - VS::get_singleton()->free(onion.captures[i]); + RS::get_singleton()->free(onion.captures[i]); } } onion.captures.clear(); @@ -1421,18 +1421,18 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { // Tweak the root viewport to ensure it's rendered before our target. RID root_vp = get_tree()->get_root()->get_viewport_rid(); Rect2 root_vp_screen_rect = Rect2(Vector2(), get_tree()->get_root()->get_size()); - VS::get_singleton()->viewport_attach_to_screen(root_vp, Rect2()); - VS::get_singleton()->viewport_set_update_mode(root_vp, VS::VIEWPORT_UPDATE_ALWAYS); + RS::get_singleton()->viewport_attach_to_screen(root_vp, Rect2()); + RS::get_singleton()->viewport_set_update_mode(root_vp, RS::VIEWPORT_UPDATE_ALWAYS); RID present_rid; if (onion.differences_only) { // Capture present scene as it is. - VS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, RID()); + RS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, RID()); present_rid = onion.captures[onion.captures.size() - 1]; - VS::get_singleton()->viewport_set_active(present_rid, true); - VS::get_singleton()->viewport_set_parent_viewport(root_vp, present_rid); - VS::get_singleton()->draw(false); - VS::get_singleton()->viewport_set_active(present_rid, false); + RS::get_singleton()->viewport_set_active(present_rid, true); + RS::get_singleton()->viewport_set_parent_viewport(root_vp, present_rid); + RS::get_singleton()->draw(false); + RS::get_singleton()->viewport_set_active(present_rid, false); } // Backup current animation state. @@ -1441,10 +1441,10 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { // Render every past/future step with the capture shader. - VS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, onion.capture.material->get_rid()); + RS::get_singleton()->canvas_item_set_material(onion.capture.canvas_item, onion.capture.material->get_rid()); onion.capture.material->set_shader_param("bkg_color", GLOBAL_GET("rendering/environment/default_clear_color")); onion.capture.material->set_shader_param("differences_only", onion.differences_only); - onion.capture.material->set_shader_param("present", onion.differences_only ? VS::get_singleton()->viewport_get_texture(present_rid) : RID()); + onion.capture.material->set_shader_param("present", onion.differences_only ? RS::get_singleton()->viewport_get_texture(present_rid) : RID()); int step_off_a = onion.past ? -onion.steps : 0; int step_off_b = onion.future ? onion.steps : 0; @@ -1468,19 +1468,19 @@ void AnimationPlayerEditor::_prepare_onion_layers_2() { get_tree()->flush_transform_notifications(); // Needed for transforms of Node3Ds. values_backup.update_skeletons(); // Needed for Skeletons (2D & 3D). - VS::get_singleton()->viewport_set_active(onion.captures[cidx], true); - VS::get_singleton()->viewport_set_parent_viewport(root_vp, onion.captures[cidx]); - VS::get_singleton()->draw(false); - VS::get_singleton()->viewport_set_active(onion.captures[cidx], false); + RS::get_singleton()->viewport_set_active(onion.captures[cidx], true); + RS::get_singleton()->viewport_set_parent_viewport(root_vp, onion.captures[cidx]); + RS::get_singleton()->draw(false); + RS::get_singleton()->viewport_set_active(onion.captures[cidx], false); } cidx++; } // Restore root viewport. - VS::get_singleton()->viewport_set_parent_viewport(root_vp, RID()); - VS::get_singleton()->viewport_attach_to_screen(root_vp, root_vp_screen_rect); - VS::get_singleton()->viewport_set_update_mode(root_vp, VS::VIEWPORT_UPDATE_WHEN_VISIBLE); + RS::get_singleton()->viewport_set_parent_viewport(root_vp, RID()); + RS::get_singleton()->viewport_attach_to_screen(root_vp, root_vp_screen_rect); + RS::get_singleton()->viewport_set_update_mode(root_vp, RS::VIEWPORT_UPDATE_WHEN_VISIBLE); // Restore animation state // (Seeking with update=true wouldn't do the trick because the current value of the properties @@ -1764,9 +1764,9 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay onion.last_frame = 0; onion.can_overlay = false; onion.capture_size = Size2(); - onion.capture.canvas = VS::get_singleton()->canvas_create(); - onion.capture.canvas_item = VS::get_singleton()->canvas_item_create(); - VS::get_singleton()->canvas_item_set_parent(onion.capture.canvas_item, onion.capture.canvas); + onion.capture.canvas = RS::get_singleton()->canvas_create(); + onion.capture.canvas_item = RS::get_singleton()->canvas_item_create(); + RS::get_singleton()->canvas_item_set_parent(onion.capture.canvas_item, onion.capture.canvas); onion.capture.material = Ref(memnew(ShaderMaterial)); @@ -1792,14 +1792,14 @@ AnimationPlayerEditor::AnimationPlayerEditor(EditorNode *p_editor, AnimationPlay COLOR = vec4(capture_samp.rgb * dir_color.rgb, bkg_mask * diff_mask); \ } \ "); - VS::get_singleton()->material_set_shader(onion.capture.material->get_rid(), onion.capture.shader->get_rid()); + RS::get_singleton()->material_set_shader(onion.capture.material->get_rid(), onion.capture.shader->get_rid()); } AnimationPlayerEditor::~AnimationPlayerEditor() { _free_onion_layers(); - VS::get_singleton()->free(onion.capture.canvas); - VS::get_singleton()->free(onion.capture.canvas_item); + RS::get_singleton()->free(onion.capture.canvas); + RS::get_singleton()->free(onion.capture.canvas_item); } void AnimationPlayerEditorPlugin::_notification(int p_what) { diff --git a/editor/plugins/audio_stream_editor_plugin.cpp b/editor/plugins/audio_stream_editor_plugin.cpp index 6cffda49d0..0459ac7618 100644 --- a/editor/plugins/audio_stream_editor_plugin.cpp +++ b/editor/plugins/audio_stream_editor_plugin.cpp @@ -89,7 +89,7 @@ void AudioStreamEditor::_draw_preview() { Vector color; color.push_back(get_theme_color("contrast_color_2", "Editor")); - VS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color); + RS::get_singleton()->canvas_item_add_multiline(_preview->get_canvas_item(), lines, color); } void AudioStreamEditor::_preview_changed(ObjectID p_which) { diff --git a/editor/plugins/canvas_item_editor_plugin.cpp b/editor/plugins/canvas_item_editor_plugin.cpp index ba9cba5515..c7ddcd5e46 100644 --- a/editor/plugins/canvas_item_editor_plugin.cpp +++ b/editor/plugins/canvas_item_editor_plugin.cpp @@ -3427,7 +3427,7 @@ void CanvasItemEditor::_draw_straight_line(Point2 p_from, Point2 p_to, Color p_c } } if (points.size() >= 2) { - VisualServer::get_singleton()->canvas_item_add_line(ci, points[0], points[1], p_color); + RenderingServer::get_singleton()->canvas_item_add_line(ci, points[0], points[1], p_color); } } @@ -3455,7 +3455,7 @@ void CanvasItemEditor::_draw_axis() { }; for (int i = 0; i < 4; i++) { - VisualServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color); + RenderingServer::get_singleton()->canvas_item_add_line(ci, screen_endpoints[i], screen_endpoints[(i + 1) % 4], area_axis_color); } } } @@ -3512,8 +3512,8 @@ void CanvasItemEditor::_draw_bones() { outline_colors.push_back(bone_outline_color); } - VisualServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors); - VisualServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector(), RID()); + RenderingServer::get_singleton()->canvas_item_add_polygon(ci, bone_shape_outline, outline_colors); + RenderingServer::get_singleton()->canvas_item_add_primitive(ci, bone_shape, colors, Vector(), RID()); } } } @@ -3744,7 +3744,7 @@ void CanvasItemEditor::_draw_viewport() { } RID ci = viewport->get_canvas_item(); - VisualServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); + RenderingServer::get_singleton()->canvas_item_add_set_transform(ci, Transform2D()); EditorPluginList *over_plugin_list = editor->get_editor_plugins_over(); if (!over_plugin_list->empty()) { @@ -4911,7 +4911,7 @@ void CanvasItemEditor::_popup_callback(int p_op) { bool preview = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE)); preview = !preview; - VS::get_singleton()->canvas_set_disable_scale(!preview); + RS::get_singleton()->canvas_set_disable_scale(!preview); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(PREVIEW_CANVAS_SCALE), preview); } break; @@ -5818,13 +5818,13 @@ void CanvasItemEditorPlugin::make_visible(bool p_visible) { if (p_visible) { canvas_item_editor->show(); canvas_item_editor->set_physics_process(true); - VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false); + RenderingServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), false); } else { canvas_item_editor->hide(); canvas_item_editor->set_physics_process(false); - VisualServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), true); + RenderingServer::get_singleton()->viewport_set_hide_canvas(editor->get_scene_root()->get_viewport_rid(), true); } } @@ -6307,7 +6307,7 @@ CanvasItemEditorViewport::CanvasItemEditorViewport(EditorNode *p_node, CanvasIte label_desc->hide(); canvas_item_editor->get_controls_container()->add_child(label_desc); - VS::get_singleton()->canvas_set_disable_scale(true); + RS::get_singleton()->canvas_set_disable_scale(true); } CanvasItemEditorViewport::~CanvasItemEditorViewport() { diff --git a/editor/plugins/editor_preview_plugins.cpp b/editor/plugins/editor_preview_plugins.cpp index 3c173ab783..a8c4bddccf 100644 --- a/editor/plugins/editor_preview_plugins.cpp +++ b/editor/plugins/editor_preview_plugins.cpp @@ -328,19 +328,19 @@ Ref EditorMaterialPreviewPlugin::generate(const RES &p_from, const Si if (material->get_shader_mode() == Shader::MODE_SPATIAL) { - VS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid()); + RS::get_singleton()->mesh_surface_set_material(sphere, 0, material->get_rid()); - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture preview_done = false; - VS::get_singleton()->request_frame_drawn_callback(const_cast(this), "_preview_done", Variant()); + RS::get_singleton()->request_frame_drawn_callback(const_cast(this), "_preview_done", Variant()); while (!preview_done) { OS::get_singleton()->delay_usec(10); } - Ref img = VS::get_singleton()->texture_2d_get(viewport_texture); - VS::get_singleton()->mesh_surface_set_material(sphere, 0, RID()); + Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); + RS::get_singleton()->mesh_surface_set_material(sphere, 0, RID()); ERR_FAIL_COND_V(!img.is_valid(), Ref()); @@ -358,35 +358,35 @@ Ref EditorMaterialPreviewPlugin::generate(const RES &p_from, const Si EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() { - scenario = VS::get_singleton()->scenario_create(); + scenario = RS::get_singleton()->scenario_create(); - viewport = VS::get_singleton()->viewport_create(); - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED); - VS::get_singleton()->viewport_set_scenario(viewport, scenario); - VS::get_singleton()->viewport_set_size(viewport, 128, 128); - VS::get_singleton()->viewport_set_transparent_background(viewport, true); - VS::get_singleton()->viewport_set_active(viewport, true); - viewport_texture = VS::get_singleton()->viewport_get_texture(viewport); + viewport = RS::get_singleton()->viewport_create(); + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_scenario(viewport, scenario); + RS::get_singleton()->viewport_set_size(viewport, 128, 128); + RS::get_singleton()->viewport_set_transparent_background(viewport, true); + RS::get_singleton()->viewport_set_active(viewport, true); + viewport_texture = RS::get_singleton()->viewport_get_texture(viewport); - camera = VS::get_singleton()->camera_create(); - VS::get_singleton()->viewport_attach_camera(viewport, camera); - VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3))); - VS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10); + camera = RS::get_singleton()->camera_create(); + RS::get_singleton()->viewport_attach_camera(viewport, camera); + RS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3))); + RS::get_singleton()->camera_set_perspective(camera, 45, 0.1, 10); - light = VS::get_singleton()->directional_light_create(); - light_instance = VS::get_singleton()->instance_create2(light, scenario); - VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0))); + light = RS::get_singleton()->directional_light_create(); + light_instance = RS::get_singleton()->instance_create2(light, scenario); + RS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0))); - light2 = VS::get_singleton()->directional_light_create(); - VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); - //VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); + light2 = RS::get_singleton()->directional_light_create(); + RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); + //RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); - light_instance2 = VS::get_singleton()->instance_create2(light2, scenario); + light_instance2 = RS::get_singleton()->instance_create2(light2, scenario); - VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1))); + RS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1))); - sphere = VS::get_singleton()->mesh_create(); - sphere_instance = VS::get_singleton()->instance_create2(sphere, scenario); + sphere = RS::get_singleton()->mesh_create(); + sphere_instance = RS::get_singleton()->instance_create2(sphere, scenario); int lats = 32; int lons = 32; @@ -453,25 +453,25 @@ EditorMaterialPreviewPlugin::EditorMaterialPreviewPlugin() { } Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX] = vertices; - arr[VS::ARRAY_NORMAL] = normals; - arr[VS::ARRAY_TANGENT] = tangents; - arr[VS::ARRAY_TEX_UV] = uvs; - VS::get_singleton()->mesh_add_surface_from_arrays(sphere, VS::PRIMITIVE_TRIANGLES, arr); + arr.resize(RS::ARRAY_MAX); + arr[RS::ARRAY_VERTEX] = vertices; + arr[RS::ARRAY_NORMAL] = normals; + arr[RS::ARRAY_TANGENT] = tangents; + arr[RS::ARRAY_TEX_UV] = uvs; + RS::get_singleton()->mesh_add_surface_from_arrays(sphere, RS::PRIMITIVE_TRIANGLES, arr); } EditorMaterialPreviewPlugin::~EditorMaterialPreviewPlugin() { - VS::get_singleton()->free(sphere); - VS::get_singleton()->free(sphere_instance); - VS::get_singleton()->free(viewport); - VS::get_singleton()->free(light); - VS::get_singleton()->free(light_instance); - VS::get_singleton()->free(light2); - VS::get_singleton()->free(light_instance2); - VS::get_singleton()->free(camera); - VS::get_singleton()->free(scenario); + RS::get_singleton()->free(sphere); + RS::get_singleton()->free(sphere_instance); + RS::get_singleton()->free(viewport); + RS::get_singleton()->free(light); + RS::get_singleton()->free(light_instance); + RS::get_singleton()->free(light2); + RS::get_singleton()->free(light_instance2); + RS::get_singleton()->free(camera); + RS::get_singleton()->free(scenario); } /////////////////////////////////////////////////////////////////////////// @@ -706,7 +706,7 @@ Ref EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 Ref mesh = p_from; ERR_FAIL_COND_V(mesh.is_null(), Ref()); - VS::get_singleton()->instance_set_base(mesh_instance, mesh->get_rid()); + RS::get_singleton()->instance_set_base(mesh_instance, mesh->get_rid()); AABB aabb = mesh->get_aabb(); Vector3 ofs = aabb.position + aabb.size * 0.5; @@ -723,21 +723,21 @@ Ref EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 xform.basis.scale(Vector3(m, m, m)); xform.origin = -xform.basis.xform(ofs); //-ofs*m; xform.origin.z -= rot_aabb.size.z * 2; - VS::get_singleton()->instance_set_transform(mesh_instance, xform); + RS::get_singleton()->instance_set_transform(mesh_instance, xform); - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture preview_done = false; - VS::get_singleton()->request_frame_drawn_callback(const_cast(this), "_preview_done", Variant()); + RS::get_singleton()->request_frame_drawn_callback(const_cast(this), "_preview_done", Variant()); while (!preview_done) { OS::get_singleton()->delay_usec(10); } - Ref img = VS::get_singleton()->texture_2d_get(viewport_texture); + Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); ERR_FAIL_COND_V(img.is_null(), Ref()); - VS::get_singleton()->instance_set_base(mesh_instance, RID()); + RS::get_singleton()->instance_set_base(mesh_instance, RID()); img->convert(Image::FORMAT_RGBA8); @@ -759,49 +759,49 @@ Ref EditorMeshPreviewPlugin::generate(const RES &p_from, const Size2 EditorMeshPreviewPlugin::EditorMeshPreviewPlugin() { - scenario = VS::get_singleton()->scenario_create(); + scenario = RS::get_singleton()->scenario_create(); - viewport = VS::get_singleton()->viewport_create(); - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED); - VS::get_singleton()->viewport_set_scenario(viewport, scenario); - VS::get_singleton()->viewport_set_size(viewport, 128, 128); - VS::get_singleton()->viewport_set_transparent_background(viewport, true); - VS::get_singleton()->viewport_set_active(viewport, true); - viewport_texture = VS::get_singleton()->viewport_get_texture(viewport); + viewport = RS::get_singleton()->viewport_create(); + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_scenario(viewport, scenario); + RS::get_singleton()->viewport_set_size(viewport, 128, 128); + RS::get_singleton()->viewport_set_transparent_background(viewport, true); + RS::get_singleton()->viewport_set_active(viewport, true); + viewport_texture = RS::get_singleton()->viewport_get_texture(viewport); - camera = VS::get_singleton()->camera_create(); - VS::get_singleton()->viewport_attach_camera(viewport, camera); - VS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3))); - //VS::get_singleton()->camera_set_perspective(camera,45,0.1,10); - VS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0); + camera = RS::get_singleton()->camera_create(); + RS::get_singleton()->viewport_attach_camera(viewport, camera); + RS::get_singleton()->camera_set_transform(camera, Transform(Basis(), Vector3(0, 0, 3))); + //RS::get_singleton()->camera_set_perspective(camera,45,0.1,10); + RS::get_singleton()->camera_set_orthogonal(camera, 1.0, 0.01, 1000.0); - light = VS::get_singleton()->directional_light_create(); - light_instance = VS::get_singleton()->instance_create2(light, scenario); - VS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0))); + light = RS::get_singleton()->directional_light_create(); + light_instance = RS::get_singleton()->instance_create2(light, scenario); + RS::get_singleton()->instance_set_transform(light_instance, Transform().looking_at(Vector3(-1, -1, -1), Vector3(0, 1, 0))); - light2 = VS::get_singleton()->directional_light_create(); - VS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); - //VS::get_singleton()->light_set_color(light2, VS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0)); - light_instance2 = VS::get_singleton()->instance_create2(light2, scenario); + light2 = RS::get_singleton()->directional_light_create(); + RS::get_singleton()->light_set_color(light2, Color(0.7, 0.7, 0.7)); + //RS::get_singleton()->light_set_color(light2, RS::LIGHT_COLOR_SPECULAR, Color(0.0, 0.0, 0.0)); + light_instance2 = RS::get_singleton()->instance_create2(light2, scenario); - VS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1))); + RS::get_singleton()->instance_set_transform(light_instance2, Transform().looking_at(Vector3(0, 1, 0), Vector3(0, 0, 1))); - //sphere = VS::get_singleton()->mesh_create(); - mesh_instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_scenario(mesh_instance, scenario); + //sphere = RS::get_singleton()->mesh_create(); + mesh_instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_scenario(mesh_instance, scenario); } EditorMeshPreviewPlugin::~EditorMeshPreviewPlugin() { - //VS::get_singleton()->free(sphere); - VS::get_singleton()->free(mesh_instance); - VS::get_singleton()->free(viewport); - VS::get_singleton()->free(light); - VS::get_singleton()->free(light_instance); - VS::get_singleton()->free(light2); - VS::get_singleton()->free(light_instance2); - VS::get_singleton()->free(camera); - VS::get_singleton()->free(scenario); + //RS::get_singleton()->free(sphere); + RS::get_singleton()->free(mesh_instance); + RS::get_singleton()->free(viewport); + RS::get_singleton()->free(light); + RS::get_singleton()->free(light_instance); + RS::get_singleton()->free(light2); + RS::get_singleton()->free(light_instance2); + RS::get_singleton()->free(camera); + RS::get_singleton()->free(scenario); } /////////////////////////////////////////////////////////////////////////// @@ -849,16 +849,16 @@ Ref EditorFontPreviewPlugin::generate_from_path(const String &p_path, font->draw(canvas_item, pos, sampled_text); preview_done = false; - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_ONCE); //once used for capture - VS::get_singleton()->request_frame_drawn_callback(const_cast(this), "_preview_done", Variant()); + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_ONCE); //once used for capture + RS::get_singleton()->request_frame_drawn_callback(const_cast(this), "_preview_done", Variant()); while (!preview_done) { OS::get_singleton()->delay_usec(10); } - VS::get_singleton()->canvas_item_clear(canvas_item); + RS::get_singleton()->canvas_item_clear(canvas_item); - Ref img = VS::get_singleton()->texture_2d_get(viewport_texture); + Ref img = RS::get_singleton()->texture_2d_get(viewport_texture); ERR_FAIL_COND_V(img.is_null(), Ref()); img->convert(Image::FORMAT_RGBA8); @@ -891,22 +891,22 @@ Ref EditorFontPreviewPlugin::generate(const RES &p_from, const Size2 EditorFontPreviewPlugin::EditorFontPreviewPlugin() { - viewport = VS::get_singleton()->viewport_create(); - VS::get_singleton()->viewport_set_update_mode(viewport, VS::VIEWPORT_UPDATE_DISABLED); - VS::get_singleton()->viewport_set_size(viewport, 128, 128); - VS::get_singleton()->viewport_set_active(viewport, true); - viewport_texture = VS::get_singleton()->viewport_get_texture(viewport); + viewport = RS::get_singleton()->viewport_create(); + RS::get_singleton()->viewport_set_update_mode(viewport, RS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_size(viewport, 128, 128); + RS::get_singleton()->viewport_set_active(viewport, true); + viewport_texture = RS::get_singleton()->viewport_get_texture(viewport); - canvas = VS::get_singleton()->canvas_create(); - canvas_item = VS::get_singleton()->canvas_item_create(); + canvas = RS::get_singleton()->canvas_create(); + canvas_item = RS::get_singleton()->canvas_item_create(); - VS::get_singleton()->viewport_attach_canvas(viewport, canvas); - VS::get_singleton()->canvas_item_set_parent(canvas_item, canvas); + RS::get_singleton()->viewport_attach_canvas(viewport, canvas); + RS::get_singleton()->canvas_item_set_parent(canvas_item, canvas); } EditorFontPreviewPlugin::~EditorFontPreviewPlugin() { - VS::get_singleton()->free(canvas_item); - VS::get_singleton()->free(canvas); - VS::get_singleton()->free(viewport); + RS::get_singleton()->free(canvas_item); + RS::get_singleton()->free(canvas); + RS::get_singleton()->free(viewport); } diff --git a/editor/plugins/material_editor_plugin.cpp b/editor/plugins/material_editor_plugin.cpp index 8129b9bd86..5623805201 100644 --- a/editor/plugins/material_editor_plugin.cpp +++ b/editor/plugins/material_editor_plugin.cpp @@ -256,14 +256,14 @@ Ref StandardMaterial3DConversionPlugin::convert(const Ref &p Ref shader; shader.instance(); - String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid()); + String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid()); shader->set_code(code); smat->set_shader(shader); List params; - VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); for (List::Element *E = params.front(); E; E = E->next()) { @@ -273,7 +273,7 @@ Ref StandardMaterial3DConversionPlugin::convert(const Ref &p if (texture.is_valid()) { smat->set_shader_param(E->get().name, texture); } else { - Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); + Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); smat->set_shader_param(E->get().name, value); } } @@ -302,17 +302,17 @@ Ref ParticlesMaterialConversionPlugin::convert(const Ref &p_ Ref shader; shader.instance(); - String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid()); + String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid()); shader->set_code(code); smat->set_shader(shader); List params; - VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); for (List::Element *E = params.front(); E; E = E->next()) { - Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); + Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); smat->set_shader_param(E->get().name, value); } @@ -340,17 +340,17 @@ Ref CanvasItemMaterialConversionPlugin::convert(const Ref &p Ref shader; shader.instance(); - String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid()); + String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid()); shader->set_code(code); smat->set_shader(shader); List params; - VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); for (List::Element *E = params.front(); E; E = E->next()) { - Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); + Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); smat->set_shader_param(E->get().name, value); } @@ -378,17 +378,17 @@ Ref ProceduralSkyMaterialConversionPlugin::convert(const Ref Ref shader; shader.instance(); - String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid()); + String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid()); shader->set_code(code); smat->set_shader(shader); List params; - VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); for (List::Element *E = params.front(); E; E = E->next()) { - Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); + Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); smat->set_shader_param(E->get().name, value); } @@ -416,17 +416,17 @@ Ref PanoramaSkyMaterialConversionPlugin::convert(const Ref & Ref shader; shader.instance(); - String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid()); + String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid()); shader->set_code(code); smat->set_shader(shader); List params; - VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); for (List::Element *E = params.front(); E; E = E->next()) { - Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); + Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); smat->set_shader_param(E->get().name, value); } @@ -454,17 +454,17 @@ Ref PhysicalSkyMaterialConversionPlugin::convert(const Ref & Ref shader; shader.instance(); - String code = VS::get_singleton()->shader_get_code(mat->get_shader_rid()); + String code = RS::get_singleton()->shader_get_code(mat->get_shader_rid()); shader->set_code(code); smat->set_shader(shader); List params; - VS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); + RS::get_singleton()->shader_get_param_list(mat->get_shader_rid(), ¶ms); for (List::Element *E = params.front(); E; E = E->next()) { - Variant value = VS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); + Variant value = RS::get_singleton()->material_get_param(mat->get_rid(), E->get().name); smat->set_shader_param(E->get().name, value); } diff --git a/editor/plugins/node_3d_editor_plugin.cpp b/editor/plugins/node_3d_editor_plugin.cpp index 07eaf3f63f..6f6d06b09d 100644 --- a/editor/plugins/node_3d_editor_plugin.cpp +++ b/editor/plugins/node_3d_editor_plugin.cpp @@ -496,7 +496,7 @@ ObjectID Node3DEditorViewport::_select_ray(const Point2 &p_pos, bool p_append, b Vector3 pos = _get_ray_pos(p_pos); Vector2 shrinked_pos = p_pos / viewport_container->get_stretch_shrink(); - Vector instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); + Vector instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); Set> found_gizmos; Node *edited_scene = get_tree()->get_edited_scene_root(); @@ -563,7 +563,7 @@ void Node3DEditorViewport::_find_items_at_pos(const Point2 &p_pos, bool &r_inclu Vector3 ray = _get_ray(p_pos); Vector3 pos = _get_ray_pos(p_pos); - Vector instances = VisualServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); + Vector instances = RenderingServer::get_singleton()->instances_cull_ray(pos, ray, get_tree()->get_root()->get_world()->get_scenario()); Set> found_gizmos; r_includes_current = false; @@ -686,7 +686,7 @@ void Node3DEditorViewport::_select_region() { frustum.push_back(far); } - Vector instances = VisualServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario()); + Vector instances = RenderingServer::get_singleton()->instances_cull_convex(frustum, get_tree()->get_root()->get_world()->get_scenario()); Vector selected; Node *edited_scene = get_tree()->get_edited_scene_root(); @@ -2395,7 +2395,7 @@ void Node3DEditorViewport::_notification(int p_what) { } previewing = cam; previewing->connect("tree_exited", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); - VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), cam->get_camera()); + RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), cam->get_camera()); surface->update(); } } @@ -2437,7 +2437,7 @@ void Node3DEditorViewport::_notification(int p_what) { aabb_s.scale(se->aabb.size); t.basis = t.basis * aabb_s; - VisualServer::get_singleton()->instance_set_transform(se->sbox_instance, t); + RenderingServer::get_singleton()->instance_set_transform(se->sbox_instance, t); } if (changed || (spatial_editor->is_gizmo_visible() && !exist)) { @@ -2643,7 +2643,7 @@ void Node3DEditorViewport::_draw() { if (_edit.mode == TRANSFORM_ROTATE) { Point2 center = _point_to_screen(_edit.center); - VisualServer::get_singleton()->canvas_item_add_line( + RenderingServer::get_singleton()->canvas_item_add_line( ci, _edit.mouse_pos, center, @@ -3082,51 +3082,51 @@ void Node3DEditorViewport::_init_gizmo_instance(int p_idx) { uint32_t layer = 1 << (GIZMO_BASE_LAYER + p_idx); for (int i = 0; i < 3; i++) { - move_gizmo_instance[i] = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(move_gizmo_instance[i], spatial_editor->get_move_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(move_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_visible(move_gizmo_instance[i], false); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i], layer); - - move_plane_gizmo_instance[i] = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(move_plane_gizmo_instance[i], spatial_editor->get_move_plane_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(move_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_plane_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(move_plane_gizmo_instance[i], layer); - - rotate_gizmo_instance[i] = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(rotate_gizmo_instance[i], spatial_editor->get_rotate_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], false); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer); - - scale_gizmo_instance[i] = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer); - - scale_plane_gizmo_instance[i] = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(scale_plane_gizmo_instance[i], spatial_editor->get_scale_plane_gizmo(i)->get_rid()); - VS::get_singleton()->instance_set_scenario(scale_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], false); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_plane_gizmo_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(scale_plane_gizmo_instance[i], layer); + move_gizmo_instance[i] = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(move_gizmo_instance[i], spatial_editor->get_move_gizmo(i)->get_rid()); + RS::get_singleton()->instance_set_scenario(move_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + RS::get_singleton()->instance_set_visible(move_gizmo_instance[i], false); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(move_gizmo_instance[i], layer); + + move_plane_gizmo_instance[i] = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(move_plane_gizmo_instance[i], spatial_editor->get_move_plane_gizmo(i)->get_rid()); + RS::get_singleton()->instance_set_scenario(move_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + RS::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(move_plane_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(move_plane_gizmo_instance[i], layer); + + rotate_gizmo_instance[i] = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(rotate_gizmo_instance[i], spatial_editor->get_rotate_gizmo(i)->get_rid()); + RS::get_singleton()->instance_set_scenario(rotate_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + RS::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], false); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(rotate_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(rotate_gizmo_instance[i], layer); + + scale_gizmo_instance[i] = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(scale_gizmo_instance[i], spatial_editor->get_scale_gizmo(i)->get_rid()); + RS::get_singleton()->instance_set_scenario(scale_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + RS::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(scale_gizmo_instance[i], layer); + + scale_plane_gizmo_instance[i] = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(scale_plane_gizmo_instance[i], spatial_editor->get_scale_plane_gizmo(i)->get_rid()); + RS::get_singleton()->instance_set_scenario(scale_plane_gizmo_instance[i], get_tree()->get_root()->get_world()->get_scenario()); + RS::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], false); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(scale_plane_gizmo_instance[i], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(scale_plane_gizmo_instance[i], layer); } } void Node3DEditorViewport::_finish_gizmo_instances() { for (int i = 0; i < 3; i++) { - VS::get_singleton()->free(move_gizmo_instance[i]); - VS::get_singleton()->free(move_plane_gizmo_instance[i]); - VS::get_singleton()->free(rotate_gizmo_instance[i]); - VS::get_singleton()->free(scale_gizmo_instance[i]); - VS::get_singleton()->free(scale_plane_gizmo_instance[i]); + RS::get_singleton()->free(move_gizmo_instance[i]); + RS::get_singleton()->free(move_plane_gizmo_instance[i]); + RS::get_singleton()->free(rotate_gizmo_instance[i]); + RS::get_singleton()->free(scale_gizmo_instance[i]); + RS::get_singleton()->free(scale_plane_gizmo_instance[i]); } } void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) { @@ -3138,7 +3138,7 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) { previewing->disconnect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); previewing = NULL; - VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore + RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore if (!preview) preview_camera->hide(); view_menu->set_disabled(false); @@ -3148,7 +3148,7 @@ void Node3DEditorViewport::_toggle_camera_preview(bool p_activate) { previewing = preview; previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); - VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace + RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), preview->get_camera()); //replace view_menu->set_disabled(true); surface->update(); } @@ -3161,7 +3161,7 @@ void Node3DEditorViewport::_toggle_cinema_preview(bool p_activate) { previewing->disconnect("tree_exited", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); previewing = NULL; - VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore + RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), camera->get_camera()); //restore preview_camera->set_pressed(false); if (!preview) { preview_camera->hide(); @@ -3212,11 +3212,11 @@ void Node3DEditorViewport::update_transform_gizmo_view() { if (xform.origin.distance_squared_to(camera_xform.origin) < 0.01) { for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], false); - VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false); - VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], false); - VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false); - VisualServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], false); } return; } @@ -3244,16 +3244,16 @@ void Node3DEditorViewport::update_transform_gizmo_view() { xform.basis.scale(scale); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); - VisualServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); - VisualServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); - VisualServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); - VisualServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], xform); - VisualServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); + RenderingServer::get_singleton()->instance_set_transform(move_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_visible(move_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); + RenderingServer::get_singleton()->instance_set_transform(move_plane_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_visible(move_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_MOVE)); + RenderingServer::get_singleton()->instance_set_transform(rotate_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_visible(rotate_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SELECT || spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_ROTATE)); + RenderingServer::get_singleton()->instance_set_transform(scale_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_visible(scale_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); + RenderingServer::get_singleton()->instance_set_transform(scale_plane_gizmo_instance[i], xform); + RenderingServer::get_singleton()->instance_set_visible(scale_plane_gizmo_instance[i], spatial_editor->is_gizmo_visible() && (spatial_editor->get_tool_mode() == Node3DEditor::TOOL_MODE_SCALE)); } } @@ -3363,7 +3363,7 @@ void Node3DEditorViewport::set_state(const Dictionary &p_state) { if (Object::cast_to(pv)) { previewing = Object::cast_to(pv); previewing->connect("tree_exiting", callable_mp(this, &Node3DEditorViewport::_preview_exited_scene)); - VS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), previewing->get_camera()); //replace + RS::get_singleton()->viewport_attach_camera(viewport->get_viewport_rid(), previewing->get_camera()); //replace view_menu->set_disabled(true); surface->update(); preview_camera->set_pressed(true); @@ -3478,7 +3478,7 @@ Vector3 Node3DEditorViewport::_get_instance_position(const Point2 &p_pos) const Vector3 world_ray = _get_ray(p_pos); Vector3 world_pos = _get_ray_pos(p_pos); - Vector instances = VisualServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario()); + Vector instances = RenderingServer::get_singleton()->instances_cull_ray(world_pos, world_ray, get_tree()->get_root()->get_world()->get_scenario()); Set> found_gizmos; float closest_dist = MAX_DISTANCE; @@ -4398,7 +4398,7 @@ Node3DEditor *Node3DEditor::singleton = NULL; Node3DEditorSelectedItem::~Node3DEditorSelectedItem() { if (sbox_instance.is_valid()) - VisualServer::get_singleton()->free(sbox_instance); + RenderingServer::get_singleton()->free(sbox_instance); } void Node3DEditor::select_gizmo_highlight_axis(int p_axis) { @@ -4484,8 +4484,8 @@ Object *Node3DEditor::_get_editor_data(Object *p_what) { Node3DEditorSelectedItem *si = memnew(Node3DEditorSelectedItem); si->sp = sp; - si->sbox_instance = VisualServer::get_singleton()->instance_create2(selection_box->get_rid(), sp->get_world()->get_scenario()); - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, VS::SHADOW_CASTING_SETTING_OFF); + si->sbox_instance = RenderingServer::get_singleton()->instance_create2(selection_box->get_rid(), sp->get_world()->get_scenario()); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(si->sbox_instance, RS::SHADOW_CASTING_SETTING_OFF); return si; } @@ -4649,7 +4649,7 @@ void Node3DEditor::set_state(const Dictionary &p_state) { if (use != view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN))) { view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), use); - VisualServer::get_singleton()->instance_set_visible(origin_instance, use); + RenderingServer::get_singleton()->instance_set_visible(origin_instance, use); } } @@ -4954,7 +4954,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { bool is_checked = view_menu->get_popup()->is_item_checked(view_menu->get_popup()->get_item_index(p_option)); origin_enabled = !is_checked; - VisualServer::get_singleton()->instance_set_visible(origin_instance, origin_enabled); + RenderingServer::get_singleton()->instance_set_visible(origin_instance, origin_enabled); // Update the grid since its appearance depends on whether the origin is enabled _finish_grid(); _init_grid(); @@ -4969,7 +4969,7 @@ void Node3DEditor::_menu_item_pressed(int p_option) { for (int i = 0; i < 3; ++i) { if (grid_enable[i]) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], grid_enabled); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], grid_enabled); grid_visible[i] = grid_enabled; } } @@ -5129,19 +5129,19 @@ void Node3DEditor::_init_indicators() { _init_grid(); - origin = VisualServer::get_singleton()->mesh_create(); + origin = RenderingServer::get_singleton()->mesh_create(); Array d; - d.resize(VS::ARRAY_MAX); - d[VisualServer::ARRAY_VERTEX] = origin_points; - d[VisualServer::ARRAY_COLOR] = origin_colors; + d.resize(RS::ARRAY_MAX); + d[RenderingServer::ARRAY_VERTEX] = origin_points; + d[RenderingServer::ARRAY_COLOR] = origin_colors; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(origin, VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat->get_rid()); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(origin, RenderingServer::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(origin, 0, indicator_mat->get_rid()); - origin_instance = VisualServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world()->get_scenario()); - VS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); + origin_instance = RenderingServer::get_singleton()->instance_create2(origin, get_tree()->get_root()->get_world()->get_scenario()); + RS::get_singleton()->instance_set_layer_mask(origin_instance, 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); - VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, VS::SHADOW_CASTING_SETTING_OFF); + RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(origin_instance, RS::SHADOW_CASTING_SETTING_OFF); } { @@ -5506,33 +5506,33 @@ void Node3DEditor::_init_grid() { grid_colors[i].push_back(line_color); } - grid[i] = VisualServer::get_singleton()->mesh_create(); + grid[i] = RenderingServer::get_singleton()->mesh_create(); Array d; - d.resize(VS::ARRAY_MAX); - d[VisualServer::ARRAY_VERTEX] = grid_points[i]; - d[VisualServer::ARRAY_COLOR] = grid_colors[i]; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); - grid_instance[i] = VisualServer::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); + d.resize(RS::ARRAY_MAX); + d[RenderingServer::ARRAY_VERTEX] = grid_points[i]; + d[RenderingServer::ARRAY_COLOR] = grid_colors[i]; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], RenderingServer::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); + grid_instance[i] = RenderingServer::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], grid_visible[i]); - VisualServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], VS::SHADOW_CASTING_SETTING_OFF); - VS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], grid_visible[i]); + RenderingServer::get_singleton()->instance_geometry_set_cast_shadows_setting(grid_instance[i], RS::SHADOW_CASTING_SETTING_OFF); + RS::get_singleton()->instance_set_layer_mask(grid_instance[i], 1 << Node3DEditorViewport::GIZMO_GRID_LAYER); } } void Node3DEditor::_finish_indicators() { - VisualServer::get_singleton()->free(origin_instance); - VisualServer::get_singleton()->free(origin); + RenderingServer::get_singleton()->free(origin_instance); + RenderingServer::get_singleton()->free(origin); _finish_grid(); } void Node3DEditor::_finish_grid() { for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->free(grid_instance[i]); - VisualServer::get_singleton()->free(grid[i]); + RenderingServer::get_singleton()->free(grid_instance[i]); + RenderingServer::get_singleton()->free(grid[i]); } } @@ -5658,8 +5658,8 @@ void Node3DEditor::snap_selected_nodes_to_floor() { } } - PhysicsDirectSpaceState *ss = get_tree()->get_root()->get_world()->get_direct_space_state(); - PhysicsDirectSpaceState::RayResult result; + PhysicsDirectSpaceState3D *ss = get_tree()->get_root()->get_world()->get_direct_space_state(); + PhysicsDirectSpaceState3D::RayResult result; Array keys = snap_data.keys(); @@ -5952,11 +5952,11 @@ void Node3DEditor::clear() { viewports[i]->reset(); } - VisualServer::get_singleton()->instance_set_visible(origin_instance, true); + RenderingServer::get_singleton()->instance_set_visible(origin_instance, true); view_menu->get_popup()->set_item_checked(view_menu->get_popup()->get_item_index(MENU_VIEW_ORIGIN), true); for (int i = 0; i < 3; ++i) { if (grid_enable[i]) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], true); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], true); grid_visible[i] = true; } } @@ -6313,7 +6313,7 @@ Node3DEditor::Node3DEditor(EditorNode *p_editor) { xform_dialog->connect("confirmed", callable_mp(this, &Node3DEditor::_xform_dialog_action)); - scenario_debug = VisualServer::SCENARIO_DEBUG_DISABLED; + scenario_debug = RenderingServer::SCENARIO_DEBUG_DISABLED; selected = NULL; diff --git a/editor/plugins/node_3d_editor_plugin.h b/editor/plugins/node_3d_editor_plugin.h index af6bc43b80..4b9f5a605b 100644 --- a/editor/plugins/node_3d_editor_plugin.h +++ b/editor/plugins/node_3d_editor_plugin.h @@ -578,7 +578,7 @@ private: ToolMode tool_mode; bool orthogonal; - VisualServer::ScenarioDebugMode scenario_debug; + RenderingServer::ScenarioDebugMode scenario_debug; RID origin; RID origin_instance; diff --git a/editor/plugins/polygon_2d_editor_plugin.cpp b/editor/plugins/polygon_2d_editor_plugin.cpp index 5a94c95dd7..f570baa885 100644 --- a/editor/plugins/polygon_2d_editor_plugin.cpp +++ b/editor/plugins/polygon_2d_editor_plugin.cpp @@ -990,9 +990,9 @@ void Polygon2DEditor::_uv_draw() { mtx.elements[2] = -uv_draw_ofs; mtx.scale_basis(Vector2(uv_draw_zoom, uv_draw_zoom)); - VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx); + RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), mtx); uv_edit_draw->draw_texture(base_tex, Point2()); - VS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D()); + RS::get_singleton()->canvas_item_add_set_transform(uv_edit_draw->get_canvas_item(), Transform2D()); if (snap_show_grid) { Color grid_color = Color(1.0, 1.0, 1.0, 0.15); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index c38bb09567..29ebfc8f7a 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -39,7 +39,7 @@ #include "editor/editor_settings.h" #include "editor/property_editor.h" #include "servers/display_server.h" -#include "servers/visual/shader_types.h" +#include "servers/rendering/shader_types.h" /*** SHADER SCRIPT EDITOR ****/ @@ -150,16 +150,16 @@ void ShaderTextEditor::_load_theme_settings() { if (shader.is_valid()) { - for (const Map::Element *E = ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())).front(); E; E = E->next()) { + for (const Map::Element *E = ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())).front(); E; E = E->next()) { for (const Map::Element *F = E->get().built_ins.front(); F; F = F->next()) { keywords.push_back(F->key()); } } - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())).size(); i++) { + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())).size(); i++) { - keywords.push_back(ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode()))[i]); + keywords.push_back(ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode()))[i]); } } @@ -200,7 +200,7 @@ void ShaderTextEditor::_code_complete_script(const String &p_code, Listget_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), r_options, calltip); + sl.complete(p_code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types(), r_options, calltip); get_text_edit()->set_code_hint(calltip); } @@ -215,7 +215,7 @@ void ShaderTextEditor::_validate_script() { ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types()); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader->get_mode())), ShaderTypes::get_singleton()->get_types()); if (err != OK) { String error_text = "error(" + itos(sl.get_error_line()) + "): " + sl.get_error_text(); diff --git a/editor/plugins/shader_editor_plugin.h b/editor/plugins/shader_editor_plugin.h index 900b40bd7a..f02ed590fc 100644 --- a/editor/plugins/shader_editor_plugin.h +++ b/editor/plugins/shader_editor_plugin.h @@ -39,7 +39,7 @@ #include "scene/gui/text_edit.h" #include "scene/main/timer.h" #include "scene/resources/shader.h" -#include "servers/visual/shader_language.h" +#include "servers/rendering/shader_language.h" class ShaderTextEditor : public CodeTextEditor { diff --git a/editor/plugins/texture_region_editor_plugin.cpp b/editor/plugins/texture_region_editor_plugin.cpp index 029159180c..d453598e33 100644 --- a/editor/plugins/texture_region_editor_plugin.cpp +++ b/editor/plugins/texture_region_editor_plugin.cpp @@ -68,9 +68,9 @@ void TextureRegionEditor::_region_draw() { mtx.elements[2] = -draw_ofs * draw_zoom; mtx.scale_basis(Vector2(draw_zoom, draw_zoom)); - VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), mtx); + RS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), mtx); edit_draw->draw_texture(base_tex, Point2()); - VS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), Transform2D()); + RS::get_singleton()->canvas_item_add_set_transform(edit_draw->get_canvas_item(), Transform2D()); if (snap_mode == SNAP_GRID) { Color grid_color = Color(1.0, 1.0, 1.0, 0.15); diff --git a/editor/plugins/tile_set_editor_plugin.cpp b/editor/plugins/tile_set_editor_plugin.cpp index f5ffcc1a28..f479139e4d 100644 --- a/editor/plugins/tile_set_editor_plugin.cpp +++ b/editor/plugins/tile_set_editor_plugin.cpp @@ -528,8 +528,8 @@ TileSetEditor::TileSetEditor(EditorNode *p_editor) { toolbar->add_child(spin_priority); spin_z_index = memnew(SpinBox); - spin_z_index->set_min(VS::CANVAS_ITEM_Z_MIN); - spin_z_index->set_max(VS::CANVAS_ITEM_Z_MAX); + spin_z_index->set_min(RS::CANVAS_ITEM_Z_MIN); + spin_z_index->set_max(RS::CANVAS_ITEM_Z_MAX); spin_z_index->set_step(1); spin_z_index->set_custom_minimum_size(Size2(100, 0)); spin_z_index->connect("value_changed", callable_mp(this, &TileSetEditor::_on_z_index_changed)); @@ -3485,7 +3485,7 @@ void TilesetEditorContext::_get_property_list(List *p_list) const p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_navigation_offset")); p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_shape_offset", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); p_list->push_back(PropertyInfo(Variant::VECTOR2, "tile_shape_transform", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_EDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, "tile_z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1")); + p_list->push_back(PropertyInfo(Variant::INT, "tile_z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1")); } if (tileset_editor->edit_mode == TileSetEditor::EDITMODE_COLLISION && tileset_editor->edited_collision_shape.is_valid()) { p_list->push_back(PropertyInfo(Variant::OBJECT, "selected_collision", PROPERTY_HINT_RESOURCE_TYPE, tileset_editor->edited_collision_shape->get_class())); diff --git a/editor/plugins/visual_shader_editor_plugin.cpp b/editor/plugins/visual_shader_editor_plugin.cpp index 36f81b21ba..594dc400ec 100644 --- a/editor/plugins/visual_shader_editor_plugin.cpp +++ b/editor/plugins/visual_shader_editor_plugin.cpp @@ -45,7 +45,7 @@ #include "scene/main/window.h" #include "scene/resources/visual_shader_nodes.h" #include "servers/display_server.h" -#include "servers/visual/shader_types.h" +#include "servers/rendering/shader_types.h" Control *VisualShaderNodePlugin::create_editor(const Ref &p_parent_resource, const Ref &p_node) { @@ -2263,7 +2263,7 @@ void VisualShaderEditor::_update_preview() { ShaderLanguage sl; - Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types()); + Error err = sl.compile(code, ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(visual_shader->get_mode())), ShaderTypes::get_singleton()->get_types()); for (int i = 0; i < preview_text->get_line_count(); i++) { preview_text->set_line_as_marked(i, false); diff --git a/editor/property_editor.cpp b/editor/property_editor.cpp index 41e15f47cc..8c5b078de0 100644 --- a/editor/property_editor.cpp +++ b/editor/property_editor.cpp @@ -1500,7 +1500,7 @@ void CustomPropertyEditor::_draw_easing() { iflp = 1.0 - iflp; } - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(iflp * s.width, prev * s.height), Point2(ifl * s.width, h * s.height), color); + RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(iflp * s.width, prev * s.height), Point2(ifl * s.width, h * s.height), color); prev = h; } diff --git a/editor/scene_tree_dock.cpp b/editor/scene_tree_dock.cpp index 7d429eb4b5..4b382f09f4 100644 --- a/editor/scene_tree_dock.cpp +++ b/editor/scene_tree_dock.cpp @@ -47,7 +47,7 @@ #include "scene/main/window.h" #include "scene/resources/packed_scene.h" #include "servers/display_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void SceneTreeDock::_nodes_drag_begin() { diff --git a/gles_builders.py b/gles_builders.py index 92cf9357cf..e4e5fafc85 100644 --- a/gles_builders.py +++ b/gles_builders.py @@ -602,7 +602,7 @@ def build_rd_header(filename): out_file_class = out_file_base.replace(".glsl.gen.h", "").title().replace("_", "").replace(".", "") + "ShaderRD" fd.write("\n") - fd.write("#include \"servers/visual/rasterizer_rd/shader_rd.h\"\n\n") + fd.write("#include \"servers/rendering/rasterizer_rd/shader_rd.h\"\n\n") fd.write("class " + out_file_class + " : public ShaderRD {\n\n") fd.write("public:\n\n") diff --git a/main/main.cpp b/main/main.cpp index 9e7e0e8842..89c8832731 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -65,13 +65,13 @@ #include "servers/audio_server.h" #include "servers/camera_server.h" #include "servers/display_server.h" -#include "servers/navigation_2d_server.h" -#include "servers/navigation_server.h" -#include "servers/physics_2d_server.h" -#include "servers/physics_server.h" +#include "servers/navigation_server_2d.h" +#include "servers/navigation_server_3d.h" +#include "servers/physics_server_2d.h" +#include "servers/physics_server_3d.h" #include "servers/register_server_types.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_wrap_mt.h" #ifdef TOOLS_ENABLED #include "editor/doc_data.h" @@ -103,13 +103,13 @@ static MessageQueue *message_queue = NULL; // Initialized in setup2() static AudioServer *audio_server = NULL; static DisplayServer *display_server = NULL; -static VisualServer *visual_server = NULL; +static RenderingServer *rendering_server = NULL; static CameraServer *camera_server = NULL; static ARVRServer *arvr_server = NULL; -static PhysicsServer *physics_server = NULL; -static Physics2DServer *physics_2d_server = NULL; -static NavigationServer *navigation_server = NULL; -static Navigation2DServer *navigation_2d_server = NULL; +static PhysicsServer3D *physics_server = NULL; +static PhysicsServer2D *physics_2d_server = NULL; +static NavigationServer3D *navigation_server = NULL; +static NavigationServer2D *navigation_2d_server = NULL; // We error out if setup2() doesn't turn this true static bool _start_success = false; @@ -180,23 +180,23 @@ static String get_full_version_string() { return String(VERSION_FULL_BUILD) + hash; } -// FIXME: Could maybe be moved to PhysicsServerManager and Physics2DServerManager directly +// FIXME: Could maybe be moved to PhysicsServer3DManager and PhysicsServer2DManager directly // to have less code in main.cpp. void initialize_physics() { /// 3D Physics Server - physics_server = PhysicsServerManager::new_server(ProjectSettings::get_singleton()->get(PhysicsServerManager::setting_property_name)); + physics_server = PhysicsServer3DManager::new_server(ProjectSettings::get_singleton()->get(PhysicsServer3DManager::setting_property_name)); if (!physics_server) { // Physics server not found, Use the default physics - physics_server = PhysicsServerManager::new_default_server(); + physics_server = PhysicsServer3DManager::new_default_server(); } ERR_FAIL_COND(!physics_server); physics_server->init(); /// 2D Physics server - physics_2d_server = Physics2DServerManager::new_server(ProjectSettings::get_singleton()->get(Physics2DServerManager::setting_property_name)); + physics_2d_server = PhysicsServer2DManager::new_server(ProjectSettings::get_singleton()->get(PhysicsServer2DManager::setting_property_name)); if (!physics_2d_server) { // Physics server not found, Use the default physics - physics_2d_server = Physics2DServerManager::new_default_server(); + physics_2d_server = PhysicsServer2DManager::new_default_server(); } ERR_FAIL_COND(!physics_2d_server); physics_2d_server->init(); @@ -213,8 +213,8 @@ void finalize_physics() { void finalize_display() { - visual_server->finish(); - memdelete(visual_server); + rendering_server->finish(); + memdelete(rendering_server); memdelete(display_server); } @@ -222,8 +222,8 @@ void finalize_display() { void initialize_navigation_server() { ERR_FAIL_COND(navigation_server != NULL); - navigation_server = NavigationServerManager::new_default_server(); - navigation_2d_server = memnew(Navigation2DServer); + navigation_server = NavigationServer3DManager::new_default_server(); + navigation_2d_server = memnew(NavigationServer2D); } void finalize_navigation_server() { @@ -1273,12 +1273,12 @@ Error Main::setup2(Thread::ID p_main_tid_override) { /* Initialize Visual Server */ - visual_server = memnew(VisualServerRaster); + rendering_server = memnew(RenderingServerRaster); if (OS::get_singleton()->get_render_thread_mode() != OS::RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD)); + rendering_server = memnew(RenderingServerWrapMT(rendering_server, OS::get_singleton()->get_render_thread_mode() == OS::RENDER_SEPARATE_THREAD)); } - visual_server->init(); + rendering_server->init(); OS::get_singleton()->initialize_joypads(); @@ -1333,7 +1333,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { MAIN_PRINT("Main: Load Remaps"); Color clear = GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3)); - VisualServer::get_singleton()->set_default_clear_color(clear); + RenderingServer::get_singleton()->set_default_clear_color(clear); if (show_logo) { //boot logo! String boot_logo_path = GLOBAL_DEF("application/boot_splash/image", String()); @@ -1355,7 +1355,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { Color boot_bg_color = GLOBAL_DEF("application/boot_splash/bg_color", boot_splash_bg_color); if (boot_logo.is_valid()) { OS::get_singleton()->_msec_splash = OS::get_singleton()->get_ticks_msec(); - VisualServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, boot_logo_filter); + RenderingServer::get_singleton()->set_boot_image(boot_logo, boot_bg_color, boot_logo_scale, boot_logo_filter); } else { #ifndef NO_DEFAULT_BOOT_LOGO @@ -1367,9 +1367,9 @@ Error Main::setup2(Thread::ID p_main_tid_override) { #endif MAIN_PRINT("Main: ClearColor"); - VisualServer::get_singleton()->set_default_clear_color(boot_bg_color); + RenderingServer::get_singleton()->set_default_clear_color(boot_bg_color); MAIN_PRINT("Main: Image"); - VisualServer::get_singleton()->set_boot_image(splash, boot_bg_color, false); + RenderingServer::get_singleton()->set_boot_image(splash, boot_bg_color, false); #endif } @@ -1380,7 +1380,7 @@ Error Main::setup2(Thread::ID p_main_tid_override) { } MAIN_PRINT("Main: DCC"); - VisualServer::get_singleton()->set_default_clear_color(GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3))); + RenderingServer::get_singleton()->set_default_clear_color(GLOBAL_DEF("rendering/environment/default_clear_color", Color(0.3, 0.3, 0.3))); MAIN_PRINT("Main: END"); GLOBAL_DEF("application/config/icon", String()); @@ -1826,7 +1826,7 @@ bool Main::start() { { int directional_atlas_size = GLOBAL_GET("rendering/quality/directional_shadow/size"); - VisualServer::get_singleton()->directional_shadow_atlas_set_size(directional_atlas_size); + RenderingServer::get_singleton()->directional_shadow_atlas_set_size(directional_atlas_size); } if (!editor && !project_manager) { @@ -2101,25 +2101,25 @@ bool Main::iteration() { uint64_t physics_begin = OS::get_singleton()->get_ticks_usec(); - PhysicsServer::get_singleton()->sync(); - PhysicsServer::get_singleton()->flush_queries(); + PhysicsServer3D::get_singleton()->sync(); + PhysicsServer3D::get_singleton()->flush_queries(); - Physics2DServer::get_singleton()->sync(); - Physics2DServer::get_singleton()->flush_queries(); + PhysicsServer2D::get_singleton()->sync(); + PhysicsServer2D::get_singleton()->flush_queries(); if (OS::get_singleton()->get_main_loop()->iteration(frame_slice * time_scale)) { exit = true; break; } - NavigationServer::get_singleton_mut()->process(frame_slice * time_scale); + NavigationServer3D::get_singleton_mut()->process(frame_slice * time_scale); message_queue->flush(); - PhysicsServer::get_singleton()->step(frame_slice * time_scale); + PhysicsServer3D::get_singleton()->step(frame_slice * time_scale); - Physics2DServer::get_singleton()->end_sync(); - Physics2DServer::get_singleton()->step(frame_slice * time_scale); + PhysicsServer2D::get_singleton()->end_sync(); + PhysicsServer2D::get_singleton()->step(frame_slice * time_scale); message_queue->flush(); @@ -2137,17 +2137,17 @@ bool Main::iteration() { } message_queue->flush(); - VisualServer::get_singleton()->sync(); //sync if still drawing from previous frames. + RenderingServer::get_singleton()->sync(); //sync if still drawing from previous frames. if (DisplayServer::get_singleton()->can_any_window_draw() && !disable_render_loop) { if ((!force_redraw_requested) && OS::get_singleton()->is_in_low_processor_usage_mode()) { - if (VisualServer::get_singleton()->has_changed()) { - VisualServer::get_singleton()->draw(true, scaled_step); // flush visual commands + if (RenderingServer::get_singleton()->has_changed()) { + RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands Engine::get_singleton()->frames_drawn++; } } else { - VisualServer::get_singleton()->draw(true, scaled_step); // flush visual commands + RenderingServer::get_singleton()->draw(true, scaled_step); // flush visual commands Engine::get_singleton()->frames_drawn++; force_redraw_requested = false; } @@ -2262,7 +2262,7 @@ void Main::cleanup() { ScriptServer::finish_languages(); // Sync pending commands that may have been queued from a different thread during ScriptServer finalization - VisualServer::get_singleton()->sync(); + RenderingServer::get_singleton()->sync(); #ifdef TOOLS_ENABLED EditorNode::unregister_editor_types(); diff --git a/main/performance.cpp b/main/performance.cpp index c7e3a41aa6..335407c9eb 100644 --- a/main/performance.cpp +++ b/main/performance.cpp @@ -35,9 +35,9 @@ #include "scene/main/node.h" #include "scene/main/scene_tree.h" #include "servers/audio_server.h" -#include "servers/physics_2d_server.h" -#include "servers/physics_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/physics_server_3d.h" +#include "servers/rendering_server.h" Performance *Performance::singleton = NULL; @@ -135,22 +135,22 @@ float Performance::get_monitor(Monitor p_monitor) const { case OBJECT_RESOURCE_COUNT: return ResourceCache::get_cached_resource_count(); case OBJECT_NODE_COUNT: return _get_node_count(); case OBJECT_ORPHAN_NODE_COUNT: return Node::orphan_node_count; - case RENDER_OBJECTS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_OBJECTS_IN_FRAME); - case RENDER_VERTICES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_VERTICES_IN_FRAME); - case RENDER_MATERIAL_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_MATERIAL_CHANGES_IN_FRAME); - case RENDER_SHADER_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME); - case RENDER_SURFACE_CHANGES_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); - case RENDER_DRAW_CALLS_IN_FRAME: return VS::get_singleton()->get_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); - case RENDER_VIDEO_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VIDEO_MEM_USED); - case RENDER_TEXTURE_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED); - case RENDER_VERTEX_MEM_USED: return VS::get_singleton()->get_render_info(VS::INFO_VERTEX_MEM_USED); - case RENDER_USAGE_VIDEO_MEM_TOTAL: return VS::get_singleton()->get_render_info(VS::INFO_USAGE_VIDEO_MEM_TOTAL); - case PHYSICS_2D_ACTIVE_OBJECTS: return Physics2DServer::get_singleton()->get_process_info(Physics2DServer::INFO_ACTIVE_OBJECTS); - case PHYSICS_2D_COLLISION_PAIRS: return Physics2DServer::get_singleton()->get_process_info(Physics2DServer::INFO_COLLISION_PAIRS); - case PHYSICS_2D_ISLAND_COUNT: return Physics2DServer::get_singleton()->get_process_info(Physics2DServer::INFO_ISLAND_COUNT); - case PHYSICS_3D_ACTIVE_OBJECTS: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_ACTIVE_OBJECTS); - case PHYSICS_3D_COLLISION_PAIRS: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_COLLISION_PAIRS); - case PHYSICS_3D_ISLAND_COUNT: return PhysicsServer::get_singleton()->get_process_info(PhysicsServer::INFO_ISLAND_COUNT); + case RENDER_OBJECTS_IN_FRAME: return RS::get_singleton()->get_render_info(RS::INFO_OBJECTS_IN_FRAME); + case RENDER_VERTICES_IN_FRAME: return RS::get_singleton()->get_render_info(RS::INFO_VERTICES_IN_FRAME); + case RENDER_MATERIAL_CHANGES_IN_FRAME: return RS::get_singleton()->get_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME); + case RENDER_SHADER_CHANGES_IN_FRAME: return RS::get_singleton()->get_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME); + case RENDER_SURFACE_CHANGES_IN_FRAME: return RS::get_singleton()->get_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME); + case RENDER_DRAW_CALLS_IN_FRAME: return RS::get_singleton()->get_render_info(RS::INFO_DRAW_CALLS_IN_FRAME); + case RENDER_VIDEO_MEM_USED: return RS::get_singleton()->get_render_info(RS::INFO_VIDEO_MEM_USED); + case RENDER_TEXTURE_MEM_USED: return RS::get_singleton()->get_render_info(RS::INFO_TEXTURE_MEM_USED); + case RENDER_VERTEX_MEM_USED: return RS::get_singleton()->get_render_info(RS::INFO_VERTEX_MEM_USED); + case RENDER_USAGE_VIDEO_MEM_TOTAL: return RS::get_singleton()->get_render_info(RS::INFO_USAGE_VIDEO_MEM_TOTAL); + case PHYSICS_2D_ACTIVE_OBJECTS: return PhysicsServer2D::get_singleton()->get_process_info(PhysicsServer2D::INFO_ACTIVE_OBJECTS); + case PHYSICS_2D_COLLISION_PAIRS: return PhysicsServer2D::get_singleton()->get_process_info(PhysicsServer2D::INFO_COLLISION_PAIRS); + case PHYSICS_2D_ISLAND_COUNT: return PhysicsServer2D::get_singleton()->get_process_info(PhysicsServer2D::INFO_ISLAND_COUNT); + case PHYSICS_3D_ACTIVE_OBJECTS: return PhysicsServer3D::get_singleton()->get_process_info(PhysicsServer3D::INFO_ACTIVE_OBJECTS); + case PHYSICS_3D_COLLISION_PAIRS: return PhysicsServer3D::get_singleton()->get_process_info(PhysicsServer3D::INFO_COLLISION_PAIRS); + case PHYSICS_3D_ISLAND_COUNT: return PhysicsServer3D::get_singleton()->get_process_info(PhysicsServer3D::INFO_ISLAND_COUNT); case AUDIO_OUTPUT_LATENCY: return AudioServer::get_singleton()->get_output_latency(); default: { diff --git a/main/tests/test_math.cpp b/main/tests/test_math.cpp index d91503501d..29fa5e73a7 100644 --- a/main/tests/test_math.cpp +++ b/main/tests/test_math.cpp @@ -43,7 +43,7 @@ #include "core/vmap.h" #include "scene/main/node.h" #include "scene/resources/texture.h" -#include "servers/visual/shader_language.h" +#include "servers/rendering/shader_language.h" #include "core/method_ptrcall.h" diff --git a/main/tests/test_physics.cpp b/main/tests/test_physics.cpp index 7727af6ad1..5e8940f453 100644 --- a/main/tests/test_physics.cpp +++ b/main/tests/test_physics.cpp @@ -37,8 +37,8 @@ #include "core/os/os.h" #include "core/print_string.h" #include "servers/display_server.h" -#include "servers/physics_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_3d.h" +#include "servers/rendering_server.h" class TestPhysicsMainLoop : public MainLoop { @@ -65,13 +65,13 @@ class TestPhysicsMainLoop : public MainLoop { Point2 joy_direction; List bodies; - Map type_shape_map; - Map type_mesh_map; + Map type_shape_map; + Map type_mesh_map; void body_changed_transform(Object *p_state, RID p_visual_instance) { - PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; - VisualServer *vs = VisualServer::get_singleton(); + PhysicsDirectBodyState3D *state = (PhysicsDirectBodyState3D *)p_state; + RenderingServer *vs = RenderingServer::get_singleton(); Transform t = state->get_transform(); vs->instance_set_transform(p_visual_instance, t); } @@ -84,23 +84,23 @@ protected: ClassDB::bind_method("body_changed_transform", &TestPhysicsMainLoop::body_changed_transform); } - RID create_body(PhysicsServer::ShapeType p_shape, PhysicsServer::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) { + RID create_body(PhysicsServer3D::ShapeType p_shape, PhysicsServer3D::BodyMode p_body, const Transform p_location, bool p_active_default = true, const Transform &p_shape_xform = Transform()) { - VisualServer *vs = VisualServer::get_singleton(); - PhysicsServer *ps = PhysicsServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); RID mesh_instance = vs->instance_create2(type_mesh_map[p_shape], scenario); RID body = ps->body_create(p_body, !p_active_default); ps->body_set_space(body, space); - ps->body_set_param(body, PhysicsServer::BODY_PARAM_BOUNCE, 0.0); + ps->body_set_param(body, PhysicsServer3D::BODY_PARAM_BOUNCE, 0.0); //todo set space ps->body_add_shape(body, type_shape_map[p_shape]); ps->body_set_force_integration_callback(body, this, "body_changed_transform", mesh_instance); - ps->body_set_state(body, PhysicsServer::BODY_STATE_TRANSFORM, p_location); + ps->body_set_state(body, PhysicsServer3D::BODY_STATE_TRANSFORM, p_location); bodies.push_back(body); - if (p_body == PhysicsServer::BODY_MODE_STATIC) { + if (p_body == PhysicsServer3D::BODY_MODE_STATIC) { vs->instance_set_transform(mesh_instance, p_location); } @@ -109,12 +109,12 @@ protected: RID create_static_plane(const Plane &p_plane) { - PhysicsServer *ps = PhysicsServer::get_singleton(); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); - RID world_margin_shape = ps->shape_create(PhysicsServer::SHAPE_PLANE); + RID world_margin_shape = ps->shape_create(PhysicsServer3D::SHAPE_PLANE); ps->shape_set_data(world_margin_shape, p_plane); - RID b = ps->body_create(PhysicsServer::BODY_MODE_STATIC); + RID b = ps->body_create(PhysicsServer3D::BODY_MODE_STATIC); ps->body_set_space(b, space); //todo set space ps->body_add_shape(b, world_margin_shape); @@ -123,24 +123,24 @@ protected: void configure_body(RID p_body, float p_mass, float p_friction, float p_bounce) { - PhysicsServer *ps = PhysicsServer::get_singleton(); - ps->body_set_param(p_body, PhysicsServer::BODY_PARAM_MASS, p_mass); - ps->body_set_param(p_body, PhysicsServer::BODY_PARAM_FRICTION, p_friction); - ps->body_set_param(p_body, PhysicsServer::BODY_PARAM_BOUNCE, p_bounce); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); + ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_MASS, p_mass); + ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_FRICTION, p_friction); + ps->body_set_param(p_body, PhysicsServer3D::BODY_PARAM_BOUNCE, p_bounce); } void init_shapes() { - VisualServer *vs = VisualServer::get_singleton(); - PhysicsServer *ps = PhysicsServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); /* SPHERE SHAPE */ RID sphere_mesh = vs->make_sphere_mesh(10, 20, 0.5); - type_mesh_map[PhysicsServer::SHAPE_SPHERE] = sphere_mesh; + type_mesh_map[PhysicsServer3D::SHAPE_SPHERE] = sphere_mesh; - RID sphere_shape = ps->shape_create(PhysicsServer::SHAPE_SPHERE); + RID sphere_shape = ps->shape_create(PhysicsServer3D::SHAPE_SPHERE); ps->shape_set_data(sphere_shape, 0.5); - type_shape_map[PhysicsServer::SHAPE_SPHERE] = sphere_shape; + type_shape_map[PhysicsServer3D::SHAPE_SPHERE] = sphere_shape; /* BOX SHAPE */ @@ -148,11 +148,11 @@ protected: RID box_mesh = vs->mesh_create(); Geometry::MeshData box_data = Geometry::build_convex_mesh(box_planes); vs->mesh_add_surface_from_mesh_data(box_mesh, box_data); - type_mesh_map[PhysicsServer::SHAPE_BOX] = box_mesh; + type_mesh_map[PhysicsServer3D::SHAPE_BOX] = box_mesh; - RID box_shape = ps->shape_create(PhysicsServer::SHAPE_BOX); + RID box_shape = ps->shape_create(PhysicsServer3D::SHAPE_BOX); ps->shape_set_data(box_shape, Vector3(0.5, 0.5, 0.5)); - type_shape_map[PhysicsServer::SHAPE_BOX] = box_shape; + type_shape_map[PhysicsServer3D::SHAPE_BOX] = box_shape; /* CAPSULE SHAPE */ @@ -162,14 +162,14 @@ protected: Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes); vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data); - type_mesh_map[PhysicsServer::SHAPE_CAPSULE] = capsule_mesh; + type_mesh_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_mesh; - RID capsule_shape = ps->shape_create(PhysicsServer::SHAPE_CAPSULE); + RID capsule_shape = ps->shape_create(PhysicsServer3D::SHAPE_CAPSULE); Dictionary capsule_params; capsule_params["radius"] = 0.5; capsule_params["height"] = 1.4; ps->shape_set_data(capsule_shape, capsule_params); - type_shape_map[PhysicsServer::SHAPE_CAPSULE] = capsule_shape; + type_shape_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_shape; /* CONVEX SHAPE */ @@ -180,18 +180,18 @@ protected: QuickHull::build(convex_data.vertices, convex_data); vs->mesh_add_surface_from_mesh_data(convex_mesh, convex_data); - type_mesh_map[PhysicsServer::SHAPE_CONVEX_POLYGON] = convex_mesh; + type_mesh_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_mesh; - RID convex_shape = ps->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON); + RID convex_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONVEX_POLYGON); ps->shape_set_data(convex_shape, convex_data.vertices); - type_shape_map[PhysicsServer::SHAPE_CONVEX_POLYGON] = convex_shape; + type_shape_map[PhysicsServer3D::SHAPE_CONVEX_POLYGON] = convex_shape; } void make_trimesh(Vector p_faces, const Transform &p_xform = Transform()) { - VisualServer *vs = VisualServer::get_singleton(); - PhysicsServer *ps = PhysicsServer::get_singleton(); - RID trimesh_shape = ps->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); + RID trimesh_shape = ps->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON); ps->shape_set_data(trimesh_shape, p_faces); p_faces = ps->shape_get_data(trimesh_shape); // optimized one Vector normals; // for drawing @@ -205,19 +205,19 @@ protected: RID trimesh_mesh = vs->mesh_create(); Array d; - d.resize(VS::ARRAY_MAX); - d[VS::ARRAY_VERTEX] = p_faces; - d[VS::ARRAY_NORMAL] = normals; - vs->mesh_add_surface_from_arrays(trimesh_mesh, VS::PRIMITIVE_TRIANGLES, d); + d.resize(RS::ARRAY_MAX); + d[RS::ARRAY_VERTEX] = p_faces; + d[RS::ARRAY_NORMAL] = normals; + vs->mesh_add_surface_from_arrays(trimesh_mesh, RS::PRIMITIVE_TRIANGLES, d); RID triins = vs->instance_create2(trimesh_mesh, scenario); - RID tribody = ps->body_create(PhysicsServer::BODY_MODE_STATIC); + RID tribody = ps->body_create(PhysicsServer3D::BODY_MODE_STATIC); ps->body_set_space(tribody, space); //todo set space ps->body_add_shape(tribody, trimesh_shape); Transform tritrans = p_xform; - ps->body_set_state(tribody, PhysicsServer::BODY_STATE_TRANSFORM, tritrans); + ps->body_set_state(tribody, PhysicsServer3D::BODY_STATE_TRANSFORM, tritrans); vs->instance_set_transform(triins, tritrans); } @@ -276,11 +276,11 @@ public: if (mover.is_valid()) { - PhysicsServer *ps = PhysicsServer::get_singleton(); - Transform t = ps->body_get_state(mover, PhysicsServer::BODY_STATE_TRANSFORM); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); + Transform t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM); t.origin += Vector3(x, y, 0); - ps->body_set_state(mover, PhysicsServer::BODY_STATE_TRANSFORM, t); + ps->body_set_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM, t); } } } @@ -294,11 +294,11 @@ public: ofs_x = ofs_y = 0; init_shapes(); - PhysicsServer *ps = PhysicsServer::get_singleton(); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); space = ps->space_create(); ps->space_set_active(space, true); - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); /* LIGHT */ RID lightaux = vs->directional_light_create(); @@ -335,17 +335,17 @@ public: if (mover.is_valid()) { static float joy_speed = 10; - PhysicsServer *ps = PhysicsServer::get_singleton(); - Transform t = ps->body_get_state(mover, PhysicsServer::BODY_STATE_TRANSFORM); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); + Transform t = ps->body_get_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM); t.origin += Vector3(joy_speed * joy_direction.x * p_time, -joy_speed * joy_direction.y * p_time, 0); - ps->body_set_state(mover, PhysicsServer::BODY_STATE_TRANSFORM, t); + ps->body_set_state(mover, PhysicsServer3D::BODY_STATE_TRANSFORM, t); }; Transform cameratr; cameratr.rotate(Vector3(0, 1, 0), ofs_x); cameratr.rotate(Vector3(1, 0, 0), -ofs_y); cameratr.translate(Vector3(0, 2, 8)); - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); vs->camera_set_transform(camera, cameratr); return quit; @@ -361,17 +361,17 @@ public: void test_character() { - VisualServer *vs = VisualServer::get_singleton(); - PhysicsServer *ps = PhysicsServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer3D *ps = PhysicsServer3D::get_singleton(); Vector capsule_planes = Geometry::build_capsule_planes(0.5, 1, 12, 5, Vector3::AXIS_Y); RID capsule_mesh = vs->mesh_create(); Geometry::MeshData capsule_data = Geometry::build_convex_mesh(capsule_planes); vs->mesh_add_surface_from_mesh_data(capsule_mesh, capsule_data); - type_mesh_map[PhysicsServer::SHAPE_CAPSULE] = capsule_mesh; + type_mesh_map[PhysicsServer3D::SHAPE_CAPSULE] = capsule_mesh; - RID capsule_shape = ps->shape_create(PhysicsServer::SHAPE_CAPSULE); + RID capsule_shape = ps->shape_create(PhysicsServer3D::SHAPE_CAPSULE); Dictionary capsule_params; capsule_params["radius"] = 0.5; capsule_params["height"] = 1; @@ -381,14 +381,14 @@ public: ps->shape_set_data(capsule_shape, capsule_params); RID mesh_instance = vs->instance_create2(capsule_mesh, scenario); - character = ps->body_create(PhysicsServer::BODY_MODE_CHARACTER); + character = ps->body_create(PhysicsServer3D::BODY_MODE_CHARACTER); ps->body_set_space(character, space); //todo add space ps->body_add_shape(character, capsule_shape); ps->body_set_force_integration_callback(character, this, "body_changed_transform", mesh_instance); - ps->body_set_state(character, PhysicsServer::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2))); + ps->body_set_state(character, PhysicsServer3D::BODY_STATE_TRANSFORM, Transform(Basis(), Vector3(-2, 5, -2))); bodies.push_back(character); } @@ -396,21 +396,21 @@ public: for (int i = 0; i < 35; i++) { - static const PhysicsServer::ShapeType shape_idx[] = { - PhysicsServer::SHAPE_CAPSULE, - PhysicsServer::SHAPE_BOX, - PhysicsServer::SHAPE_SPHERE, - PhysicsServer::SHAPE_CONVEX_POLYGON + static const PhysicsServer3D::ShapeType shape_idx[] = { + PhysicsServer3D::SHAPE_CAPSULE, + PhysicsServer3D::SHAPE_BOX, + PhysicsServer3D::SHAPE_SPHERE, + PhysicsServer3D::SHAPE_CONVEX_POLYGON }; - PhysicsServer::ShapeType type = shape_idx[i % 4]; + PhysicsServer3D::ShapeType type = shape_idx[i % 4]; Transform t; t.origin = Vector3(0.0 * i, 3.5 + 1.1 * i, 0.7 + 0.0 * i); t.basis.rotate(Vector3(0.2, -1, 0), Math_PI / 2 * 0.6); - create_body(type, PhysicsServer::BODY_MODE_RIGID, t); + create_body(type, PhysicsServer3D::BODY_MODE_RIGID, t); } create_static_plane(Plane(Vector3(0, 1, 0), -1)); @@ -418,7 +418,7 @@ public: void test_activate() { - create_body(PhysicsServer::SHAPE_BOX, PhysicsServer::BODY_MODE_RIGID, Transform(Basis(), Vector3(0, 2, 0)), true); + create_body(PhysicsServer3D::SHAPE_BOX, PhysicsServer3D::BODY_MODE_RIGID, Transform(Basis(), Vector3(0, 2, 0)), true); create_static_plane(Plane(Vector3(0, 1, 0), -1)); } diff --git a/main/tests/test_physics_2d.cpp b/main/tests/test_physics_2d.cpp index 4403e40b76..6feff3b0a9 100644 --- a/main/tests/test_physics_2d.cpp +++ b/main/tests/test_physics_2d.cpp @@ -36,8 +36,8 @@ #include "core/print_string.h" #include "scene/resources/texture.h" #include "servers/display_server.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" static const unsigned char convex_png[] = { 0x89, 0x50, 0x4e, 0x47, 0xd, 0xa, 0x1a, 0xa, 0x0, 0x0, 0x0, 0xd, 0x49, 0x48, 0x44, 0x52, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x40, 0x8, 0x6, 0x0, 0x0, 0x0, 0xaa, 0x69, 0x71, 0xde, 0x0, 0x0, 0x0, 0x1, 0x73, 0x52, 0x47, 0x42, 0x0, 0xae, 0xce, 0x1c, 0xe9, 0x0, 0x0, 0x0, 0x6, 0x62, 0x4b, 0x47, 0x44, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf9, 0x43, 0xbb, 0x7f, 0x0, 0x0, 0x0, 0x9, 0x70, 0x48, 0x59, 0x73, 0x0, 0x0, 0xb, 0x13, 0x0, 0x0, 0xb, 0x13, 0x1, 0x0, 0x9a, 0x9c, 0x18, 0x0, 0x0, 0x0, 0x7, 0x74, 0x49, 0x4d, 0x45, 0x7, 0xdb, 0x6, 0xa, 0x3, 0x13, 0x31, 0x66, 0xa7, 0xac, 0x79, 0x0, 0x0, 0x4, 0xef, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xed, 0x9b, 0xdd, 0x4e, 0x2a, 0x57, 0x14, 0xc7, 0xf7, 0x1e, 0xc0, 0x19, 0x38, 0x32, 0x80, 0xa, 0x6a, 0xda, 0x18, 0xa3, 0xc6, 0x47, 0x50, 0x7b, 0xa1, 0xd9, 0x36, 0x27, 0x7e, 0x44, 0xed, 0x45, 0x4d, 0x93, 0x3e, 0x40, 0x1f, 0x64, 0x90, 0xf4, 0x1, 0xbc, 0xf0, 0xc2, 0x9c, 0x57, 0x30, 0x4d, 0xbc, 0xa8, 0x6d, 0xc, 0x69, 0x26, 0xb5, 0x68, 0x8b, 0x35, 0x7e, 0x20, 0xb4, 0xf5, 0x14, 0xbf, 0x51, 0x3c, 0x52, 0xe, 0xc, 0xe, 0xc8, 0xf0, 0xb1, 0x7a, 0x51, 0x3d, 0xb1, 0x9e, 0x19, 0x1c, 0x54, 0x70, 0x1c, 0xdc, 0x9, 0x17, 0x64, 0x8, 0xc9, 0xff, 0xb7, 0xd6, 0x7f, 0xcd, 0x3f, 0x2b, 0xd9, 0x8, 0xbd, 0x9c, 0xda, 0x3e, 0xf8, 0x31, 0xff, 0xc, 0x0, 0x8, 0x42, 0x88, 0x9c, 0x9f, 0x9f, 0xbf, 0xa, 0x87, 0xc3, 0xad, 0x7d, 0x7d, 0x7d, 0x7f, 0x23, 0x84, 0x78, 0x8c, 0x31, 0xaf, 0x55, 0x0, 0xc6, 0xc7, 0x14, 0x1e, 0x8f, 0xc7, 0xbf, 0x38, 0x3c, 0x3c, 0x6c, 0x9b, 0x9f, 0x9f, 0x6f, 0xb8, 0x82, 0x9b, 0xee, 0xe8, 0xe8, 0xf8, 0x12, 0x0, 0xbe, 0xd3, 0x2a, 0x8, 0xfc, 0x50, 0xd1, 0xf9, 0x7c, 0x9e, 0x8a, 0x46, 0xa3, 0x5f, 0x9d, 0x9e, 0x9e, 0x7e, 0xb2, 0xb0, 0xb0, 0x60, 0xe5, 0x79, 0x1e, 0xf1, 0xfc, 0x7f, 0x3a, 0x9, 0x21, 0x88, 0x10, 0x82, 0x26, 0x26, 0x26, 0xde, 0x77, 0x75, 0x75, 0x85, 0x59, 0x96, 0xfd, 0x5e, 0x6b, 0x20, 0xf0, 0x7d, 0x85, 0x4b, 0x92, 0xf4, 0xfa, 0xe0, 0xe0, 0xe0, 0xd3, 0xb9, 0xb9, 0xb9, 0x46, 0x49, 0x92, 0xea, 0x6f, 0xa, 0xbf, 0x7d, 0x8, 0x21, 0x68, 0x70, 0x70, 0xb0, 0x38, 0x39, 0x39, 0x79, 0xd6, 0xd9, 0xd9, 0xb9, 0xcf, 0x30, 0xcc, 0xa2, 0xd6, 0xad, 0x21, 0x2b, 0x1c, 0x0, 0x38, 0x41, 0x10, 0xfc, 0xdb, 0xdb, 0xdb, 0x27, 0x1e, 0x8f, 0x27, 0x4b, 0x8, 0x1, 0x84, 0x90, 0xea, 0xf, 0x21, 0x4, 0x3c, 0x1e, 0x4f, 0x76, 0x67, 0x67, 0x67, 0x3f, 0x9f, 0xcf, 0xff, 0x7c, 0x5, 0xf3, 0xd9, 0x0, 0xe0, 0x2, 0x81, 0xc0, 0xa9, 0xdb, 0xed, 0x2e, 0x94, 0x2b, 0x5c, 0xe, 0xc4, 0xca, 0xca, 0x8a, 0x18, 0x8d, 0x46, 0x3, 0x0, 0xc0, 0x69, 0x1e, 0x4, 0x0, 0x90, 0x48, 0x24, 0x12, 0xe4, 0x38, 0xee, 0x41, 0xc2, 0x6f, 0x43, 0xe0, 0x38, 0xe, 0xfc, 0x7e, 0xbf, 0x10, 0x8b, 0xc5, 0xd6, 0x35, 0xd, 0x22, 0x9b, 0xcd, 0x7a, 0x96, 0x97, 0x97, 0x33, 0xf, 0xad, 0x7c, 0x29, 0x10, 0x9b, 0x9b, 0x9b, 0xef, 0x2e, 0x2e, 0x2e, 0x7e, 0xd5, 0x1c, 0x8, 0x0, 0x20, 0xe1, 0x70, 0x38, 0xfc, 0x98, 0xd5, 0x57, 0x2, 0xe1, 0x76, 0xbb, 0xf3, 0xa1, 0x50, 0xe8, 0x38, 0x9b, 0xcd, 0xfe, 0xa2, 0x9, 0x8, 0x0, 0x40, 0x2e, 0x2f, 0x2f, 0x7d, 0x4b, 0x4b, 0x4b, 0xb9, 0x4a, 0x54, 0x5f, 0x9, 0xc4, 0xd2, 0xd2, 0x92, 0xb4, 0xb7, 0xb7, 0xf7, 0x36, 0x97, 0xcb, 0x4d, 0x3d, 0x29, 0x8, 0x0, 0xe0, 0x42, 0xa1, 0xd0, 0x71, 0xb5, 0xc4, 0xdf, 0xb6, 0xc5, 0x93, 0xe, 0x4a, 0x0, 0x20, 0xa9, 0x54, 0xea, 0x37, 0xb7, 0xdb, 0x5d, 0xa8, 0xa6, 0x78, 0x39, 0x10, 0x6b, 0x6b, 0x6b, 0xf1, 0x64, 0x32, 0xb9, 0x5a, 0x55, 0x10, 0x0, 0xc0, 0x6d, 0x6c, 0x6c, 0x9c, 0x57, 0xbb, 0xfa, 0x25, 0x40, 0x14, 0x3, 0x81, 0x40, 0x34, 0x93, 0xc9, 0x2c, 0x57, 0x1c, 0x4, 0x0, 0x90, 0x58, 0x2c, 0xb6, 0x5e, 0xe9, 0xc1, 0x77, 0x1f, 0x10, 0x53, 0x53, 0x53, 0x52, 0xc5, 0x83, 0x14, 0x0, 0x70, 0x7e, 0xbf, 0x5f, 0xd0, 0x42, 0xf5, 0x95, 0x40, 0xf8, 0x7c, 0xbe, 0xcb, 0xa3, 0xa3, 0xa3, 0x3f, 0x1e, 0xbd, 0x1b, 0x0, 0x80, 0x1c, 0x1f, 0x1f, 0x87, 0xb4, 0x56, 0xfd, 0xaa, 0x5, 0x29, 0x51, 0x14, 0xbf, 0xf5, 0xf9, 0x7c, 0x97, 0x5a, 0xad, 0xbe, 0x12, 0x88, 0xf5, 0xf5, 0xf5, 0xd8, 0x83, 0x83, 0x54, 0xb5, 0x42, 0x8f, 0x66, 0x83, 0x94, 0xd6, 0xbd, 0x5f, 0xce, 0x7c, 0x38, 0x3c, 0x3c, 0xfc, 0xb3, 0x50, 0x28, 0xb8, 0xcb, 0x2, 0x1, 0x0, 0xdc, 0xf4, 0xf4, 0xf4, 0xfe, 0x73, 0x15, 0x2f, 0x17, 0xa4, 0x22, 0x91, 0x48, 0x50, 0xb5, 0x2d, 0x0, 0x80, 0x9b, 0x99, 0x99, 0x79, 0xfb, 0xdc, 0x1, 0xc8, 0x5, 0xa9, 0x44, 0x22, 0xf1, 0xfb, 0x9d, 0x10, 0x0, 0x80, 0x9b, 0x9d, 0x9d, 0xd, 0xea, 0x5, 0xc0, 0xad, 0xfd, 0x43, 0x1a, 0x0, 0xb8, 0xdb, 0x9a, 0xa9, 0x8f, 0xb6, 0xa4, 0x46, 0xa3, 0xa4, 0xb7, 0xd5, 0x37, 0xcf, 0xf3, 0x68, 0x75, 0x75, 0xf5, 0x4c, 0xee, 0x99, 0x1c, 0x80, 0x9c, 0x1e, 0xf7, 0xff, 0x16, 0x8b, 0x45, 0x50, 0x5, 0xa0, 0xb7, 0xb7, 0xb7, 0x85, 0x10, 0xa2, 0x2b, 0xf1, 0x84, 0x10, 0xd4, 0xdf, 0xdf, 0x6f, 0x57, 0x3, 0x80, 0x37, 0x18, 0xc, 0x5, 0x3d, 0x2, 0xa0, 0x69, 0x3a, 0x8b, 0x10, 0xe2, 0x4b, 0x2, 0xc0, 0x18, 0xf3, 0xc1, 0x60, 0x70, 0x47, 0x8f, 0x16, 0x38, 0x3a, 0x3a, 0x5a, 0x93, 0x5b, 0xc3, 0x7f, 0x64, 0x81, 0xba, 0xba, 0x3a, 0x49, 0x8f, 0x0, 0x1a, 0x1a, 0x1a, 0xd4, 0xcd, 0x0, 0x93, 0xc9, 0xa4, 0xcb, 0x21, 0xe8, 0x74, 0x3a, 0xd5, 0x1, 0xa0, 0x69, 0x5a, 0x77, 0x1d, 0x80, 0x31, 0x2e, 0x38, 0x9d, 0x4e, 0xb1, 0x66, 0x1, 0x30, 0xc, 0x23, 0x28, 0x3d, 0x93, 0x9b, 0x1, 0xb9, 0x9a, 0x6, 0x60, 0x36, 0x9b, 0x75, 0xd7, 0x1, 0x4a, 0x21, 0xa8, 0x26, 0x0, 0x94, 0xa, 0x41, 0xb2, 0x0, 0x18, 0x86, 0xc9, 0xe9, 0xd, 0x80, 0x52, 0x8, 0x92, 0x5, 0x60, 0xb1, 0x58, 0x74, 0x67, 0x1, 0xa5, 0x10, 0xa4, 0x4, 0x40, 0x77, 0x43, 0xd0, 0xe1, 0x70, 0xa8, 0x9f, 0x1, 0x14, 0x45, 0x1, 0x45, 0x51, 0x79, 0x3d, 0x1, 0x68, 0x6e, 0x6e, 0x4e, 0xaa, 0x6, 0x80, 0x10, 0x42, 0x6, 0x83, 0x41, 0x37, 0x36, 0x28, 0x15, 0x82, 0x6a, 0x2, 0x0, 0x4d, 0xd3, 0xa9, 0x52, 0xcf, 0x95, 0x0, 0xe8, 0x66, 0xe, 0x98, 0xcd, 0x66, 0xa1, 0x6c, 0x0, 0x7a, 0x5a, 0x8b, 0x59, 0x2c, 0x96, 0x64, 0xcd, 0x2, 0xb8, 0x2b, 0x4, 0xe9, 0xde, 0x2, 0x77, 0x85, 0xa0, 0x9a, 0xb0, 0x40, 0xa9, 0x10, 0xa4, 0x8, 0xc0, 0x64, 0x32, 0xe9, 0x6, 0x40, 0xa9, 0x10, 0x54, 0xaa, 0x3, 0x74, 0xf3, 0x16, 0x70, 0xb9, 0x5c, 0xe5, 0x3, 0xe8, 0xe9, 0xe9, 0x69, 0xd5, 0xc3, 0x66, 0x18, 0x63, 0x5c, 0x68, 0x6a, 0x6a, 0x12, 0xcb, 0x5, 0xa0, 0x9b, 0xd5, 0x38, 0x4d, 0xd3, 0x29, 0x8a, 0xa2, 0xa0, 0x2c, 0x0, 0x18, 0x63, 0x3e, 0x14, 0xa, 0xfd, 0x55, 0xb, 0x21, 0x48, 0xd1, 0x2, 0x7a, 0x59, 0x8d, 0xdf, 0x1b, 0x80, 0x1e, 0x56, 0xe3, 0x84, 0x10, 0x34, 0x30, 0x30, 0x60, 0xbb, 0xeb, 0x77, 0x46, 0x5, 0xef, 0x48, 0xcf, 0x4d, 0xec, 0x8d, 0x99, 0x5, 0xf5, 0xf5, 0xf5, 0xef, 0x46, 0x47, 0x47, 0xb, 0x2e, 0x97, 0xeb, 0xbc, 0x54, 0x8, 0x52, 0x4, 0xc0, 0x30, 0x8c, 0xf4, 0x5c, 0x4, 0x9b, 0x4c, 0xa6, 0xf4, 0xf8, 0xf8, 0xb8, 0xc8, 0xb2, 0x6c, 0x32, 0x9d, 0x4e, 0xff, 0xd4, 0xdd, 0xdd, 0x7d, 0x66, 0x34, 0x1a, 0x8b, 0xd7, 0x3, 0xfd, 0xae, 0x5b, 0x29, 0xb2, 0x57, 0x66, 0xb6, 0xb6, 0xb6, 0xde, 0xc4, 0xe3, 0xf1, 0x6f, 0xae, 0xaf, 0xc1, 0x28, 0x5d, 0x85, 0x79, 0x2, 0xc1, 0x60, 0xb5, 0x5a, 0xa3, 0xa3, 0xa3, 0xa3, 0x45, 0xab, 0xd5, 0x9a, 0x2a, 0x16, 0x8b, 0x8b, 0x6d, 0x6d, 0x6d, 0xef, 0xd5, 0x8a, 0x55, 0xd, 0x20, 0x91, 0x48, 0xbc, 0x3e, 0x38, 0x38, 0xf8, 0xda, 0x6e, 0xb7, 0xf7, 0x5f, 0x5c, 0x5c, 0xd4, 0x7b, 0xbd, 0xde, 0xbc, 0x20, 0x8, 0xcd, 0x85, 0x42, 0x81, 0xfe, 0xf0, 0xae, 0xac, 0x10, 0x98, 0x9b, 0xd5, 0xc5, 0x18, 0x17, 0x59, 0x96, 0x3d, 0x1d, 0x19, 0x19, 0x1, 0x96, 0x65, 0x5, 0x8a, 0xa2, 0x7e, 0x6c, 0x69, 0x69, 0x49, 0x3d, 0x44, 0xb0, 0x2a, 0x0, 0x1f, 0xcc, 0x74, 0x75, 0x41, 0xea, 0xfa, 0x7b, 0x32, 0x99, 0x64, 0x76, 0x77, 0x77, 0x5d, 0xe, 0x87, 0xa3, 0x5f, 0x14, 0xc5, 0x57, 0x57, 0x60, 0x5a, 0x8b, 0xc5, 0xa2, 0xf1, 0xbe, 0x50, 0x6e, 0xa, 0x66, 0x18, 0x26, 0x31, 0x36, 0x36, 0x96, 0x65, 0x59, 0x36, 0x29, 0x49, 0x92, 0xb7, 0xbd, 0xbd, 0xfd, 0x9f, 0x72, 0xda, 0xf9, 0xd1, 0x1, 0xa8, 0x1, 0x93, 0xcf, 0xe7, 0xa9, 0x93, 0x93, 0x13, 0x1b, 0x4d, 0xd3, 0x9f, 0xb, 0x82, 0x60, 0xf5, 0x7a, 0xbd, 0xd9, 0x54, 0x2a, 0xe5, 0xcc, 0x64, 0x32, 0xe, 0xb9, 0x6e, 0xb9, 0x16, 0x8c, 0x31, 0x2e, 0xda, 0x6c, 0xb6, 0xc8, 0xd0, 0xd0, 0x10, 0x65, 0xb3, 0xd9, 0x92, 0x95, 0xa8, 0x6e, 0xc5, 0x0, 0xa8, 0xe9, 0x96, 0x68, 0x34, 0x6a, 0xdd, 0xdf, 0xdf, 0x6f, 0x76, 0xb9, 0x5c, 0x9f, 0x89, 0xa2, 0x58, 0xbf, 0xb8, 0xb8, 0x8, 0x26, 0x93, 0x29, 0x3b, 0x3c, 0x3c, 0x8c, 0xed, 0x76, 0x7b, 0xd2, 0x68, 0x34, 0xfe, 0xd0, 0xd8, 0xd8, 0x98, 0xae, 0xb6, 0xe0, 0x8a, 0x1, 0x50, 0xb, 0xe6, 0xa9, 0x5, 0xbf, 0x9c, 0x97, 0xf3, 0xff, 0xf3, 0x2f, 0x6a, 0x82, 0x7f, 0xf6, 0x4e, 0xca, 0x1b, 0xf5, 0x0, 0x0, 0x0, 0x0, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 @@ -66,8 +66,8 @@ class TestPhysics2DMainLoop : public MainLoop { BodyShapeData body_shape_data[8]; void _create_body_shape_data() { - VisualServer *vs = VisualServer::get_singleton(); - Physics2DServer *ps = Physics2DServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); // SEGMENT @@ -86,13 +86,13 @@ class TestPhysics2DMainLoop : public MainLoop { Ref image = memnew(Image(32, 2, 0, Image::FORMAT_LA8, pixels)); - body_shape_data[Physics2DServer::SHAPE_SEGMENT].image = vs->texture_2d_create(image); + body_shape_data[PhysicsServer2D::SHAPE_SEGMENT].image = vs->texture_2d_create(image); RID segment_shape = ps->segment_shape_create(); Rect2 sg(Point2(-16, 0), Point2(16, 0)); ps->shape_set_data(segment_shape, sg); - body_shape_data[Physics2DServer::SHAPE_SEGMENT].shape = segment_shape; + body_shape_data[PhysicsServer2D::SHAPE_SEGMENT].shape = segment_shape; } // CIRCLE @@ -113,12 +113,12 @@ class TestPhysics2DMainLoop : public MainLoop { Ref image = memnew(Image(32, 32, 0, Image::FORMAT_LA8, pixels)); - body_shape_data[Physics2DServer::SHAPE_CIRCLE].image = vs->texture_2d_create(image); + body_shape_data[PhysicsServer2D::SHAPE_CIRCLE].image = vs->texture_2d_create(image); RID circle_shape = ps->circle_shape_create(); ps->shape_set_data(circle_shape, 16); - body_shape_data[Physics2DServer::SHAPE_CIRCLE].shape = circle_shape; + body_shape_data[PhysicsServer2D::SHAPE_CIRCLE].shape = circle_shape; } // BOX @@ -140,12 +140,12 @@ class TestPhysics2DMainLoop : public MainLoop { Ref image = memnew(Image(32, 32, 0, Image::FORMAT_LA8, pixels)); - body_shape_data[Physics2DServer::SHAPE_RECTANGLE].image = vs->texture_2d_create(image); + body_shape_data[PhysicsServer2D::SHAPE_RECTANGLE].image = vs->texture_2d_create(image); RID rectangle_shape = ps->rectangle_shape_create(); ps->shape_set_data(rectangle_shape, Vector2(16, 16)); - body_shape_data[Physics2DServer::SHAPE_RECTANGLE].shape = rectangle_shape; + body_shape_data[PhysicsServer2D::SHAPE_RECTANGLE].shape = rectangle_shape; } // CAPSULE @@ -168,12 +168,12 @@ class TestPhysics2DMainLoop : public MainLoop { Ref image = memnew(Image(32, 64, 0, Image::FORMAT_LA8, pixels)); - body_shape_data[Physics2DServer::SHAPE_CAPSULE].image = vs->texture_2d_create(image); + body_shape_data[PhysicsServer2D::SHAPE_CAPSULE].image = vs->texture_2d_create(image); RID capsule_shape = ps->capsule_shape_create(); ps->shape_set_data(capsule_shape, Vector2(16, 32)); - body_shape_data[Physics2DServer::SHAPE_CAPSULE].shape = capsule_shape; + body_shape_data[PhysicsServer2D::SHAPE_CAPSULE].shape = capsule_shape; } // CONVEX @@ -182,7 +182,7 @@ class TestPhysics2DMainLoop : public MainLoop { Ref image = memnew(Image(convex_png)); - body_shape_data[Physics2DServer::SHAPE_CONVEX_POLYGON].image = vs->texture_2d_create(image); + body_shape_data[PhysicsServer2D::SHAPE_CONVEX_POLYGON].image = vs->texture_2d_create(image); RID convex_polygon_shape = ps->convex_polygon_shape_create(); @@ -197,14 +197,14 @@ class TestPhysics2DMainLoop : public MainLoop { arr.push_back(Point2(11, 7) - sb); ps->shape_set_data(convex_polygon_shape, arr); - body_shape_data[Physics2DServer::SHAPE_CONVEX_POLYGON].shape = convex_polygon_shape; + body_shape_data[PhysicsServer2D::SHAPE_CONVEX_POLYGON].shape = convex_polygon_shape; } } void _do_ray_query() { /* - Physics2DServer *ps = Physics2DServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); ps->query_intersection_segment(ray_query,ray_from,ray_to); */ } @@ -246,16 +246,16 @@ protected: } } - RID _add_body(Physics2DServer::ShapeType p_shape, const Transform2D &p_xform) { + RID _add_body(PhysicsServer2D::ShapeType p_shape, const Transform2D &p_xform) { - VisualServer *vs = VisualServer::get_singleton(); - Physics2DServer *ps = Physics2DServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); RID body = ps->body_create(); ps->body_add_shape(body, body_shape_data[p_shape].shape); ps->body_set_space(body, space); - ps->body_set_continuous_collision_detection_mode(body, Physics2DServer::CCD_MODE_CAST_SHAPE); - ps->body_set_state(body, Physics2DServer::BODY_STATE_TRANSFORM, p_xform); + ps->body_set_continuous_collision_detection_mode(body, PhysicsServer2D::CCD_MODE_CAST_SHAPE); + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, p_xform); //print_line("add body with xform: "+p_xform); RID sprite = vs->canvas_item_create(); @@ -273,7 +273,7 @@ protected: void _add_plane(const Vector2 &p_normal, real_t p_d) { - Physics2DServer *ps = Physics2DServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); Array arr; arr.push_back(p_normal); @@ -283,23 +283,23 @@ protected: ps->shape_set_data(plane, arr); RID plane_body = ps->body_create(); - ps->body_set_mode(plane_body, Physics2DServer::BODY_MODE_STATIC); + ps->body_set_mode(plane_body, PhysicsServer2D::BODY_MODE_STATIC); ps->body_set_space(plane_body, space); ps->body_add_shape(plane_body, plane); } void _add_concave(const Vector &p_points, const Transform2D &p_xform = Transform2D()) { - Physics2DServer *ps = Physics2DServer::get_singleton(); - VisualServer *vs = VisualServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); RID concave = ps->concave_polygon_shape_create(); ps->shape_set_data(concave, p_points); RID body = ps->body_create(); - ps->body_set_mode(body, Physics2DServer::BODY_MODE_STATIC); + ps->body_set_mode(body, PhysicsServer2D::BODY_MODE_STATIC); ps->body_set_space(body, space); ps->body_add_shape(body, concave); - ps->body_set_state(body, Physics2DServer::BODY_STATE_TRANSFORM, p_xform); + ps->body_set_state(body, PhysicsServer2D::BODY_STATE_TRANSFORM, p_xform); RID sprite = vs->canvas_item_create(); vs->canvas_item_set_parent(sprite, canvas); @@ -310,8 +310,8 @@ protected: } void _body_moved(Object *p_state, RID p_sprite) { - Physics2DDirectBodyState *state = (Physics2DDirectBodyState *)p_state; - VisualServer::get_singleton()->canvas_item_set_transform(p_sprite, state->get_transform()); + PhysicsDirectBodyState2D *state = (PhysicsDirectBodyState2D *)p_state; + RenderingServer::get_singleton()->canvas_item_set_transform(p_sprite, state->get_transform()); } void _ray_query_callback(const RID &p_rid, ObjectID p_id, int p_shape, const Vector2 &p_point, const Vector2 &p_normal) { @@ -324,7 +324,7 @@ protected: ray_end = ray_to; } - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); vs->canvas_item_clear(ray); vs->canvas_item_add_line(ray, ray_from, ray_end, p_rid.is_valid() ? Color(0, 1, 0.4) : Color(1, 0.4, 0), 2); @@ -341,14 +341,14 @@ protected: public: virtual void init() { - VisualServer *vs = VisualServer::get_singleton(); - Physics2DServer *ps = Physics2DServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); space = ps->space_create(); ps->space_set_active(space, true); ps->set_active(true); - ps->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY_VECTOR, Vector2(0, 1)); - ps->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY, 98); + ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, Vector2(0, 1)); + ps->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, 98); { @@ -378,25 +378,25 @@ public: for (int i = 0; i < 32; i++) { - Physics2DServer::ShapeType types[4] = { - Physics2DServer::SHAPE_CIRCLE, - Physics2DServer::SHAPE_CAPSULE, - Physics2DServer::SHAPE_RECTANGLE, - Physics2DServer::SHAPE_CONVEX_POLYGON, + PhysicsServer2D::ShapeType types[4] = { + PhysicsServer2D::SHAPE_CIRCLE, + PhysicsServer2D::SHAPE_CAPSULE, + PhysicsServer2D::SHAPE_RECTANGLE, + PhysicsServer2D::SHAPE_CONVEX_POLYGON, }; - Physics2DServer::ShapeType type = types[i % 4]; - //type=Physics2DServer::SHAPE_SEGMENT; + PhysicsServer2D::ShapeType type = types[i % 4]; + //type=PhysicsServer2D::SHAPE_SEGMENT; _add_body(type, Transform2D(i * 0.8, Point2(152 + i * 40, 100 - 40 * i))); /* if (i==0) - ps->body_set_mode(b,Physics2DServer::BODY_MODE_STATIC); + ps->body_set_mode(b,PhysicsServer2D::BODY_MODE_STATIC); */ } - //RID b= _add_body(Physics2DServer::SHAPE_CIRCLE,Transform2D(0,Point2(101,140))); - //ps->body_set_mode(b,Physics2DServer::BODY_MODE_STATIC); + //RID b= _add_body(PhysicsServer2D::SHAPE_CIRCLE,Transform2D(0,Point2(101,140))); + //ps->body_set_mode(b,PhysicsServer2D::BODY_MODE_STATIC); Point2 prev; diff --git a/main/tests/test_render.cpp b/main/tests/test_render.cpp index 0fbc5ea697..bcfcf61e25 100644 --- a/main/tests/test_render.cpp +++ b/main/tests/test_render.cpp @@ -37,7 +37,7 @@ #include "core/os/os.h" #include "core/print_string.h" #include "servers/display_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #define OBJECT_COUNT 50 @@ -75,7 +75,7 @@ public: virtual void init() { print_line("INITIALIZING TEST RENDER"); - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); test_cube = vs->get_test_cube(); scenario = vs->scenario_create(); @@ -126,7 +126,7 @@ public: print_line("ERR: " + itos(err)); test_cube = vs->mesh_create(); vs->mesh_add_surface_from_mesh_data(test_cube, md); - //vs->scenario_set_debug(scenario,VS::SCENARIO_DEBUG_WIREFRAME); + //vs->scenario_set_debug(scenario,RS::SCENARIO_DEBUG_WIREFRAME); /* RID sm = vs->shader_create(); @@ -174,16 +174,16 @@ public: vs->camera_set_perspective(camera, 60, 0.1, 1000); /* - RID lightaux = vs->light_create( VisualServer::LIGHT_OMNI ); - vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_RADIUS, 80 ); - vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ATTENUATION, 1 ); - vs->light_set_var( lightaux, VisualServer::LIGHT_VAR_ENERGY, 1.5 ); + RID lightaux = vs->light_create( RenderingServer::LIGHT_OMNI ); + vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_RADIUS, 80 ); + vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_ATTENUATION, 1 ); + vs->light_set_var( lightaux, RenderingServer::LIGHT_VAR_ENERGY, 1.5 ); light = vs->instance_create( lightaux ); */ RID lightaux; lightaux = vs->directional_light_create(); - //vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) ); + //vs->light_set_color( lightaux, RenderingServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,0.0) ); vs->light_set_color(lightaux, Color(1.0, 1.0, 1.0)); //vs->light_set_shadow( lightaux, true ); light = vs->instance_create2(lightaux, scenario); @@ -194,10 +194,10 @@ public: vs->instance_set_transform(light, lla); lightaux = vs->omni_light_create(); - //vs->light_set_color( lightaux, VisualServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,1.0) ); + //vs->light_set_color( lightaux, RenderingServer::LIGHT_COLOR_AMBIENT, Color(0.0,0.0,1.0) ); vs->light_set_color(lightaux, Color(1.0, 1.0, 0.0)); - vs->light_set_param(lightaux, VisualServer::LIGHT_PARAM_RANGE, 4); - vs->light_set_param(lightaux, VisualServer::LIGHT_PARAM_ENERGY, 8); + vs->light_set_param(lightaux, RenderingServer::LIGHT_PARAM_RANGE, 4); + vs->light_set_param(lightaux, RenderingServer::LIGHT_PARAM_ENERGY, 8); //vs->light_set_shadow( lightaux, true ); //light = vs->instance_create( lightaux ); @@ -206,7 +206,7 @@ public: } virtual bool iteration(float p_time) { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); //Transform t; //t.rotate(Vector3(0, 1, 0), ofs); //t.translate(Vector3(0,0,20 )); diff --git a/main/tests/test_shader_lang.cpp b/main/tests/test_shader_lang.cpp index 941a6771bf..dd525d7653 100644 --- a/main/tests/test_shader_lang.cpp +++ b/main/tests/test_shader_lang.cpp @@ -37,7 +37,7 @@ #include "core/print_string.h" #include "scene/gui/control.h" #include "scene/gui/text_edit.h" -#include "servers/visual/shader_language.h" +#include "servers/rendering/shader_language.h" typedef ShaderLanguage SL; diff --git a/modules/assimp/editor_scene_importer_assimp.cpp b/modules/assimp/editor_scene_importer_assimp.cpp index 1482fe99eb..d163512bb3 100644 --- a/modules/assimp/editor_scene_importer_assimp.cpp +++ b/modules/assimp/editor_scene_importer_assimp.cpp @@ -1208,9 +1208,9 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat } Array array_copy; - array_copy.resize(VisualServer::ARRAY_MAX); + array_copy.resize(RenderingServer::ARRAY_MAX); - for (int l = 0; l < VisualServer::ARRAY_MAX; l++) { + for (int l = 0; l < RenderingServer::ARRAY_MAX; l++) { array_copy[l] = array_mesh[l].duplicate(true); } @@ -1224,13 +1224,13 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Vector3 position = Vector3(ai_pos.x, ai_pos.y, ai_pos.z); vertices.ptrw()[l] = position; } - PackedVector3Array new_vertices = array_copy[VisualServer::ARRAY_VERTEX].duplicate(true); + PackedVector3Array new_vertices = array_copy[RenderingServer::ARRAY_VERTEX].duplicate(true); ERR_CONTINUE(vertices.size() != new_vertices.size()); for (int32_t l = 0; l < new_vertices.size(); l++) { Vector3 *w = new_vertices.ptrw(); w[l] = vertices[l]; } - array_copy[VisualServer::ARRAY_VERTEX] = new_vertices; + array_copy[RenderingServer::ARRAY_VERTEX] = new_vertices; } int32_t color_set = 0; @@ -1242,13 +1242,13 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Color color = Color(ai_color.r, ai_color.g, ai_color.b, ai_color.a); colors.ptrw()[l] = color; } - PackedColorArray new_colors = array_copy[VisualServer::ARRAY_COLOR].duplicate(true); + PackedColorArray new_colors = array_copy[RenderingServer::ARRAY_COLOR].duplicate(true); ERR_CONTINUE(colors.size() != new_colors.size()); for (int32_t l = 0; l < colors.size(); l++) { Color *w = new_colors.ptrw(); w[l] = colors[l]; } - array_copy[VisualServer::ARRAY_COLOR] = new_colors; + array_copy[RenderingServer::ARRAY_COLOR] = new_colors; } if (ai_mesh->mAnimMeshes[j]->HasNormals()) { @@ -1259,13 +1259,13 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat Vector3 normal = Vector3(ai_normal.x, ai_normal.y, ai_normal.z); normals.ptrw()[l] = normal; } - PackedVector3Array new_normals = array_copy[VisualServer::ARRAY_NORMAL].duplicate(true); + PackedVector3Array new_normals = array_copy[RenderingServer::ARRAY_NORMAL].duplicate(true); ERR_CONTINUE(normals.size() != new_normals.size()); for (int l = 0; l < normals.size(); l++) { Vector3 *w = new_normals.ptrw(); w[l] = normals[l]; } - array_copy[VisualServer::ARRAY_NORMAL] = new_normals; + array_copy[RenderingServer::ARRAY_NORMAL] = new_normals; } if (ai_mesh->mAnimMeshes[j]->HasTangentsAndBitangents()) { @@ -1275,7 +1275,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat for (size_t l = 0; l < num_vertices; l++) { AssimpUtils::calc_tangent_from_mesh(ai_mesh, j, l, l, w); } - PackedFloat32Array new_tangents = array_copy[VisualServer::ARRAY_TANGENT].duplicate(true); + PackedFloat32Array new_tangents = array_copy[RenderingServer::ARRAY_TANGENT].duplicate(true); ERR_CONTINUE(new_tangents.size() != tangents.size() * 4); for (int32_t l = 0; l < tangents.size(); l++) { new_tangents.ptrw()[l + 0] = tangents[l].r; @@ -1283,7 +1283,7 @@ EditorSceneImporterAssimp::_generate_mesh_from_surface_indices(ImportState &stat new_tangents.ptrw()[l + 2] = tangents[l].b; new_tangents.ptrw()[l + 3] = tangents[l].a; } - array_copy[VisualServer::ARRAY_TANGENT] = new_tangents; + array_copy[RenderingServer::ARRAY_TANGENT] = new_tangents; } morphs[j] = array_copy; diff --git a/modules/basis_universal/register_types.cpp b/modules/basis_universal/register_types.cpp index c29e91b5aa..bf6bc1debd 100644 --- a/modules/basis_universal/register_types.cpp +++ b/modules/basis_universal/register_types.cpp @@ -31,7 +31,7 @@ #include "register_types.h" #include "core/os/os.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #include "texture_basisu.h" #ifdef TOOLS_ENABLED @@ -164,10 +164,10 @@ static Ref basis_universal_unpacker(const Vector &p_buffer) { switch (*(uint32_t *)(ptr)) { case BASIS_DECOMPRESS_RG: { - if (VS::get_singleton()->has_os_feature("rgtc")) { + if (RS::get_singleton()->has_os_feature("rgtc")) { format = basist::transcoder_texture_format::cTFBC5; // get this from renderer imgfmt = Image::FORMAT_RGTC_RG; - } else if (VS::get_singleton()->has_os_feature("etc2")) { + } else if (RS::get_singleton()->has_os_feature("etc2")) { //unfortunately, basis universal does not support // ERR_FAIL_V(image); //unimplemented here @@ -179,13 +179,13 @@ static Ref basis_universal_unpacker(const Vector &p_buffer) { } } break; case BASIS_DECOMPRESS_RGB: { - if (VS::get_singleton()->has_os_feature("bptc")) { + if (RS::get_singleton()->has_os_feature("bptc")) { format = basist::transcoder_texture_format::cTFBC7_M6_OPAQUE_ONLY; // get this from renderer imgfmt = Image::FORMAT_BPTC_RGBA; - } else if (VS::get_singleton()->has_os_feature("s3tc")) { + } else if (RS::get_singleton()->has_os_feature("s3tc")) { format = basist::transcoder_texture_format::cTFBC1; // get this from renderer imgfmt = Image::FORMAT_DXT1; - } else if (VS::get_singleton()->has_os_feature("etc")) { + } else if (RS::get_singleton()->has_os_feature("etc")) { format = basist::transcoder_texture_format::cTFETC1; // get this from renderer imgfmt = Image::FORMAT_ETC; @@ -196,13 +196,13 @@ static Ref basis_universal_unpacker(const Vector &p_buffer) { } break; case BASIS_DECOMPRESS_RGBA: { - if (VS::get_singleton()->has_os_feature("bptc")) { + if (RS::get_singleton()->has_os_feature("bptc")) { format = basist::transcoder_texture_format::cTFBC7_M5; // get this from renderer imgfmt = Image::FORMAT_BPTC_RGBA; - } else if (VS::get_singleton()->has_os_feature("s3tc")) { + } else if (RS::get_singleton()->has_os_feature("s3tc")) { format = basist::transcoder_texture_format::cTFBC3; // get this from renderer imgfmt = Image::FORMAT_DXT5; - } else if (VS::get_singleton()->has_os_feature("etc2")) { + } else if (RS::get_singleton()->has_os_feature("etc2")) { format = basist::transcoder_texture_format::cTFETC2; // get this from renderer imgfmt = Image::FORMAT_ETC2_RGBA8; } else { @@ -212,10 +212,10 @@ static Ref basis_universal_unpacker(const Vector &p_buffer) { } } break; case BASIS_DECOMPRESS_RG_AS_RA: { - if (VS::get_singleton()->has_os_feature("s3tc")) { + if (RS::get_singleton()->has_os_feature("s3tc")) { format = basist::transcoder_texture_format::cTFBC3; // get this from renderer imgfmt = Image::FORMAT_DXT5_RA_AS_RG; - } else if (VS::get_singleton()->has_os_feature("etc2")) { + } else if (RS::get_singleton()->has_os_feature("etc2")) { format = basist::transcoder_texture_format::cTFETC2; // get this from renderer imgfmt = Image::FORMAT_ETC2_RGBA8; } else { diff --git a/modules/basis_universal/texture_basisu.cpp b/modules/basis_universal/texture_basisu.cpp index 12f3241c98..9c3cdac36c 100644 --- a/modules/basis_universal/texture_basisu.cpp +++ b/modules/basis_universal/texture_basisu.cpp @@ -72,7 +72,7 @@ bool TextureBasisU::has_alpha() const { void TextureBasisU::set_flags(uint32_t p_flags) { flags = p_flags; - VisualServer::get_singleton()->texture_set_flags(texture, p_flags); + RenderingServer::get_singleton()->texture_set_flags(texture, p_flags); }; uint32_t TextureBasisU::get_flags() const { @@ -144,8 +144,8 @@ void TextureBasisU::set_basisu_data(const Vector& p_data) { img.instance(); img->create(info.m_width, info.m_height, info.m_total_levels > 1, imgfmt, gpudata); - VisualServer::get_singleton()->texture_allocate(texture, tex_size.x, tex_size.y, 0, img->get_format(), VS::TEXTURE_TYPE_2D, flags); - VisualServer::get_singleton()->texture_set_data(texture, img); + RenderingServer::get_singleton()->texture_allocate(texture, tex_size.x, tex_size.y, 0, img->get_format(), RS::TEXTURE_TYPE_2D, flags); + RenderingServer::get_singleton()->texture_set_data(texture, img); }; Error TextureBasisU::import(const Ref& p_img) { @@ -221,13 +221,13 @@ Vector TextureBasisU::get_basisu_data() const { TextureBasisU::TextureBasisU() { flags = FLAGS_DEFAULT; - texture = VisualServer::get_singleton()->texture_create(); + texture = RenderingServer::get_singleton()->texture_create(); }; TextureBasisU::~TextureBasisU() { - VisualServer::get_singleton()->free(texture); + RenderingServer::get_singleton()->free(texture); }; #endif diff --git a/modules/bullet/area_bullet.cpp b/modules/bullet/area_bullet.cpp index e8a5c1475a..4d727529ef 100644 --- a/modules/bullet/area_bullet.cpp +++ b/modules/bullet/area_bullet.cpp @@ -46,7 +46,7 @@ AreaBullet::AreaBullet() : RigidCollisionObjectBullet(CollisionObjectBullet::TYPE_AREA), monitorable(true), - spOv_mode(PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED), + spOv_mode(PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED), spOv_gravityPoint(false), spOv_gravityPointDistanceScale(0), spOv_gravityPointAttenuation(1), @@ -86,11 +86,11 @@ void AreaBullet::dispatch_callbacks() { switch (otherObj.state) { case OVERLAP_STATE_ENTER: otherObj.state = OVERLAP_STATE_INSIDE; - call_event(otherObj.object, PhysicsServer::AREA_BODY_ADDED); + call_event(otherObj.object, PhysicsServer3D::AREA_BODY_ADDED); otherObj.object->on_enter_area(this); break; case OVERLAP_STATE_EXIT: - call_event(otherObj.object, PhysicsServer::AREA_BODY_REMOVED); + call_event(otherObj.object, PhysicsServer3D::AREA_BODY_REMOVED); otherObj.object->on_exit_area(this); overlappingObjects.remove(i); // Remove after callback break; @@ -101,7 +101,7 @@ void AreaBullet::dispatch_callbacks() { } } -void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status) { +void AreaBullet::call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status) { InOutEventCallback &event = eventsCallbacks[static_cast(p_otherObject->getType())]; Object *areaGodoObject = ObjectDB::get_instance(event.event_callback_id); @@ -130,7 +130,7 @@ void AreaBullet::scratch() { void AreaBullet::clear_overlaps(bool p_notify) { for (int i = overlappingObjects.size() - 1; 0 <= i; --i) { if (p_notify) - call_event(overlappingObjects[i].object, PhysicsServer::AREA_BODY_REMOVED); + call_event(overlappingObjects[i].object, PhysicsServer3D::AREA_BODY_REMOVED); overlappingObjects[i].object->on_exit_area(this); } overlappingObjects.clear(); @@ -140,7 +140,7 @@ void AreaBullet::remove_overlap(CollisionObjectBullet *p_object, bool p_notify) for (int i = overlappingObjects.size() - 1; 0 <= i; --i) { if (overlappingObjects[i].object == p_object) { if (p_notify) - call_event(overlappingObjects[i].object, PhysicsServer::AREA_BODY_REMOVED); + call_event(overlappingObjects[i].object, PhysicsServer3D::AREA_BODY_REMOVED); overlappingObjects[i].object->on_exit_area(this); overlappingObjects.remove(i); break; @@ -218,30 +218,30 @@ void AreaBullet::put_overlap_as_inside(int p_index) { } } -void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) { +void AreaBullet::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: set_spOv_gravityMag(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: set_spOv_gravityVec(p_value); break; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: set_spOv_linearDump(p_value); break; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: set_spOv_angularDump(p_value); break; - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_PRIORITY: set_spOv_priority(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: set_spOv_gravityPoint(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: set_spOv_gravityPointDistanceScale(p_value); break; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: set_spOv_gravityPointAttenuation(p_value); break; default: @@ -249,23 +249,23 @@ void AreaBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant & } } -Variant AreaBullet::get_param(PhysicsServer::AreaParameter p_param) const { +Variant AreaBullet::get_param(PhysicsServer3D::AreaParameter p_param) const { switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: return spOv_gravityMag; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: return spOv_gravityVec; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: return spOv_linearDump; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: return spOv_angularDump; - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_PRIORITY: return spOv_priority; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return spOv_gravityPoint; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return spOv_gravityPointDistanceScale; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return spOv_gravityPointAttenuation; default: WARN_PRINT("Area doesn't support this parameter in the Bullet backend: " + itos(p_param)); diff --git a/modules/bullet/area_bullet.h b/modules/bullet/area_bullet.h index 18888c6725..56977d4451 100644 --- a/modules/bullet/area_bullet.h +++ b/modules/bullet/area_bullet.h @@ -33,7 +33,7 @@ #include "collision_object_bullet.h" #include "core/vector.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "space_bullet.h" /** @@ -88,7 +88,7 @@ private: Vector overlappingObjects; bool monitorable; - PhysicsServer::AreaSpaceOverrideMode spOv_mode; + PhysicsServer3D::AreaSpaceOverrideMode spOv_mode; bool spOv_gravityPoint; real_t spOv_gravityPointDistanceScale; real_t spOv_gravityPointAttenuation; @@ -114,8 +114,8 @@ public: bool is_monitoring() const; - _FORCE_INLINE_ void set_spOv_mode(PhysicsServer::AreaSpaceOverrideMode p_mode) { spOv_mode = p_mode; } - _FORCE_INLINE_ PhysicsServer::AreaSpaceOverrideMode get_spOv_mode() { return spOv_mode; } + _FORCE_INLINE_ void set_spOv_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { spOv_mode = p_mode; } + _FORCE_INLINE_ PhysicsServer3D::AreaSpaceOverrideMode get_spOv_mode() { return spOv_mode; } _FORCE_INLINE_ void set_spOv_gravityPoint(bool p_isGP) { spOv_gravityPoint = p_isGP; } _FORCE_INLINE_ bool is_spOv_gravityPoint() { return spOv_gravityPoint; } @@ -146,7 +146,7 @@ public: virtual void set_space(SpaceBullet *p_space); virtual void dispatch_callbacks(); - void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer::AreaBodyStatus p_status); + void call_event(CollisionObjectBullet *p_otherObject, PhysicsServer3D::AreaBodyStatus p_status); void set_on_state_change(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); void scratch(); @@ -162,8 +162,8 @@ public: void put_overlap_as_exit(int p_index); void put_overlap_as_inside(int p_index); - void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value); - Variant get_param(PhysicsServer::AreaParameter p_param) const; + void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); + Variant get_param(PhysicsServer3D::AreaParameter p_param) const; void set_event_callback(Type p_callbackObjectType, ObjectID p_id, const StringName &p_method); bool has_event_callback(Type p_callbackObjectType); diff --git a/modules/bullet/bullet_physics_server.cpp b/modules/bullet/bullet_physics_server.cpp index 89868babc6..5b3fe1bfac 100644 --- a/modules/bullet/bullet_physics_server.cpp +++ b/modules/bullet/bullet_physics_server.cpp @@ -74,18 +74,18 @@ body->get_space()->add_constraint(joint, joint->is_disabled_collisions_between_bodies()); // <--------------- Joint creation asserts -void BulletPhysicsServer::_bind_methods() { - //ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer::DoTest); +void BulletPhysicsServer3D::_bind_methods() { + //ClassDB::bind_method(D_METHOD("DoTest"), &BulletPhysicsServer3D::DoTest); } -BulletPhysicsServer::BulletPhysicsServer() : - PhysicsServer(), +BulletPhysicsServer3D::BulletPhysicsServer3D() : + PhysicsServer3D(), active(true), active_spaces_count(0) {} -BulletPhysicsServer::~BulletPhysicsServer() {} +BulletPhysicsServer3D::~BulletPhysicsServer3D() {} -RID BulletPhysicsServer::shape_create(ShapeType p_shape) { +RID BulletPhysicsServer3D::shape_create(ShapeType p_shape) { ShapeBullet *shape = NULL; switch (p_shape) { @@ -133,51 +133,51 @@ RID BulletPhysicsServer::shape_create(ShapeType p_shape) { CreateThenReturnRID(shape_owner, shape) } -void BulletPhysicsServer::shape_set_data(RID p_shape, const Variant &p_data) { +void BulletPhysicsServer3D::shape_set_data(RID p_shape, const Variant &p_data) { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND(!shape); shape->set_data(p_data); } -void BulletPhysicsServer::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { +void BulletPhysicsServer3D::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { //WARN_PRINT("Bias not supported by Bullet physics engine"); } -PhysicsServer::ShapeType BulletPhysicsServer::shape_get_type(RID p_shape) const { +PhysicsServer3D::ShapeType BulletPhysicsServer3D::shape_get_type(RID p_shape) const { ShapeBullet *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, PhysicsServer::SHAPE_CUSTOM); + ERR_FAIL_COND_V(!shape, PhysicsServer3D::SHAPE_CUSTOM); return shape->get_type(); } -Variant BulletPhysicsServer::shape_get_data(RID p_shape) const { +Variant BulletPhysicsServer3D::shape_get_data(RID p_shape) const { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, Variant()); return shape->get_data(); } -void BulletPhysicsServer::shape_set_margin(RID p_shape, real_t p_margin) { +void BulletPhysicsServer3D::shape_set_margin(RID p_shape, real_t p_margin) { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND(!shape); shape->set_margin(p_margin); } -real_t BulletPhysicsServer::shape_get_margin(RID p_shape) const { +real_t BulletPhysicsServer3D::shape_get_margin(RID p_shape) const { ShapeBullet *shape = shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, 0.0); return shape->get_margin(); } -real_t BulletPhysicsServer::shape_get_custom_solver_bias(RID p_shape) const { +real_t BulletPhysicsServer3D::shape_get_custom_solver_bias(RID p_shape) const { //WARN_PRINT("Bias not supported by Bullet physics engine"); return 0.; } -RID BulletPhysicsServer::space_create() { +RID BulletPhysicsServer3D::space_create() { SpaceBullet *space = bulletnew(SpaceBullet); CreateThenReturnRID(space_owner, space); } -void BulletPhysicsServer::space_set_active(RID p_space, bool p_active) { +void BulletPhysicsServer3D::space_set_active(RID p_space, bool p_active) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); @@ -195,61 +195,61 @@ void BulletPhysicsServer::space_set_active(RID p_space, bool p_active) { } } -bool BulletPhysicsServer::space_is_active(RID p_space) const { +bool BulletPhysicsServer3D::space_is_active(RID p_space) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, false); return -1 != active_spaces.find(space); } -void BulletPhysicsServer::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { +void BulletPhysicsServer3D::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); space->set_param(p_param, p_value); } -real_t BulletPhysicsServer::space_get_param(RID p_space, SpaceParameter p_param) const { +real_t BulletPhysicsServer3D::space_get_param(RID p_space, SpaceParameter p_param) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, 0); return space->get_param(p_param); } -PhysicsDirectSpaceState *BulletPhysicsServer::space_get_direct_state(RID p_space) { +PhysicsDirectSpaceState3D *BulletPhysicsServer3D::space_get_direct_state(RID p_space) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, NULL); return space->get_direct_state(); } -void BulletPhysicsServer::space_set_debug_contacts(RID p_space, int p_max_contacts) { +void BulletPhysicsServer3D::space_set_debug_contacts(RID p_space, int p_max_contacts) { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND(!space); space->set_debug_contacts(p_max_contacts); } -Vector BulletPhysicsServer::space_get_contacts(RID p_space) const { +Vector BulletPhysicsServer3D::space_get_contacts(RID p_space) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, Vector()); return space->get_debug_contacts(); } -int BulletPhysicsServer::space_get_contact_count(RID p_space) const { +int BulletPhysicsServer3D::space_get_contact_count(RID p_space) const { SpaceBullet *space = space_owner.getornull(p_space); ERR_FAIL_COND_V(!space, 0); return space->get_debug_contact_count(); } -RID BulletPhysicsServer::area_create() { +RID BulletPhysicsServer3D::area_create() { AreaBullet *area = bulletnew(AreaBullet); area->set_collision_layer(1); area->set_collision_mask(1); CreateThenReturnRID(area_owner, area) } -void BulletPhysicsServer::area_set_space(RID p_area, RID p_space) { +void BulletPhysicsServer3D::area_set_space(RID p_area, RID p_space) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); SpaceBullet *space = NULL; @@ -260,26 +260,26 @@ void BulletPhysicsServer::area_set_space(RID p_area, RID p_space) { area->set_space(space); } -RID BulletPhysicsServer::area_get_space(RID p_area) const { +RID BulletPhysicsServer3D::area_get_space(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); return area->get_space()->get_self(); } -void BulletPhysicsServer::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { +void BulletPhysicsServer3D::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_spOv_mode(p_mode); } -PhysicsServer::AreaSpaceOverrideMode BulletPhysicsServer::area_get_space_override_mode(RID p_area) const { +PhysicsServer3D::AreaSpaceOverrideMode BulletPhysicsServer3D::area_get_space_override_mode(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED); + ERR_FAIL_COND_V(!area, PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED); return area->get_spOv_mode(); } -void BulletPhysicsServer::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { +void BulletPhysicsServer3D::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); @@ -289,7 +289,7 @@ void BulletPhysicsServer::area_add_shape(RID p_area, RID p_shape, const Transfor area->add_shape(shape, p_transform, p_disabled); } -void BulletPhysicsServer::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { +void BulletPhysicsServer3D::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); @@ -299,41 +299,41 @@ void BulletPhysicsServer::area_set_shape(RID p_area, int p_shape_idx, RID p_shap area->set_shape(p_shape_idx, shape); } -void BulletPhysicsServer::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { +void BulletPhysicsServer3D::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_shape_transform(p_shape_idx, p_transform); } -int BulletPhysicsServer::area_get_shape_count(RID p_area) const { +int BulletPhysicsServer3D::area_get_shape_count(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, 0); return area->get_shape_count(); } -RID BulletPhysicsServer::area_get_shape(RID p_area, int p_shape_idx) const { +RID BulletPhysicsServer3D::area_get_shape(RID p_area, int p_shape_idx) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, RID()); return area->get_shape(p_shape_idx)->get_self(); } -Transform BulletPhysicsServer::area_get_shape_transform(RID p_area, int p_shape_idx) const { +Transform BulletPhysicsServer3D::area_get_shape_transform(RID p_area, int p_shape_idx) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, Transform()); return area->get_shape_transform(p_shape_idx); } -void BulletPhysicsServer::area_remove_shape(RID p_area, int p_shape_idx) { +void BulletPhysicsServer3D::area_remove_shape(RID p_area, int p_shape_idx) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); return area->remove_shape_full(p_shape_idx); } -void BulletPhysicsServer::area_clear_shapes(RID p_area) { +void BulletPhysicsServer3D::area_clear_shapes(RID p_area) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); @@ -341,14 +341,14 @@ void BulletPhysicsServer::area_clear_shapes(RID p_area) { area->remove_shape_full(0); } -void BulletPhysicsServer::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { +void BulletPhysicsServer3D::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_shape_disabled(p_shape_idx, p_disabled); } -void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_id) { +void BulletPhysicsServer3D::area_attach_object_instance_id(RID p_area, ObjectID p_id) { if (space_owner.owns(p_area)) { return; } @@ -357,7 +357,7 @@ void BulletPhysicsServer::area_attach_object_instance_id(RID p_area, ObjectID p_ area->set_instance_id(p_id); } -ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const { +ObjectID BulletPhysicsServer3D::area_get_object_instance_id(RID p_area) const { if (space_owner.owns(p_area)) { return ObjectID(); } @@ -366,7 +366,7 @@ ObjectID BulletPhysicsServer::area_get_object_instance_id(RID p_area) const { return area->get_instance_id(); } -void BulletPhysicsServer::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { +void BulletPhysicsServer3D::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { if (space_owner.owns(p_area)) { SpaceBullet *space = space_owner.getornull(p_area); if (space) { @@ -381,7 +381,7 @@ void BulletPhysicsServer::area_set_param(RID p_area, AreaParameter p_param, cons } } -Variant BulletPhysicsServer::area_get_param(RID p_area, AreaParameter p_param) const { +Variant BulletPhysicsServer3D::area_get_param(RID p_area, AreaParameter p_param) const { if (space_owner.owns(p_area)) { SpaceBullet *space = space_owner.getornull(p_area); return space->get_param(p_param); @@ -393,64 +393,64 @@ Variant BulletPhysicsServer::area_get_param(RID p_area, AreaParameter p_param) c } } -void BulletPhysicsServer::area_set_transform(RID p_area, const Transform &p_transform) { +void BulletPhysicsServer3D::area_set_transform(RID p_area, const Transform &p_transform) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_transform(p_transform); } -Transform BulletPhysicsServer::area_get_transform(RID p_area) const { +Transform BulletPhysicsServer3D::area_get_transform(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, Transform()); return area->get_transform(); } -void BulletPhysicsServer::area_set_collision_mask(RID p_area, uint32_t p_mask) { +void BulletPhysicsServer3D::area_set_collision_mask(RID p_area, uint32_t p_mask) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_collision_mask(p_mask); } -void BulletPhysicsServer::area_set_collision_layer(RID p_area, uint32_t p_layer) { +void BulletPhysicsServer3D::area_set_collision_layer(RID p_area, uint32_t p_layer) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_collision_layer(p_layer); } -void BulletPhysicsServer::area_set_monitorable(RID p_area, bool p_monitorable) { +void BulletPhysicsServer3D::area_set_monitorable(RID p_area, bool p_monitorable) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_monitorable(p_monitorable); } -void BulletPhysicsServer::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { +void BulletPhysicsServer3D::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_event_callback(CollisionObjectBullet::TYPE_RIGID_BODY, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } -void BulletPhysicsServer::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { +void BulletPhysicsServer3D::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_event_callback(CollisionObjectBullet::TYPE_AREA, p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); } -void BulletPhysicsServer::area_set_ray_pickable(RID p_area, bool p_enable) { +void BulletPhysicsServer3D::area_set_ray_pickable(RID p_area, bool p_enable) { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND(!area); area->set_ray_pickable(p_enable); } -bool BulletPhysicsServer::area_is_ray_pickable(RID p_area) const { +bool BulletPhysicsServer3D::area_is_ray_pickable(RID p_area) const { AreaBullet *area = area_owner.getornull(p_area); ERR_FAIL_COND_V(!area, false); return area->is_ray_pickable(); } -RID BulletPhysicsServer::body_create(BodyMode p_mode, bool p_init_sleeping) { +RID BulletPhysicsServer3D::body_create(BodyMode p_mode, bool p_init_sleeping) { RigidBodyBullet *body = bulletnew(RigidBodyBullet); body->set_mode(p_mode); body->set_collision_layer(1); @@ -460,7 +460,7 @@ RID BulletPhysicsServer::body_create(BodyMode p_mode, bool p_init_sleeping) { CreateThenReturnRID(rigid_body_owner, body); } -void BulletPhysicsServer::body_set_space(RID p_body, RID p_space) { +void BulletPhysicsServer3D::body_set_space(RID p_body, RID p_space) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); SpaceBullet *space = NULL; @@ -476,7 +476,7 @@ void BulletPhysicsServer::body_set_space(RID p_body, RID p_space) { body->set_space(space); } -RID BulletPhysicsServer::body_get_space(RID p_body) const { +RID BulletPhysicsServer3D::body_get_space(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, RID()); @@ -486,19 +486,19 @@ RID BulletPhysicsServer::body_get_space(RID p_body) const { return space->get_self(); } -void BulletPhysicsServer::body_set_mode(RID p_body, PhysicsServer::BodyMode p_mode) { +void BulletPhysicsServer3D::body_set_mode(RID p_body, PhysicsServer3D::BodyMode p_mode) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_mode(p_mode); } -PhysicsServer::BodyMode BulletPhysicsServer::body_get_mode(RID p_body) const { +PhysicsServer3D::BodyMode BulletPhysicsServer3D::body_get_mode(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); return body->get_mode(); } -void BulletPhysicsServer::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { +void BulletPhysicsServer3D::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -509,7 +509,7 @@ void BulletPhysicsServer::body_add_shape(RID p_body, RID p_shape, const Transfor body->add_shape(shape, p_transform, p_disabled); } -void BulletPhysicsServer::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { +void BulletPhysicsServer3D::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -519,20 +519,20 @@ void BulletPhysicsServer::body_set_shape(RID p_body, int p_shape_idx, RID p_shap body->set_shape(p_shape_idx, shape); } -void BulletPhysicsServer::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { +void BulletPhysicsServer3D::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_shape_transform(p_shape_idx, p_transform); } -int BulletPhysicsServer::body_get_shape_count(RID p_body) const { +int BulletPhysicsServer3D::body_get_shape_count(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_shape_count(); } -RID BulletPhysicsServer::body_get_shape(RID p_body, int p_shape_idx) const { +RID BulletPhysicsServer3D::body_get_shape(RID p_body, int p_shape_idx) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, RID()); @@ -542,113 +542,113 @@ RID BulletPhysicsServer::body_get_shape(RID p_body, int p_shape_idx) const { return shape->get_self(); } -Transform BulletPhysicsServer::body_get_shape_transform(RID p_body, int p_shape_idx) const { +Transform BulletPhysicsServer3D::body_get_shape_transform(RID p_body, int p_shape_idx) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Transform()); return body->get_shape_transform(p_shape_idx); } -void BulletPhysicsServer::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { +void BulletPhysicsServer3D::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_shape_disabled(p_shape_idx, p_disabled); } -void BulletPhysicsServer::body_remove_shape(RID p_body, int p_shape_idx) { +void BulletPhysicsServer3D::body_remove_shape(RID p_body, int p_shape_idx) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->remove_shape_full(p_shape_idx); } -void BulletPhysicsServer::body_clear_shapes(RID p_body) { +void BulletPhysicsServer3D::body_clear_shapes(RID p_body) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->remove_all_shapes(); } -void BulletPhysicsServer::body_attach_object_instance_id(RID p_body, ObjectID p_id) { +void BulletPhysicsServer3D::body_attach_object_instance_id(RID p_body, ObjectID p_id) { CollisionObjectBullet *body = get_collisin_object(p_body); ERR_FAIL_COND(!body); body->set_instance_id(p_id); } -ObjectID BulletPhysicsServer::body_get_object_instance_id(RID p_body) const { +ObjectID BulletPhysicsServer3D::body_get_object_instance_id(RID p_body) const { CollisionObjectBullet *body = get_collisin_object(p_body); ERR_FAIL_COND_V(!body, ObjectID()); return body->get_instance_id(); } -void BulletPhysicsServer::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { +void BulletPhysicsServer3D::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_continuous_collision_detection(p_enable); } -bool BulletPhysicsServer::body_is_continuous_collision_detection_enabled(RID p_body) const { +bool BulletPhysicsServer3D::body_is_continuous_collision_detection_enabled(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->is_continuous_collision_detection_enabled(); } -void BulletPhysicsServer::body_set_collision_layer(RID p_body, uint32_t p_layer) { +void BulletPhysicsServer3D::body_set_collision_layer(RID p_body, uint32_t p_layer) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_layer(p_layer); } -uint32_t BulletPhysicsServer::body_get_collision_layer(RID p_body) const { +uint32_t BulletPhysicsServer3D::body_get_collision_layer(RID p_body) const { const RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_layer(); } -void BulletPhysicsServer::body_set_collision_mask(RID p_body, uint32_t p_mask) { +void BulletPhysicsServer3D::body_set_collision_mask(RID p_body, uint32_t p_mask) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_mask(p_mask); } -uint32_t BulletPhysicsServer::body_get_collision_mask(RID p_body) const { +uint32_t BulletPhysicsServer3D::body_get_collision_mask(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_mask(); } -void BulletPhysicsServer::body_set_user_flags(RID p_body, uint32_t p_flags) { +void BulletPhysicsServer3D::body_set_user_flags(RID p_body, uint32_t p_flags) { // This function si not currently supported } -uint32_t BulletPhysicsServer::body_get_user_flags(RID p_body) const { +uint32_t BulletPhysicsServer3D::body_get_user_flags(RID p_body) const { // This function si not currently supported return 0; } -void BulletPhysicsServer::body_set_param(RID p_body, BodyParameter p_param, float p_value) { +void BulletPhysicsServer3D::body_set_param(RID p_body, BodyParameter p_param, float p_value) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_param(p_param, p_value); } -float BulletPhysicsServer::body_get_param(RID p_body, BodyParameter p_param) const { +float BulletPhysicsServer3D::body_get_param(RID p_body, BodyParameter p_param) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_param(p_param); } -void BulletPhysicsServer::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { +void BulletPhysicsServer3D::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -658,7 +658,7 @@ void BulletPhysicsServer::body_set_kinematic_safe_margin(RID p_body, real_t p_ma } } -real_t BulletPhysicsServer::body_get_kinematic_safe_margin(RID p_body) const { +real_t BulletPhysicsServer3D::body_get_kinematic_safe_margin(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); @@ -670,90 +670,90 @@ real_t BulletPhysicsServer::body_get_kinematic_safe_margin(RID p_body) const { return 0; } -void BulletPhysicsServer::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { +void BulletPhysicsServer3D::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_state(p_state, p_variant); } -Variant BulletPhysicsServer::body_get_state(RID p_body, BodyState p_state) const { +Variant BulletPhysicsServer3D::body_get_state(RID p_body, BodyState p_state) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Variant()); return body->get_state(p_state); } -void BulletPhysicsServer::body_set_applied_force(RID p_body, const Vector3 &p_force) { +void BulletPhysicsServer3D::body_set_applied_force(RID p_body, const Vector3 &p_force) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_applied_force(p_force); } -Vector3 BulletPhysicsServer::body_get_applied_force(RID p_body) const { +Vector3 BulletPhysicsServer3D::body_get_applied_force(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3()); return body->get_applied_force(); } -void BulletPhysicsServer::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { +void BulletPhysicsServer3D::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_applied_torque(p_torque); } -Vector3 BulletPhysicsServer::body_get_applied_torque(RID p_body) const { +Vector3 BulletPhysicsServer3D::body_get_applied_torque(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3()); return body->get_applied_torque(); } -void BulletPhysicsServer::body_add_central_force(RID p_body, const Vector3 &p_force) { +void BulletPhysicsServer3D::body_add_central_force(RID p_body, const Vector3 &p_force) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_central_force(p_force); } -void BulletPhysicsServer::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { +void BulletPhysicsServer3D::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_force(p_force, p_pos); } -void BulletPhysicsServer::body_add_torque(RID p_body, const Vector3 &p_torque) { +void BulletPhysicsServer3D::body_add_torque(RID p_body, const Vector3 &p_torque) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_torque(p_torque); } -void BulletPhysicsServer::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_central_impulse(p_impulse); } -void BulletPhysicsServer::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_impulse(p_pos, p_impulse); } -void BulletPhysicsServer::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { +void BulletPhysicsServer3D::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->apply_torque_impulse(p_impulse); } -void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { +void BulletPhysicsServer3D::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -764,19 +764,19 @@ void BulletPhysicsServer::body_set_axis_velocity(RID p_body, const Vector3 &p_ax body->set_linear_velocity(v); } -void BulletPhysicsServer::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { +void BulletPhysicsServer3D::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_axis_lock(p_axis, p_lock); } -bool BulletPhysicsServer::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { +bool BulletPhysicsServer3D::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { const RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->is_axis_locked(p_axis); } -void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::body_add_collision_exception(RID p_body, RID p_body_b) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -786,7 +786,7 @@ void BulletPhysicsServer::body_add_collision_exception(RID p_body, RID p_body_b) body->add_collision_exception(other_body); } -void BulletPhysicsServer::body_remove_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::body_remove_collision_exception(RID p_body, RID p_body_b) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -796,7 +796,7 @@ void BulletPhysicsServer::body_remove_collision_exception(RID p_body, RID p_body body->remove_collision_exception(other_body); } -void BulletPhysicsServer::body_get_collision_exceptions(RID p_body, List *p_exceptions) { +void BulletPhysicsServer3D::body_get_collision_exceptions(RID p_body, List *p_exceptions) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); for (int i = 0; i < body->get_exceptions().size(); i++) { @@ -804,68 +804,68 @@ void BulletPhysicsServer::body_get_collision_exceptions(RID p_body, List *p } } -void BulletPhysicsServer::body_set_max_contacts_reported(RID p_body, int p_contacts) { +void BulletPhysicsServer3D::body_set_max_contacts_reported(RID p_body, int p_contacts) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_max_collisions_detection(p_contacts); } -int BulletPhysicsServer::body_get_max_contacts_reported(RID p_body) const { +int BulletPhysicsServer3D::body_get_max_contacts_reported(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_max_collisions_detection(); } -void BulletPhysicsServer::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) { +void BulletPhysicsServer3D::body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) { // Not supported by bullet and even Godot } -float BulletPhysicsServer::body_get_contacts_reported_depth_threshold(RID p_body) const { +float BulletPhysicsServer3D::body_get_contacts_reported_depth_threshold(RID p_body) const { // Not supported by bullet and even Godot return 0.; } -void BulletPhysicsServer::body_set_omit_force_integration(RID p_body, bool p_omit) { +void BulletPhysicsServer3D::body_set_omit_force_integration(RID p_body, bool p_omit) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_omit_forces_integration(p_omit); } -bool BulletPhysicsServer::body_is_omitting_force_integration(RID p_body) const { +bool BulletPhysicsServer3D::body_is_omitting_force_integration(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->get_omit_forces_integration(); } -void BulletPhysicsServer::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { +void BulletPhysicsServer3D::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); } -void BulletPhysicsServer::body_set_ray_pickable(RID p_body, bool p_enable) { +void BulletPhysicsServer3D::body_set_ray_pickable(RID p_body, bool p_enable) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_ray_pickable(p_enable); } -bool BulletPhysicsServer::body_is_ray_pickable(RID p_body) const { +bool BulletPhysicsServer3D::body_is_ray_pickable(RID p_body) const { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->is_ray_pickable(); } -PhysicsDirectBodyState *BulletPhysicsServer::body_get_direct_state(RID p_body) { +PhysicsDirectBodyState3D *BulletPhysicsServer3D::body_get_direct_state(RID p_body) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, NULL); return BulletPhysicsDirectBodyState::get_singleton(body); } -bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) { +bool BulletPhysicsServer3D::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); ERR_FAIL_COND_V(!body->get_space(), false); @@ -873,7 +873,7 @@ bool BulletPhysicsServer::body_test_motion(RID p_body, const Transform &p_from, return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, r_result, p_exclude_raycast_shapes); } -int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { +int BulletPhysicsServer3D::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { RigidBodyBullet *body = rigid_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); ERR_FAIL_COND_V(!body->get_space(), 0); @@ -881,7 +881,7 @@ int BulletPhysicsServer::body_test_ray_separation(RID p_body, const Transform &p return body->get_space()->test_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); } -RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) { +RID BulletPhysicsServer3D::soft_body_create(bool p_init_sleeping) { SoftBodyBullet *body = bulletnew(SoftBodyBullet); body->set_collision_layer(1); body->set_collision_mask(1); @@ -890,14 +890,14 @@ RID BulletPhysicsServer::soft_body_create(bool p_init_sleeping) { CreateThenReturnRID(soft_body_owner, body); } -void BulletPhysicsServer::soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler) { +void BulletPhysicsServer3D::soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); - body->update_visual_server(p_visual_server_handler); + body->update_rendering_server(p_rendering_server_handler); } -void BulletPhysicsServer::soft_body_set_space(RID p_body, RID p_space) { +void BulletPhysicsServer3D::soft_body_set_space(RID p_body, RID p_space) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); SpaceBullet *space = NULL; @@ -913,7 +913,7 @@ void BulletPhysicsServer::soft_body_set_space(RID p_body, RID p_space) { body->set_space(space); } -RID BulletPhysicsServer::soft_body_get_space(RID p_body) const { +RID BulletPhysicsServer3D::soft_body_get_space(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, RID()); @@ -923,42 +923,42 @@ RID BulletPhysicsServer::soft_body_get_space(RID p_body) const { return space->get_self(); } -void BulletPhysicsServer::soft_body_set_mesh(RID p_body, const REF &p_mesh) { +void BulletPhysicsServer3D::soft_body_set_mesh(RID p_body, const REF &p_mesh) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_soft_mesh(p_mesh); } -void BulletPhysicsServer::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { +void BulletPhysicsServer3D::soft_body_set_collision_layer(RID p_body, uint32_t p_layer) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_layer(p_layer); } -uint32_t BulletPhysicsServer::soft_body_get_collision_layer(RID p_body) const { +uint32_t BulletPhysicsServer3D::soft_body_get_collision_layer(RID p_body) const { const SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_layer(); } -void BulletPhysicsServer::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { +void BulletPhysicsServer3D::soft_body_set_collision_mask(RID p_body, uint32_t p_mask) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_collision_mask(p_mask); } -uint32_t BulletPhysicsServer::soft_body_get_collision_mask(RID p_body) const { +uint32_t BulletPhysicsServer3D::soft_body_get_collision_mask(RID p_body) const { const SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0); return body->get_collision_mask(); } -void BulletPhysicsServer::soft_body_add_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::soft_body_add_collision_exception(RID p_body, RID p_body_b) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -971,7 +971,7 @@ void BulletPhysicsServer::soft_body_add_collision_exception(RID p_body, RID p_bo body->add_collision_exception(other_body); } -void BulletPhysicsServer::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { +void BulletPhysicsServer3D::soft_body_remove_collision_exception(RID p_body, RID p_body_b) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); @@ -984,7 +984,7 @@ void BulletPhysicsServer::soft_body_remove_collision_exception(RID p_body, RID p body->remove_collision_exception(other_body); } -void BulletPhysicsServer::soft_body_get_collision_exceptions(RID p_body, List *p_exceptions) { +void BulletPhysicsServer3D::soft_body_get_collision_exceptions(RID p_body, List *p_exceptions) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); for (int i = 0; i < body->get_exceptions().size(); i++) { @@ -992,25 +992,25 @@ void BulletPhysicsServer::soft_body_get_collision_exceptions(RID p_body, Listset_soft_transform(p_transform); } -Vector3 BulletPhysicsServer::soft_body_get_vertex_position(RID p_body, int vertex_index) const { +Vector3 BulletPhysicsServer3D::soft_body_get_vertex_position(RID p_body, int vertex_index) const { const SoftBodyBullet *body = soft_body_owner.getornull(p_body); Vector3 pos; ERR_FAIL_COND_V(!body, pos); @@ -1019,133 +1019,133 @@ Vector3 BulletPhysicsServer::soft_body_get_vertex_position(RID p_body, int verte return pos; } -void BulletPhysicsServer::soft_body_set_ray_pickable(RID p_body, bool p_enable) { +void BulletPhysicsServer3D::soft_body_set_ray_pickable(RID p_body, bool p_enable) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_ray_pickable(p_enable); } -bool BulletPhysicsServer::soft_body_is_ray_pickable(RID p_body) const { +bool BulletPhysicsServer3D::soft_body_is_ray_pickable(RID p_body) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, false); return body->is_ray_pickable(); } -void BulletPhysicsServer::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { +void BulletPhysicsServer3D::soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_simulation_precision(p_simulation_precision); } -int BulletPhysicsServer::soft_body_get_simulation_precision(RID p_body) { +int BulletPhysicsServer3D::soft_body_get_simulation_precision(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_simulation_precision(); } -void BulletPhysicsServer::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { +void BulletPhysicsServer3D::soft_body_set_total_mass(RID p_body, real_t p_total_mass) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_total_mass(p_total_mass); } -real_t BulletPhysicsServer::soft_body_get_total_mass(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_total_mass(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_total_mass(); } -void BulletPhysicsServer::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_linear_stiffness(p_stiffness); } -real_t BulletPhysicsServer::soft_body_get_linear_stiffness(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_linear_stiffness(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_linear_stiffness(); } -void BulletPhysicsServer::soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_areaAngular_stiffness(p_stiffness); } -real_t BulletPhysicsServer::soft_body_get_areaAngular_stiffness(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_areaAngular_stiffness(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_areaAngular_stiffness(); } -void BulletPhysicsServer::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) { +void BulletPhysicsServer3D::soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_volume_stiffness(p_stiffness); } -real_t BulletPhysicsServer::soft_body_get_volume_stiffness(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_volume_stiffness(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_volume_stiffness(); } -void BulletPhysicsServer::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { +void BulletPhysicsServer3D::soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_pressure_coefficient(p_pressure_coefficient); } -real_t BulletPhysicsServer::soft_body_get_pressure_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_pressure_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_pressure_coefficient(); } -void BulletPhysicsServer::soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) { +void BulletPhysicsServer3D::soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); return body->set_pose_matching_coefficient(p_pose_matching_coefficient); } -real_t BulletPhysicsServer::soft_body_get_pose_matching_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_pose_matching_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_pose_matching_coefficient(); } -void BulletPhysicsServer::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { +void BulletPhysicsServer3D::soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_damping_coefficient(p_damping_coefficient); } -real_t BulletPhysicsServer::soft_body_get_damping_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_damping_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_damping_coefficient(); } -void BulletPhysicsServer::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { +void BulletPhysicsServer3D::soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_drag_coefficient(p_drag_coefficient); } -real_t BulletPhysicsServer::soft_body_get_drag_coefficient(RID p_body) { +real_t BulletPhysicsServer3D::soft_body_get_drag_coefficient(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_drag_coefficient(); } -void BulletPhysicsServer::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { +void BulletPhysicsServer3D::soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_node_position(p_point_index, p_global_position); } -Vector3 BulletPhysicsServer::soft_body_get_point_global_position(RID p_body, int p_point_index) { +Vector3 BulletPhysicsServer3D::soft_body_get_point_global_position(RID p_body, int p_point_index) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3(0., 0., 0.)); Vector3 pos; @@ -1153,7 +1153,7 @@ Vector3 BulletPhysicsServer::soft_body_get_point_global_position(RID p_body, int return pos; } -Vector3 BulletPhysicsServer::soft_body_get_point_offset(RID p_body, int p_point_index) const { +Vector3 BulletPhysicsServer3D::soft_body_get_point_offset(RID p_body, int p_point_index) const { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, Vector3()); Vector3 res; @@ -1161,54 +1161,54 @@ Vector3 BulletPhysicsServer::soft_body_get_point_offset(RID p_body, int p_point_ return res; } -void BulletPhysicsServer::soft_body_remove_all_pinned_points(RID p_body) { +void BulletPhysicsServer3D::soft_body_remove_all_pinned_points(RID p_body) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->reset_all_node_mass(); } -void BulletPhysicsServer::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { +void BulletPhysicsServer3D::soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND(!body); body->set_node_mass(p_point_index, p_pin ? 0 : 1); } -bool BulletPhysicsServer::soft_body_is_point_pinned(RID p_body, int p_point_index) { +bool BulletPhysicsServer3D::soft_body_is_point_pinned(RID p_body, int p_point_index) { SoftBodyBullet *body = soft_body_owner.getornull(p_body); ERR_FAIL_COND_V(!body, 0.f); return body->get_node_mass(p_point_index); } -PhysicsServer::JointType BulletPhysicsServer::joint_get_type(RID p_joint) const { +PhysicsServer3D::JointType BulletPhysicsServer3D::joint_get_type(RID p_joint) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, JOINT_PIN); return joint->get_type(); } -void BulletPhysicsServer::joint_set_solver_priority(RID p_joint, int p_priority) { +void BulletPhysicsServer3D::joint_set_solver_priority(RID p_joint, int p_priority) { // Joint priority not supported by bullet } -int BulletPhysicsServer::joint_get_solver_priority(RID p_joint) const { +int BulletPhysicsServer3D::joint_get_solver_priority(RID p_joint) const { // Joint priority not supported by bullet return 0; } -void BulletPhysicsServer::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { +void BulletPhysicsServer3D::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); joint->disable_collisions_between_bodies(p_disable); } -bool BulletPhysicsServer::joint_is_disabled_collisions_between_bodies(RID p_joint) const { +bool BulletPhysicsServer3D::joint_is_disabled_collisions_between_bodies(RID p_joint) const { JointBullet *joint(joint_owner.getornull(p_joint)); ERR_FAIL_COND_V(!joint, false); return joint->is_disabled_collisions_between_bodies(); } -RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { +RID BulletPhysicsServer3D::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); @@ -1229,7 +1229,7 @@ RID BulletPhysicsServer::joint_create_pin(RID p_body_A, const Vector3 &p_local_A CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) { +void BulletPhysicsServer3D::pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_PIN); @@ -1237,7 +1237,7 @@ void BulletPhysicsServer::pin_joint_set_param(RID p_joint, PinJointParam p_param pin_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { +float BulletPhysicsServer3D::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0); @@ -1245,7 +1245,7 @@ float BulletPhysicsServer::pin_joint_get_param(RID p_joint, PinJointParam p_para return pin_joint->get_param(p_param); } -void BulletPhysicsServer::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { +void BulletPhysicsServer3D::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_PIN); @@ -1253,7 +1253,7 @@ void BulletPhysicsServer::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) pin_joint->setPivotInA(p_A); } -Vector3 BulletPhysicsServer::pin_joint_get_local_a(RID p_joint) const { +Vector3 BulletPhysicsServer3D::pin_joint_get_local_a(RID p_joint) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, Vector3()); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); @@ -1261,7 +1261,7 @@ Vector3 BulletPhysicsServer::pin_joint_get_local_a(RID p_joint) const { return pin_joint->getPivotInA(); } -void BulletPhysicsServer::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { +void BulletPhysicsServer3D::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_PIN); @@ -1269,7 +1269,7 @@ void BulletPhysicsServer::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) pin_joint->setPivotInB(p_B); } -Vector3 BulletPhysicsServer::pin_joint_get_local_b(RID p_joint) const { +Vector3 BulletPhysicsServer3D::pin_joint_get_local_b(RID p_joint) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, Vector3()); ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); @@ -1277,7 +1277,7 @@ Vector3 BulletPhysicsServer::pin_joint_get_local_b(RID p_joint) const { return pin_joint->getPivotInB(); } -RID BulletPhysicsServer::joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) { +RID BulletPhysicsServer3D::joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); @@ -1297,7 +1297,7 @@ RID BulletPhysicsServer::joint_create_hinge(RID p_body_A, const Transform &p_hin CreateThenReturnRID(joint_owner, joint); } -RID BulletPhysicsServer::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { +RID BulletPhysicsServer3D::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); @@ -1317,7 +1317,7 @@ RID BulletPhysicsServer::joint_create_hinge_simple(RID p_body_A, const Vector3 & CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) { +void BulletPhysicsServer3D::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); @@ -1325,7 +1325,7 @@ void BulletPhysicsServer::hinge_joint_set_param(RID p_joint, HingeJointParam p_p hinge_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { +float BulletPhysicsServer3D::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0); @@ -1333,7 +1333,7 @@ float BulletPhysicsServer::hinge_joint_get_param(RID p_joint, HingeJointParam p_ return hinge_joint->get_param(p_param); } -void BulletPhysicsServer::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { +void BulletPhysicsServer3D::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); @@ -1341,7 +1341,7 @@ void BulletPhysicsServer::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_fla hinge_joint->set_flag(p_flag, p_value); } -bool BulletPhysicsServer::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { +bool BulletPhysicsServer3D::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, false); ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false); @@ -1349,7 +1349,7 @@ bool BulletPhysicsServer::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_fla return hinge_joint->get_flag(p_flag); } -RID BulletPhysicsServer::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { +RID BulletPhysicsServer3D::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); @@ -1369,7 +1369,7 @@ RID BulletPhysicsServer::joint_create_slider(RID p_body_A, const Transform &p_lo CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) { +void BulletPhysicsServer3D::slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER); @@ -1377,7 +1377,7 @@ void BulletPhysicsServer::slider_joint_set_param(RID p_joint, SliderJointParam p slider_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { +float BulletPhysicsServer3D::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_SLIDER, 0); @@ -1385,7 +1385,7 @@ float BulletPhysicsServer::slider_joint_get_param(RID p_joint, SliderJointParam return slider_joint->get_param(p_param); } -RID BulletPhysicsServer::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { +RID BulletPhysicsServer3D::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); @@ -1403,7 +1403,7 @@ RID BulletPhysicsServer::joint_create_cone_twist(RID p_body_A, const Transform & CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) { +void BulletPhysicsServer3D::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST); @@ -1411,7 +1411,7 @@ void BulletPhysicsServer::cone_twist_joint_set_param(RID p_joint, ConeTwistJoint coneTwist_joint->set_param(p_param, p_value); } -float BulletPhysicsServer::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { +float BulletPhysicsServer3D::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0.); ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0.); @@ -1419,7 +1419,7 @@ float BulletPhysicsServer::cone_twist_joint_get_param(RID p_joint, ConeTwistJoin return coneTwist_joint->get_param(p_param); } -RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { +RID BulletPhysicsServer3D::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { RigidBodyBullet *body_A = rigid_body_owner.getornull(p_body_A); ERR_FAIL_COND_V(!body_A, RID()); JointAssertSpace(body_A, "A", RID()); @@ -1439,7 +1439,7 @@ RID BulletPhysicsServer::joint_create_generic_6dof(RID p_body_A, const Transform CreateThenReturnRID(joint_owner, joint); } -void BulletPhysicsServer::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) { +void BulletPhysicsServer3D::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, float p_value) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); @@ -1447,7 +1447,7 @@ void BulletPhysicsServer::generic_6dof_joint_set_param(RID p_joint, Vector3::Axi generic_6dof_joint->set_param(p_axis, p_param, p_value); } -float BulletPhysicsServer::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) { +float BulletPhysicsServer3D::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0); @@ -1455,7 +1455,7 @@ float BulletPhysicsServer::generic_6dof_joint_get_param(RID p_joint, Vector3::Ax return generic_6dof_joint->get_param(p_axis, p_param); } -void BulletPhysicsServer::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { +void BulletPhysicsServer3D::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); @@ -1463,7 +1463,7 @@ void BulletPhysicsServer::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); } -bool BulletPhysicsServer::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) { +bool BulletPhysicsServer3D::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, false); ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false); @@ -1471,7 +1471,7 @@ bool BulletPhysicsServer::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis return generic_6dof_joint->get_flag(p_axis, p_flag); } -void BulletPhysicsServer::generic_6dof_joint_set_precision(RID p_joint, int p_precision) { +void BulletPhysicsServer3D::generic_6dof_joint_set_precision(RID p_joint, int p_precision) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND(!joint); ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); @@ -1479,7 +1479,7 @@ void BulletPhysicsServer::generic_6dof_joint_set_precision(RID p_joint, int p_pr generic_6dof_joint->set_precision(p_precision); } -int BulletPhysicsServer::generic_6dof_joint_get_precision(RID p_joint) { +int BulletPhysicsServer3D::generic_6dof_joint_get_precision(RID p_joint) { JointBullet *joint = joint_owner.getornull(p_joint); ERR_FAIL_COND_V(!joint, 0); ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0); @@ -1487,7 +1487,7 @@ int BulletPhysicsServer::generic_6dof_joint_get_precision(RID p_joint) { return generic_6dof_joint->get_precision(); } -void BulletPhysicsServer::free(RID p_rid) { +void BulletPhysicsServer3D::free(RID p_rid) { if (shape_owner.owns(p_rid)) { ShapeBullet *shape = shape_owner.getornull(p_rid); @@ -1552,11 +1552,11 @@ void BulletPhysicsServer::free(RID p_rid) { } } -void BulletPhysicsServer::init() { +void BulletPhysicsServer3D::init() { BulletPhysicsDirectBodyState::initSingleton(); } -void BulletPhysicsServer::step(float p_deltaTime) { +void BulletPhysicsServer3D::step(float p_deltaTime) { if (!active) return; @@ -1568,21 +1568,21 @@ void BulletPhysicsServer::step(float p_deltaTime) { } } -void BulletPhysicsServer::sync() { +void BulletPhysicsServer3D::sync() { } -void BulletPhysicsServer::flush_queries() { +void BulletPhysicsServer3D::flush_queries() { } -void BulletPhysicsServer::finish() { +void BulletPhysicsServer3D::finish() { BulletPhysicsDirectBodyState::destroySingleton(); } -int BulletPhysicsServer::get_process_info(ProcessInfo p_info) { +int BulletPhysicsServer3D::get_process_info(ProcessInfo p_info) { return 0; } -CollisionObjectBullet *BulletPhysicsServer::get_collisin_object(RID p_object) const { +CollisionObjectBullet *BulletPhysicsServer3D::get_collisin_object(RID p_object) const { if (rigid_body_owner.owns(p_object)) { return rigid_body_owner.getornull(p_object); } @@ -1595,7 +1595,7 @@ CollisionObjectBullet *BulletPhysicsServer::get_collisin_object(RID p_object) co return NULL; } -RigidCollisionObjectBullet *BulletPhysicsServer::get_rigid_collisin_object(RID p_object) const { +RigidCollisionObjectBullet *BulletPhysicsServer3D::get_rigid_collisin_object(RID p_object) const { if (rigid_body_owner.owns(p_object)) { return rigid_body_owner.getornull(p_object); } diff --git a/modules/bullet/bullet_physics_server.h b/modules/bullet/bullet_physics_server.h index 6ea9a7a974..1269dac78b 100644 --- a/modules/bullet/bullet_physics_server.h +++ b/modules/bullet/bullet_physics_server.h @@ -36,7 +36,7 @@ #include "core/rid_owner.h" #include "joint_bullet.h" #include "rigid_body_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "shape_bullet.h" #include "soft_body_bullet.h" #include "space_bullet.h" @@ -44,8 +44,8 @@ @author AndreaCatania */ -class BulletPhysicsServer : public PhysicsServer { - GDCLASS(BulletPhysicsServer, PhysicsServer); +class BulletPhysicsServer3D : public PhysicsServer3D { + GDCLASS(BulletPhysicsServer3D, PhysicsServer3D); friend class BulletPhysicsDirectSpaceState; @@ -64,8 +64,8 @@ protected: static void _bind_methods(); public: - BulletPhysicsServer(); - ~BulletPhysicsServer(); + BulletPhysicsServer3D(); + ~BulletPhysicsServer3D(); _FORCE_INLINE_ RID_PtrOwner *get_space_owner() { return &space_owner; @@ -111,7 +111,7 @@ public: /// Not supported virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; - virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space); + virtual PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space); virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); virtual Vector space_get_contacts(RID p_space) const; @@ -252,7 +252,7 @@ public: virtual bool body_is_ray_pickable(RID p_body) const; // this function only works on physics process, errors and returns null otherwise - virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); + virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body); virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); @@ -261,7 +261,7 @@ public: virtual RID soft_body_create(bool p_init_sleeping = false); - virtual void soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler); + virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler); virtual void soft_body_set_space(RID p_body, RID p_space); virtual RID soft_body_get_space(RID p_body) const; @@ -387,7 +387,7 @@ public: } static bool singleton_isActive() { - return static_cast(get_singleton())->active; + return static_cast(get_singleton())->active; } bool isActive() { diff --git a/modules/bullet/collision_object_bullet.cpp b/modules/bullet/collision_object_bullet.cpp index 5b7e7281e4..0ce57811d7 100644 --- a/modules/bullet/collision_object_bullet.cpp +++ b/modules/bullet/collision_object_bullet.cpp @@ -60,7 +60,7 @@ void CollisionObjectBullet::ShapeWrapper::set_transform(const btTransform &p_tra } btTransform CollisionObjectBullet::ShapeWrapper::get_adjusted_transform() const { - if (shape->get_type() == PhysicsServer::SHAPE_HEIGHTMAP) { + if (shape->get_type() == PhysicsServer3D::SHAPE_HEIGHTMAP) { const HeightMapShapeBullet *hm_shape = (const HeightMapShapeBullet *)shape; // should be safe to cast now btTransform adjusted_transform; diff --git a/modules/bullet/cone_twist_joint_bullet.cpp b/modules/bullet/cone_twist_joint_bullet.cpp index 23eb39fe7e..aac51034b8 100644 --- a/modules/bullet/cone_twist_joint_bullet.cpp +++ b/modules/bullet/cone_twist_joint_bullet.cpp @@ -64,43 +64,43 @@ ConeTwistJointBullet::ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet setup(coneConstraint); } -void ConeTwistJointBullet::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) { +void ConeTwistJointBullet::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: coneConstraint->setLimit(5, p_value); coneConstraint->setLimit(4, p_value); break; - case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN: coneConstraint->setLimit(3, p_value); break; - case PhysicsServer::CONE_TWIST_JOINT_BIAS: + case PhysicsServer3D::CONE_TWIST_JOINT_BIAS: coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), p_value, coneConstraint->getRelaxationFactor()); break; - case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS: + case PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS: coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), p_value, coneConstraint->getBiasFactor(), coneConstraint->getRelaxationFactor()); break; - case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: + case PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION: coneConstraint->setLimit(coneConstraint->getSwingSpan1(), coneConstraint->getSwingSpan2(), coneConstraint->getTwistSpan(), coneConstraint->getLimitSoftness(), coneConstraint->getBiasFactor(), p_value); break; - case PhysicsServer::CONE_TWIST_MAX: + case PhysicsServer3D::CONE_TWIST_MAX: // Internal size value, nothing to do. break; } } -real_t ConeTwistJointBullet::get_param(PhysicsServer::ConeTwistJointParam p_param) const { +real_t ConeTwistJointBullet::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const { switch (p_param) { - case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: return coneConstraint->getSwingSpan1(); - case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN: + case PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN: return coneConstraint->getTwistSpan(); - case PhysicsServer::CONE_TWIST_JOINT_BIAS: + case PhysicsServer3D::CONE_TWIST_JOINT_BIAS: return coneConstraint->getBiasFactor(); - case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS: + case PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS: return coneConstraint->getLimitSoftness(); - case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: + case PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION: return coneConstraint->getRelaxationFactor(); - case PhysicsServer::CONE_TWIST_MAX: + case PhysicsServer3D::CONE_TWIST_MAX: // Internal size value, nothing to do. return 0; } diff --git a/modules/bullet/cone_twist_joint_bullet.h b/modules/bullet/cone_twist_joint_bullet.h index 134706f8bb..ed4baa9d1b 100644 --- a/modules/bullet/cone_twist_joint_bullet.h +++ b/modules/bullet/cone_twist_joint_bullet.h @@ -45,9 +45,9 @@ class ConeTwistJointBullet : public JointBullet { public: ConeTwistJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &rbAFrame, const Transform &rbBFrame); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_CONE_TWIST; } - void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const; + void set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::ConeTwistJointParam p_param) const; }; #endif diff --git a/modules/bullet/generic_6dof_joint_bullet.cpp b/modules/bullet/generic_6dof_joint_bullet.cpp index 45ab3d3bb2..a6a01ebaa8 100644 --- a/modules/bullet/generic_6dof_joint_bullet.cpp +++ b/modules/bullet/generic_6dof_joint_bullet.cpp @@ -118,62 +118,62 @@ void Generic6DOFJointBullet::set_angular_upper_limit(const Vector3 &angularUpper sixDOFConstraint->setAngularUpperLimit(btVec); } -void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) { +void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) { ERR_FAIL_INDEX(p_axis, 3); switch (p_param) { - case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: limits_lower[0][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: limits_upper[0][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: limits_lower[1][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: limits_upper[1][p_axis] = p_value; - set_flag(p_axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter + set_flag(p_axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, flags[p_axis][PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT]); // Reload bullet parameter break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping = p_value; break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint = p_value; break; - case PhysicsServer::G6DOF_JOINT_MAX: + case PhysicsServer3D::G6DOF_JOINT_MAX: // Internal size value, nothing to do. break; default: @@ -182,42 +182,42 @@ void Generic6DOFJointBullet::set_param(Vector3::Axis p_axis, PhysicsServer::G6DO } } -real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const { +real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const { ERR_FAIL_INDEX_V(p_axis, 3, 0.); switch (p_param) { - case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: return limits_lower[0][p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: return limits_upper[0][p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: return sixDOFConstraint->getTranslationalLimitMotor()->m_targetVelocity.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getTranslationalLimitMotor()->m_maxMotorForce.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: return sixDOFConstraint->getTranslationalLimitMotor()->m_springDamping.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: return sixDOFConstraint->getTranslationalLimitMotor()->m_springStiffness.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: return sixDOFConstraint->getTranslationalLimitMotor()->m_equilibriumPoint.m_floats[p_axis]; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: return limits_lower[1][p_axis]; - case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: return limits_upper[1][p_axis]; - case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_bounce; - case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_stopERP; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_targetVelocity; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_maxMotorForce; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springStiffness; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_springDamping; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: return sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_equilibriumPoint; - case PhysicsServer::G6DOF_JOINT_MAX: + case PhysicsServer3D::G6DOF_JOINT_MAX: // Internal size value, nothing to do. return 0; default: @@ -226,45 +226,45 @@ real_t Generic6DOFJointBullet::get_param(Vector3::Axis p_axis, PhysicsServer::G6 } } -void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value) { +void Generic6DOFJointBullet::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) { ERR_FAIL_INDEX(p_axis, 3); flags[p_axis][p_flag] = p_value; switch (p_flag) { - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: if (flags[p_axis][p_flag]) { sixDOFConstraint->setLimit(p_axis, limits_lower[0][p_axis], limits_upper[0][p_axis]); } else { sixDOFConstraint->setLimit(p_axis, 0, -1); // Free } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: if (flags[p_axis][p_flag]) { sixDOFConstraint->setLimit(p_axis + 3, limits_lower[1][p_axis], limits_upper[1][p_axis]); } else { sixDOFConstraint->setLimit(p_axis + 3, 0, -1); // Free } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableSpring = p_value; break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: sixDOFConstraint->getTranslationalLimitMotor()->m_enableSpring[p_axis] = p_value; break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: sixDOFConstraint->getRotationalLimitMotor(p_axis)->m_enableMotor = flags[p_axis][p_flag]; break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: sixDOFConstraint->getTranslationalLimitMotor()->m_enableMotor[p_axis] = flags[p_axis][p_flag]; break; - case PhysicsServer::G6DOF_JOINT_FLAG_MAX: + case PhysicsServer3D::G6DOF_JOINT_FLAG_MAX: // Internal size value, nothing to do. break; } } -bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const { +bool Generic6DOFJointBullet::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const { ERR_FAIL_INDEX_V(p_axis, 3, false); return flags[p_axis][p_flag]; } diff --git a/modules/bullet/generic_6dof_joint_bullet.h b/modules/bullet/generic_6dof_joint_bullet.h index 75c8005811..316708bb11 100644 --- a/modules/bullet/generic_6dof_joint_bullet.h +++ b/modules/bullet/generic_6dof_joint_bullet.h @@ -45,12 +45,12 @@ class Generic6DOFJointBullet : public JointBullet { // First is linear second is angular Vector3 limits_lower[2]; Vector3 limits_upper[2]; - bool flags[3][PhysicsServer::G6DOF_JOINT_FLAG_MAX]; + bool flags[3][PhysicsServer3D::G6DOF_JOINT_FLAG_MAX]; public: Generic6DOFJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_6DOF; } Transform getFrameOffsetA() const; Transform getFrameOffsetB() const; @@ -63,11 +63,11 @@ public: void set_angular_lower_limit(const Vector3 &angularLower); void set_angular_upper_limit(const Vector3 &angularUpper); - void set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value); - real_t get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const; + void set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value); + real_t get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const; - void set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value); - bool get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const; + void set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value); + bool get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const; void set_precision(int p_precision); int get_precision() const; diff --git a/modules/bullet/godot_result_callbacks.cpp b/modules/bullet/godot_result_callbacks.cpp index 20467e3ef3..ad054e3027 100644 --- a/modules/bullet/godot_result_callbacks.cpp +++ b/modules/bullet/godot_result_callbacks.cpp @@ -107,7 +107,7 @@ btScalar GodotAllConvexResultCallback::addSingleResult(btCollisionWorld::LocalCo CollisionObjectBullet *gObj = static_cast(convexResult.m_hitCollisionObject->getUserPointer()); - PhysicsDirectSpaceState::ShapeResult &result = m_results[count]; + PhysicsDirectSpaceState3D::ShapeResult &result = m_results[count]; result.shape = convexResult.m_localShapeInfo->m_triangleIndex; // "m_triangleIndex" Is a odd name but contains the compound shape ID result.rid = gObj->get_self(); @@ -207,7 +207,7 @@ btScalar GodotAllContactResultCallback::addSingleResult(btManifoldPoint &cp, con if (cp.getDistance() <= 0) { - PhysicsDirectSpaceState::ShapeResult &result = m_results[m_count]; + PhysicsDirectSpaceState3D::ShapeResult &result = m_results[m_count]; // Penetrated CollisionObjectBullet *colObj; diff --git a/modules/bullet/godot_result_callbacks.h b/modules/bullet/godot_result_callbacks.h index 4f634ed6f0..7e74a2b22e 100644 --- a/modules/bullet/godot_result_callbacks.h +++ b/modules/bullet/godot_result_callbacks.h @@ -31,7 +31,7 @@ #ifndef GODOT_RESULT_CALLBACKS_H #define GODOT_RESULT_CALLBACKS_H -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include #include @@ -85,12 +85,12 @@ public: // store all colliding object struct GodotAllConvexResultCallback : public btCollisionWorld::ConvexResultCallback { public: - PhysicsDirectSpaceState::ShapeResult *m_results; + PhysicsDirectSpaceState3D::ShapeResult *m_results; int m_resultMax; const Set *m_exclude; int count; - GodotAllConvexResultCallback(PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set *p_exclude) : + GodotAllConvexResultCallback(PhysicsDirectSpaceState3D::ShapeResult *p_results, int p_resultMax, const Set *p_exclude) : m_results(p_results), m_resultMax(p_resultMax), m_exclude(p_exclude), @@ -137,7 +137,7 @@ public: struct GodotAllContactResultCallback : public btCollisionWorld::ContactResultCallback { public: const btCollisionObject *m_self_object; - PhysicsDirectSpaceState::ShapeResult *m_results; + PhysicsDirectSpaceState3D::ShapeResult *m_results; int m_resultMax; const Set *m_exclude; int m_count; @@ -145,7 +145,7 @@ public: bool collide_with_bodies; bool collide_with_areas; - GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeResult *p_results, int p_resultMax, const Set *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : + GodotAllContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState3D::ShapeResult *p_results, int p_resultMax, const Set *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_results(p_results), m_resultMax(p_resultMax), @@ -188,7 +188,7 @@ public: struct GodotRestInfoContactResultCallback : public btCollisionWorld::ContactResultCallback { public: const btCollisionObject *m_self_object; - PhysicsDirectSpaceState::ShapeRestInfo *m_result; + PhysicsDirectSpaceState3D::ShapeRestInfo *m_result; const Set *m_exclude; bool m_collided; real_t m_min_distance; @@ -197,7 +197,7 @@ public: bool collide_with_bodies; bool collide_with_areas; - GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState::ShapeRestInfo *p_result, const Set *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : + GodotRestInfoContactResultCallback(btCollisionObject *p_self_object, PhysicsDirectSpaceState3D::ShapeRestInfo *p_result, const Set *p_exclude, bool p_collide_with_bodies, bool p_collide_with_areas) : m_self_object(p_self_object), m_result(p_result), m_exclude(p_exclude), diff --git a/modules/bullet/hinge_joint_bullet.cpp b/modules/bullet/hinge_joint_bullet.cpp index 970732688a..eaac1d650d 100644 --- a/modules/bullet/hinge_joint_bullet.cpp +++ b/modules/bullet/hinge_joint_bullet.cpp @@ -93,58 +93,58 @@ real_t HingeJointBullet::get_hinge_angle() { return hingeConstraint->getHingeAngle(); } -void HingeJointBullet::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) { +void HingeJointBullet::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::HINGE_JOINT_BIAS: + case PhysicsServer3D::HINGE_JOINT_BIAS: WARN_DEPRECATED_MSG("The HingeJoint parameter \"bias\" is deprecated."); break; - case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), p_value, hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER: hingeConstraint->setLimit(p_value, hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), p_value, hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), p_value, hingeConstraint->getLimitBiasFactor(), hingeConstraint->getLimitRelaxationFactor()); break; - case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: + case PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION: hingeConstraint->setLimit(hingeConstraint->getLowerLimit(), hingeConstraint->getUpperLimit(), hingeConstraint->getLimitSoftness(), hingeConstraint->getLimitBiasFactor(), p_value); break; - case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY: hingeConstraint->setMotorTargetVelocity(p_value); break; - case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: + case PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE: hingeConstraint->setMaxMotorImpulse(p_value); break; - case PhysicsServer::HINGE_JOINT_MAX: + case PhysicsServer3D::HINGE_JOINT_MAX: // Internal size value, nothing to do. break; } } -real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const { +real_t HingeJointBullet::get_param(PhysicsServer3D::HingeJointParam p_param) const { switch (p_param) { - case PhysicsServer::HINGE_JOINT_BIAS: + case PhysicsServer3D::HINGE_JOINT_BIAS: WARN_DEPRECATED_MSG("The HingeJoint parameter \"bias\" is deprecated."); return 0; - case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER: return hingeConstraint->getUpperLimit(); - case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: + case PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER: return hingeConstraint->getLowerLimit(); - case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS: return hingeConstraint->getLimitBiasFactor(); - case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: + case PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS: return hingeConstraint->getLimitSoftness(); - case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: + case PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION: return hingeConstraint->getLimitRelaxationFactor(); - case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: + case PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY: return hingeConstraint->getMotorTargetVelocity(); - case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: + case PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE: return hingeConstraint->getMaxMotorImpulse(); - case PhysicsServer::HINGE_JOINT_MAX: + case PhysicsServer3D::HINGE_JOINT_MAX: // Internal size value, nothing to do. return 0; } @@ -152,25 +152,25 @@ real_t HingeJointBullet::get_param(PhysicsServer::HingeJointParam p_param) const return 0; } -void HingeJointBullet::set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value) { +void HingeJointBullet::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) { switch (p_flag) { - case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: + case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: if (!p_value) { hingeConstraint->setLimit(-Math_PI, Math_PI); } break; - case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: + case PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR: hingeConstraint->enableMotor(p_value); break; - case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning + case PhysicsServer3D::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning } } -bool HingeJointBullet::get_flag(PhysicsServer::HingeJointFlag p_flag) const { +bool HingeJointBullet::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const { switch (p_flag) { - case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: + case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: return true; - case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: + case PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR: return hingeConstraint->getEnableAngularMotor(); default: return false; diff --git a/modules/bullet/hinge_joint_bullet.h b/modules/bullet/hinge_joint_bullet.h index d1061fe52f..120c40e5c0 100644 --- a/modules/bullet/hinge_joint_bullet.h +++ b/modules/bullet/hinge_joint_bullet.h @@ -44,14 +44,14 @@ public: HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameA, const Transform &frameB); HingeJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_HINGE; } real_t get_hinge_angle(); - void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::HingeJointParam p_param) const; + void set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::HingeJointParam p_param) const; - void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value); - bool get_flag(PhysicsServer::HingeJointFlag p_flag) const; + void set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value); + bool get_flag(PhysicsServer3D::HingeJointFlag p_flag) const; }; #endif diff --git a/modules/bullet/joint_bullet.h b/modules/bullet/joint_bullet.h index c840eb8f14..9cb8aab276 100644 --- a/modules/bullet/joint_bullet.h +++ b/modules/bullet/joint_bullet.h @@ -32,7 +32,7 @@ #define JOINT_BULLET_H #include "constraint_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" /** @author AndreaCatania @@ -47,6 +47,6 @@ public: JointBullet(); virtual ~JointBullet(); - virtual PhysicsServer::JointType get_type() const = 0; + virtual PhysicsServer3D::JointType get_type() const = 0; }; #endif diff --git a/modules/bullet/pin_joint_bullet.cpp b/modules/bullet/pin_joint_bullet.cpp index 8d109f1866..68b40d7405 100644 --- a/modules/bullet/pin_joint_bullet.cpp +++ b/modules/bullet/pin_joint_bullet.cpp @@ -62,27 +62,27 @@ PinJointBullet::PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a PinJointBullet::~PinJointBullet() {} -void PinJointBullet::set_param(PhysicsServer::PinJointParam p_param, real_t p_value) { +void PinJointBullet::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: + case PhysicsServer3D::PIN_JOINT_BIAS: p2pConstraint->m_setting.m_tau = p_value; break; - case PhysicsServer::PIN_JOINT_DAMPING: + case PhysicsServer3D::PIN_JOINT_DAMPING: p2pConstraint->m_setting.m_damping = p_value; break; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + case PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP: p2pConstraint->m_setting.m_impulseClamp = p_value; break; } } -real_t PinJointBullet::get_param(PhysicsServer::PinJointParam p_param) const { +real_t PinJointBullet::get_param(PhysicsServer3D::PinJointParam p_param) const { switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: + case PhysicsServer3D::PIN_JOINT_BIAS: return p2pConstraint->m_setting.m_tau; - case PhysicsServer::PIN_JOINT_DAMPING: + case PhysicsServer3D::PIN_JOINT_DAMPING: return p2pConstraint->m_setting.m_damping; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: + case PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP: return p2pConstraint->m_setting.m_impulseClamp; } // Compiler doesn't seem to notice that all code paths are fulfilled... diff --git a/modules/bullet/pin_joint_bullet.h b/modules/bullet/pin_joint_bullet.h index d6e7a945b5..e7d05f34d4 100644 --- a/modules/bullet/pin_joint_bullet.h +++ b/modules/bullet/pin_joint_bullet.h @@ -46,10 +46,10 @@ public: PinJointBullet(RigidBodyBullet *p_body_a, const Vector3 &p_pos_a, RigidBodyBullet *p_body_b, const Vector3 &p_pos_b); ~PinJointBullet(); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_PIN; } - void set_param(PhysicsServer::PinJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::PinJointParam p_param) const; + void set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::PinJointParam p_param) const; void setPivotInA(const Vector3 &p_pos); void setPivotInB(const Vector3 &p_pos); diff --git a/modules/bullet/register_types.cpp b/modules/bullet/register_types.cpp index 7819b67cad..009d0dff63 100644 --- a/modules/bullet/register_types.cpp +++ b/modules/bullet/register_types.cpp @@ -39,15 +39,15 @@ */ #ifndef _3D_DISABLED -PhysicsServer *_createBulletPhysicsCallback() { - return memnew(BulletPhysicsServer); +PhysicsServer3D *_createBulletPhysicsCallback() { + return memnew(BulletPhysicsServer3D); } #endif void register_bullet_types() { #ifndef _3D_DISABLED - PhysicsServerManager::register_server("Bullet", &_createBulletPhysicsCallback); - PhysicsServerManager::set_default_server("Bullet", 1); + PhysicsServer3DManager::register_server("Bullet", &_createBulletPhysicsCallback); + PhysicsServer3DManager::set_default_server("Bullet", 1); GLOBAL_DEF("physics/3d/active_soft_world", true); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/active_soft_world", PropertyInfo(Variant::BOOL, "physics/3d/active_soft_world")); diff --git a/modules/bullet/rid_bullet.h b/modules/bullet/rid_bullet.h index b76641ca54..3551ca05f9 100644 --- a/modules/bullet/rid_bullet.h +++ b/modules/bullet/rid_bullet.h @@ -37,17 +37,17 @@ @author AndreaCatania */ -class BulletPhysicsServer; +class BulletPhysicsServer3D; class RIDBullet { RID self; - BulletPhysicsServer *physicsServer; + BulletPhysicsServer3D *physicsServer; public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } - _FORCE_INLINE_ void _set_physics_server(BulletPhysicsServer *p_physicsServer) { physicsServer = p_physicsServer; } - _FORCE_INLINE_ BulletPhysicsServer *get_physics_server() const { return physicsServer; } + _FORCE_INLINE_ void _set_physics_server(BulletPhysicsServer3D *p_physicsServer) { physicsServer = p_physicsServer; } + _FORCE_INLINE_ BulletPhysicsServer3D *get_physics_server() const { return physicsServer; } }; #endif diff --git a/modules/bullet/rigid_body_bullet.cpp b/modules/bullet/rigid_body_bullet.cpp index 80f42c8441..b92166e653 100644 --- a/modules/bullet/rigid_body_bullet.cpp +++ b/modules/bullet/rigid_body_bullet.cpp @@ -194,7 +194,7 @@ Vector3 BulletPhysicsDirectBodyState::get_contact_collider_velocity_at_position( return velocityAtPoint; } -PhysicsDirectSpaceState *BulletPhysicsDirectBodyState::get_space_state() { +PhysicsDirectSpaceState3D *BulletPhysicsDirectBodyState::get_space_state() { return body->get_space()->get_direct_state(); } @@ -231,12 +231,12 @@ void RigidBodyBullet::KinematicUtilities::copyAllOwnerShapes() { shapes.write[i].transform = shape_wrapper->transform; shapes.write[i].transform.getOrigin() *= owner_scale; switch (shape_wrapper->shape->get_type()) { - case PhysicsServer::SHAPE_SPHERE: - case PhysicsServer::SHAPE_BOX: - case PhysicsServer::SHAPE_CAPSULE: - case PhysicsServer::SHAPE_CYLINDER: - case PhysicsServer::SHAPE_CONVEX_POLYGON: - case PhysicsServer::SHAPE_RAY: { + case PhysicsServer3D::SHAPE_SPHERE: + case PhysicsServer3D::SHAPE_BOX: + case PhysicsServer3D::SHAPE_CAPSULE: + case PhysicsServer3D::SHAPE_CYLINDER: + case PhysicsServer3D::SHAPE_CONVEX_POLYGON: + case PhysicsServer3D::SHAPE_RAY: { shapes.write[i].shape = static_cast(shape_wrapper->shape->create_bt_shape(owner_scale * shape_wrapper->scale, safe_margin)); } break; default: @@ -286,7 +286,7 @@ RigidBodyBullet::RigidBodyBullet() : reload_shapes(); setupBulletCollisionObject(btBody); - set_mode(PhysicsServer::BODY_MODE_RIGID); + set_mode(PhysicsServer3D::BODY_MODE_RIGID); reload_axis_lock(); areasWhereIam.resize(maxAreasWhereIam); @@ -487,29 +487,29 @@ void RigidBodyBullet::set_omit_forces_integration(bool p_omit) { omit_forces_integration = p_omit; } -void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { +void RigidBodyBullet::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::BODY_PARAM_BOUNCE: + case PhysicsServer3D::BODY_PARAM_BOUNCE: btBody->setRestitution(p_value); break; - case PhysicsServer::BODY_PARAM_FRICTION: + case PhysicsServer3D::BODY_PARAM_FRICTION: btBody->setFriction(p_value); break; - case PhysicsServer::BODY_PARAM_MASS: { + case PhysicsServer3D::BODY_PARAM_MASS: { ERR_FAIL_COND(p_value < 0); mass = p_value; _internal_set_mass(p_value); break; } - case PhysicsServer::BODY_PARAM_LINEAR_DAMP: + case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: linearDamp = p_value; btBody->setDamping(linearDamp, angularDamp); break; - case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP: angularDamp = p_value; btBody->setDamping(linearDamp, angularDamp); break; - case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: + case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: gravity_scale = p_value; /// The Bullet gravity will be is set by reload_space_override_modificator scratch_space_override_modificator(); @@ -519,21 +519,21 @@ void RigidBodyBullet::set_param(PhysicsServer::BodyParameter p_param, real_t p_v } } -real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const { +real_t RigidBodyBullet::get_param(PhysicsServer3D::BodyParameter p_param) const { switch (p_param) { - case PhysicsServer::BODY_PARAM_BOUNCE: + case PhysicsServer3D::BODY_PARAM_BOUNCE: return btBody->getRestitution(); - case PhysicsServer::BODY_PARAM_FRICTION: + case PhysicsServer3D::BODY_PARAM_FRICTION: return btBody->getFriction(); - case PhysicsServer::BODY_PARAM_MASS: { + case PhysicsServer3D::BODY_PARAM_MASS: { const btScalar invMass = btBody->getInvMass(); return 0 == invMass ? 0 : 1 / invMass; } - case PhysicsServer::BODY_PARAM_LINEAR_DAMP: + case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: return linearDamp; - case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP: return angularDamp; - case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: + case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: return gravity_scale; default: WARN_PRINT("Parameter " + itos(p_param) + " not supported by bullet"); @@ -541,31 +541,31 @@ real_t RigidBodyBullet::get_param(PhysicsServer::BodyParameter p_param) const { } } -void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { +void RigidBodyBullet::set_mode(PhysicsServer3D::BodyMode p_mode) { // This is necessary to block force_integration untile next move can_integrate_forces = false; destroy_kinematic_utilities(); // The mode change is relevant to its mass switch (p_mode) { - case PhysicsServer::BODY_MODE_KINEMATIC: - mode = PhysicsServer::BODY_MODE_KINEMATIC; + case PhysicsServer3D::BODY_MODE_KINEMATIC: + mode = PhysicsServer3D::BODY_MODE_KINEMATIC; reload_axis_lock(); _internal_set_mass(0); init_kinematic_utilities(); break; - case PhysicsServer::BODY_MODE_STATIC: - mode = PhysicsServer::BODY_MODE_STATIC; + case PhysicsServer3D::BODY_MODE_STATIC: + mode = PhysicsServer3D::BODY_MODE_STATIC; reload_axis_lock(); _internal_set_mass(0); break; - case PhysicsServer::BODY_MODE_RIGID: - mode = PhysicsServer::BODY_MODE_RIGID; + case PhysicsServer3D::BODY_MODE_RIGID: + mode = PhysicsServer3D::BODY_MODE_RIGID; reload_axis_lock(); _internal_set_mass(0 == mass ? 1 : mass); scratch_space_override_modificator(); break; - case PhysicsServer::BODY_MODE_CHARACTER: - mode = PhysicsServer::BODY_MODE_CHARACTER; + case PhysicsServer3D::BODY_MODE_CHARACTER: + mode = PhysicsServer3D::BODY_MODE_CHARACTER; reload_axis_lock(); _internal_set_mass(0 == mass ? 1 : mass); scratch_space_override_modificator(); @@ -575,26 +575,26 @@ void RigidBodyBullet::set_mode(PhysicsServer::BodyMode p_mode) { btBody->setAngularVelocity(btVector3(0, 0, 0)); btBody->setLinearVelocity(btVector3(0, 0, 0)); } -PhysicsServer::BodyMode RigidBodyBullet::get_mode() const { +PhysicsServer3D::BodyMode RigidBodyBullet::get_mode() const { return mode; } -void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant &p_variant) { +void RigidBodyBullet::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { switch (p_state) { - case PhysicsServer::BODY_STATE_TRANSFORM: + case PhysicsServer3D::BODY_STATE_TRANSFORM: set_transform(p_variant); break; - case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: set_linear_velocity(p_variant); break; - case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: set_angular_velocity(p_variant); break; - case PhysicsServer::BODY_STATE_SLEEPING: + case PhysicsServer3D::BODY_STATE_SLEEPING: set_activation_state(!bool(p_variant)); break; - case PhysicsServer::BODY_STATE_CAN_SLEEP: + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: can_sleep = bool(p_variant); if (!can_sleep) { // Can't sleep @@ -606,17 +606,17 @@ void RigidBodyBullet::set_state(PhysicsServer::BodyState p_state, const Variant } } -Variant RigidBodyBullet::get_state(PhysicsServer::BodyState p_state) const { +Variant RigidBodyBullet::get_state(PhysicsServer3D::BodyState p_state) const { switch (p_state) { - case PhysicsServer::BODY_STATE_TRANSFORM: + case PhysicsServer3D::BODY_STATE_TRANSFORM: return get_transform(); - case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: return get_linear_velocity(); - case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: return get_angular_velocity(); - case PhysicsServer::BODY_STATE_SLEEPING: + case PhysicsServer3D::BODY_STATE_SLEEPING: return !is_active(); - case PhysicsServer::BODY_STATE_CAN_SLEEP: + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: return can_sleep; default: WARN_PRINT("This state " + itos(p_state) + " is not supported by Bullet"); @@ -714,7 +714,7 @@ Vector3 RigidBodyBullet::get_applied_torque() const { return gTotTorq; } -void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) { +void RigidBodyBullet::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { if (lock) { locked_axis |= p_axis; } else { @@ -724,18 +724,18 @@ void RigidBodyBullet::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) { reload_axis_lock(); } -bool RigidBodyBullet::is_axis_locked(PhysicsServer::BodyAxis p_axis) const { +bool RigidBodyBullet::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const { return locked_axis & p_axis; } void RigidBodyBullet::reload_axis_lock() { - btBody->setLinearFactor(btVector3(float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_X)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Y)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_LINEAR_Z)))); - if (PhysicsServer::BODY_MODE_CHARACTER == mode) { + btBody->setLinearFactor(btVector3(float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_X)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Y)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_LINEAR_Z)))); + if (PhysicsServer3D::BODY_MODE_CHARACTER == mode) { /// When character angular is always locked btBody->setAngularFactor(btVector3(0., 0., 0.)); } else { - btBody->setAngularFactor(btVector3(float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_X)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Y)), float(!is_axis_locked(PhysicsServer::BODY_AXIS_ANGULAR_Z)))); + btBody->setAngularFactor(btVector3(float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_X)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Y)), float(!is_axis_locked(PhysicsServer3D::BODY_AXIS_ANGULAR_Z)))); } } @@ -794,7 +794,7 @@ Vector3 RigidBodyBullet::get_angular_velocity() const { } void RigidBodyBullet::set_transform__bullet(const btTransform &p_global_transform) { - if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { if (space && space->get_delta_time() != 0) btBody->setLinearVelocity((p_global_transform.getOrigin() - btBody->getWorldTransform().getOrigin()) / space->get_delta_time()); // The kinematic use MotionState class @@ -862,7 +862,7 @@ void RigidBodyBullet::on_enter_area(AreaBullet *p_area) { } } } - if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { + if (PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { scratch_space_override_modificator(); } @@ -895,7 +895,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { --areaWhereIamCount; areasWhereIam.write[areaWhereIamCount] = NULL; // Even if this is not required, I clear the last element to be safe - if (PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { + if (PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED != p_area->get_spOv_mode()) { scratch_space_override_modificator(); } } @@ -904,7 +904,7 @@ void RigidBodyBullet::on_exit_area(AreaBullet *p_area) { void RigidBodyBullet::reload_space_override_modificator() { // Make sure that kinematic bodies have their total gravity calculated - if (!is_active() && PhysicsServer::BODY_MODE_KINEMATIC != mode) + if (!is_active() && PhysicsServer3D::BODY_MODE_KINEMATIC != mode) return; Vector3 newGravity(space->get_gravity_direction() * space->get_gravity_magnitude()); @@ -920,7 +920,7 @@ void RigidBodyBullet::reload_space_override_modificator() { currentArea = areasWhereIam[i]; - if (!currentArea || PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) { + if (!currentArea || PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED == currentArea->get_spOv_mode()) { continue; } @@ -954,11 +954,11 @@ void RigidBodyBullet::reload_space_override_modificator() { } switch (currentArea->get_spOv_mode()) { - case PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED: /// This area does not affect gravity/damp. These are generally areas /// that exist only to detect collisions, and objects entering or exiting them. break; - case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: /// This area adds its gravity/damp values to whatever has been /// calculated so far. This way, many overlapping areas can combine /// their physics to make interesting @@ -967,7 +967,7 @@ void RigidBodyBullet::reload_space_override_modificator() { newAngularDamp += currentArea->get_spOv_angularDamp(); ++countCombined; break; - case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: /// This area adds its gravity/damp values to whatever has been calculated /// so far. Then stops taking into account the rest of the areas, even the /// default one. @@ -976,7 +976,7 @@ void RigidBodyBullet::reload_space_override_modificator() { newAngularDamp += currentArea->get_spOv_angularDamp(); ++countCombined; goto endAreasCycle; - case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: /// This area replaces any gravity/damp, even the default one, and /// stops taking into account the rest of the areas. newGravity = support_gravity; @@ -984,7 +984,7 @@ void RigidBodyBullet::reload_space_override_modificator() { newAngularDamp = currentArea->get_spOv_angularDamp(); countCombined = 1; goto endAreasCycle; - case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: /// This area replaces any gravity/damp calculated so far, but keeps /// calculating the rest of the areas, down to the default one. newGravity = support_gravity; @@ -1032,14 +1032,14 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) { const bool isDynamic = p_mass != 0.f; if (isDynamic) { - if (PhysicsServer::BODY_MODE_RIGID != mode && PhysicsServer::BODY_MODE_CHARACTER != mode) + if (PhysicsServer3D::BODY_MODE_RIGID != mode && PhysicsServer3D::BODY_MODE_CHARACTER != mode) return; m_isStatic = false; if (mainShape) mainShape->calculateLocalInertia(p_mass, localInertia); - if (PhysicsServer::BODY_MODE_RIGID == mode) { + if (PhysicsServer3D::BODY_MODE_RIGID == mode) { btBody->setCollisionFlags(clearedCurrentFlags); // Just set the flags without Kin and Static } else { @@ -1054,11 +1054,11 @@ void RigidBodyBullet::_internal_set_mass(real_t p_mass) { } } else { - if (PhysicsServer::BODY_MODE_STATIC != mode && PhysicsServer::BODY_MODE_KINEMATIC != mode) + if (PhysicsServer3D::BODY_MODE_STATIC != mode && PhysicsServer3D::BODY_MODE_KINEMATIC != mode) return; m_isStatic = true; - if (PhysicsServer::BODY_MODE_STATIC == mode) { + if (PhysicsServer3D::BODY_MODE_STATIC == mode) { btBody->setCollisionFlags(clearedCurrentFlags | btCollisionObject::CF_STATIC_OBJECT); } else { diff --git a/modules/bullet/rigid_body_bullet.h b/modules/bullet/rigid_body_bullet.h index ca599f7a77..bce3511282 100644 --- a/modules/bullet/rigid_body_bullet.h +++ b/modules/bullet/rigid_body_bullet.h @@ -51,10 +51,10 @@ class BulletPhysicsDirectBodyState; /// is set to be only in one single thread. /// /// In the system there is only one object at a time that manage all bodies and is -/// created by BulletPhysicsServer and is held by the "singleton" variable of this class +/// created by BulletPhysicsServer3D and is held by the "singleton" variable of this class /// Each time something require it, the body must be set again. -class BulletPhysicsDirectBodyState : public PhysicsDirectBodyState { - GDCLASS(BulletPhysicsDirectBodyState, PhysicsDirectBodyState); +class BulletPhysicsDirectBodyState : public PhysicsDirectBodyState3D { + GDCLASS(BulletPhysicsDirectBodyState, PhysicsDirectBodyState3D); static BulletPhysicsDirectBodyState *singleton; @@ -138,7 +138,7 @@ public: // Skip the execution of this function } - virtual PhysicsDirectSpaceState *get_space_state(); + virtual PhysicsDirectSpaceState3D *get_space_state(); }; class RigidBodyBullet : public RigidCollisionObjectBullet { @@ -192,7 +192,7 @@ private: // This is required only for Kinematic movement KinematicUtilities *kinematic_utilities; - PhysicsServer::BodyMode mode; + PhysicsServer3D::BodyMode mode; GodotMotionState *godotMotionState; btRigidBody *btBody; uint16_t locked_axis; @@ -278,14 +278,14 @@ public: void set_omit_forces_integration(bool p_omit); _FORCE_INLINE_ bool get_omit_forces_integration() const { return omit_forces_integration; } - void set_param(PhysicsServer::BodyParameter p_param, real_t); - real_t get_param(PhysicsServer::BodyParameter p_param) const; + void set_param(PhysicsServer3D::BodyParameter p_param, real_t); + real_t get_param(PhysicsServer3D::BodyParameter p_param) const; - void set_mode(PhysicsServer::BodyMode p_mode); - PhysicsServer::BodyMode get_mode() const; + void set_mode(PhysicsServer3D::BodyMode p_mode); + PhysicsServer3D::BodyMode get_mode() const; - void set_state(PhysicsServer::BodyState p_state, const Variant &p_variant); - Variant get_state(PhysicsServer::BodyState p_state) const; + void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant); + Variant get_state(PhysicsServer3D::BodyState p_state) const; void apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse); void apply_central_impulse(const Vector3 &p_impulse); @@ -300,8 +300,8 @@ public: void set_applied_torque(const Vector3 &p_torque); Vector3 get_applied_torque() const; - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock); - bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const; + void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock); + bool is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const; void reload_axis_lock(); /// Doc: diff --git a/modules/bullet/shape_bullet.cpp b/modules/bullet/shape_bullet.cpp index 6780f89d9e..6b73525d10 100644 --- a/modules/bullet/shape_bullet.cpp +++ b/modules/bullet/shape_bullet.cpp @@ -150,7 +150,7 @@ btHeightfieldTerrainShape *ShapeBullet::create_shape_height_field(Vector btHeightfieldTerrainShape *heightfield = bulletnew(btHeightfieldTerrainShape(p_width, p_depth, heightsPtr, ignoredHeightScale, p_min_height, p_max_height, YAxis, PHY_FLOAT, flipQuadEdges)); - // The shape can be created without params when you do PhysicsServer.shape_create(PhysicsServer.SHAPE_HEIGHTMAP) + // The shape can be created without params when you do PhysicsServer3D.shape_create(PhysicsServer3D.SHAPE_HEIGHTMAP) if (heightsPtr) heightfield->buildAccelerator(16); @@ -176,8 +176,8 @@ Variant PlaneShapeBullet::get_data() const { return plane; } -PhysicsServer::ShapeType PlaneShapeBullet::get_type() const { - return PhysicsServer::SHAPE_PLANE; +PhysicsServer3D::ShapeType PlaneShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_PLANE; } void PlaneShapeBullet::setup(const Plane &p_plane) { @@ -204,8 +204,8 @@ Variant SphereShapeBullet::get_data() const { return radius; } -PhysicsServer::ShapeType SphereShapeBullet::get_type() const { - return PhysicsServer::SHAPE_SPHERE; +PhysicsServer3D::ShapeType SphereShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_SPHERE; } void SphereShapeBullet::setup(real_t p_radius) { @@ -231,8 +231,8 @@ Variant BoxShapeBullet::get_data() const { return g_half_extents; } -PhysicsServer::ShapeType BoxShapeBullet::get_type() const { - return PhysicsServer::SHAPE_BOX; +PhysicsServer3D::ShapeType BoxShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_BOX; } void BoxShapeBullet::setup(const Vector3 &p_half_extents) { @@ -263,8 +263,8 @@ Variant CapsuleShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType CapsuleShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CAPSULE; +PhysicsServer3D::ShapeType CapsuleShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CAPSULE; } void CapsuleShapeBullet::setup(real_t p_height, real_t p_radius) { @@ -296,8 +296,8 @@ Variant CylinderShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType CylinderShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CYLINDER; +PhysicsServer3D::ShapeType CylinderShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CYLINDER; } void CylinderShapeBullet::setup(real_t p_height, real_t p_radius) { @@ -334,8 +334,8 @@ Variant ConvexPolygonShapeBullet::get_data() const { return out_vertices; } -PhysicsServer::ShapeType ConvexPolygonShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CONVEX_POLYGON; +PhysicsServer3D::ShapeType ConvexPolygonShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CONVEX_POLYGON; } void ConvexPolygonShapeBullet::setup(const Vector &p_vertices) { @@ -381,8 +381,8 @@ Variant ConcavePolygonShapeBullet::get_data() const { return faces; } -PhysicsServer::ShapeType ConcavePolygonShapeBullet::get_type() const { - return PhysicsServer::SHAPE_CONCAVE_POLYGON; +PhysicsServer3D::ShapeType ConcavePolygonShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } void ConcavePolygonShapeBullet::setup(Vector p_faces) { @@ -536,8 +536,8 @@ Variant HeightMapShapeBullet::get_data() const { ERR_FAIL_V(Variant()); } -PhysicsServer::ShapeType HeightMapShapeBullet::get_type() const { - return PhysicsServer::SHAPE_HEIGHTMAP; +PhysicsServer3D::ShapeType HeightMapShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_HEIGHTMAP; } void HeightMapShapeBullet::setup(Vector &p_heights, int p_width, int p_depth, real_t p_min_height, real_t p_max_height) { @@ -580,8 +580,8 @@ Variant RayShapeBullet::get_data() const { return d; } -PhysicsServer::ShapeType RayShapeBullet::get_type() const { - return PhysicsServer::SHAPE_RAY; +PhysicsServer3D::ShapeType RayShapeBullet::get_type() const { + return PhysicsServer3D::SHAPE_RAY; } void RayShapeBullet::setup(real_t p_length, bool p_slips_on_slope) { diff --git a/modules/bullet/shape_bullet.h b/modules/bullet/shape_bullet.h index c8b5ca102a..0dbc616fe5 100644 --- a/modules/bullet/shape_bullet.h +++ b/modules/bullet/shape_bullet.h @@ -34,7 +34,7 @@ #include "core/math/geometry.h" #include "core/variant.h" #include "rid_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include #include @@ -78,7 +78,7 @@ public: virtual void set_data(const Variant &p_data) = 0; virtual Variant get_data() const = 0; - virtual PhysicsServer::ShapeType get_type() const = 0; + virtual PhysicsServer3D::ShapeType get_type() const = 0; public: static class btEmptyShape *create_shape_empty(); @@ -103,7 +103,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -120,7 +120,7 @@ public: _FORCE_INLINE_ real_t get_radius() { return radius; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -137,7 +137,7 @@ public: _FORCE_INLINE_ const btVector3 &get_half_extents() { return half_extents; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -156,7 +156,7 @@ public: _FORCE_INLINE_ real_t get_radius() { return radius; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -175,7 +175,7 @@ public: _FORCE_INLINE_ real_t get_radius() { return radius; } virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_margin = 0); private: @@ -192,7 +192,7 @@ public: virtual void set_data(const Variant &p_data); void get_vertices(Vector &out_vertices); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -210,7 +210,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -230,7 +230,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: @@ -247,7 +247,7 @@ public: virtual void set_data(const Variant &p_data); virtual Variant get_data() const; - virtual PhysicsServer::ShapeType get_type() const; + virtual PhysicsServer3D::ShapeType get_type() const; virtual btCollisionShape *create_bt_shape(const btVector3 &p_implicit_scale, real_t p_extra_edge = 0); private: diff --git a/modules/bullet/slider_joint_bullet.cpp b/modules/bullet/slider_joint_bullet.cpp index d9ebb9d580..f193daef39 100644 --- a/modules/bullet/slider_joint_bullet.cpp +++ b/modules/bullet/slider_joint_bullet.cpp @@ -342,58 +342,58 @@ real_t SliderJointBullet::getLinearPos() { ; } -void SliderJointBullet::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) { +void SliderJointBullet::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: setUpperLinLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: setLowerLinLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: setSoftnessLimLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: setRestitutionLimLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: setDampingLimLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: setSoftnessDirLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: setRestitutionDirLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: setDampingDirLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: setDampingOrthoLin(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: setUpperAngLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: setLowerAngLimit(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: setSoftnessLimAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: setRestitutionLimAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: setDampingLimAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: setSoftnessDirAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: setRestitutionDirAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: setDampingDirAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: setDampingOrthoAng(p_value); break; - case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: setUpperLinLimit(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER: setLowerLinLimit(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: setSoftnessLimLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: setRestitutionLimLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: setDampingLimLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: setSoftnessDirLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: setRestitutionDirLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING: setDampingDirLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: setDampingOrthoLin(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: setUpperAngLimit(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: setLowerAngLimit(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: setSoftnessLimAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: setRestitutionLimAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: setDampingLimAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: setSoftnessDirAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: setRestitutionDirAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: setDampingDirAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: setSoftnessOrthoAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: setRestitutionOrthoAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: setDampingOrthoAng(p_value); break; + case PhysicsServer3D::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning } } -real_t SliderJointBullet::get_param(PhysicsServer::SliderJointParam p_param) const { +real_t SliderJointBullet::get_param(PhysicsServer3D::SliderJointParam p_param) const { switch (p_param) { - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return getUpperLinLimit(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: return getLowerLinLimit(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: return getSoftnessLimLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: return getRestitutionLimLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: return getDampingLimLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: return getSoftnessDirLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: return getRestitutionDirLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: return getDampingDirLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoLin(); - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: return getDampingOrthoLin(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: return getUpperAngLimit(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: return getLowerAngLimit(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: return getSoftnessLimAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: return getRestitutionLimAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: return getDampingLimAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: return getSoftnessDirAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: return getRestitutionDirAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: return getDampingDirAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoAng(); - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return getDampingOrthoAng(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return getUpperLinLimit(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER: return getLowerLinLimit(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: return getSoftnessLimLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: return getRestitutionLimLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: return getDampingLimLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: return getSoftnessDirLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: return getRestitutionDirLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING: return getDampingDirLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoLin(); + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: return getDampingOrthoLin(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: return getUpperAngLimit(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: return getLowerAngLimit(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: return getSoftnessLimAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: return getRestitutionLimAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: return getDampingLimAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: return getSoftnessDirAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: return getRestitutionDirAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: return getDampingDirAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return getSoftnessOrthoAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return getRestitutionOrthoAng(); + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return getDampingOrthoAng(); default: return 0; } diff --git a/modules/bullet/slider_joint_bullet.h b/modules/bullet/slider_joint_bullet.h index d98a1b8c95..6410b952ed 100644 --- a/modules/bullet/slider_joint_bullet.h +++ b/modules/bullet/slider_joint_bullet.h @@ -46,7 +46,7 @@ public: /// Reference frame is A SliderJointBullet(RigidBodyBullet *rbA, RigidBodyBullet *rbB, const Transform &frameInA, const Transform &frameInB); - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; } + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_SLIDER; } const RigidBodyBullet *getRigidBodyA() const; const RigidBodyBullet *getRigidBodyB() const; @@ -115,7 +115,7 @@ public: real_t getMaxAngMotorForce(); real_t getLinearPos(); - void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::SliderJointParam p_param) const; + void set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::SliderJointParam p_param) const; }; #endif diff --git a/modules/bullet/soft_body_bullet.cpp b/modules/bullet/soft_body_bullet.cpp index fb36a0d3e1..2984bf9c2b 100644 --- a/modules/bullet/soft_body_bullet.cpp +++ b/modules/bullet/soft_body_bullet.cpp @@ -76,7 +76,7 @@ void SoftBodyBullet::on_enter_area(AreaBullet *p_area) {} void SoftBodyBullet::on_exit_area(AreaBullet *p_area) {} -void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_server_handler) { +void SoftBodyBullet::update_rendering_server(SoftBodyRenderingServerHandler *p_rendering_server_handler) { if (!bt_soft_body) return; @@ -96,8 +96,8 @@ void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_ const int vs_indices_size(vs_indices->size()); for (int x = 0; x < vs_indices_size; ++x) { - p_visual_server_handler->set_vertex((*vs_indices)[x], vertex_position); - p_visual_server_handler->set_normal((*vs_indices)[x], vertex_normal); + p_rendering_server_handler->set_vertex((*vs_indices)[x], vertex_position); + p_rendering_server_handler->set_normal((*vs_indices)[x], vertex_normal); } } @@ -112,7 +112,7 @@ void SoftBodyBullet::update_visual_server(SoftBodyVisualServerHandler *p_visual_ B_TO_G(aabb_min, aabb.position); B_TO_G(size, aabb.size); - p_visual_server_handler->set_aabb(aabb); + p_rendering_server_handler->set_aabb(aabb); } void SoftBodyBullet::set_soft_mesh(const Ref &p_mesh) { @@ -129,8 +129,8 @@ void SoftBodyBullet::set_soft_mesh(const Ref &p_mesh) { } Array arrays = soft_mesh->surface_get_arrays(0); - ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & VS::ARRAY_FORMAT_INDEX)); - set_trimesh_body_shape(arrays[VS::ARRAY_INDEX], arrays[VS::ARRAY_VERTEX]); + ERR_FAIL_COND(!(soft_mesh->surface_get_format(0) & RS::ARRAY_FORMAT_INDEX)); + set_trimesh_body_shape(arrays[RS::ARRAY_INDEX], arrays[RS::ARRAY_VERTEX]); } void SoftBodyBullet::destroy_soft_body() { @@ -184,7 +184,7 @@ void SoftBodyBullet::get_node_offset(int p_node_index, Vector3 &r_offset) const return; Array arrays = soft_mesh->surface_get_arrays(0); - Vector vertices(arrays[VS::ARRAY_VERTEX]); + Vector vertices(arrays[RS::ARRAY_VERTEX]); if (0 <= p_node_index && vertices.size() > p_node_index) { r_offset = vertices[p_node_index]; @@ -230,7 +230,7 @@ void SoftBodyBullet::reset_all_node_positions() { return; Array arrays = soft_mesh->surface_get_arrays(0); - Vector vs_vertices(arrays[VS::ARRAY_VERTEX]); + Vector vs_vertices(arrays[RS::ARRAY_VERTEX]); const Vector3 *vs_vertices_read = vs_vertices.ptr(); for (int vertex_index = bt_soft_body->m_nodes.size() - 1; 0 <= vertex_index; --vertex_index) { diff --git a/modules/bullet/soft_body_bullet.h b/modules/bullet/soft_body_bullet.h index 05d7e6ce3f..3c6871e0d6 100644 --- a/modules/bullet/soft_body_bullet.h +++ b/modules/bullet/soft_body_bullet.h @@ -43,7 +43,7 @@ #include "BulletSoftBody/btSoftBodyHelpers.h" #include "collision_object_bullet.h" #include "scene/resources/mesh.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #ifdef x11_None /// This is required to re add the macro None defined by x11 compiler @@ -100,7 +100,7 @@ public: _FORCE_INLINE_ btSoftBody *get_bt_soft_body() const { return bt_soft_body; } - void update_visual_server(class SoftBodyVisualServerHandler *p_visual_server_handler); + void update_rendering_server(class SoftBodyRenderingServerHandler *p_rendering_server_handler); void set_soft_mesh(const Ref &p_mesh); void destroy_soft_body(); diff --git a/modules/bullet/space_bullet.cpp b/modules/bullet/space_bullet.cpp index f6df97f11d..c40a1500f0 100644 --- a/modules/bullet/space_bullet.cpp +++ b/modules/bullet/space_bullet.cpp @@ -39,7 +39,7 @@ #include "godot_collision_configuration.h" #include "godot_collision_dispatcher.h" #include "rigid_body_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "soft_body_bullet.h" #include @@ -59,7 +59,7 @@ */ BulletPhysicsDirectSpaceState::BulletPhysicsDirectSpaceState(SpaceBullet *p_space) : - PhysicsDirectSpaceState(), + PhysicsDirectSpaceState3D(), space(p_space) {} int BulletPhysicsDirectSpaceState::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { @@ -366,27 +366,27 @@ void SpaceBullet::step(real_t p_delta_time) { dynamicsWorld->stepSimulation(p_delta_time, 0, 0); } -void SpaceBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) { +void SpaceBullet::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { assert(dynamicsWorld); switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: gravityMagnitude = p_value; update_gravity(); break; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: gravityDirection = p_value; update_gravity(); break; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: break; // No damp - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_PRIORITY: // Priority is always 0, the lower break; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: break; default: WARN_PRINT("This set parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it."); @@ -394,22 +394,22 @@ void SpaceBullet::set_param(PhysicsServer::AreaParameter p_param, const Variant } } -Variant SpaceBullet::get_param(PhysicsServer::AreaParameter p_param) { +Variant SpaceBullet::get_param(PhysicsServer3D::AreaParameter p_param) { switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: + case PhysicsServer3D::AREA_PARAM_GRAVITY: return gravityMagnitude; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: return gravityDirection; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: return 0; // No damp - case PhysicsServer::AREA_PARAM_PRIORITY: + case PhysicsServer3D::AREA_PARAM_PRIORITY: return 0; // Priority is always 0, the lower - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return false; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return 0; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return 0; default: WARN_PRINT("This get parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it."); @@ -417,32 +417,32 @@ Variant SpaceBullet::get_param(PhysicsServer::AreaParameter p_param) { } } -void SpaceBullet::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) { +void SpaceBullet::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) { switch (p_param) { - case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: - case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: - case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: - case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: - case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION: + case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: + case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: + case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: default: WARN_PRINT("This set parameter (" + itos(p_param) + ") is ignored, the SpaceBullet doesn't support it."); break; } } -real_t SpaceBullet::get_param(PhysicsServer::SpaceParameter p_param) { +real_t SpaceBullet::get_param(PhysicsServer3D::SpaceParameter p_param) { switch (p_param) { - case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: - case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: - case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: - case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: - case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: - case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: + case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION: + case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: + case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: + case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP: + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: + case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: default: WARN_PRINT("The SpaceBullet doesn't support this get parameter (" + itos(p_param) + "), 0 is returned."); return 0.f; @@ -891,7 +891,7 @@ static Ref red_mat; static Ref blue_mat; #endif -bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes) { +bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) { #if debug_test_motion /// Yes I know this is not good, but I've used it as fast debugging hack. @@ -1042,7 +1042,7 @@ bool SpaceBullet::test_body_motion(RigidBodyBullet *p_body, const Transform &p_f return has_penetration; } -int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin) { +int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, float p_margin) { btTransform body_transform; G_TO_B(p_transform, body_transform); @@ -1054,7 +1054,7 @@ int SpaceBullet::test_ray_separation(RigidBodyBullet *p_body, const Transform &p int rays_found_this_round = 0; for (int t(RECOVERING_MOVEMENT_CYCLES); 0 < t; --t) { - PhysicsServer::SeparationResult *next_results = &r_results[rays_found]; + PhysicsServer3D::SeparationResult *next_results = &r_results[rays_found]; rays_found_this_round = recover_from_penetration_ray(p_body, body_transform, RECOVERING_MOVEMENT_SCALE, p_infinite_inertia, p_result_max - rays_found, recover_motion, next_results); rays_found += rays_found_this_round; @@ -1333,7 +1333,7 @@ bool SpaceBullet::RFP_convex_world_test(const btConvexShape *p_shapeA, const btC return false; } -int SpaceBullet::add_separation_result(PhysicsServer::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { +int SpaceBullet::add_separation_result(PhysicsServer3D::SeparationResult *r_result, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const { // optimize results (ignore non-colliding) if (p_recover_result.penetration_distance < 0.0) { @@ -1355,7 +1355,7 @@ int SpaceBullet::add_separation_result(PhysicsServer::SeparationResult *r_result } } -int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results) { +int SpaceBullet::recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer3D::SeparationResult *r_results) { // Calculate the cumulative AABB of all shapes of the kinematic body btVector3 aabb_min, aabb_max; diff --git a/modules/bullet/space_bullet.h b/modules/bullet/space_bullet.h index 32372f1630..fce715b48d 100644 --- a/modules/bullet/space_bullet.h +++ b/modules/bullet/space_bullet.h @@ -35,7 +35,7 @@ #include "core/vector.h" #include "godot_result_callbacks.h" #include "rid_bullet.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include #include @@ -67,8 +67,8 @@ class btGjkEpaPenetrationDepthSolver; extern ContactAddedCallback gContactAddedCallback; -class BulletPhysicsDirectSpaceState : public PhysicsDirectSpaceState { - GDCLASS(BulletPhysicsDirectSpaceState, PhysicsDirectSpaceState); +class BulletPhysicsDirectSpaceState : public PhysicsDirectSpaceState3D { + GDCLASS(BulletPhysicsDirectSpaceState, PhysicsDirectSpaceState3D); private: SpaceBullet *space; @@ -131,15 +131,15 @@ public: /// @param p_param: /// AREA_PARAM_GRAVITY to set the gravity magnitude of entire world /// AREA_PARAM_GRAVITY_VECTOR to set the gravity direction of entire world - void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value); + void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); /// Used to get some parameters to Bullet world /// @param p_param: /// AREA_PARAM_GRAVITY to get the gravity magnitude of entire world /// AREA_PARAM_GRAVITY_VECTOR to get the gravity direction of entire world - Variant get_param(PhysicsServer::AreaParameter p_param); + Variant get_param(PhysicsServer3D::AreaParameter p_param); - void set_param(PhysicsServer::SpaceParameter p_param, real_t p_value); - real_t get_param(PhysicsServer::SpaceParameter p_param); + void set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value); + real_t get_param(PhysicsServer3D::SpaceParameter p_param); void add_area(AreaBullet *p_area); void remove_area(AreaBullet *p_area); @@ -177,8 +177,8 @@ public: void update_gravity(); - bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes); - int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, float p_margin); + bool test_body_motion(RigidBodyBullet *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes); + int test_ray_separation(RigidBodyBullet *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, float p_margin); private: void create_empty_world(bool p_create_soft_world); @@ -213,7 +213,7 @@ private: /// Using this we leave Bullet to select the best algorithm, For example GJK in case we have Convex Convex, or a Bullet accelerated algorithm bool RFP_convex_world_test(const btConvexShape *p_shapeA, const btCollisionShape *p_shapeB, btCollisionObject *p_objectA, btCollisionObject *p_objectB, int p_shapeId_A, int p_shapeId_B, const btTransform &p_transformA, const btTransform &p_transformB, btScalar p_recover_movement_scale, btVector3 &r_delta_recover_movement, RecoverResult *r_recover_result = NULL); - int add_separation_result(PhysicsServer::SeparationResult *r_results, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; - int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer::SeparationResult *r_results); + int add_separation_result(PhysicsServer3D::SeparationResult *r_results, const SpaceBullet::RecoverResult &p_recover_result, int p_shape_id, const btCollisionObject *p_other_object) const; + int recover_from_penetration_ray(RigidBodyBullet *p_body, const btTransform &p_body_position, btScalar p_recover_movement_scale, bool p_infinite_inertia, int p_result_max, btVector3 &r_delta_recover_movement, PhysicsServer3D::SeparationResult *r_results); }; #endif diff --git a/modules/csg/csg_shape.cpp b/modules/csg/csg_shape.cpp index d052eba41c..848b865efb 100644 --- a/modules/csg/csg_shape.cpp +++ b/modules/csg/csg_shape.cpp @@ -43,16 +43,16 @@ void CSGShape3D::set_use_collision(bool p_enable) { if (use_collision) { root_collision_shape.instance(); - root_collision_instance = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_state(root_collision_instance, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); - PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); - PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); + root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); + PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); set_collision_layer(collision_layer); set_collision_mask(collision_mask); _make_dirty(); //force update } else { - PhysicsServer::get_singleton()->free(root_collision_instance); + PhysicsServer3D::get_singleton()->free(root_collision_instance); root_collision_instance = RID(); root_collision_shape.unref(); } @@ -66,7 +66,7 @@ bool CSGShape3D::is_using_collision() const { void CSGShape3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; if (root_collision_instance.is_valid()) { - PhysicsServer::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer); + PhysicsServer3D::get_singleton()->body_set_collision_layer(root_collision_instance, p_layer); } } @@ -79,7 +79,7 @@ void CSGShape3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; if (root_collision_instance.is_valid()) { - PhysicsServer::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask); + PhysicsServer3D::get_singleton()->body_set_collision_mask(root_collision_instance, p_mask); } } @@ -506,11 +506,11 @@ void CSGShape3D::_notification(int p_what) { if (use_collision && is_root_shape()) { root_collision_shape.instance(); - root_collision_instance = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_state(root_collision_instance, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); - PhysicsServer::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); - PhysicsServer::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); + root_collision_instance = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_set_state(root_collision_instance, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_add_shape(root_collision_instance, root_collision_shape->get_rid()); + PhysicsServer3D::get_singleton()->body_set_space(root_collision_instance, get_world()->get_space()); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(root_collision_instance, get_instance_id()); set_collision_layer(collision_layer); set_collision_mask(collision_mask); } @@ -539,7 +539,7 @@ void CSGShape3D::_notification(int p_what) { parent = NULL; if (use_collision && is_root_shape() && root_collision_instance.is_valid()) { - PhysicsServer::get_singleton()->free(root_collision_instance); + PhysicsServer3D::get_singleton()->free(root_collision_instance); root_collision_instance = RID(); root_collision_shape.unref(); } diff --git a/modules/gdnative/arvr/arvr_interface_gdnative.cpp b/modules/gdnative/arvr/arvr_interface_gdnative.cpp index 0f0c864df2..faa891e624 100644 --- a/modules/gdnative/arvr/arvr_interface_gdnative.cpp +++ b/modules/gdnative/arvr/arvr_interface_gdnative.cpp @@ -31,7 +31,7 @@ #include "arvr_interface_gdnative.h" #include "core/input/input_filter.h" #include "servers/arvr/arvr_positional_tracker.h" -#include "servers/visual/visual_server_globals.h" +#include "servers/rendering/rendering_server_globals.h" void ARVRInterfaceGDNative::_bind_methods() { ADD_PROPERTY_DEFAULT("interface_is_initialized", false); @@ -292,7 +292,7 @@ void GDAPI godot_arvr_blit(godot_int p_eye, godot_rid *p_render_target, godot_re #warning this needs to be redone #endif #if 0 - VSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0); + RSG::rasterizer->blit_render_target_to_screen(*render_target, screen_rect, 0); #endif } @@ -302,13 +302,13 @@ godot_int GDAPI godot_arvr_get_texid(godot_rid *p_render_target) { #if 0 RID *render_target = (RID *)p_render_target; - RID eye_texture = VSG::storage->render_target_get_texture(*render_target); + RID eye_texture = RSG::storage->render_target_get_texture(*render_target); #endif #ifndef _MSC_VER #warning need to obtain this ID again #endif - uint32_t texid = 0; //VS::get_singleton()->texture_get_texid(eye_texture); + uint32_t texid = 0; //RS::get_singleton()->texture_get_texid(eye_texture); return texid; } diff --git a/modules/gdnavigation/gd_navigation_server.cpp b/modules/gdnavigation/gd_navigation_server.cpp index a1f6ddfedc..cade6c8a6d 100644 --- a/modules/gdnavigation/gd_navigation_server.cpp +++ b/modules/gdnavigation/gd_navigation_server.cpp @@ -114,7 +114,7 @@ void GdNavigationServer::MERGE(_cmd_, F_NAME)(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) GdNavigationServer::GdNavigationServer() : - NavigationServer(), + NavigationServer3D(), active(true) { } diff --git a/modules/gdnavigation/gd_navigation_server.h b/modules/gdnavigation/gd_navigation_server.h index e9f5c1ffe6..01d1a4fba9 100644 --- a/modules/gdnavigation/gd_navigation_server.h +++ b/modules/gdnavigation/gd_navigation_server.h @@ -33,7 +33,7 @@ #include "core/rid.h" #include "core/rid_owner.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" #include "nav_map.h" #include "nav_region.h" @@ -67,7 +67,7 @@ struct SetCommand { virtual void exec(GdNavigationServer *server) = 0; }; -class GdNavigationServer : public NavigationServer { +class GdNavigationServer : public NavigationServer3D { Mutex commands_mutex; /// Mutex used to make any operation threadsafe. Mutex operations_mutex; diff --git a/modules/gdnavigation/register_types.cpp b/modules/gdnavigation/register_types.cpp index d717733787..9965a89fde 100644 --- a/modules/gdnavigation/register_types.cpp +++ b/modules/gdnavigation/register_types.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "gd_navigation_server.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" #ifndef _3D_DISABLED #include "navigation_mesh_generator.h" @@ -50,12 +50,12 @@ NavigationMeshGenerator *_nav_mesh_generator = NULL; #endif -NavigationServer *new_server() { +NavigationServer3D *new_server() { return memnew(GdNavigationServer); } void register_gdnavigation_types() { - NavigationServerManager::set_default_server(new_server); + NavigationServer3DManager::set_default_server(new_server); #ifndef _3D_DISABLED _nav_mesh_generator = memnew(NavigationMeshGenerator); diff --git a/modules/glslang/register_types.cpp b/modules/glslang/register_types.cpp index d2b4a18fc7..2540ba476c 100644 --- a/modules/glslang/register_types.cpp +++ b/modules/glslang/register_types.cpp @@ -30,7 +30,7 @@ #include "register_types.h" -#include "servers/visual/rendering_device.h" +#include "servers/rendering/rendering_device.h" #include #include diff --git a/modules/gridmap/grid_map.cpp b/modules/gridmap/grid_map.cpp index 61f18fbfee..35c214d3cf 100644 --- a/modules/gridmap/grid_map.cpp +++ b/modules/gridmap/grid_map.cpp @@ -36,8 +36,8 @@ #include "scene/resources/mesh_library.h" #include "scene/resources/surface_tool.h" #include "scene/scene_string_names.h" -#include "servers/navigation_server.h" -#include "servers/visual_server.h" +#include "servers/navigation_server_3d.h" +#include "servers/rendering_server.h" bool GridMap::_set(const StringName &p_name, const Variant &p_value) { @@ -76,12 +76,12 @@ bool GridMap::_set(const StringName &p_name, const Variant &p_value) { BakedMesh bm; bm.mesh = meshes[i]; ERR_CONTINUE(!bm.mesh.is_valid()); - bm.instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); - VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); + bm.instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); + RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); + RS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); } baked_meshes.push_back(bm); } @@ -306,17 +306,17 @@ void GridMap::set_cell_item(int p_x, int p_y, int p_z, int p_item, int p_rot) { //create octant because it does not exist Octant *g = memnew(Octant); g->dirty = true; - g->static_body = PhysicsServer::get_singleton()->body_create(PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id()); - PhysicsServer::get_singleton()->body_set_collision_layer(g->static_body, collision_layer); - PhysicsServer::get_singleton()->body_set_collision_mask(g->static_body, collision_mask); + g->static_body = PhysicsServer3D::get_singleton()->body_create(PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(g->static_body, get_instance_id()); + PhysicsServer3D::get_singleton()->body_set_collision_layer(g->static_body, collision_layer); + PhysicsServer3D::get_singleton()->body_set_collision_mask(g->static_body, collision_mask); SceneTree *st = SceneTree::get_singleton(); if (st && st->is_debugging_collisions_hint()) { - g->collision_debug = VisualServer::get_singleton()->mesh_create(); - g->collision_debug_instance = VisualServer::get_singleton()->instance_create(); - VisualServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug); + g->collision_debug = RenderingServer::get_singleton()->mesh_create(); + g->collision_debug_instance = RenderingServer::get_singleton()->instance_create(); + RenderingServer::get_singleton()->instance_set_base(g->collision_debug_instance, g->collision_debug); } octant_map[octantkey] = g; @@ -392,14 +392,14 @@ void GridMap::_octant_transform(const OctantKey &p_key) { ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - PhysicsServer::get_singleton()->body_set_state(g.static_body, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); if (g.collision_debug_instance.is_valid()) { - VS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); + RS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); } for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); } } @@ -410,17 +410,17 @@ bool GridMap::_octant_update(const OctantKey &p_key) { return false; //erase body shapes - PhysicsServer::get_singleton()->body_clear_shapes(g.static_body); + PhysicsServer3D::get_singleton()->body_clear_shapes(g.static_body); //erase body shapes debug if (g.collision_debug.is_valid()) { - VS::get_singleton()->mesh_clear(g.collision_debug); + RS::get_singleton()->mesh_clear(g.collision_debug); } //erase navigation for (Map::Element *E = g.navmesh_ids.front(); E; E = E->next()) { - NavigationServer::get_singleton()->free(E->get().region); + NavigationServer3D::get_singleton()->free(E->get().region); } g.navmesh_ids.clear(); @@ -428,8 +428,8 @@ bool GridMap::_octant_update(const OctantKey &p_key) { for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->free(g.multimesh_instances[i].instance); - VS::get_singleton()->free(g.multimesh_instances[i].multimesh); + RS::get_singleton()->free(g.multimesh_instances[i].instance); + RS::get_singleton()->free(g.multimesh_instances[i].multimesh); } g.multimesh_instances.clear(); @@ -484,7 +484,7 @@ bool GridMap::_octant_update(const OctantKey &p_key) { // add the item's shape if (!shapes[i].shape.is_valid()) continue; - PhysicsServer::get_singleton()->body_add_shape(g.static_body, shapes[i].shape->get_rid(), xform * shapes[i].local_transform); + PhysicsServer3D::get_singleton()->body_add_shape(g.static_body, shapes[i].shape->get_rid(), xform * shapes[i].local_transform); if (g.collision_debug.is_valid()) { shapes.write[i].shape->add_vertices_to_array(col_debug, xform * shapes[i].local_transform); } @@ -497,10 +497,10 @@ bool GridMap::_octant_update(const OctantKey &p_key) { nm.xform = xform * mesh_library->get_item_navmesh_transform(c.item); if (navigation) { - RID region = NavigationServer::get_singleton()->region_create(); - NavigationServer::get_singleton()->region_set_navmesh(region, navmesh); - NavigationServer::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform); - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_navmesh(region, navmesh); + NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * nm.xform); + NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); nm.region = region; } g.navmesh_ids[E->get()] = nm; @@ -513,13 +513,13 @@ bool GridMap::_octant_update(const OctantKey &p_key) { for (Map>>::Element *E = multimesh_items.front(); E; E = E->next()) { Octant::MultimeshInstance mmi; - RID mm = VS::get_singleton()->multimesh_create(); - VS::get_singleton()->multimesh_allocate(mm, E->get().size(), VS::MULTIMESH_TRANSFORM_3D); - VS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid()); + RID mm = RS::get_singleton()->multimesh_create(); + RS::get_singleton()->multimesh_allocate(mm, E->get().size(), RS::MULTIMESH_TRANSFORM_3D); + RS::get_singleton()->multimesh_set_mesh(mm, mesh_library->get_item_mesh(E->key())->get_rid()); int idx = 0; for (List>::Element *F = E->get().front(); F; F = F->next()) { - VS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first); + RS::get_singleton()->multimesh_instance_set_transform(mm, idx, F->get().first); #ifdef TOOLS_ENABLED Octant::MultimeshInstance::Item it; @@ -532,12 +532,12 @@ bool GridMap::_octant_update(const OctantKey &p_key) { idx++; } - RID instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->instance_set_base(instance, mm); + RID instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->instance_set_base(instance, mm); if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); + RS::get_singleton()->instance_set_transform(instance, get_global_transform()); } mmi.multimesh = mm; @@ -550,13 +550,13 @@ bool GridMap::_octant_update(const OctantKey &p_key) { if (col_debug.size()) { Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX] = col_debug; + arr.resize(RS::ARRAY_MAX); + arr[RS::ARRAY_VERTEX] = col_debug; - VS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, VS::PRIMITIVE_LINES, arr); + RS::get_singleton()->mesh_add_surface_from_arrays(g.collision_debug, RS::PRIMITIVE_LINES, arr); SceneTree *st = SceneTree::get_singleton(); if (st) { - VS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid()); + RS::get_singleton()->mesh_surface_set_material(g.collision_debug, 0, st->get_debug_collision_material()->get_rid()); } } @@ -567,8 +567,8 @@ bool GridMap::_octant_update(const OctantKey &p_key) { void GridMap::_reset_physic_bodies_collision_filters() { for (Map::Element *E = octant_map.front(); E; E = E->next()) { - PhysicsServer::get_singleton()->body_set_collision_layer(E->get()->static_body, collision_layer); - PhysicsServer::get_singleton()->body_set_collision_mask(E->get()->static_body, collision_mask); + PhysicsServer3D::get_singleton()->body_set_collision_layer(E->get()->static_body, collision_layer); + PhysicsServer3D::get_singleton()->body_set_collision_mask(E->get()->static_body, collision_mask); } } @@ -576,17 +576,17 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) { ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - PhysicsServer::get_singleton()->body_set_state(g.static_body, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_set_space(g.static_body, get_world()->get_space()); + PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_space(g.static_body, get_world()->get_space()); if (g.collision_debug_instance.is_valid()) { - VS::get_singleton()->instance_set_scenario(g.collision_debug_instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(g.collision_debug_instance, get_world()->get_scenario()); + RS::get_singleton()->instance_set_transform(g.collision_debug_instance, get_global_transform()); } for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, get_world()->get_scenario()); + RS::get_singleton()->instance_set_transform(g.multimesh_instances[i].instance, get_global_transform()); } if (navigation && mesh_library.is_valid()) { @@ -595,10 +595,10 @@ void GridMap::_octant_enter_world(const OctantKey &p_key) { if (cell_map.has(F->key()) && F->get().region.is_valid() == false) { Ref nm = mesh_library->get_item_navmesh(cell_map[F->key()].item); if (nm.is_valid()) { - RID region = NavigationServer::get_singleton()->region_create(); - NavigationServer::get_singleton()->region_set_navmesh(region, nm); - NavigationServer::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform); - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + RID region = NavigationServer3D::get_singleton()->region_create(); + NavigationServer3D::get_singleton()->region_set_navmesh(region, nm); + NavigationServer3D::get_singleton()->region_set_transform(region, navigation->get_global_transform() * F->get().xform); + NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); F->get().region = region; } } @@ -610,23 +610,23 @@ void GridMap::_octant_exit_world(const OctantKey &p_key) { ERR_FAIL_COND(!octant_map.has(p_key)); Octant &g = *octant_map[p_key]; - PhysicsServer::get_singleton()->body_set_state(g.static_body, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); - PhysicsServer::get_singleton()->body_set_space(g.static_body, RID()); + PhysicsServer3D::get_singleton()->body_set_state(g.static_body, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_space(g.static_body, RID()); if (g.collision_debug_instance.is_valid()) { - VS::get_singleton()->instance_set_scenario(g.collision_debug_instance, RID()); + RS::get_singleton()->instance_set_scenario(g.collision_debug_instance, RID()); } for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID()); + RS::get_singleton()->instance_set_scenario(g.multimesh_instances[i].instance, RID()); } if (navigation) { for (Map::Element *F = g.navmesh_ids.front(); F; F = F->next()) { if (F->get().region.is_valid()) { - NavigationServer::get_singleton()->free(F->get().region); + NavigationServer3D::get_singleton()->free(F->get().region); F->get().region = RID(); } } @@ -639,15 +639,15 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) { Octant &g = *octant_map[p_key]; if (g.collision_debug.is_valid()) - VS::get_singleton()->free(g.collision_debug); + RS::get_singleton()->free(g.collision_debug); if (g.collision_debug_instance.is_valid()) - VS::get_singleton()->free(g.collision_debug_instance); + RS::get_singleton()->free(g.collision_debug_instance); - PhysicsServer::get_singleton()->free(g.static_body); + PhysicsServer3D::get_singleton()->free(g.static_body); // Erase navigation for (Map::Element *E = g.navmesh_ids.front(); E; E = E->next()) { - NavigationServer::get_singleton()->free(E->get().region); + NavigationServer3D::get_singleton()->free(E->get().region); } g.navmesh_ids.clear(); @@ -655,8 +655,8 @@ void GridMap::_octant_clean_up(const OctantKey &p_key) { for (int i = 0; i < g.multimesh_instances.size(); i++) { - VS::get_singleton()->free(g.multimesh_instances[i].instance); - VS::get_singleton()->free(g.multimesh_instances[i].multimesh); + RS::get_singleton()->free(g.multimesh_instances[i].instance); + RS::get_singleton()->free(g.multimesh_instances[i].multimesh); } g.multimesh_instances.clear(); } @@ -684,8 +684,8 @@ void GridMap::_notification(int p_what) { } for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, get_world()->get_scenario()); + RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); } } break; @@ -702,7 +702,7 @@ void GridMap::_notification(int p_what) { last_transform = new_xform; for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); + RS::get_singleton()->instance_set_transform(baked_meshes[i].instance, get_global_transform()); } } break; @@ -718,7 +718,7 @@ void GridMap::_notification(int p_what) { //_update_octants_callback(); //_update_area_instances(); for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID()); + RS::get_singleton()->instance_set_scenario(baked_meshes[i].instance, RID()); } } break; @@ -738,7 +738,7 @@ void GridMap::_update_visibility() { Octant *octant = e->value(); for (int i = 0; i < octant->multimesh_instances.size(); i++) { const Octant::MultimeshInstance &mi = octant->multimesh_instances[i]; - VS::get_singleton()->instance_set_visible(mi.instance, is_visible()); + RS::get_singleton()->instance_set_visible(mi.instance, is_visible()); } } } @@ -975,7 +975,7 @@ Vector3 GridMap::_get_offset() const { void GridMap::clear_baked_meshes() { for (int i = 0; i < baked_meshes.size(); i++) { - VS::get_singleton()->free(baked_meshes[i].instance); + RS::get_singleton()->free(baked_meshes[i].instance); } baked_meshes.clear(); @@ -1050,12 +1050,12 @@ void GridMap::make_baked_meshes(bool p_gen_lightmap_uv, float p_lightmap_uv_texe BakedMesh bm; bm.mesh = mesh; - bm.instance = VS::get_singleton()->instance_create(); - VS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); - VS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); + bm.instance = RS::get_singleton()->instance_create(); + RS::get_singleton()->get_singleton()->instance_set_base(bm.instance, bm.mesh->get_rid()); + RS::get_singleton()->instance_attach_object_instance_id(bm.instance, get_instance_id()); if (is_inside_tree()) { - VS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); - VS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); + RS::get_singleton()->instance_set_scenario(bm.instance, get_world()->get_scenario()); + RS::get_singleton()->instance_set_transform(bm.instance, get_global_transform()); } if (p_gen_lightmap_uv) { diff --git a/modules/gridmap/grid_map.h b/modules/gridmap/grid_map.h index 43f4c09715..3f3da09fe9 100644 --- a/modules/gridmap/grid_map.h +++ b/modules/gridmap/grid_map.h @@ -166,10 +166,10 @@ class GridMap : public Node3D { struct BakeLight { - VS::LightType type; + RS::LightType type; Vector3 pos; Vector3 dir; - float param[VS::LIGHT_PARAM_MAX]; + float param[RS::LIGHT_PARAM_MAX]; }; _FORCE_INLINE_ Vector3 _octant_get_offset(const OctantKey &p_key) const { diff --git a/modules/gridmap/grid_map_editor_plugin.cpp b/modules/gridmap/grid_map_editor_plugin.cpp index a2479e764f..4a6cb8762f 100644 --- a/modules/gridmap/grid_map_editor_plugin.cpp +++ b/modules/gridmap/grid_map_editor_plugin.cpp @@ -281,8 +281,8 @@ void GridMapEditor::_update_cursor_transform() { cursor_transform = node->get_global_transform() * cursor_transform; if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); - VisualServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); + RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, cursor_visible); } } @@ -292,9 +292,9 @@ void GridMapEditor::_update_selection_transform() { if (!selection.active) { - VisualServer::get_singleton()->instance_set_transform(selection_instance, xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_instance, xf_zero); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); } return; } @@ -303,11 +303,11 @@ void GridMapEditor::_update_selection_transform() { xf.scale((Vector3(1, 1, 1) + (selection.end - selection.begin)) * node->get_cell_size()); xf.origin = selection.begin * node->get_cell_size(); - VisualServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(selection_instance, node->get_global_transform() * xf); for (int i = 0; i < 3; i++) { if (i != edit_axis || (edit_floor[edit_axis] < selection.begin[edit_axis]) || (edit_floor[edit_axis] > selection.end[edit_axis] + 1)) { - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf_zero); } else { Vector3 scale = (selection.end - selection.begin + Vector3(1, 1, 1)); @@ -322,7 +322,7 @@ void GridMapEditor::_update_selection_transform() { xf2.basis.scale(scale); xf2.origin = pos; - VisualServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); + RenderingServer::get_singleton()->instance_set_transform(selection_level_instance[i], xf2); } } } @@ -416,7 +416,7 @@ bool GridMapEditor::do_input_action(Camera3D *p_camera, const Point2 &p_point, b } } - VS::get_singleton()->instance_set_transform(grid_instance[edit_axis], node->get_global_transform() * edit_grid_xform); + RS::get_singleton()->instance_set_transform(grid_instance[edit_axis], node->get_global_transform() * edit_grid_xform); if (cursor_instance.is_valid()) { @@ -528,7 +528,7 @@ void GridMapEditor::_clear_clipboard_data() { for (List::Element *E = clipboard_items.front(); E; E = E->next()) { - VisualServer::get_singleton()->free(E->get().instance); + RenderingServer::get_singleton()->free(E->get().instance); } clipboard_items.clear(); @@ -556,7 +556,7 @@ void GridMapEditor::_set_clipboard_data() { item.cell_item = itm; item.grid_offset = Vector3(i, j, k) - selection.begin; item.orientation = node->get_cell_item_orientation(i, j, k); - item.instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); + item.instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); clipboard_items.push_back(item); } @@ -570,7 +570,7 @@ void GridMapEditor::_update_paste_indicator() { Transform xf; xf.basis.set_zero(); - VisualServer::get_singleton()->instance_set_transform(paste_instance, xf); + RenderingServer::get_singleton()->instance_set_transform(paste_instance, xf); return; } @@ -584,7 +584,7 @@ void GridMapEditor::_update_paste_indicator() { xf.basis = rot * xf.basis; xf.translate((-center * node->get_cell_size()) / scale); - VisualServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(paste_instance, node->get_global_transform() * xf); for (List::Element *E = clipboard_items.front(); E; E = E->next()) { @@ -599,7 +599,7 @@ void GridMapEditor::_update_paste_indicator() { item_rot.set_orthogonal_index(item.orientation); xf.basis = item_rot * xf.basis * node->get_cell_scale(); - VisualServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); + RenderingServer::get_singleton()->instance_set_transform(item.instance, node->get_global_transform() * xf); } } @@ -969,11 +969,11 @@ void GridMapEditor::edit(GridMap *p_gridmap) { if (!node) { set_process(false); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], false); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], false); } if (cursor_instance.is_valid()) { - VisualServer::get_singleton()->instance_set_visible(cursor_instance, false); + RenderingServer::get_singleton()->instance_set_visible(cursor_instance, false); } return; @@ -1011,7 +1011,7 @@ void GridMapEditor::update_grid() { edit_grid_xform.basis = Basis(); for (int i = 0; i < 3; i++) { - VisualServer::get_singleton()->instance_set_visible(grid_instance[i], i == edit_axis); + RenderingServer::get_singleton()->instance_set_visible(grid_instance[i], i == edit_axis); } updating = true; @@ -1023,7 +1023,7 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { Vector3 edited_floor = node->has_meta("_editor_floor_") ? node->get_meta("_editor_floor_") : Variant(); for (int i = 0; i < 3; i++) { - VS::get_singleton()->mesh_clear(grid[i]); + RS::get_singleton()->mesh_clear(grid[i]); edit_floor[i] = edited_floor[i]; } @@ -1065,11 +1065,11 @@ void GridMapEditor::_draw_grids(const Vector3 &cell_size) { } Array d; - d.resize(VS::ARRAY_MAX); - d[VS::ARRAY_VERTEX] = grid_points[i]; - d[VS::ARRAY_COLOR] = grid_colors[i]; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], VisualServer::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); + d.resize(RS::ARRAY_MAX); + d[RS::ARRAY_VERTEX] = grid_points[i]; + d[RS::ARRAY_COLOR] = grid_colors[i]; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(grid[i], RenderingServer::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(grid[i], 0, indicator_mat->get_rid()); } } @@ -1082,13 +1082,13 @@ void GridMapEditor::_notification(int p_what) { mesh_library_palette->connect("item_selected", callable_mp(this, &GridMapEditor::_item_selected_cbk)); for (int i = 0; i < 3; i++) { - grid[i] = VS::get_singleton()->mesh_create(); - grid_instance[i] = VS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); - selection_level_instance[i] = VisualServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario()); + grid[i] = RS::get_singleton()->mesh_create(); + grid_instance[i] = RS::get_singleton()->instance_create2(grid[i], get_tree()->get_root()->get_world()->get_scenario()); + selection_level_instance[i] = RenderingServer::get_singleton()->instance_create2(selection_level_mesh[i], get_tree()->get_root()->get_world()->get_scenario()); } - selection_instance = VisualServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario()); - paste_instance = VisualServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario()); + selection_instance = RenderingServer::get_singleton()->instance_create2(selection_mesh, get_tree()->get_root()->get_world()->get_scenario()); + paste_instance = RenderingServer::get_singleton()->instance_create2(paste_mesh, get_tree()->get_root()->get_world()->get_scenario()); _update_selection_transform(); _update_paste_indicator(); @@ -1100,15 +1100,15 @@ void GridMapEditor::_notification(int p_what) { for (int i = 0; i < 3; i++) { - VS::get_singleton()->free(grid_instance[i]); - VS::get_singleton()->free(grid[i]); + RS::get_singleton()->free(grid_instance[i]); + RS::get_singleton()->free(grid[i]); grid_instance[i] = RID(); grid[i] = RID(); - VisualServer::get_singleton()->free(selection_level_instance[i]); + RenderingServer::get_singleton()->free(selection_level_instance[i]); } - VisualServer::get_singleton()->free(selection_instance); - VisualServer::get_singleton()->free(paste_instance); + RenderingServer::get_singleton()->free(selection_instance); + RenderingServer::get_singleton()->free(paste_instance); selection_instance = RID(); paste_instance = RID(); } break; @@ -1123,7 +1123,7 @@ void GridMapEditor::_notification(int p_what) { if (xf != grid_xform) { for (int i = 0; i < 3; i++) { - VS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform); + RS::get_singleton()->instance_set_transform(grid_instance[i], xf * edit_grid_xform); } grid_xform = xf; } @@ -1159,7 +1159,7 @@ void GridMapEditor::_update_cursor_instance() { } if (cursor_instance.is_valid()) - VisualServer::get_singleton()->free(cursor_instance); + RenderingServer::get_singleton()->free(cursor_instance); cursor_instance = RID(); if (selected_palette >= 0) { @@ -1168,8 +1168,8 @@ void GridMapEditor::_update_cursor_instance() { Ref mesh = node->get_mesh_library()->get_item_mesh(selected_palette); if (!mesh.is_null() && mesh->get_rid().is_valid()) { - cursor_instance = VisualServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); - VisualServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); + cursor_instance = RenderingServer::get_singleton()->instance_create2(mesh->get_rid(), get_tree()->get_root()->get_world()->get_scenario()); + RenderingServer::get_singleton()->instance_set_transform(cursor_instance, cursor_transform); } } } @@ -1353,8 +1353,8 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { lock_view = false; cursor_rot = 0; - selection_mesh = VisualServer::get_singleton()->mesh_create(); - paste_mesh = VisualServer::get_singleton()->mesh_create(); + selection_mesh = RenderingServer::get_singleton()->mesh_create(); + paste_mesh = RenderingServer::get_singleton()->mesh_create(); { // Selection mesh create. @@ -1431,16 +1431,16 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { } Array d; - d.resize(VS::ARRAY_MAX); + d.resize(RS::ARRAY_MAX); inner_mat.instance(); inner_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.2)); inner_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); inner_mat->set_transparency(StandardMaterial3D::TRANSPARENCY_ALPHA); - d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); + d[RS::ARRAY_VERTEX] = triangles; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 0, inner_mat->get_rid()); outer_mat.instance(); outer_mat->set_albedo(Color(0.7, 0.7, 1.0, 0.8)); @@ -1454,23 +1454,23 @@ GridMapEditor::GridMapEditor(EditorNode *p_editor) { selection_floor_mat->set_on_top_of_alpha(); selection_floor_mat->set_shading_mode(StandardMaterial3D::SHADING_MODE_UNSHADED); - d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); + d[RS::ARRAY_VERTEX] = lines; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_mesh, RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_mesh, 1, outer_mat->get_rid()); - d[VS::ARRAY_VERTEX] = triangles; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_TRIANGLES, d); - VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); + d[RS::ARRAY_VERTEX] = triangles; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, RS::PRIMITIVE_TRIANGLES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(paste_mesh, 0, inner_mat->get_rid()); - d[VS::ARRAY_VERTEX] = lines; - VisualServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); + d[RS::ARRAY_VERTEX] = lines; + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(paste_mesh, RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(paste_mesh, 1, outer_mat->get_rid()); for (int i = 0; i < 3; i++) { - d[VS::ARRAY_VERTEX] = square[i]; - selection_level_mesh[i] = VS::get_singleton()->mesh_create(); - VisualServer::get_singleton()->mesh_add_surface_from_arrays(selection_level_mesh[i], VS::PRIMITIVE_LINES, d); - VisualServer::get_singleton()->mesh_surface_set_material(selection_level_mesh[i], 0, selection_floor_mat->get_rid()); + d[RS::ARRAY_VERTEX] = square[i]; + selection_level_mesh[i] = RS::get_singleton()->mesh_create(); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(selection_level_mesh[i], RS::PRIMITIVE_LINES, d); + RenderingServer::get_singleton()->mesh_surface_set_material(selection_level_mesh[i], 0, selection_floor_mat->get_rid()); } } @@ -1493,24 +1493,24 @@ GridMapEditor::~GridMapEditor() { for (int i = 0; i < 3; i++) { if (grid[i].is_valid()) - VisualServer::get_singleton()->free(grid[i]); + RenderingServer::get_singleton()->free(grid[i]); if (grid_instance[i].is_valid()) - VisualServer::get_singleton()->free(grid_instance[i]); + RenderingServer::get_singleton()->free(grid_instance[i]); if (cursor_instance.is_valid()) - VisualServer::get_singleton()->free(cursor_instance); + RenderingServer::get_singleton()->free(cursor_instance); if (selection_level_instance[i].is_valid()) - VisualServer::get_singleton()->free(selection_level_instance[i]); + RenderingServer::get_singleton()->free(selection_level_instance[i]); if (selection_level_mesh[i].is_valid()) - VisualServer::get_singleton()->free(selection_level_mesh[i]); + RenderingServer::get_singleton()->free(selection_level_mesh[i]); } - VisualServer::get_singleton()->free(selection_mesh); + RenderingServer::get_singleton()->free(selection_mesh); if (selection_instance.is_valid()) - VisualServer::get_singleton()->free(selection_instance); + RenderingServer::get_singleton()->free(selection_instance); - VisualServer::get_singleton()->free(paste_mesh); + RenderingServer::get_singleton()->free(paste_mesh); if (paste_instance.is_valid()) - VisualServer::get_singleton()->free(paste_instance); + RenderingServer::get_singleton()->free(paste_instance); } void GridMapEditorPlugin::_notification(int p_what) { diff --git a/modules/mobile_vr/mobile_vr_interface.cpp b/modules/mobile_vr/mobile_vr_interface.cpp index 1b253d3699..c82a521a43 100644 --- a/modules/mobile_vr/mobile_vr_interface.cpp +++ b/modules/mobile_vr/mobile_vr_interface.cpp @@ -32,7 +32,7 @@ #include "core/input/input_filter.h" #include "core/os/os.h" #include "servers/display_server.h" -#include "servers/visual/visual_server_globals.h" +#include "servers/rendering/rendering_server_globals.h" StringName MobileVRInterface::get_name() const { return "Native mobile"; diff --git a/modules/opensimplex/noise_texture.cpp b/modules/opensimplex/noise_texture.cpp index 8e5b04f995..1a08ec416f 100644 --- a/modules/opensimplex/noise_texture.cpp +++ b/modules/opensimplex/noise_texture.cpp @@ -50,7 +50,7 @@ NoiseTexture::NoiseTexture() { NoiseTexture::~NoiseTexture() { if (texture.is_valid()) { - VS::get_singleton()->free(texture); + RS::get_singleton()->free(texture); } if (noise_thread) { Thread::wait_to_finish(noise_thread); @@ -100,10 +100,10 @@ void NoiseTexture::_set_texture_data(const Ref &p_image) { data = p_image; if (data.is_valid()) { if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(p_image); - VS::get_singleton()->texture_replace(texture, new_texture); + RID new_texture = RS::get_singleton()->texture_2d_create(p_image); + RS::get_singleton()->texture_replace(texture, new_texture); } else { - texture = VS::get_singleton()->texture_2d_create(p_image); + texture = RS::get_singleton()->texture_2d_create(p_image); } } emit_changed(); @@ -254,7 +254,7 @@ int NoiseTexture::get_height() const { RID NoiseTexture::get_rid() const { if (!texture.is_valid()) { - texture = VS::get_singleton()->texture_2d_placeholder_create(); + texture = RS::get_singleton()->texture_2d_placeholder_create(); } return texture; diff --git a/platform/android/os_android.cpp b/platform/android/os_android.cpp index e3792b1f31..537230826c 100644 --- a/platform/android/os_android.cpp +++ b/platform/android/os_android.cpp @@ -39,8 +39,8 @@ #include "drivers/unix/file_access_unix.h" #include "file_access_android.h" #include "main/main.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_wrap_mt.h" #include "dir_access_jandroid.h" #include "file_access_jandroid.h" @@ -146,12 +146,12 @@ Error OS_Android::initialize(const VideoMode &p_desired, int p_video_driver, int video_driver_index = p_video_driver; - visual_server = memnew(VisualServerRaster); + rendering_server = memnew(RenderingServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, false)); + rendering_server = memnew(RenderingServerWrapMT(rendering_server, false)); } - visual_server->init(); + rendering_server->init(); AudioDriverManager::initialize(p_audio_driver); @@ -759,7 +759,7 @@ OS_Android::OS_Android(GodotJavaWrapper *p_godot_java, GodotIOJavaWrapper *p_god //rasterizer = NULL; use_gl2 = false; - visual_server = NULL; + rendering_server = NULL; godot_java = p_godot_java; godot_io_java = p_godot_io_java; diff --git a/platform/android/os_android.h b/platform/android/os_android.h index d09f4e10d6..8a91412ef6 100644 --- a/platform/android/os_android.h +++ b/platform/android/os_android.h @@ -37,7 +37,7 @@ #include "core/os/main_loop.h" #include "drivers/unix/os_unix.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" +#include "servers/rendering/rasterizer.h" class GodotJavaWrapper; class GodotIOJavaWrapper; @@ -75,7 +75,7 @@ private: bool use_16bits_fbo; - VisualServer *visual_server; + RenderingServer *rendering_server; mutable String data_dir_cache; diff --git a/platform/haiku/os_haiku.cpp b/platform/haiku/os_haiku.cpp index a082ba53f9..7939ea0a1e 100644 --- a/platform/haiku/os_haiku.cpp +++ b/platform/haiku/os_haiku.cpp @@ -32,9 +32,9 @@ #include "drivers/gles2/rasterizer_gles2.h" #include "main/main.h" -#include "servers/physics/physics_server_sw.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/physics_3d/physics_server_3d_sw.h" +#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_wrap_mt.h" #include @@ -116,13 +116,13 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p RasterizerGLES2::make_current(); #endif - visual_server = memnew(VisualServerRaster); + rendering_server = memnew(RenderingServerRaster); // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, false)); + rendering_server = memnew(RenderingServerWrapMT(rendering_server, false)); } - ERR_FAIL_COND_V(!visual_server, ERR_UNAVAILABLE); + ERR_FAIL_COND_V(!rendering_server, ERR_UNAVAILABLE); video_driver_index = p_video_driver; @@ -130,7 +130,7 @@ Error OS_Haiku::initialize(const VideoMode &p_desired, int p_video_driver, int p window->SetInput(input); window->Show(); - visual_server->init(); + rendering_server->init(); AudioDriverManager::initialize(p_audio_driver); @@ -144,8 +144,8 @@ void OS_Haiku::finalize() { main_loop = NULL; - visual_server->finish(); - memdelete(visual_server); + rendering_server->finish(); + memdelete(rendering_server); memdelete(input); @@ -267,7 +267,7 @@ void OS_Haiku::set_window_position(const Point2 &p_position) { void OS_Haiku::set_window_fullscreen(bool p_enabled) { window->SetFullScreen(p_enabled); current_video_mode.fullscreen = p_enabled; - visual_server->init(); + rendering_server->init(); } bool OS_Haiku::is_window_fullscreen() const { diff --git a/platform/haiku/os_haiku.h b/platform/haiku/os_haiku.h index 90c0abc3ef..64f5690dd1 100644 --- a/platform/haiku/os_haiku.h +++ b/platform/haiku/os_haiku.h @@ -38,7 +38,7 @@ #include "haiku_application.h" #include "haiku_direct_window.h" #include "servers/audio_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class OS_Haiku : public OS_Unix { private: @@ -46,7 +46,7 @@ private: HaikuDirectWindow *window; MainLoop *main_loop; InputDefault *input; - VisualServer *visual_server; + RenderingServer *rendering_server; VideoMode current_video_mode; int video_driver_index; diff --git a/platform/iphone/os_iphone.cpp b/platform/iphone/os_iphone.cpp index 497f2f747d..fe912621bb 100644 --- a/platform/iphone/os_iphone.cpp +++ b/platform/iphone/os_iphone.cpp @@ -37,13 +37,13 @@ #endif #if defined(VULKAN_ENABLED) -#include "servers/visual/rasterizer_rd/rasterizer_rd.h" +#include "servers/rendering/rasterizer_rd/rasterizer_rd.h" // #import #include #endif -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_wrap_mt.h" #include "main/main.h" @@ -134,16 +134,16 @@ Error OSIPhone::initialize(const VideoMode &p_desired, int p_video_driver, int p RasterizerRD::make_current(); #endif - visual_server = memnew(VisualServerRaster); + rendering_server = memnew(RenderingServerRaster); // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, false)); + rendering_server = memnew(RenderingServerWrapMT(rendering_server, false)); } - visual_server->init(); - //visual_server->cursor_set_visible(false, 0); + rendering_server->init(); + //rendering_server->cursor_set_visible(false, 0); #if defined(OPENGL_ENABLED) - // reset this to what it should be, it will have been set to 0 after visual_server->init() is called + // reset this to what it should be, it will have been set to 0 after rendering_server->init() is called RasterizerStorageGLES2::system_fbo = gl_view_base_fb; #endif @@ -361,8 +361,8 @@ void OSIPhone::finalize() { memdelete(icloud); #endif - visual_server->finish(); - memdelete(visual_server); + rendering_server->finish(); + memdelete(rendering_server); // memdelete(rasterizer); // Free unhandled events before close @@ -636,7 +636,7 @@ OSIPhone::OSIPhone(int width, int height, String p_data_dir) { ios_init_callbacks_capacity = 0; main_loop = NULL; - visual_server = NULL; + rendering_server = NULL; VideoMode vm; vm.fullscreen = true; diff --git a/platform/iphone/os_iphone.h b/platform/iphone/os_iphone.h index 2efb7af7c2..96cf041c37 100644 --- a/platform/iphone/os_iphone.h +++ b/platform/iphone/os_iphone.h @@ -41,8 +41,8 @@ #include "in_app_store.h" #include "ios.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" #if defined(VULKAN_ENABLED) #include "drivers/vulkan/rendering_device_vulkan.h" @@ -60,7 +60,7 @@ private: static HashMap dynamic_symbol_lookup_table; friend void register_dynamic_symbol(char *name, void *address); - VisualServer *visual_server; + RenderingServer *rendering_server; AudioDriverCoreAudio audio_driver; diff --git a/platform/javascript/os_javascript.cpp b/platform/javascript/os_javascript.cpp index b7feb5bfbd..40c42a5c03 100644 --- a/platform/javascript/os_javascript.cpp +++ b/platform/javascript/os_javascript.cpp @@ -36,7 +36,7 @@ #include "drivers/unix/dir_access_unix.h" #include "drivers/unix/file_access_unix.h" #include "main/main.h" -#include "servers/visual/visual_server_raster.h" +#include "servers/rendering/rendering_server_raster.h" #include #include @@ -962,7 +962,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, setenv("LANG", locale_ptr, true); AudioDriverManager::initialize(p_audio_driver); - VisualServer *visual_server = memnew(VisualServerRaster()); + RenderingServer *rendering_server = memnew(RenderingServerRaster()); input = memnew(InputDefault); EMSCRIPTEN_RESULT result; @@ -1016,7 +1016,7 @@ Error OS_JavaScript::initialize(const VideoMode &p_desired, int p_video_driver, ); /* clang-format on */ - visual_server->init(); + rendering_server->init(); return OK; } diff --git a/platform/javascript/os_javascript.h b/platform/javascript/os_javascript.h index 1a3a6616b0..368e9a2155 100644 --- a/platform/javascript/os_javascript.h +++ b/platform/javascript/os_javascript.h @@ -35,7 +35,7 @@ #include "core/input/input_filter.h" #include "drivers/unix/os_unix.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" +#include "servers/rendering/rasterizer.h" #include diff --git a/platform/linuxbsd/display_server_x11.cpp b/platform/linuxbsd/display_server_x11.cpp index 4bea458187..c2b5657081 100644 --- a/platform/linuxbsd/display_server_x11.cpp +++ b/platform/linuxbsd/display_server_x11.cpp @@ -44,7 +44,7 @@ #endif #if defined(VULKAN_ENABLED) -#include "servers/visual/rasterizer_rd/rasterizer_rd.h" +#include "servers/rendering/rasterizer_rd/rasterizer_rd.h" #endif #include "scene/resources/texture.h" @@ -3615,9 +3615,9 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode #endif /* - visual_server = memnew(VisualServerRaster); + rendering_server = memnew(RenderingServerRaster); if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); + rendering_server = memnew(RenderingServerWrapMT(rendering_server, get_render_thread_mode() == RENDER_SEPARATE_THREAD)); } */ diff --git a/platform/linuxbsd/display_server_x11.h b/platform/linuxbsd/display_server_x11.h index d1680b0508..aa10be555c 100644 --- a/platform/linuxbsd/display_server_x11.h +++ b/platform/linuxbsd/display_server_x11.h @@ -43,8 +43,8 @@ #include "drivers/unix/os_unix.h" #include "joypad_linux.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" #if defined(OPENGL_ENABLED) #include "context_gl_x11.h" diff --git a/platform/linuxbsd/os_linuxbsd.h b/platform/linuxbsd/os_linuxbsd.h index 6c656c1945..100cb53ba3 100644 --- a/platform/linuxbsd/os_linuxbsd.h +++ b/platform/linuxbsd/os_linuxbsd.h @@ -39,8 +39,8 @@ #include "drivers/unix/os_unix.h" #include "joypad_linux.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" class OS_LinuxBSD : public OS_Unix { diff --git a/platform/server/os_server.cpp b/platform/server/os_server.cpp index 3257ec261c..6b26ceed57 100644 --- a/platform/server/os_server.cpp +++ b/platform/server/os_server.cpp @@ -33,7 +33,7 @@ #include "core/print_string.h" #include "drivers/dummy/rasterizer_dummy.h" #include "drivers/dummy/texture_loader_dummy.h" -#include "servers/visual/visual_server_raster.h" +#include "servers/rendering/rendering_server_raster.h" #include "main/main.h" @@ -80,8 +80,8 @@ Error OS_Server::initialize(const VideoMode &p_desired, int p_video_driver, int video_driver_index = p_video_driver; // unused in server platform, but should still be initialized - visual_server = memnew(VisualServerRaster); - visual_server->init(); + rendering_server = memnew(RenderingServerRaster); + rendering_server->init(); AudioDriverManager::initialize(p_audio_driver); @@ -101,8 +101,8 @@ void OS_Server::finalize() { memdelete(main_loop); main_loop = NULL; - visual_server->finish(); - memdelete(visual_server); + rendering_server->finish(); + memdelete(rendering_server); memdelete(input); diff --git a/platform/server/os_server.h b/platform/server/os_server.h index d40905718e..62028b26e4 100644 --- a/platform/server/os_server.h +++ b/platform/server/os_server.h @@ -41,14 +41,14 @@ #include "platform/x11/crash_handler_linuxbsd.h" #endif #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" #undef CursorShape class OS_Server : public OS_Unix { - VisualServer *visual_server; + RenderingServer *rendering_server; VideoMode current_videomode; List args; MainLoop *main_loop; diff --git a/platform/uwp/os_uwp.cpp b/platform/uwp/os_uwp.cpp index 4ddb5463d0..85719d13ae 100644 --- a/platform/uwp/os_uwp.cpp +++ b/platform/uwp/os_uwp.cpp @@ -45,8 +45,8 @@ #include "main/main.h" #include "platform/windows/windows_terminal_logger.h" #include "servers/audio_server.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_wrap_mt.h" #include "thread_uwp.h" #include @@ -254,13 +254,13 @@ Error OS_UWP::initialize(const VideoMode &p_desired, int p_video_driver, int p_a set_video_mode(vm); - visual_server = memnew(VisualServerRaster); + rendering_server = memnew(RenderingServerRaster); // FIXME: Reimplement threaded rendering if (get_render_thread_mode() != RENDER_THREAD_UNSAFE) { - visual_server = memnew(VisualServerWrapMT(visual_server, false)); + rendering_server = memnew(RenderingServerWrapMT(rendering_server, false)); } - visual_server->init(); + rendering_server->init(); input = memnew(InputDefault); @@ -349,8 +349,8 @@ void OS_UWP::finalize() { main_loop = NULL; - visual_server->finish(); - memdelete(visual_server); + rendering_server->finish(); + memdelete(rendering_server); #ifdef OPENGL_ENABLED if (gl_context) memdelete(gl_context); diff --git a/platform/uwp/os_uwp.h b/platform/uwp/os_uwp.h index cc4dfcc79f..de3b094ef4 100644 --- a/platform/uwp/os_uwp.h +++ b/platform/uwp/os_uwp.h @@ -39,8 +39,8 @@ #include "drivers/xaudio2/audio_driver_xaudio2.h" #include "joypad_uwp.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" #include #include @@ -88,7 +88,7 @@ private: bool outside; int old_x, old_y; Point2i center; - VisualServer *visual_server; + RenderingServer *rendering_server; int pressrc; ContextEGL_UWP *gl_context; diff --git a/platform/windows/display_server_windows.h b/platform/windows/display_server_windows.h index 47bb3f59a6..b0386d551e 100644 --- a/platform/windows/display_server_windows.h +++ b/platform/windows/display_server_windows.h @@ -13,9 +13,9 @@ #include "joypad_windows.h" #include "key_mapping_windows.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/rasterizer_rd/rasterizer_rd.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering/rasterizer_rd/rasterizer_rd.h" +#include "servers/rendering_server.h" #ifdef XAUDIO2_ENABLED #include "drivers/xaudio2/audio_driver_xaudio2.h" diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index f78c87be93..4112135cec 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -46,8 +46,8 @@ #include "main/main.h" #include "platform/windows/display_server_windows.h" #include "servers/audio_server.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual/visual_server_wrap_mt.h" +#include "servers/rendering/rendering_server_raster.h" +#include "servers/rendering/rendering_server_wrap_mt.h" #include "windows_terminal_logger.h" #include diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h index 040951668d..29280eb17c 100644 --- a/platform/windows/os_windows.h +++ b/platform/windows/os_windows.h @@ -40,8 +40,8 @@ #include "drivers/winmidi/midi_driver_winmidi.h" #include "key_mapping_windows.h" #include "servers/audio_server.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" #ifdef XAUDIO2_ENABLED #include "drivers/xaudio2/audio_driver_xaudio2.h" #endif diff --git a/scene/2d/area_2d.cpp b/scene/2d/area_2d.cpp index b99c4c88bf..4ccff07416 100644 --- a/scene/2d/area_2d.cpp +++ b/scene/2d/area_2d.cpp @@ -32,12 +32,12 @@ #include "scene/scene_string_names.h" #include "servers/audio_server.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" void Area2D::set_space_override_mode(SpaceOverride p_mode) { space_override = p_mode; - Physics2DServer::get_singleton()->area_set_space_override_mode(get_rid(), Physics2DServer::AreaSpaceOverrideMode(p_mode)); + PhysicsServer2D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer2D::AreaSpaceOverrideMode(p_mode)); } Area2D::SpaceOverride Area2D::get_space_override_mode() const { @@ -47,7 +47,7 @@ Area2D::SpaceOverride Area2D::get_space_override_mode() const { void Area2D::set_gravity_is_point(bool p_enabled) { gravity_is_point = p_enabled; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); } bool Area2D::is_gravity_a_point() const { @@ -57,7 +57,7 @@ bool Area2D::is_gravity_a_point() const { void Area2D::set_gravity_distance_scale(real_t p_scale) { gravity_distance_scale = p_scale; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); } real_t Area2D::get_gravity_distance_scale() const { @@ -67,7 +67,7 @@ real_t Area2D::get_gravity_distance_scale() const { void Area2D::set_gravity_vector(const Vector2 &p_vec) { gravity_vec = p_vec; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_GRAVITY_VECTOR, p_vec); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, p_vec); } Vector2 Area2D::get_gravity_vector() const { @@ -77,7 +77,7 @@ Vector2 Area2D::get_gravity_vector() const { void Area2D::set_gravity(real_t p_gravity) { gravity = p_gravity; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_GRAVITY, p_gravity); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_GRAVITY, p_gravity); } real_t Area2D::get_gravity() const { @@ -87,7 +87,7 @@ real_t Area2D::get_gravity() const { void Area2D::set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_LINEAR_DAMP, p_linear_damp); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, p_linear_damp); } real_t Area2D::get_linear_damp() const { @@ -97,7 +97,7 @@ real_t Area2D::get_linear_damp() const { void Area2D::set_angular_damp(real_t p_angular_damp) { angular_damp = p_angular_damp; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_ANGULAR_DAMP, p_angular_damp); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, p_angular_damp); } real_t Area2D::get_angular_damp() const { @@ -108,7 +108,7 @@ real_t Area2D::get_angular_damp() const { void Area2D::set_priority(real_t p_priority) { priority = p_priority; - Physics2DServer::get_singleton()->area_set_param(get_rid(), Physics2DServer::AREA_PARAM_PRIORITY, p_priority); + PhysicsServer2D::get_singleton()->area_set_param(get_rid(), PhysicsServer2D::AREA_PARAM_PRIORITY, p_priority); } real_t Area2D::get_priority() const { @@ -151,7 +151,7 @@ void Area2D::_body_exit_tree(ObjectID p_id) { void Area2D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) { - bool body_in = p_status == Physics2DServer::AREA_BODY_ADDED; + bool body_in = p_status == PhysicsServer2D::AREA_BODY_ADDED; ObjectID objid = p_instance; Object *obj = ObjectDB::get_instance(objid); @@ -254,7 +254,7 @@ void Area2D::_area_exit_tree(ObjectID p_id) { void Area2D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) { - bool area_in = p_status == Physics2DServer::AREA_BODY_ADDED; + bool area_in = p_status == PhysicsServer2D::AREA_BODY_ADDED; ObjectID objid = p_instance; Object *obj = ObjectDB::get_instance(objid); @@ -403,12 +403,12 @@ void Area2D::set_monitoring(bool p_enable) { if (monitoring) { - Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout); - Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout); + PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout); + PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout); } else { - Physics2DServer::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); - Physics2DServer::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); + PhysicsServer2D::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); + PhysicsServer2D::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); _clear_monitoring(); } } @@ -420,14 +420,14 @@ bool Area2D::is_monitoring() const { void Area2D::set_monitorable(bool p_enable) { - ERR_FAIL_COND_MSG(locked || (is_inside_tree() && Physics2DServer::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false)."); + ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer2D::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false)."); if (p_enable == monitorable) return; monitorable = p_enable; - Physics2DServer::get_singleton()->area_set_monitorable(get_rid(), monitorable); + PhysicsServer2D::get_singleton()->area_set_monitorable(get_rid(), monitorable); } bool Area2D::is_monitorable() const { @@ -492,7 +492,7 @@ bool Area2D::overlaps_body(Node *p_body) const { void Area2D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; - Physics2DServer::get_singleton()->area_set_collision_mask(get_rid(), p_mask); + PhysicsServer2D::get_singleton()->area_set_collision_mask(get_rid(), p_mask); } uint32_t Area2D::get_collision_mask() const { @@ -503,7 +503,7 @@ uint32_t Area2D::get_collision_mask() const { void Area2D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; - Physics2DServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); + PhysicsServer2D::get_singleton()->area_set_collision_layer(get_rid(), p_layer); } uint32_t Area2D::get_collision_layer() const { @@ -676,7 +676,7 @@ void Area2D::_bind_methods() { } Area2D::Area2D() : - CollisionObject2D(Physics2DServer::get_singleton()->area_create(), true) { + CollisionObject2D(PhysicsServer2D::get_singleton()->area_create(), true) { space_override = SPACE_OVERRIDE_DISABLED; set_gravity(98); diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp index df0b17800f..55d111439a 100644 --- a/scene/2d/audio_stream_player_2d.cpp +++ b/scene/2d/audio_stream_player_2d.cpp @@ -187,9 +187,9 @@ void AudioStreamPlayer2D::_notification(int p_what) { //check if any area is diverting sound into a bus - Physics2DDirectSpaceState *space_state = Physics2DServer::get_singleton()->space_get_direct_state(world_2d->get_space()); + PhysicsDirectSpaceState2D *space_state = PhysicsServer2D::get_singleton()->space_get_direct_state(world_2d->get_space()); - Physics2DDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; + PhysicsDirectSpaceState2D::ShapeResult sr[MAX_INTERSECT_AREAS]; int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set(), area_mask, false, true); diff --git a/scene/2d/back_buffer_copy.cpp b/scene/2d/back_buffer_copy.cpp index faeb6b7169..4c952b7ca6 100644 --- a/scene/2d/back_buffer_copy.cpp +++ b/scene/2d/back_buffer_copy.cpp @@ -36,15 +36,15 @@ void BackBufferCopy::_update_copy_mode() { case COPY_MODE_DISABLED: { - VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(), false, Rect2()); + RS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(), false, Rect2()); } break; case COPY_MODE_RECT: { - VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(), true, rect); + RS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(), true, rect); } break; case COPY_MODE_VIEWPORT: { - VS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(), true, Rect2()); + RS::get_singleton()->canvas_item_set_copy_to_backbuffer(get_canvas_item(), true, Rect2()); } break; } diff --git a/scene/2d/camera_2d.cpp b/scene/2d/camera_2d.cpp index a8860c3d81..6d8d981974 100644 --- a/scene/2d/camera_2d.cpp +++ b/scene/2d/camera_2d.cpp @@ -33,7 +33,7 @@ #include "core/engine.h" #include "core/math/math_funcs.h" #include "scene/scene_string_names.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void Camera2D::_update_scroll() { diff --git a/scene/2d/canvas_modulate.cpp b/scene/2d/canvas_modulate.cpp index 25db434918..05f8804e2a 100644 --- a/scene/2d/canvas_modulate.cpp +++ b/scene/2d/canvas_modulate.cpp @@ -35,23 +35,23 @@ void CanvasModulate::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_CANVAS) { if (is_visible_in_tree()) { - VS::get_singleton()->canvas_set_modulate(get_canvas(), color); + RS::get_singleton()->canvas_set_modulate(get_canvas(), color); add_to_group("_canvas_modulate_" + itos(get_canvas().get_id())); } } else if (p_what == NOTIFICATION_EXIT_CANVAS) { if (is_visible_in_tree()) { - VS::get_singleton()->canvas_set_modulate(get_canvas(), Color(1, 1, 1, 1)); + RS::get_singleton()->canvas_set_modulate(get_canvas(), Color(1, 1, 1, 1)); remove_from_group("_canvas_modulate_" + itos(get_canvas().get_id())); } } else if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { if (is_visible_in_tree()) { - VS::get_singleton()->canvas_set_modulate(get_canvas(), color); + RS::get_singleton()->canvas_set_modulate(get_canvas(), color); add_to_group("_canvas_modulate_" + itos(get_canvas().get_id())); } else { - VS::get_singleton()->canvas_set_modulate(get_canvas(), Color(1, 1, 1, 1)); + RS::get_singleton()->canvas_set_modulate(get_canvas(), Color(1, 1, 1, 1)); remove_from_group("_canvas_modulate_" + itos(get_canvas().get_id())); } @@ -71,7 +71,7 @@ void CanvasModulate::set_color(const Color &p_color) { color = p_color; if (is_visible_in_tree()) { - VS::get_singleton()->canvas_set_modulate(get_canvas(), color); + RS::get_singleton()->canvas_set_modulate(get_canvas(), color); } } Color CanvasModulate::get_color() const { diff --git a/scene/2d/collision_object_2d.cpp b/scene/2d/collision_object_2d.cpp index 4af2e846f7..5535043432 100644 --- a/scene/2d/collision_object_2d.cpp +++ b/scene/2d/collision_object_2d.cpp @@ -31,7 +31,7 @@ #include "collision_object_2d.h" #include "scene/scene_string_names.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" void CollisionObject2D::_notification(int p_what) { @@ -42,15 +42,15 @@ void CollisionObject2D::_notification(int p_what) { Transform2D global_transform = get_global_transform(); if (area) - Physics2DServer::get_singleton()->area_set_transform(rid, global_transform); + PhysicsServer2D::get_singleton()->area_set_transform(rid, global_transform); else - Physics2DServer::get_singleton()->body_set_state(rid, Physics2DServer::BODY_STATE_TRANSFORM, global_transform); + PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform); RID space = get_world_2d()->get_space(); if (area) { - Physics2DServer::get_singleton()->area_set_space(rid, space); + PhysicsServer2D::get_singleton()->area_set_space(rid, space); } else - Physics2DServer::get_singleton()->body_set_space(rid, space); + PhysicsServer2D::get_singleton()->body_set_space(rid, space); _update_pickable(); @@ -60,9 +60,9 @@ void CollisionObject2D::_notification(int p_what) { case NOTIFICATION_ENTER_CANVAS: { if (area) - Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, get_canvas_layer_instance_id()); + PhysicsServer2D::get_singleton()->area_attach_canvas_instance_id(rid, get_canvas_layer_instance_id()); else - Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, get_canvas_layer_instance_id()); + PhysicsServer2D::get_singleton()->body_attach_canvas_instance_id(rid, get_canvas_layer_instance_id()); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -78,26 +78,26 @@ void CollisionObject2D::_notification(int p_what) { Transform2D global_transform = get_global_transform(); if (area) - Physics2DServer::get_singleton()->area_set_transform(rid, global_transform); + PhysicsServer2D::get_singleton()->area_set_transform(rid, global_transform); else - Physics2DServer::get_singleton()->body_set_state(rid, Physics2DServer::BODY_STATE_TRANSFORM, global_transform); + PhysicsServer2D::get_singleton()->body_set_state(rid, PhysicsServer2D::BODY_STATE_TRANSFORM, global_transform); } break; case NOTIFICATION_EXIT_TREE: { if (area) { - Physics2DServer::get_singleton()->area_set_space(rid, RID()); + PhysicsServer2D::get_singleton()->area_set_space(rid, RID()); } else - Physics2DServer::get_singleton()->body_set_space(rid, RID()); + PhysicsServer2D::get_singleton()->body_set_space(rid, RID()); } break; case NOTIFICATION_EXIT_CANVAS: { if (area) - Physics2DServer::get_singleton()->area_attach_canvas_instance_id(rid, ObjectID()); + PhysicsServer2D::get_singleton()->area_attach_canvas_instance_id(rid, ObjectID()); else - Physics2DServer::get_singleton()->body_attach_canvas_instance_id(rid, ObjectID()); + PhysicsServer2D::get_singleton()->body_attach_canvas_instance_id(rid, ObjectID()); } break; } } @@ -136,9 +136,9 @@ void CollisionObject2D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl sd.disabled = p_disabled; for (int i = 0; i < sd.shapes.size(); i++) { if (area) { - Physics2DServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + PhysicsServer2D::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); } else { - Physics2DServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + PhysicsServer2D::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); } } } @@ -160,7 +160,7 @@ void CollisionObject2D::shape_owner_set_one_way_collision(uint32_t p_owner, bool ShapeData &sd = shapes[p_owner]; sd.one_way_collision = p_enable; for (int i = 0; i < sd.shapes.size(); i++) { - Physics2DServer::get_singleton()->body_set_shape_as_one_way_collision(rid, sd.shapes[i].index, sd.one_way_collision, sd.one_way_collision_margin); + PhysicsServer2D::get_singleton()->body_set_shape_as_one_way_collision(rid, sd.shapes[i].index, sd.one_way_collision, sd.one_way_collision_margin); } } @@ -181,7 +181,7 @@ void CollisionObject2D::shape_owner_set_one_way_collision_margin(uint32_t p_owne ShapeData &sd = shapes[p_owner]; sd.one_way_collision_margin = p_margin; for (int i = 0; i < sd.shapes.size(); i++) { - Physics2DServer::get_singleton()->body_set_shape_as_one_way_collision(rid, sd.shapes[i].index, sd.one_way_collision, sd.one_way_collision_margin); + PhysicsServer2D::get_singleton()->body_set_shape_as_one_way_collision(rid, sd.shapes[i].index, sd.one_way_collision, sd.one_way_collision_margin); } } @@ -218,9 +218,9 @@ void CollisionObject2D::shape_owner_set_transform(uint32_t p_owner, const Transf sd.xform = p_transform; for (int i = 0; i < sd.shapes.size(); i++) { if (area) { - Physics2DServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, sd.xform); + PhysicsServer2D::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, sd.xform); } else { - Physics2DServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, sd.xform); + PhysicsServer2D::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, sd.xform); } } } @@ -248,9 +248,9 @@ void CollisionObject2D::shape_owner_add_shape(uint32_t p_owner, const Refarea_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + PhysicsServer2D::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); } else { - Physics2DServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + PhysicsServer2D::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); } sd.shapes.push_back(s); @@ -284,9 +284,9 @@ void CollisionObject2D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) int index_to_remove = shapes[p_owner].shapes[p_shape].index; if (area) { - Physics2DServer::get_singleton()->area_remove_shape(rid, index_to_remove); + PhysicsServer2D::get_singleton()->area_remove_shape(rid, index_to_remove); } else { - Physics2DServer::get_singleton()->body_remove_shape(rid, index_to_remove); + PhysicsServer2D::get_singleton()->body_remove_shape(rid, index_to_remove); } shapes[p_owner].shapes.remove(p_shape); @@ -375,9 +375,9 @@ void CollisionObject2D::_update_pickable() { bool is_pickable = pickable && is_visible_in_tree(); if (area) - Physics2DServer::get_singleton()->area_set_pickable(rid, is_pickable); + PhysicsServer2D::get_singleton()->area_set_pickable(rid, is_pickable); else - Physics2DServer::get_singleton()->body_set_pickable(rid, is_pickable); + PhysicsServer2D::get_singleton()->body_set_pickable(rid, is_pickable); } String CollisionObject2D::get_configuration_warning() const { @@ -442,9 +442,9 @@ CollisionObject2D::CollisionObject2D(RID p_rid, bool p_area) { if (p_area) { - Physics2DServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); + PhysicsServer2D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); } else { - Physics2DServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + PhysicsServer2D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); } } @@ -457,5 +457,5 @@ CollisionObject2D::CollisionObject2D() { CollisionObject2D::~CollisionObject2D() { - Physics2DServer::get_singleton()->free(rid); + PhysicsServer2D::get_singleton()->free(rid); } diff --git a/scene/2d/collision_polygon_2d.cpp b/scene/2d/collision_polygon_2d.cpp index e9dfb94cb2..5880045e90 100644 --- a/scene/2d/collision_polygon_2d.cpp +++ b/scene/2d/collision_polygon_2d.cpp @@ -106,7 +106,7 @@ void CollisionPolygon2D::_notification(int p_what) { /*if (Engine::get_singleton()->is_editor_hint()) { //display above all else set_z_as_relative(false); - set_z_index(VS::CANVAS_ITEM_Z_MAX - 1); + set_z_index(RS::CANVAS_ITEM_Z_MAX - 1); }*/ } break; diff --git a/scene/2d/collision_shape_2d.cpp b/scene/2d/collision_shape_2d.cpp index b2ad040654..cb2953cc15 100644 --- a/scene/2d/collision_shape_2d.cpp +++ b/scene/2d/collision_shape_2d.cpp @@ -73,7 +73,7 @@ void CollisionShape2D::_notification(int p_what) { /*if (Engine::get_singleton()->is_editor_hint()) { //display above all else set_z_as_relative(false); - set_z_index(VS::CANVAS_ITEM_Z_MAX - 1); + set_z_index(RS::CANVAS_ITEM_Z_MAX - 1); }*/ } break; diff --git a/scene/2d/cpu_particles_2d.cpp b/scene/2d/cpu_particles_2d.cpp index 8678e5a1f4..ba604c086e 100644 --- a/scene/2d/cpu_particles_2d.cpp +++ b/scene/2d/cpu_particles_2d.cpp @@ -34,7 +34,7 @@ #include "scene/2d/gpu_particles_2d.h" #include "scene/main/canvas_item.h" #include "scene/resources/particles_material.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void CPUParticles2D::set_emitting(bool p_emitting) { @@ -60,7 +60,7 @@ void CPUParticles2D::set_amount(int p_amount) { } particle_data.resize((8 + 4 + 4) * p_amount); - VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_2D, true, true); + RS::get_singleton()->multimesh_allocate(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_2D, true, true); particle_order.resize(p_amount); } @@ -198,14 +198,14 @@ void CPUParticles2D::_update_mesh_texture() { indices.push_back(0); Array arr; - arr.resize(VS::ARRAY_MAX); - arr[VS::ARRAY_VERTEX] = vertices; - arr[VS::ARRAY_TEX_UV] = uvs; - arr[VS::ARRAY_COLOR] = colors; - arr[VS::ARRAY_INDEX] = indices; + arr.resize(RS::ARRAY_MAX); + arr[RS::ARRAY_VERTEX] = vertices; + arr[RS::ARRAY_TEX_UV] = uvs; + arr[RS::ARRAY_COLOR] = colors; + arr[RS::ARRAY_INDEX] = indices; - VS::get_singleton()->mesh_clear(mesh); - VS::get_singleton()->mesh_add_surface_from_arrays(mesh, VS::PRIMITIVE_TRIANGLES, arr); + RS::get_singleton()->mesh_clear(mesh); + RS::get_singleton()->mesh_add_surface_from_arrays(mesh, RS::PRIMITIVE_TRIANGLES, arr); } void CPUParticles2D::set_texture(const Ref &p_texture) { @@ -1046,17 +1046,17 @@ void CPUParticles2D::_set_redraw(bool p_redraw) { MutexLock lock(update_mutex); if (redraw) { - VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles2D::_update_render_thread)); - VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true); + RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles2D::_update_render_thread)); + RS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), true); - VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1); + RS::get_singleton()->multimesh_set_visible_instances(multimesh, -1); } else { - if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles2D::_update_render_thread))) { - VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles2D::_update_render_thread)); + if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles2D::_update_render_thread))) { + RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles2D::_update_render_thread)); } - VS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false); + RS::get_singleton()->canvas_item_set_update_when_visible(get_canvas_item(), false); - VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0); + RS::get_singleton()->multimesh_set_visible_instances(multimesh, 0); } } @@ -1067,7 +1067,7 @@ void CPUParticles2D::_update_render_thread() { MutexLock lock(update_mutex); - VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); + RS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); } void CPUParticles2D::_notification(int p_what) { @@ -1098,7 +1098,7 @@ void CPUParticles2D::_notification(int p_what) { normrid = normalmap->get_rid(); } - VS::get_singleton()->canvas_item_add_multimesh(get_canvas_item(), multimesh, texrid, normrid); + RS::get_singleton()->canvas_item_add_multimesh(get_canvas_item(), multimesh, texrid, normrid); } if (p_what == NOTIFICATION_INTERNAL_PROCESS) { @@ -1428,9 +1428,9 @@ CPUParticles2D::CPUParticles2D() { redraw = false; emitting = false; - mesh = VisualServer::get_singleton()->mesh_create(); - multimesh = VisualServer::get_singleton()->multimesh_create(); - VisualServer::get_singleton()->multimesh_set_mesh(multimesh, mesh); + mesh = RenderingServer::get_singleton()->mesh_create(); + multimesh = RenderingServer::get_singleton()->multimesh_create(); + RenderingServer::get_singleton()->multimesh_set_mesh(multimesh, mesh); set_emitting(true); set_one_shot(false); @@ -1481,6 +1481,6 @@ CPUParticles2D::CPUParticles2D() { } CPUParticles2D::~CPUParticles2D() { - VS::get_singleton()->free(multimesh); - VS::get_singleton()->free(mesh); + RS::get_singleton()->free(multimesh); + RS::get_singleton()->free(mesh); } diff --git a/scene/2d/gpu_particles_2d.cpp b/scene/2d/gpu_particles_2d.cpp index d3d1326018..fd9706eb2a 100644 --- a/scene/2d/gpu_particles_2d.cpp +++ b/scene/2d/gpu_particles_2d.cpp @@ -40,7 +40,7 @@ void GPUParticles2D::set_emitting(bool p_emitting) { - VS::get_singleton()->particles_set_emitting(particles, p_emitting); + RS::get_singleton()->particles_set_emitting(particles, p_emitting); if (p_emitting && one_shot) { set_process_internal(true); @@ -53,25 +53,25 @@ void GPUParticles2D::set_amount(int p_amount) { ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles cannot be smaller than 1."); amount = p_amount; - VS::get_singleton()->particles_set_amount(particles, amount); + RS::get_singleton()->particles_set_amount(particles, amount); } void GPUParticles2D::set_lifetime(float p_lifetime) { ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0."); lifetime = p_lifetime; - VS::get_singleton()->particles_set_lifetime(particles, lifetime); + RS::get_singleton()->particles_set_lifetime(particles, lifetime); } void GPUParticles2D::set_one_shot(bool p_enable) { one_shot = p_enable; - VS::get_singleton()->particles_set_one_shot(particles, one_shot); + RS::get_singleton()->particles_set_one_shot(particles, one_shot); if (is_emitting()) { set_process_internal(true); if (!one_shot) - VisualServer::get_singleton()->particles_restart(particles); + RenderingServer::get_singleton()->particles_restart(particles); } if (!one_shot) @@ -80,17 +80,17 @@ void GPUParticles2D::set_one_shot(bool p_enable) { void GPUParticles2D::set_pre_process_time(float p_time) { pre_process_time = p_time; - VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); + RS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); } void GPUParticles2D::set_explosiveness_ratio(float p_ratio) { explosiveness_ratio = p_ratio; - VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); + RS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); } void GPUParticles2D::set_randomness_ratio(float p_ratio) { randomness_ratio = p_ratio; - VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); + RS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); } void GPUParticles2D::set_visibility_rect(const Rect2 &p_visibility_rect) { @@ -101,7 +101,7 @@ void GPUParticles2D::set_visibility_rect(const Rect2 &p_visibility_rect) { aabb.size.x = p_visibility_rect.size.x; aabb.size.y = p_visibility_rect.size.y; - VS::get_singleton()->particles_set_custom_aabb(particles, aabb); + RS::get_singleton()->particles_set_custom_aabb(particles, aabb); _change_notify("visibility_rect"); update(); @@ -109,7 +109,7 @@ void GPUParticles2D::set_visibility_rect(const Rect2 &p_visibility_rect) { void GPUParticles2D::set_use_local_coordinates(bool p_enable) { local_coords = p_enable; - VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); + RS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); set_notify_transform(!p_enable); if (!p_enable && is_inside_tree()) { _update_particle_emission_transform(); @@ -124,7 +124,7 @@ void GPUParticles2D::_update_particle_emission_transform() { xf.basis.set_axis(1, Vector3(xf2d.get_axis(1).x, xf2d.get_axis(1).y, 0)); xf.set_origin(Vector3(xf2d.get_origin().x, xf2d.get_origin().y, 0)); - VS::get_singleton()->particles_set_emission_transform(particles, xf); + RS::get_singleton()->particles_set_emission_transform(particles, xf); } void GPUParticles2D::set_process_material(const Ref &p_material) { @@ -139,7 +139,7 @@ void GPUParticles2D::set_process_material(const Ref &p_material) { RID material_rid; if (process_material.is_valid()) material_rid = process_material->get_rid(); - VS::get_singleton()->particles_set_process_material(particles, material_rid); + RS::get_singleton()->particles_set_process_material(particles, material_rid); update_configuration_warning(); } @@ -147,12 +147,12 @@ void GPUParticles2D::set_process_material(const Ref &p_material) { void GPUParticles2D::set_speed_scale(float p_scale) { speed_scale = p_scale; - VS::get_singleton()->particles_set_speed_scale(particles, p_scale); + RS::get_singleton()->particles_set_speed_scale(particles, p_scale); } bool GPUParticles2D::is_emitting() const { - return VS::get_singleton()->particles_get_emitting(particles); + return RS::get_singleton()->particles_get_emitting(particles); } int GPUParticles2D::get_amount() const { @@ -200,7 +200,7 @@ float GPUParticles2D::get_speed_scale() const { void GPUParticles2D::set_draw_order(DrawOrder p_order) { draw_order = p_order; - VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); + RS::get_singleton()->particles_set_draw_order(particles, RS::ParticlesDrawOrder(p_order)); } GPUParticles2D::DrawOrder GPUParticles2D::get_draw_order() const { @@ -210,7 +210,7 @@ GPUParticles2D::DrawOrder GPUParticles2D::get_draw_order() const { void GPUParticles2D::set_fixed_fps(int p_count) { fixed_fps = p_count; - VS::get_singleton()->particles_set_fixed_fps(particles, p_count); + RS::get_singleton()->particles_set_fixed_fps(particles, p_count); } int GPUParticles2D::get_fixed_fps() const { @@ -219,7 +219,7 @@ int GPUParticles2D::get_fixed_fps() const { void GPUParticles2D::set_fractional_delta(bool p_enable) { fractional_delta = p_enable; - VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); + RS::get_singleton()->particles_set_fractional_delta(particles, p_enable); } bool GPUParticles2D::get_fractional_delta() const { @@ -228,7 +228,7 @@ bool GPUParticles2D::get_fractional_delta() const { String GPUParticles2D::get_configuration_warning() const { - if (VisualServer::get_singleton()->is_low_end()) { + if (RenderingServer::get_singleton()->is_low_end()) { return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); } @@ -259,7 +259,7 @@ String GPUParticles2D::get_configuration_warning() const { Rect2 GPUParticles2D::capture_rect() const { - AABB aabb = VS::get_singleton()->particles_get_current_aabb(particles); + AABB aabb = RS::get_singleton()->particles_get_current_aabb(particles); Rect2 r; r.position.x = aabb.position.x; r.position.y = aabb.position.y; @@ -291,8 +291,8 @@ void GPUParticles2D::_validate_property(PropertyInfo &property) const { } void GPUParticles2D::restart() { - VS::get_singleton()->particles_restart(particles); - VS::get_singleton()->particles_set_emitting(particles, true); + RS::get_singleton()->particles_restart(particles); + RS::get_singleton()->particles_set_emitting(particles, true); } void GPUParticles2D::_notification(int p_what) { @@ -306,7 +306,7 @@ void GPUParticles2D::_notification(int p_what) { if (normal_map.is_valid()) normal_rid = normal_map->get_rid(); - VS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid, normal_rid); + RS::get_singleton()->canvas_item_add_particles(get_canvas_item(), particles, texture_rid, normal_rid); #ifdef TOOLS_ENABLED if (Engine::get_singleton()->is_editor_hint() && (this == get_tree()->get_edited_scene_root() || get_tree()->get_edited_scene_root()->is_a_parent_of(this))) { @@ -318,10 +318,10 @@ void GPUParticles2D::_notification(int p_what) { if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { - VS::get_singleton()->particles_set_speed_scale(particles, speed_scale); + RS::get_singleton()->particles_set_speed_scale(particles, speed_scale); } else { - VS::get_singleton()->particles_set_speed_scale(particles, 0); + RS::get_singleton()->particles_set_speed_scale(particles, 0); } } @@ -408,7 +408,7 @@ void GPUParticles2D::_bind_methods() { GPUParticles2D::GPUParticles2D() { - particles = VS::get_singleton()->particles_create(); + particles = RS::get_singleton()->particles_create(); one_shot = false; // Needed so that set_emitting doesn't access uninitialized values set_emitting(true); @@ -428,5 +428,5 @@ GPUParticles2D::GPUParticles2D() { GPUParticles2D::~GPUParticles2D() { - VS::get_singleton()->free(particles); + RS::get_singleton()->free(particles); } diff --git a/scene/2d/joints_2d.cpp b/scene/2d/joints_2d.cpp index 9cc9ab25ac..6cbb0d2a39 100644 --- a/scene/2d/joints_2d.cpp +++ b/scene/2d/joints_2d.cpp @@ -32,15 +32,15 @@ #include "core/engine.h" #include "physics_body_2d.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" void Joint2D::_update_joint(bool p_only_free) { if (joint.is_valid()) { if (ba.is_valid() && bb.is_valid() && exclude_from_collision) - Physics2DServer::get_singleton()->joint_disable_collisions_between_bodies(joint, false); + PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, false); - Physics2DServer::get_singleton()->free(joint); + PhysicsServer2D::get_singleton()->free(joint); joint = RID(); ba = RID(); bb = RID(); @@ -66,12 +66,12 @@ void Joint2D::_update_joint(bool p_only_free) { if (!joint.is_valid()) return; - Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint, Physics2DServer::JOINT_PARAM_BIAS, bias); + PhysicsServer2D::get_singleton()->get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias); ba = body_a->get_rid(); bb = body_b->get_rid(); - Physics2DServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); + PhysicsServer2D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); } void Joint2D::set_node_a(const NodePath &p_node_a) { @@ -119,7 +119,7 @@ void Joint2D::set_bias(real_t p_bias) { bias = p_bias; if (joint.is_valid()) - Physics2DServer::get_singleton()->get_singleton()->joint_set_param(joint, Physics2DServer::JOINT_PARAM_BIAS, bias); + PhysicsServer2D::get_singleton()->get_singleton()->joint_set_param(joint, PhysicsServer2D::JOINT_PARAM_BIAS, bias); } real_t Joint2D::get_bias() const { @@ -192,8 +192,8 @@ void PinJoint2D::_notification(int p_what) { RID PinJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b) { - RID pj = Physics2DServer::get_singleton()->pin_joint_create(get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID()); - Physics2DServer::get_singleton()->pin_joint_set_param(pj, Physics2DServer::PIN_JOINT_SOFTNESS, softness); + RID pj = PhysicsServer2D::get_singleton()->pin_joint_create(get_global_transform().get_origin(), body_a->get_rid(), body_b ? body_b->get_rid() : RID()); + PhysicsServer2D::get_singleton()->pin_joint_set_param(pj, PhysicsServer2D::PIN_JOINT_SOFTNESS, softness); return pj; } @@ -202,7 +202,7 @@ void PinJoint2D::set_softness(real_t p_softness) { softness = p_softness; update(); if (get_joint().is_valid()) - Physics2DServer::get_singleton()->pin_joint_set_param(get_joint(), Physics2DServer::PIN_JOINT_SOFTNESS, p_softness); + PhysicsServer2D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer2D::PIN_JOINT_SOFTNESS, p_softness); } real_t PinJoint2D::get_softness() const { @@ -253,7 +253,7 @@ RID GrooveJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D *body_b Vector2 groove_A2 = gt.xform(Vector2(0, length)); Vector2 anchor_B = gt.xform(Vector2(0, initial_offset)); - return Physics2DServer::get_singleton()->groove_joint_create(groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid()); + return PhysicsServer2D::get_singleton()->groove_joint_create(groove_A1, groove_A2, anchor_B, body_a->get_rid(), body_b->get_rid()); } void GrooveJoint2D::set_length(real_t p_length) { @@ -324,11 +324,11 @@ RID DampedSpringJoint2D::_configure_joint(PhysicsBody2D *body_a, PhysicsBody2D * Vector2 anchor_A = gt.get_origin(); Vector2 anchor_B = gt.xform(Vector2(0, length)); - RID dsj = Physics2DServer::get_singleton()->damped_spring_joint_create(anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid()); + RID dsj = PhysicsServer2D::get_singleton()->damped_spring_joint_create(anchor_A, anchor_B, body_a->get_rid(), body_b->get_rid()); if (rest_length) - Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj, Physics2DServer::DAMPED_STRING_REST_LENGTH, rest_length); - Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj, Physics2DServer::DAMPED_STRING_STIFFNESS, stiffness); - Physics2DServer::get_singleton()->damped_string_joint_set_param(dsj, Physics2DServer::DAMPED_STRING_DAMPING, damping); + PhysicsServer2D::get_singleton()->damped_string_joint_set_param(dsj, PhysicsServer2D::DAMPED_STRING_REST_LENGTH, rest_length); + PhysicsServer2D::get_singleton()->damped_string_joint_set_param(dsj, PhysicsServer2D::DAMPED_STRING_STIFFNESS, stiffness); + PhysicsServer2D::get_singleton()->damped_string_joint_set_param(dsj, PhysicsServer2D::DAMPED_STRING_DAMPING, damping); return dsj; } @@ -349,7 +349,7 @@ void DampedSpringJoint2D::set_rest_length(real_t p_rest_length) { rest_length = p_rest_length; update(); if (get_joint().is_valid()) - Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(), Physics2DServer::DAMPED_STRING_REST_LENGTH, p_rest_length ? p_rest_length : length); + PhysicsServer2D::get_singleton()->damped_string_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_STRING_REST_LENGTH, p_rest_length ? p_rest_length : length); } real_t DampedSpringJoint2D::get_rest_length() const { @@ -362,7 +362,7 @@ void DampedSpringJoint2D::set_stiffness(real_t p_stiffness) { stiffness = p_stiffness; update(); if (get_joint().is_valid()) - Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(), Physics2DServer::DAMPED_STRING_STIFFNESS, p_stiffness); + PhysicsServer2D::get_singleton()->damped_string_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_STRING_STIFFNESS, p_stiffness); } real_t DampedSpringJoint2D::get_stiffness() const { @@ -375,7 +375,7 @@ void DampedSpringJoint2D::set_damping(real_t p_damping) { damping = p_damping; update(); if (get_joint().is_valid()) - Physics2DServer::get_singleton()->damped_string_joint_set_param(get_joint(), Physics2DServer::DAMPED_STRING_DAMPING, p_damping); + PhysicsServer2D::get_singleton()->damped_string_joint_set_param(get_joint(), PhysicsServer2D::DAMPED_STRING_DAMPING, p_damping); } real_t DampedSpringJoint2D::get_damping() const { diff --git a/scene/2d/light_2d.cpp b/scene/2d/light_2d.cpp index e61b1fa339..b3d54b81f8 100644 --- a/scene/2d/light_2d.cpp +++ b/scene/2d/light_2d.cpp @@ -31,7 +31,7 @@ #include "light_2d.h" #include "core/engine.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #ifdef TOOLS_ENABLED Dictionary Light2D::_edit_get_state() const { @@ -100,7 +100,7 @@ void Light2D::_update_light_visibility() { } #endif - VS::get_singleton()->canvas_light_set_enabled(canvas_light, enabled && is_visible_in_tree() && editor_ok); + RS::get_singleton()->canvas_light_set_enabled(canvas_light, enabled && is_visible_in_tree() && editor_ok); } void Light2D::set_enabled(bool p_enabled) { @@ -129,9 +129,9 @@ void Light2D::set_texture(const Ref &p_texture) { texture = p_texture; if (texture.is_valid()) - VS::get_singleton()->canvas_light_set_texture(canvas_light, texture->get_rid()); + RS::get_singleton()->canvas_light_set_texture(canvas_light, texture->get_rid()); else - VS::get_singleton()->canvas_light_set_texture(canvas_light, RID()); + RS::get_singleton()->canvas_light_set_texture(canvas_light, RID()); update_configuration_warning(); } @@ -144,7 +144,7 @@ Ref Light2D::get_texture() const { void Light2D::set_texture_offset(const Vector2 &p_offset) { texture_offset = p_offset; - VS::get_singleton()->canvas_light_set_texture_offset(canvas_light, texture_offset); + RS::get_singleton()->canvas_light_set_texture_offset(canvas_light, texture_offset); item_rect_changed(); _change_notify("offset"); } @@ -157,7 +157,7 @@ Vector2 Light2D::get_texture_offset() const { void Light2D::set_color(const Color &p_color) { color = p_color; - VS::get_singleton()->canvas_light_set_color(canvas_light, color); + RS::get_singleton()->canvas_light_set_color(canvas_light, color); } Color Light2D::get_color() const { @@ -167,7 +167,7 @@ Color Light2D::get_color() const { void Light2D::set_height(float p_height) { height = p_height; - VS::get_singleton()->canvas_light_set_height(canvas_light, height); + RS::get_singleton()->canvas_light_set_height(canvas_light, height); } float Light2D::get_height() const { @@ -178,7 +178,7 @@ float Light2D::get_height() const { void Light2D::set_energy(float p_energy) { energy = p_energy; - VS::get_singleton()->canvas_light_set_energy(canvas_light, energy); + RS::get_singleton()->canvas_light_set_energy(canvas_light, energy); } float Light2D::get_energy() const { @@ -193,7 +193,7 @@ void Light2D::set_texture_scale(float p_scale) { if (_scale == 0) { _scale = CMP_EPSILON; } - VS::get_singleton()->canvas_light_set_scale(canvas_light, _scale); + RS::get_singleton()->canvas_light_set_scale(canvas_light, _scale); item_rect_changed(); } @@ -205,7 +205,7 @@ float Light2D::get_texture_scale() const { void Light2D::set_z_range_min(int p_min_z) { z_min = p_min_z; - VS::get_singleton()->canvas_light_set_z_range(canvas_light, z_min, z_max); + RS::get_singleton()->canvas_light_set_z_range(canvas_light, z_min, z_max); } int Light2D::get_z_range_min() const { @@ -215,7 +215,7 @@ int Light2D::get_z_range_min() const { void Light2D::set_z_range_max(int p_max_z) { z_max = p_max_z; - VS::get_singleton()->canvas_light_set_z_range(canvas_light, z_min, z_max); + RS::get_singleton()->canvas_light_set_z_range(canvas_light, z_min, z_max); } int Light2D::get_z_range_max() const { @@ -225,7 +225,7 @@ int Light2D::get_z_range_max() const { void Light2D::set_layer_range_min(int p_min_layer) { layer_min = p_min_layer; - VS::get_singleton()->canvas_light_set_layer_range(canvas_light, layer_min, layer_max); + RS::get_singleton()->canvas_light_set_layer_range(canvas_light, layer_min, layer_max); } int Light2D::get_layer_range_min() const { @@ -235,7 +235,7 @@ int Light2D::get_layer_range_min() const { void Light2D::set_layer_range_max(int p_max_layer) { layer_max = p_max_layer; - VS::get_singleton()->canvas_light_set_layer_range(canvas_light, layer_min, layer_max); + RS::get_singleton()->canvas_light_set_layer_range(canvas_light, layer_min, layer_max); } int Light2D::get_layer_range_max() const { @@ -245,7 +245,7 @@ int Light2D::get_layer_range_max() const { void Light2D::set_item_cull_mask(int p_mask) { item_mask = p_mask; - VS::get_singleton()->canvas_light_set_item_cull_mask(canvas_light, item_mask); + RS::get_singleton()->canvas_light_set_item_cull_mask(canvas_light, item_mask); } int Light2D::get_item_cull_mask() const { @@ -256,7 +256,7 @@ int Light2D::get_item_cull_mask() const { void Light2D::set_item_shadow_cull_mask(int p_mask) { item_shadow_mask = p_mask; - VS::get_singleton()->canvas_light_set_item_shadow_cull_mask(canvas_light, item_shadow_mask); + RS::get_singleton()->canvas_light_set_item_shadow_cull_mask(canvas_light, item_shadow_mask); } int Light2D::get_item_shadow_cull_mask() const { @@ -267,7 +267,7 @@ int Light2D::get_item_shadow_cull_mask() const { void Light2D::set_mode(Mode p_mode) { mode = p_mode; - VS::get_singleton()->canvas_light_set_mode(canvas_light, VS::CanvasLightMode(p_mode)); + RS::get_singleton()->canvas_light_set_mode(canvas_light, RS::CanvasLightMode(p_mode)); } Light2D::Mode Light2D::get_mode() const { @@ -278,7 +278,7 @@ Light2D::Mode Light2D::get_mode() const { void Light2D::set_shadow_enabled(bool p_enabled) { shadow = p_enabled; - VS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light, shadow); + RS::get_singleton()->canvas_light_set_shadow_enabled(canvas_light, shadow); } bool Light2D::is_shadow_enabled() const { @@ -288,7 +288,7 @@ bool Light2D::is_shadow_enabled() const { void Light2D::set_shadow_buffer_size(int p_size) { shadow_buffer_size = p_size; - VS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light, shadow_buffer_size); + RS::get_singleton()->canvas_light_set_shadow_buffer_size(canvas_light, shadow_buffer_size); } int Light2D::get_shadow_buffer_size() const { @@ -299,7 +299,7 @@ int Light2D::get_shadow_buffer_size() const { void Light2D::set_shadow_filter(ShadowFilter p_filter) { ERR_FAIL_INDEX(p_filter, SHADOW_FILTER_MAX); shadow_filter = p_filter; - VS::get_singleton()->canvas_light_set_shadow_filter(canvas_light, VS::CanvasLightShadowFilter(p_filter)); + RS::get_singleton()->canvas_light_set_shadow_filter(canvas_light, RS::CanvasLightShadowFilter(p_filter)); } Light2D::ShadowFilter Light2D::get_shadow_filter() const { @@ -309,7 +309,7 @@ Light2D::ShadowFilter Light2D::get_shadow_filter() const { void Light2D::set_shadow_color(const Color &p_shadow_color) { shadow_color = p_shadow_color; - VS::get_singleton()->canvas_light_set_shadow_color(canvas_light, shadow_color); + RS::get_singleton()->canvas_light_set_shadow_color(canvas_light, shadow_color); } Color Light2D::get_shadow_color() const { @@ -320,13 +320,13 @@ void Light2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - VS::get_singleton()->canvas_light_attach_to_canvas(canvas_light, get_canvas()); + RS::get_singleton()->canvas_light_attach_to_canvas(canvas_light, get_canvas()); _update_light_visibility(); } if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { - VS::get_singleton()->canvas_light_set_transform(canvas_light, get_global_transform()); + RS::get_singleton()->canvas_light_set_transform(canvas_light, get_global_transform()); } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { @@ -335,7 +335,7 @@ void Light2D::_notification(int p_what) { if (p_what == NOTIFICATION_EXIT_TREE) { - VS::get_singleton()->canvas_light_attach_to_canvas(canvas_light, RID()); + RS::get_singleton()->canvas_light_attach_to_canvas(canvas_light, RID()); _update_light_visibility(); } } @@ -352,7 +352,7 @@ String Light2D::get_configuration_warning() const { void Light2D::set_shadow_smooth(float p_amount) { shadow_smooth = p_amount; - VS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth); + RS::get_singleton()->canvas_light_set_shadow_smooth(canvas_light, shadow_smooth); } float Light2D::get_shadow_smooth() const { @@ -432,8 +432,8 @@ void Light2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Add,Sub,Mix,Mask"), "set_mode", "get_mode"); ADD_GROUP("Range", "range_"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "range_height", PROPERTY_HINT_RANGE, "-2048,2048,0.1,or_lesser,or_greater"), "set_height", "get_height"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_min", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_min", "get_z_range_min"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "range_z_max", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_range_max", "get_z_range_max"); ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_min", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_min", "get_layer_range_min"); ADD_PROPERTY(PropertyInfo(Variant::INT, "range_layer_max", PROPERTY_HINT_RANGE, "-512,512,1"), "set_layer_range_max", "get_layer_range_max"); ADD_PROPERTY(PropertyInfo(Variant::INT, "range_item_cull_mask", PROPERTY_HINT_LAYERS_2D_RENDER), "set_item_cull_mask", "get_item_cull_mask"); @@ -458,7 +458,7 @@ void Light2D::_bind_methods() { Light2D::Light2D() { - canvas_light = VisualServer::get_singleton()->canvas_light_create(); + canvas_light = RenderingServer::get_singleton()->canvas_light_create(); enabled = true; editor_only = false; shadow = false; @@ -483,5 +483,5 @@ Light2D::Light2D() { Light2D::~Light2D() { - VisualServer::get_singleton()->free(canvas_light); + RenderingServer::get_singleton()->free(canvas_light); } diff --git a/scene/2d/light_occluder_2d.cpp b/scene/2d/light_occluder_2d.cpp index d4a5c93823..bd1a820aec 100644 --- a/scene/2d/light_occluder_2d.cpp +++ b/scene/2d/light_occluder_2d.cpp @@ -88,7 +88,7 @@ void OccluderPolygon2D::set_polygon(const Vector &p_polygon) { polygon = p_polygon; rect_cache_dirty = true; - VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, p_polygon, closed); + RS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, p_polygon, closed); emit_changed(); } @@ -103,7 +103,7 @@ void OccluderPolygon2D::set_closed(bool p_closed) { return; closed = p_closed; if (polygon.size()) - VS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, polygon, closed); + RS::get_singleton()->canvas_occluder_polygon_set_shape(occ_polygon, polygon, closed); emit_changed(); } @@ -115,7 +115,7 @@ bool OccluderPolygon2D::is_closed() const { void OccluderPolygon2D::set_cull_mode(CullMode p_mode) { cull = p_mode; - VS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon, VS::CanvasOccluderPolygonCullMode(p_mode)); + RS::get_singleton()->canvas_occluder_polygon_set_cull_mode(occ_polygon, RS::CanvasOccluderPolygonCullMode(p_mode)); } OccluderPolygon2D::CullMode OccluderPolygon2D::get_cull_mode() const { @@ -150,7 +150,7 @@ void OccluderPolygon2D::_bind_methods() { OccluderPolygon2D::OccluderPolygon2D() { - occ_polygon = VS::get_singleton()->canvas_occluder_polygon_create(); + occ_polygon = RS::get_singleton()->canvas_occluder_polygon_create(); closed = true; cull = CULL_DISABLED; rect_cache_dirty = true; @@ -158,7 +158,7 @@ OccluderPolygon2D::OccluderPolygon2D() { OccluderPolygon2D::~OccluderPolygon2D() { - VS::get_singleton()->free(occ_polygon); + RS::get_singleton()->free(occ_polygon); } void LightOccluder2D::_poly_changed() { @@ -172,17 +172,17 @@ void LightOccluder2D::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_CANVAS) { - VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, get_canvas()); - VS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform()); - VS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree()); + RS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, get_canvas()); + RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform()); + RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree()); } if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { - VS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform()); + RS::get_singleton()->canvas_light_occluder_set_transform(occluder, get_global_transform()); } if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { - VS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree()); + RS::get_singleton()->canvas_light_occluder_set_enabled(occluder, is_visible_in_tree()); } if (p_what == NOTIFICATION_DRAW) { @@ -214,7 +214,7 @@ void LightOccluder2D::_notification(int p_what) { if (p_what == NOTIFICATION_EXIT_CANVAS) { - VS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, RID()); + RS::get_singleton()->canvas_light_occluder_attach_to_canvas(occluder, RID()); } } @@ -239,9 +239,9 @@ void LightOccluder2D::set_occluder_polygon(const Ref &p_polyg occluder_polygon = p_polygon; if (occluder_polygon.is_valid()) - VS::get_singleton()->canvas_light_occluder_set_polygon(occluder, occluder_polygon->get_rid()); + RS::get_singleton()->canvas_light_occluder_set_polygon(occluder, occluder_polygon->get_rid()); else - VS::get_singleton()->canvas_light_occluder_set_polygon(occluder, RID()); + RS::get_singleton()->canvas_light_occluder_set_polygon(occluder, RID()); #ifdef DEBUG_ENABLED if (occluder_polygon.is_valid()) @@ -258,7 +258,7 @@ Ref LightOccluder2D::get_occluder_polygon() const { void LightOccluder2D::set_occluder_light_mask(int p_mask) { mask = p_mask; - VS::get_singleton()->canvas_light_occluder_set_light_mask(occluder, mask); + RS::get_singleton()->canvas_light_occluder_set_light_mask(occluder, mask); } int LightOccluder2D::get_occluder_light_mask() const { @@ -293,12 +293,12 @@ void LightOccluder2D::_bind_methods() { LightOccluder2D::LightOccluder2D() { - occluder = VS::get_singleton()->canvas_light_occluder_create(); + occluder = RS::get_singleton()->canvas_light_occluder_create(); mask = 1; set_notify_transform(true); } LightOccluder2D::~LightOccluder2D() { - VS::get_singleton()->free(occluder); + RS::get_singleton()->free(occluder); } diff --git a/scene/2d/line_2d.cpp b/scene/2d/line_2d.cpp index 873c901c0a..c45eab70df 100644 --- a/scene/2d/line_2d.cpp +++ b/scene/2d/line_2d.cpp @@ -311,7 +311,7 @@ void Line2D::_draw() { lb.build(); - VS::get_singleton()->canvas_item_add_triangle_array( + RS::get_singleton()->canvas_item_add_triangle_array( get_canvas_item(), lb.indices, lb.vertices, diff --git a/scene/2d/navigation_2d.cpp b/scene/2d/navigation_2d.cpp index bbabfa16c7..ae9fc0f32c 100644 --- a/scene/2d/navigation_2d.cpp +++ b/scene/2d/navigation_2d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "navigation_2d.h" -#include "servers/navigation_2d_server.h" +#include "servers/navigation_server_2d.h" void Navigation2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_rid"), &Navigation2D::get_rid); @@ -51,44 +51,44 @@ void Navigation2D::_bind_methods() { void Navigation2D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - Navigation2DServer::get_singleton()->map_set_active(map, true); + NavigationServer2D::get_singleton()->map_set_active(map, true); } break; case NOTIFICATION_EXIT_TREE: { - Navigation2DServer::get_singleton()->map_set_active(map, false); + NavigationServer2D::get_singleton()->map_set_active(map, false); } break; } } void Navigation2D::set_cell_size(float p_cell_size) { cell_size = p_cell_size; - Navigation2DServer::get_singleton()->map_set_cell_size(map, cell_size); + NavigationServer2D::get_singleton()->map_set_cell_size(map, cell_size); } void Navigation2D::set_edge_connection_margin(float p_edge_connection_margin) { edge_connection_margin = p_edge_connection_margin; - Navigation2DServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); + NavigationServer2D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); } Vector Navigation2D::get_simple_path(const Vector2 &p_start, const Vector2 &p_end, bool p_optimize) const { - return Navigation2DServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); + return NavigationServer2D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); } Vector2 Navigation2D::get_closest_point(const Vector2 &p_point) const { - return Navigation2DServer::get_singleton()->map_get_closest_point(map, p_point); + return NavigationServer2D::get_singleton()->map_get_closest_point(map, p_point); } RID Navigation2D::get_closest_point_owner(const Vector2 &p_point) const { - return Navigation2DServer::get_singleton()->map_get_closest_point_owner(map, p_point); + return NavigationServer2D::get_singleton()->map_get_closest_point_owner(map, p_point); } Navigation2D::Navigation2D() { - map = Navigation2DServer::get_singleton()->map_create(); + map = NavigationServer2D::get_singleton()->map_create(); set_cell_size(10); // Ten pixels set_edge_connection_margin(100); } Navigation2D::~Navigation2D() { - Navigation2DServer::get_singleton()->free(map); + NavigationServer2D::get_singleton()->free(map); } diff --git a/scene/2d/navigation_agent_2d.cpp b/scene/2d/navigation_agent_2d.cpp index e345a076ae..c70d5ab1fe 100644 --- a/scene/2d/navigation_agent_2d.cpp +++ b/scene/2d/navigation_agent_2d.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "scene/2d/navigation_2d.h" -#include "servers/navigation_2d_server.h" +#include "servers/navigation_server_2d.h" void NavigationAgent2D::_bind_methods() { @@ -94,7 +94,7 @@ void NavigationAgent2D::_notification(int p_what) { agent_parent = Object::cast_to(get_parent()); - Navigation2DServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + NavigationServer2D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); // Search the navigation node and set it { @@ -121,7 +121,7 @@ void NavigationAgent2D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (agent_parent) { - Navigation2DServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().get_origin()); + NavigationServer2D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().get_origin()); if (!target_reached) { if (distance_to_target() < target_desired_distance) { emit_signal("target_reached"); @@ -142,7 +142,7 @@ NavigationAgent2D::NavigationAgent2D() : velocity_submitted(false), target_reached(false), navigation_finished(true) { - agent = Navigation2DServer::get_singleton()->agent_create(); + agent = NavigationServer2D::get_singleton()->agent_create(); set_neighbor_dist(500.0); set_max_neighbors(10); set_time_horizon(20.0); @@ -151,7 +151,7 @@ NavigationAgent2D::NavigationAgent2D() : } NavigationAgent2D::~NavigationAgent2D() { - Navigation2DServer::get_singleton()->free(agent); + NavigationServer2D::get_singleton()->free(agent); agent = RID(); // Pointless } @@ -160,7 +160,7 @@ void NavigationAgent2D::set_navigation(Navigation2D *p_nav) { return; // Pointless navigation = p_nav; - Navigation2DServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); + NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); } void NavigationAgent2D::set_navigation_node(Node *p_nav) { @@ -179,27 +179,27 @@ void NavigationAgent2D::set_target_desired_distance(real_t p_dd) { void NavigationAgent2D::set_radius(real_t p_radius) { radius = p_radius; - Navigation2DServer::get_singleton()->agent_set_radius(agent, radius); + NavigationServer2D::get_singleton()->agent_set_radius(agent, radius); } void NavigationAgent2D::set_neighbor_dist(real_t p_dist) { neighbor_dist = p_dist; - Navigation2DServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); + NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); } void NavigationAgent2D::set_max_neighbors(int p_count) { max_neighbors = p_count; - Navigation2DServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); + NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); } void NavigationAgent2D::set_time_horizon(real_t p_time) { time_horizon = p_time; - Navigation2DServer::get_singleton()->agent_set_time_horizon(agent, time_horizon); + NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, time_horizon); } void NavigationAgent2D::set_max_speed(real_t p_max_speed) { max_speed = p_max_speed; - Navigation2DServer::get_singleton()->agent_set_max_speed(agent, max_speed); + NavigationServer2D::get_singleton()->agent_set_max_speed(agent, max_speed); } void NavigationAgent2D::set_path_max_distance(real_t p_pmd) { @@ -260,8 +260,8 @@ Vector2 NavigationAgent2D::get_final_location() { void NavigationAgent2D::set_velocity(Vector2 p_velocity) { target_velocity = p_velocity; - Navigation2DServer::get_singleton()->agent_set_target_velocity(agent, target_velocity); - Navigation2DServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); + NavigationServer2D::get_singleton()->agent_set_target_velocity(agent, target_velocity); + NavigationServer2D::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); velocity_submitted = true; } @@ -298,7 +298,7 @@ void NavigationAgent2D::update_navigation() { bool reload_path = false; - if (Navigation2DServer::get_singleton()->agent_is_map_changed(agent)) { + if (NavigationServer2D::get_singleton()->agent_is_map_changed(agent)) { reload_path = true; } else if (navigation_path.size() == 0) { reload_path = true; @@ -317,7 +317,7 @@ void NavigationAgent2D::update_navigation() { } if (reload_path) { - navigation_path = Navigation2DServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_path = NavigationServer2D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); navigation_finished = false; nav_path_index = 0; emit_signal("path_changed"); diff --git a/scene/2d/navigation_obstacle_2d.cpp b/scene/2d/navigation_obstacle_2d.cpp index cc9f5740a9..4c6e777e73 100644 --- a/scene/2d/navigation_obstacle_2d.cpp +++ b/scene/2d/navigation_obstacle_2d.cpp @@ -33,7 +33,7 @@ #include "scene/2d/collision_shape_2d.h" #include "scene/2d/navigation_2d.h" #include "scene/2d/physics_body_2d.h" -#include "servers/navigation_2d_server.h" +#include "servers/navigation_server_2d.h" void NavigationObstacle2D::_bind_methods() { @@ -71,7 +71,7 @@ void NavigationObstacle2D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { Node2D *node = Object::cast_to(get_parent()); if (node) { - Navigation2DServer::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin()); + NavigationServer2D::get_singleton()->agent_set_position(agent, node->get_global_transform().get_origin()); } } break; @@ -81,11 +81,11 @@ void NavigationObstacle2D::_notification(int p_what) { NavigationObstacle2D::NavigationObstacle2D() : navigation(NULL), agent(RID()) { - agent = Navigation2DServer::get_singleton()->agent_create(); + agent = NavigationServer2D::get_singleton()->agent_create(); } NavigationObstacle2D::~NavigationObstacle2D() { - Navigation2DServer::get_singleton()->free(agent); + NavigationServer2D::get_singleton()->free(agent); agent = RID(); // Pointless } @@ -94,7 +94,7 @@ void NavigationObstacle2D::set_navigation(Navigation2D *p_nav) { return; // Pointless navigation = p_nav; - Navigation2DServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); + NavigationServer2D::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); } void NavigationObstacle2D::set_navigation_node(Node *p_nav) { @@ -146,9 +146,9 @@ void NavigationObstacle2D::update_agent_shape() { radius = 1.0; // Never a 0 radius // Initialize the Agent as an object - Navigation2DServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0); - Navigation2DServer::get_singleton()->agent_set_max_neighbors(agent, 0); - Navigation2DServer::get_singleton()->agent_set_time_horizon(agent, 0.0); - Navigation2DServer::get_singleton()->agent_set_radius(agent, radius); - Navigation2DServer::get_singleton()->agent_set_max_speed(agent, 0.0); + NavigationServer2D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer2D::get_singleton()->agent_set_max_neighbors(agent, 0); + NavigationServer2D::get_singleton()->agent_set_time_horizon(agent, 0.0); + NavigationServer2D::get_singleton()->agent_set_radius(agent, radius); + NavigationServer2D::get_singleton()->agent_set_max_speed(agent, 0.0); } diff --git a/scene/2d/navigation_region_2d.cpp b/scene/2d/navigation_region_2d.cpp index bc3e305281..f0839b4597 100644 --- a/scene/2d/navigation_region_2d.cpp +++ b/scene/2d/navigation_region_2d.cpp @@ -34,7 +34,7 @@ #include "core/engine.h" #include "core/os/mutex.h" #include "navigation_2d.h" -#include "servers/navigation_2d_server.h" +#include "servers/navigation_server_2d.h" #include "thirdparty/misc/triangulator.h" @@ -385,12 +385,12 @@ void NavigationRegion2D::set_enabled(bool p_enabled) { if (!enabled) { - Navigation2DServer::get_singleton()->region_set_map(region, RID()); + NavigationServer2D::get_singleton()->region_set_map(region, RID()); } else { if (navigation) { - Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid()); } } @@ -429,7 +429,7 @@ void NavigationRegion2D::_notification(int p_what) { if (enabled) { - Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid()); } break; } @@ -440,14 +440,14 @@ void NavigationRegion2D::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - Navigation2DServer::get_singleton()->region_set_transform(region, get_global_transform()); + NavigationServer2D::get_singleton()->region_set_transform(region, get_global_transform()); } break; case NOTIFICATION_EXIT_TREE: { if (navigation) { - Navigation2DServer::get_singleton()->region_set_map(region, RID()); + NavigationServer2D::get_singleton()->region_set_map(region, RID()); } navigation = NULL; } break; @@ -494,7 +494,7 @@ void NavigationRegion2D::_notification(int p_what) { } } } - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors); + RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, vertices, colors); } } break; } @@ -511,7 +511,7 @@ void NavigationRegion2D::set_navigation_polygon(const Ref &p_ } navpoly = p_navpoly; - Navigation2DServer::get_singleton()->region_set_navpoly(region, p_navpoly); + NavigationServer2D::get_singleton()->region_set_navpoly(region, p_navpoly); if (navpoly.is_valid()) { navpoly->connect(CoreStringNames::get_singleton()->changed, callable_mp(this, &NavigationRegion2D::_navpoly_changed)); @@ -572,11 +572,11 @@ NavigationRegion2D::NavigationRegion2D() { enabled = true; set_notify_transform(true); - region = Navigation2DServer::get_singleton()->region_create(); + region = NavigationServer2D::get_singleton()->region_create(); navigation = NULL; } NavigationRegion2D::~NavigationRegion2D() { - Navigation2DServer::get_singleton()->free(region); + NavigationServer2D::get_singleton()->free(region); } diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp index 0b0b9820d3..ac8a77b6cb 100644 --- a/scene/2d/node_2d.cpp +++ b/scene/2d/node_2d.cpp @@ -33,7 +33,7 @@ #include "core/message_queue.h" #include "scene/gui/control.h" #include "scene/main/window.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #ifdef TOOLS_ENABLED Dictionary Node2D::_edit_get_state() const { @@ -136,7 +136,7 @@ void Node2D::_update_transform() { _mat.set_rotation_and_scale(angle, _scale); _mat.elements[2] = pos; - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat); + RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat); if (!is_inside_tree()) return; @@ -315,7 +315,7 @@ void Node2D::set_transform(const Transform2D &p_transform) { _mat = p_transform; _xform_dirty = true; - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat); + RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), _mat); if (!is_inside_tree()) return; @@ -334,10 +334,10 @@ void Node2D::set_global_transform(const Transform2D &p_transform) { void Node2D::set_z_index(int p_z) { - ERR_FAIL_COND(p_z < VS::CANVAS_ITEM_Z_MIN); - ERR_FAIL_COND(p_z > VS::CANVAS_ITEM_Z_MAX); + ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN); + ERR_FAIL_COND(p_z > RS::CANVAS_ITEM_Z_MAX); z_index = p_z; - VS::get_singleton()->canvas_item_set_z_index(get_canvas_item(), z_index); + RS::get_singleton()->canvas_item_set_z_index(get_canvas_item(), z_index); _change_notify("z_index"); } @@ -346,7 +346,7 @@ void Node2D::set_z_as_relative(bool p_enabled) { if (z_relative == p_enabled) return; z_relative = p_enabled; - VS::get_singleton()->canvas_item_set_z_as_relative_to_parent(get_canvas_item(), p_enabled); + RS::get_singleton()->canvas_item_set_z_as_relative_to_parent(get_canvas_item(), p_enabled); } bool Node2D::is_z_relative() const { @@ -452,7 +452,7 @@ void Node2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "global_transform", PROPERTY_HINT_NONE, "", 0), "set_global_transform", "get_global_transform"); ADD_GROUP("Z Index", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1"), "set_z_index", "get_z_index"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "z_as_relative"), "set_z_as_relative", "is_z_relative"); } diff --git a/scene/2d/parallax_layer.cpp b/scene/2d/parallax_layer.cpp index 5aea1025ef..181f0f158c 100644 --- a/scene/2d/parallax_layer.cpp +++ b/scene/2d/parallax_layer.cpp @@ -78,7 +78,7 @@ void ParallaxLayer::_update_mirroring() { RID c = pb->get_canvas(); RID ci = get_canvas_item(); Point2 mirrorScale = mirroring * get_scale(); - VisualServer::get_singleton()->canvas_set_item_mirroring(c, ci, mirrorScale); + RenderingServer::get_singleton()->canvas_set_item_mirroring(c, ci, mirrorScale); } } diff --git a/scene/2d/physics_body_2d.cpp b/scene/2d/physics_body_2d.cpp index 9bfeca7e56..289860d9c6 100644 --- a/scene/2d/physics_body_2d.cpp +++ b/scene/2d/physics_body_2d.cpp @@ -82,7 +82,7 @@ void PhysicsBody2D::_bind_methods() { void PhysicsBody2D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; - Physics2DServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); + PhysicsServer2D::get_singleton()->body_set_collision_layer(get_rid(), p_layer); } uint32_t PhysicsBody2D::get_collision_layer() const { @@ -93,7 +93,7 @@ uint32_t PhysicsBody2D::get_collision_layer() const { void PhysicsBody2D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; - Physics2DServer::get_singleton()->body_set_collision_mask(get_rid(), p_mask); + PhysicsServer2D::get_singleton()->body_set_collision_mask(get_rid(), p_mask); } uint32_t PhysicsBody2D::get_collision_mask() const { @@ -130,10 +130,10 @@ bool PhysicsBody2D::get_collision_layer_bit(int p_bit) const { return get_collision_layer() & (1 << p_bit); } -PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : - CollisionObject2D(Physics2DServer::get_singleton()->body_create(), false) { +PhysicsBody2D::PhysicsBody2D(PhysicsServer2D::BodyMode p_mode) : + CollisionObject2D(PhysicsServer2D::get_singleton()->body_create(), false) { - Physics2DServer::get_singleton()->body_set_mode(get_rid(), p_mode); + PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), p_mode); collision_layer = 1; collision_mask = 1; set_pickable(false); @@ -141,11 +141,11 @@ PhysicsBody2D::PhysicsBody2D(Physics2DServer::BodyMode p_mode) : Array PhysicsBody2D::get_collision_exceptions() { List exceptions; - Physics2DServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); + PhysicsServer2D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); Array ret; for (List::Element *E = exceptions.front(); E; E = E->next()) { RID body = E->get(); - ObjectID instance_id = Physics2DServer::get_singleton()->body_get_object_instance_id(body); + ObjectID instance_id = PhysicsServer2D::get_singleton()->body_get_object_instance_id(body); Object *obj = ObjectDB::get_instance(instance_id); PhysicsBody2D *physics_body = Object::cast_to(obj); ret.append(physics_body); @@ -158,7 +158,7 @@ void PhysicsBody2D::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); PhysicsBody2D *physics_body = Object::cast_to(p_node); ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody type."); - Physics2DServer::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid()); + PhysicsServer2D::get_singleton()->body_add_collision_exception(get_rid(), physics_body->get_rid()); } void PhysicsBody2D::remove_collision_exception_with(Node *p_node) { @@ -166,19 +166,19 @@ void PhysicsBody2D::remove_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); PhysicsBody2D *physics_body = Object::cast_to(p_node); ERR_FAIL_COND_MSG(!physics_body, "Collision exception only works between two objects of PhysicsBody type."); - Physics2DServer::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid()); + PhysicsServer2D::get_singleton()->body_remove_collision_exception(get_rid(), physics_body->get_rid()); } void StaticBody2D::set_constant_linear_velocity(const Vector2 &p_vel) { constant_linear_velocity = p_vel; - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); } void StaticBody2D::set_constant_angular_velocity(real_t p_vel) { constant_angular_velocity = p_vel; - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); } Vector2 StaticBody2D::get_constant_linear_velocity() const { @@ -225,7 +225,7 @@ void StaticBody2D::_bind_methods() { } StaticBody2D::StaticBody2D() : - PhysicsBody2D(Physics2DServer::BODY_MODE_STATIC) { + PhysicsBody2D(PhysicsServer2D::BODY_MODE_STATIC) { constant_angular_velocity = 0; } @@ -235,11 +235,11 @@ StaticBody2D::~StaticBody2D() { void StaticBody2D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, 0); - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, 1); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1); } else { - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } @@ -362,16 +362,16 @@ struct _RigidBody2DInOut { bool RigidBody2D::_test_motion(const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref &p_result) { - Physics2DServer::MotionResult *r = NULL; + PhysicsServer2D::MotionResult *r = NULL; if (p_result.is_valid()) r = p_result->get_result_ptr(); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r); + return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), get_global_transform(), p_motion, p_infinite_inertia, p_margin, r); } void RigidBody2D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED - state = Object::cast_to(p_state); + state = Object::cast_to(p_state); #else state = (Physics2DDirectBodyState *)p_state; //trust it #endif @@ -484,20 +484,20 @@ void RigidBody2D::set_mode(Mode p_mode) { case MODE_RIGID: { - Physics2DServer::get_singleton()->body_set_mode(get_rid(), Physics2DServer::BODY_MODE_RIGID); + PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_RIGID); } break; case MODE_STATIC: { - Physics2DServer::get_singleton()->body_set_mode(get_rid(), Physics2DServer::BODY_MODE_STATIC); + PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_STATIC); } break; case MODE_KINEMATIC: { - Physics2DServer::get_singleton()->body_set_mode(get_rid(), Physics2DServer::BODY_MODE_KINEMATIC); + PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_KINEMATIC); } break; case MODE_CHARACTER: { - Physics2DServer::get_singleton()->body_set_mode(get_rid(), Physics2DServer::BODY_MODE_CHARACTER); + PhysicsServer2D::get_singleton()->body_set_mode(get_rid(), PhysicsServer2D::BODY_MODE_CHARACTER); } break; } @@ -514,7 +514,7 @@ void RigidBody2D::set_mass(real_t p_mass) { mass = p_mass; _change_notify("mass"); _change_notify("weight"); - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_MASS, mass); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_MASS, mass); } real_t RigidBody2D::get_mass() const { @@ -524,12 +524,12 @@ real_t RigidBody2D::get_mass() const { void RigidBody2D::set_inertia(real_t p_inertia) { ERR_FAIL_COND(p_inertia < 0); - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_INERTIA, p_inertia); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA, p_inertia); } real_t RigidBody2D::get_inertia() const { - return Physics2DServer::get_singleton()->body_get_param(get_rid(), Physics2DServer::BODY_PARAM_INERTIA); + return PhysicsServer2D::get_singleton()->body_get_param(get_rid(), PhysicsServer2D::BODY_PARAM_INERTIA); } void RigidBody2D::set_weight(real_t p_weight) { @@ -564,7 +564,7 @@ Ref RigidBody2D::get_physics_material_override() const { void RigidBody2D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } real_t RigidBody2D::get_gravity_scale() const { @@ -575,7 +575,7 @@ void RigidBody2D::set_linear_damp(real_t p_linear_damp) { ERR_FAIL_COND(p_linear_damp < -1); linear_damp = p_linear_damp; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_LINEAR_DAMP, linear_damp); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_LINEAR_DAMP, linear_damp); } real_t RigidBody2D::get_linear_damp() const { @@ -586,7 +586,7 @@ void RigidBody2D::set_angular_damp(real_t p_angular_damp) { ERR_FAIL_COND(p_angular_damp < -1); angular_damp = p_angular_damp; - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_ANGULAR_DAMP, angular_damp); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP, angular_damp); } real_t RigidBody2D::get_angular_damp() const { @@ -602,7 +602,7 @@ void RigidBody2D::set_axis_velocity(const Vector2 &p_axis) { if (state) { set_linear_velocity(v); } else { - Physics2DServer::get_singleton()->body_set_axis_velocity(get_rid(), p_axis); + PhysicsServer2D::get_singleton()->body_set_axis_velocity(get_rid(), p_axis); linear_velocity = v; } } @@ -614,7 +614,7 @@ void RigidBody2D::set_linear_velocity(const Vector2 &p_velocity) { state->set_linear_velocity(linear_velocity); else { - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_LINEAR_VELOCITY, linear_velocity); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } } @@ -629,7 +629,7 @@ void RigidBody2D::set_angular_velocity(real_t p_velocity) { if (state) state->set_angular_velocity(angular_velocity); else - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); } real_t RigidBody2D::get_angular_velocity() const { @@ -642,7 +642,7 @@ void RigidBody2D::set_use_custom_integrator(bool p_enable) { return; custom_integrator = p_enable; - Physics2DServer::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); + PhysicsServer2D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); } bool RigidBody2D::is_using_custom_integrator() { @@ -652,13 +652,13 @@ bool RigidBody2D::is_using_custom_integrator() { void RigidBody2D::set_sleeping(bool p_sleeping) { sleeping = p_sleeping; - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_SLEEPING, sleeping); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_SLEEPING, sleeping); } void RigidBody2D::set_can_sleep(bool p_active) { can_sleep = p_active; - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_CAN_SLEEP, p_active); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_CAN_SLEEP, p_active); } bool RigidBody2D::is_able_to_sleep() const { @@ -674,7 +674,7 @@ bool RigidBody2D::is_sleeping() const { void RigidBody2D::set_max_contacts_reported(int p_amount) { max_contacts_reported = p_amount; - Physics2DServer::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); + PhysicsServer2D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); } int RigidBody2D::get_max_contacts_reported() const { @@ -683,55 +683,55 @@ int RigidBody2D::get_max_contacts_reported() const { } void RigidBody2D::apply_central_impulse(const Vector2 &p_impulse) { - Physics2DServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); + PhysicsServer2D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } void RigidBody2D::apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) { - Physics2DServer::get_singleton()->body_apply_impulse(get_rid(), p_offset, p_impulse); + PhysicsServer2D::get_singleton()->body_apply_impulse(get_rid(), p_offset, p_impulse); } void RigidBody2D::apply_torque_impulse(float p_torque) { - Physics2DServer::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque); + PhysicsServer2D::get_singleton()->body_apply_torque_impulse(get_rid(), p_torque); } void RigidBody2D::set_applied_force(const Vector2 &p_force) { - Physics2DServer::get_singleton()->body_set_applied_force(get_rid(), p_force); + PhysicsServer2D::get_singleton()->body_set_applied_force(get_rid(), p_force); }; Vector2 RigidBody2D::get_applied_force() const { - return Physics2DServer::get_singleton()->body_get_applied_force(get_rid()); + return PhysicsServer2D::get_singleton()->body_get_applied_force(get_rid()); }; void RigidBody2D::set_applied_torque(const float p_torque) { - Physics2DServer::get_singleton()->body_set_applied_torque(get_rid(), p_torque); + PhysicsServer2D::get_singleton()->body_set_applied_torque(get_rid(), p_torque); }; float RigidBody2D::get_applied_torque() const { - return Physics2DServer::get_singleton()->body_get_applied_torque(get_rid()); + return PhysicsServer2D::get_singleton()->body_get_applied_torque(get_rid()); }; void RigidBody2D::add_central_force(const Vector2 &p_force) { - Physics2DServer::get_singleton()->body_add_central_force(get_rid(), p_force); + PhysicsServer2D::get_singleton()->body_add_central_force(get_rid(), p_force); } void RigidBody2D::add_force(const Vector2 &p_offset, const Vector2 &p_force) { - Physics2DServer::get_singleton()->body_add_force(get_rid(), p_offset, p_force); + PhysicsServer2D::get_singleton()->body_add_force(get_rid(), p_offset, p_force); } void RigidBody2D::add_torque(const float p_torque) { - Physics2DServer::get_singleton()->body_add_torque(get_rid(), p_torque); + PhysicsServer2D::get_singleton()->body_add_torque(get_rid(), p_torque); } void RigidBody2D::set_continuous_collision_detection_mode(CCDMode p_mode) { ccd_mode = p_mode; - Physics2DServer::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), Physics2DServer::CCDMode(p_mode)); + PhysicsServer2D::get_singleton()->body_set_continuous_collision_detection_mode(get_rid(), PhysicsServer2D::CCDMode(p_mode)); } RigidBody2D::CCDMode RigidBody2D::get_continuous_collision_detection_mode() const { @@ -939,7 +939,7 @@ void RigidBody2D::_bind_methods() { } RigidBody2D::RigidBody2D() : - PhysicsBody2D(Physics2DServer::BODY_MODE_RIGID) { + PhysicsBody2D(PhysicsServer2D::BODY_MODE_RIGID) { mode = MODE_RIGID; @@ -960,7 +960,7 @@ RigidBody2D::RigidBody2D() : contact_monitor = NULL; can_sleep = true; - Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); } RigidBody2D::~RigidBody2D() { @@ -971,11 +971,11 @@ RigidBody2D::~RigidBody2D() { void RigidBody2D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, 0); - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, 1); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, 0); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, 1); } else { - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - Physics2DServer::get_singleton()->body_set_param(get_rid(), Physics2DServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer2D::get_singleton()->body_set_param(get_rid(), PhysicsServer2D::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } @@ -1001,12 +1001,12 @@ Ref KinematicBody2D::_move(const Vector2 &p_motion, bool p bool KinematicBody2D::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) { - Physics2DServer::SeparationResult sep_res[8]; //max 8 rays + PhysicsServer2D::SeparationResult sep_res[8]; //max 8 rays Transform2D gt = get_global_transform(); Vector2 recover; - int hits = Physics2DServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); + int hits = PhysicsServer2D::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); int deepest = -1; float deepest_depth; for (int i = 0; i < hits; i++) { @@ -1042,8 +1042,8 @@ bool KinematicBody2D::move_and_collide(const Vector2 &p_motion, bool p_infinite_ ERR_PRINT("Functions move_and_slide and move_and_collide do not work together with 'sync to physics' option. Please read the documentation."); } Transform2D gt = get_global_transform(); - Physics2DServer::MotionResult result; - bool colliding = Physics2DServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes); + PhysicsServer2D::MotionResult result; + bool colliding = PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, margin, &result, p_exclude_raycast_shapes); if (colliding) { r_collision.collider_metadata = result.collider_metadata; @@ -1077,7 +1077,7 @@ Vector2 KinematicBody2D::move_and_slide(const Vector2 &p_linear_velocity, const Vector2 current_floor_velocity = floor_velocity; if (on_floor && on_floor_body.is_valid()) { //this approach makes sure there is less delay between the actual body velocity and the one we saved - Physics2DDirectBodyState *bs = Physics2DServer::get_singleton()->body_get_direct_state(on_floor_body); + PhysicsDirectBodyState2D *bs = PhysicsServer2D::get_singleton()->body_get_direct_state(on_floor_body); if (bs) { current_floor_velocity = bs->get_linear_velocity(); } @@ -1227,7 +1227,7 @@ bool KinematicBody2D::test_move(const Transform2D &p_from, const Vector2 &p_moti ERR_FAIL_COND_V(!is_inside_tree(), false); - return Physics2DServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin); + return PhysicsServer2D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia, margin); } void KinematicBody2D::set_safe_margin(float p_margin) { @@ -1277,11 +1277,11 @@ void KinematicBody2D::set_sync_to_physics(bool p_enable) { return; if (p_enable) { - Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); set_only_update_transform_changes(true); set_notify_local_transform(true); } else { - Physics2DServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + PhysicsServer2D::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); set_only_update_transform_changes(false); set_notify_local_transform(false); } @@ -1296,7 +1296,7 @@ void KinematicBody2D::_direct_state_changed(Object *p_state) { if (!sync_to_physics) return; - Physics2DDirectBodyState *state = Object::cast_to(p_state); + PhysicsDirectBodyState2D *state = Object::cast_to(p_state); last_valid_transform = state->get_transform(); set_notify_local_transform(false); @@ -1320,7 +1320,7 @@ void KinematicBody2D::_notification(int p_what) { if (p_what == NOTIFICATION_LOCAL_TRANSFORM_CHANGED) { //used by sync to physics, send the new transform to the physics Transform2D new_transform = get_global_transform(); - Physics2DServer::get_singleton()->body_set_state(get_rid(), Physics2DServer::BODY_STATE_TRANSFORM, new_transform); + PhysicsServer2D::get_singleton()->body_set_state(get_rid(), PhysicsServer2D::BODY_STATE_TRANSFORM, new_transform); //but then revert changes set_notify_local_transform(false); set_global_transform(last_valid_transform); @@ -1357,7 +1357,7 @@ void KinematicBody2D::_bind_methods() { } KinematicBody2D::KinematicBody2D() : - PhysicsBody2D(Physics2DServer::BODY_MODE_KINEMATIC) { + PhysicsBody2D(PhysicsServer2D::BODY_MODE_KINEMATIC) { margin = 0.08; diff --git a/scene/2d/physics_body_2d.h b/scene/2d/physics_body_2d.h index eb7aefb495..5bce5f6be3 100644 --- a/scene/2d/physics_body_2d.h +++ b/scene/2d/physics_body_2d.h @@ -34,7 +34,7 @@ #include "core/vset.h" #include "scene/2d/collision_object_2d.h" #include "scene/resources/physics_material.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" class KinematicCollision2D; @@ -50,7 +50,7 @@ class PhysicsBody2D : public CollisionObject2D { protected: void _notification(int p_what); - PhysicsBody2D(Physics2DServer::BodyMode p_mode); + PhysicsBody2D(PhysicsServer2D::BodyMode p_mode); static void _bind_methods(); @@ -123,7 +123,7 @@ public: private: bool can_sleep; - Physics2DDirectBodyState *state; + PhysicsDirectBodyState2D *state; Mode mode; real_t mass; @@ -303,7 +303,7 @@ private: Vector> slide_colliders; Ref motion_cache; - _FORCE_INLINE_ bool _ignores_mode(Physics2DServer::BodyMode) const; + _FORCE_INLINE_ bool _ignores_mode(PhysicsServer2D::BodyMode) const; Ref _move(const Vector2 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); Ref _get_slide_collision(int p_bounce); diff --git a/scene/2d/polygon_2d.cpp b/scene/2d/polygon_2d.cpp index 95656b9610..8d20053c6e 100644 --- a/scene/2d/polygon_2d.cpp +++ b/scene/2d/polygon_2d.cpp @@ -111,10 +111,10 @@ void Polygon2D::_notification(int p_what) { ObjectID new_skeleton_id; if (skeleton_node) { - VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton()); + RS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), skeleton_node->get_skeleton()); new_skeleton_id = skeleton_node->get_instance_id(); } else { - VS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID()); + RS::get_singleton()->canvas_item_attach_skeleton(get_canvas_item(), RID()); } if (new_skeleton_id != current_skeleton_id) { @@ -307,7 +307,7 @@ void Polygon2D::_notification(int p_what) { if (invert || polygons.size() == 0) { Vector indices = Geometry::triangulate_polygon(points); if (indices.size()) { - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, normal_map.is_valid() ? normal_map->get_rid() : RID(), specular_map.is_valid() ? specular_map->get_rid() : RID(), Color(specular_color.r, specular_color.g, specular_color.b, shininess)); + RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID(), -1, normal_map.is_valid() ? normal_map->get_rid() : RID(), specular_map.is_valid() ? specular_map->get_rid() : RID(), Color(specular_color.r, specular_color.g, specular_color.b, shininess)); } } else { //draw individual polygons @@ -341,7 +341,7 @@ void Polygon2D::_notification(int p_what) { } if (total_indices.size()) { - VS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); + RS::get_singleton()->canvas_item_add_triangle_array(get_canvas_item(), total_indices, points, colors, uvs, bones, weights, texture.is_valid() ? texture->get_rid() : RID()); } } diff --git a/scene/2d/ray_cast_2d.cpp b/scene/2d/ray_cast_2d.cpp index fd6e0aebcc..ed971b1c3a 100644 --- a/scene/2d/ray_cast_2d.cpp +++ b/scene/2d/ray_cast_2d.cpp @@ -33,7 +33,7 @@ #include "collision_object_2d.h" #include "core/engine.h" #include "physics_body_2d.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" void RayCast2D::set_cast_to(const Vector2 &p_point) { @@ -205,7 +205,7 @@ void RayCast2D::_update_raycast_state() { Ref w2d = get_world_2d(); ERR_FAIL_COND(w2d.is_null()); - Physics2DDirectSpaceState *dss = Physics2DServer::get_singleton()->space_get_direct_state(w2d->get_space()); + PhysicsDirectSpaceState2D *dss = PhysicsServer2D::get_singleton()->space_get_direct_state(w2d->get_space()); ERR_FAIL_COND(!dss); Transform2D gt = get_global_transform(); @@ -214,7 +214,7 @@ void RayCast2D::_update_raycast_state() { if (to == Vector2()) to = Vector2(0, 0.01); - Physics2DDirectSpaceState::RayResult rr; + PhysicsDirectSpaceState2D::RayResult rr; if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) { diff --git a/scene/2d/skeleton_2d.cpp b/scene/2d/skeleton_2d.cpp index 9ebaf23c3a..2be6b6a75c 100644 --- a/scene/2d/skeleton_2d.cpp +++ b/scene/2d/skeleton_2d.cpp @@ -186,7 +186,7 @@ void Skeleton2D::_update_bone_setup() { return; bone_setup_dirty = false; - VS::get_singleton()->skeleton_allocate(skeleton, bones.size(), true); + RS::get_singleton()->skeleton_allocate(skeleton, bones.size(), true); bones.sort(); //sorty so they are always in the same order/index @@ -240,7 +240,7 @@ void Skeleton2D::_update_transform() { for (int i = 0; i < bones.size(); i++) { Transform2D final_xform = bones[i].accum_transform * bones[i].rest_inverse; - VS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, final_xform); + RS::get_singleton()->skeleton_bone_set_transform_2d(skeleton, i, final_xform); } } @@ -276,7 +276,7 @@ void Skeleton2D::_notification(int p_what) { } if (p_what == NOTIFICATION_TRANSFORM_CHANGED) { - VS::get_singleton()->skeleton_set_base_transform_2d(skeleton, get_global_transform()); + RS::get_singleton()->skeleton_set_base_transform_2d(skeleton, get_global_transform()); } } @@ -300,11 +300,11 @@ Skeleton2D::Skeleton2D() { bone_setup_dirty = true; transform_dirty = true; - skeleton = VS::get_singleton()->skeleton_create(); + skeleton = RS::get_singleton()->skeleton_create(); set_notify_transform(true); } Skeleton2D::~Skeleton2D() { - VS::get_singleton()->free(skeleton); + RS::get_singleton()->free(skeleton); } diff --git a/scene/2d/sprite_2d.cpp b/scene/2d/sprite_2d.cpp index d45fe9a2a5..df8859bd9a 100644 --- a/scene/2d/sprite_2d.cpp +++ b/scene/2d/sprite_2d.cpp @@ -131,7 +131,7 @@ void Sprite2D::_notification(int p_what) { Rect2 src_rect, dst_rect; bool filter_clip; _get_rects(src_rect, dst_rect, filter_clip); - texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, specular, Color(specular_color.r, specular_color.g, specular_color.b, shininess), VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, filter_clip); + texture->draw_rect_region(ci, dst_rect, src_rect, Color(1, 1, 1), false, normal_map, specular, Color(specular_color.r, specular_color.g, specular_color.b, shininess), RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, filter_clip); } break; } diff --git a/scene/2d/tile_map.cpp b/scene/2d/tile_map.cpp index 601be17274..c468389040 100644 --- a/scene/2d/tile_map.cpp +++ b/scene/2d/tile_map.cpp @@ -35,8 +35,8 @@ #include "core/method_bind_ext.gen.inc" #include "core/os/os.h" #include "scene/2d/area_2d.h" -#include "servers/navigation_2d_server.h" -#include "servers/physics_2d_server.h" +#include "servers/navigation_server_2d.h" +#include "servers/physics_server_2d.h" int TileMap::_get_quadrant_size() const { @@ -87,7 +87,7 @@ void TileMap::_notification(int p_what) { if (navigation) { for (Map::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - Navigation2DServer::get_singleton()->region_set_map(F->get().region, RID()); + NavigationServer2D::get_singleton()->region_set_map(F->get().region, RID()); } q.navpoly_ids.clear(); } @@ -98,7 +98,7 @@ void TileMap::_notification(int p_what) { } for (Map::Element *F = q.occluder_instances.front(); F; F = F->next()) { - VS::get_singleton()->free(F->get().id); + RS::get_singleton()->free(F->get().id); } q.occluder_instances.clear(); } @@ -130,7 +130,7 @@ void TileMap::_update_quadrant_space(const RID &p_space) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - Physics2DServer::get_singleton()->body_set_space(q.body, p_space); + PhysicsServer2D::get_singleton()->body_set_space(q.body, p_space); } } } @@ -158,18 +158,18 @@ void TileMap::_update_quadrant_transform() { if (!use_parent) { xform = global_transform * xform; - Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform); + PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); } if (navigation) { for (Map::Element *F = q.navpoly_ids.front(); F; F = F->next()) { - Navigation2DServer::get_singleton()->region_set_transform(F->get().region, nav_rel * F->get().xform); + NavigationServer2D::get_singleton()->region_set_transform(F->get().region, nav_rel * F->get().xform); } } for (Map::Element *F = q.occluder_instances.front(); F; F = F->next()) { - VS::get_singleton()->canvas_light_occluder_set_transform(F->get().id, global_transform * F->get().xform); + RS::get_singleton()->canvas_light_occluder_set_transform(F->get().id, global_transform * F->get().xform); } } } @@ -298,7 +298,7 @@ void TileMap::_fix_cell_transform(Transform2D &xform, const Cell &p_cell, const } void TileMap::_add_shape(int &shape_idx, const Quadrant &p_q, const Ref &p_shape, const TileSet::ShapeData &p_shape_data, const Transform2D &p_xform, const Vector2 &p_metadata) { - Physics2DServer *ps = Physics2DServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); if (!use_parent) { ps->body_add_shape(p_q.body, p_shape->get_rid(), p_xform); @@ -334,8 +334,8 @@ void TileMap::update_dirty_quadrants() { return; } - VisualServer *vs = VisualServer::get_singleton(); - Physics2DServer *ps = Physics2DServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); + PhysicsServer2D *ps = PhysicsServer2D::get_singleton(); Vector2 tofs = get_cell_draw_offset(); Transform2D nav_rel; if (navigation) @@ -378,13 +378,13 @@ void TileMap::update_dirty_quadrants() { if (navigation) { for (Map::Element *E = q.navpoly_ids.front(); E; E = E->next()) { - Navigation2DServer::get_singleton()->region_set_map(E->get().region, RID()); + NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID()); } q.navpoly_ids.clear(); } for (Map::Element *E = q.occluder_instances.front(); E; E = E->next()) { - VS::get_singleton()->free(E->get().id); + RS::get_singleton()->free(E->get().id); } q.occluder_instances.clear(); Ref prev_material; @@ -439,7 +439,7 @@ void TileMap::update_dirty_quadrants() { debug_canvas_item = vs->canvas_item_create(); vs->canvas_item_set_parent(debug_canvas_item, canvas_item); vs->canvas_item_set_z_as_relative_to_parent(debug_canvas_item, false); - vs->canvas_item_set_z_index(debug_canvas_item, VS::CANVAS_ITEM_Z_MAX - 1); + vs->canvas_item_set_z_index(debug_canvas_item, RS::CANVAS_ITEM_Z_MAX - 1); q.canvas_items.push_back(debug_canvas_item); prev_debug_canvas_item = debug_canvas_item; } @@ -550,7 +550,7 @@ void TileMap::update_dirty_quadrants() { if (r == Rect2()) { tex->draw_rect(canvas_item, rect, false, modulate, c.transpose, normal_map); } else { - tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map, Ref(), Color(1, 1, 1, 1), VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, clip_uv); + tex->draw_rect_region(canvas_item, rect, r, modulate, c.transpose, normal_map, Ref(), Color(1, 1, 1, 1), RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, clip_uv); } Vector shapes = tile_set->tile_get_shapes(c.id); @@ -612,10 +612,10 @@ void TileMap::update_dirty_quadrants() { xform.set_origin(offset.floor() + q.pos); _fix_cell_transform(xform, c, npoly_ofs, s); - RID region = Navigation2DServer::get_singleton()->region_create(); - Navigation2DServer::get_singleton()->region_set_map(region, navigation->get_rid()); - Navigation2DServer::get_singleton()->region_set_transform(region, nav_rel * xform); - Navigation2DServer::get_singleton()->region_set_navpoly(region, navpoly); + RID region = NavigationServer2D::get_singleton()->region_create(); + NavigationServer2D::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer2D::get_singleton()->region_set_transform(region, nav_rel * xform); + NavigationServer2D::get_singleton()->region_set_navpoly(region, navpoly); Quadrant::NavPoly np; np.region = region; @@ -626,7 +626,7 @@ void TileMap::update_dirty_quadrants() { RID debug_navigation_item = vs->canvas_item_create(); vs->canvas_item_set_parent(debug_navigation_item, canvas_item); vs->canvas_item_set_z_as_relative_to_parent(debug_navigation_item, false); - vs->canvas_item_set_z_index(debug_navigation_item, VS::CANVAS_ITEM_Z_MAX - 2); // Display one below collision debug + vs->canvas_item_set_z_index(debug_navigation_item, RS::CANVAS_ITEM_Z_MAX - 2); // Display one below collision debug if (debug_navigation_item.is_valid()) { Vector navigation_polygon_vertices = navpoly->get_vertices(); @@ -685,11 +685,11 @@ void TileMap::update_dirty_quadrants() { xform.set_origin(offset.floor() + q.pos); _fix_cell_transform(xform, c, occluder_ofs, s); - RID orid = VS::get_singleton()->canvas_light_occluder_create(); - VS::get_singleton()->canvas_light_occluder_set_transform(orid, get_global_transform() * xform); - VS::get_singleton()->canvas_light_occluder_set_polygon(orid, occluder->get_rid()); - VS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid, get_canvas()); - VS::get_singleton()->canvas_light_occluder_set_light_mask(orid, occluder_light_mask); + RID orid = RS::get_singleton()->canvas_light_occluder_create(); + RS::get_singleton()->canvas_light_occluder_set_transform(orid, get_global_transform() * xform); + RS::get_singleton()->canvas_light_occluder_set_polygon(orid, occluder->get_rid()); + RS::get_singleton()->canvas_light_occluder_attach_to_canvas(orid, get_canvas()); + RS::get_singleton()->canvas_light_occluder_set_light_mask(orid, occluder_light_mask); Quadrant::Occluder oc; oc.xform = xform; oc.id = orid; @@ -711,7 +711,7 @@ void TileMap::update_dirty_quadrants() { Quadrant &q = E->get(); for (List::Element *F = q.canvas_items.front(); F; F = F->next()) { - VS::get_singleton()->canvas_item_set_draw_index(F->get(), index++); + RS::get_singleton()->canvas_item_set_draw_index(F->get(), index++); } } @@ -763,24 +763,24 @@ Map::Element *TileMap::_create_quadrant(cons q.pos.y += cell_size.y; xform.set_origin(q.pos); - //q.canvas_item = VisualServer::get_singleton()->canvas_item_create(); + //q.canvas_item = RenderingServer::get_singleton()->canvas_item_create(); if (!use_parent) { - q.body = Physics2DServer::get_singleton()->body_create(); - Physics2DServer::get_singleton()->body_set_mode(q.body, use_kinematic ? Physics2DServer::BODY_MODE_KINEMATIC : Physics2DServer::BODY_MODE_STATIC); + q.body = PhysicsServer2D::get_singleton()->body_create(); + PhysicsServer2D::get_singleton()->body_set_mode(q.body, use_kinematic ? PhysicsServer2D::BODY_MODE_KINEMATIC : PhysicsServer2D::BODY_MODE_STATIC); - Physics2DServer::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id()); - Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); - Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask); - Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, friction); - Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, bounce); + PhysicsServer2D::get_singleton()->body_attach_object_instance_id(q.body, get_instance_id()); + PhysicsServer2D::get_singleton()->body_set_collision_layer(q.body, collision_layer); + PhysicsServer2D::get_singleton()->body_set_collision_mask(q.body, collision_mask); + PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_FRICTION, friction); + PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_BOUNCE, bounce); if (is_inside_tree()) { xform = get_global_transform() * xform; RID space = get_world_2d()->get_space(); - Physics2DServer::get_singleton()->body_set_space(q.body, space); + PhysicsServer2D::get_singleton()->body_set_space(q.body, space); } - Physics2DServer::get_singleton()->body_set_state(q.body, Physics2DServer::BODY_STATE_TRANSFORM, xform); + PhysicsServer2D::get_singleton()->body_set_state(q.body, PhysicsServer2D::BODY_STATE_TRANSFORM, xform); } else if (collision_parent) { xform = get_transform() * xform; q.shape_owner_id = collision_parent->create_shape_owner(this); @@ -797,14 +797,14 @@ void TileMap::_erase_quadrant(Map::Element *Q) { Quadrant &q = Q->get(); if (!use_parent) { - Physics2DServer::get_singleton()->free(q.body); + PhysicsServer2D::get_singleton()->free(q.body); } else if (collision_parent) { collision_parent->remove_shape_owner(q.shape_owner_id); } for (List::Element *E = q.canvas_items.front(); E; E = E->next()) { - VisualServer::get_singleton()->free(E->get()); + RenderingServer::get_singleton()->free(E->get()); } q.canvas_items.clear(); if (q.dirty_list.in_list()) @@ -813,13 +813,13 @@ void TileMap::_erase_quadrant(Map::Element *Q) { if (navigation) { for (Map::Element *E = q.navpoly_ids.front(); E; E = E->next()) { - Navigation2DServer::get_singleton()->region_set_map(E->get().region, RID()); + NavigationServer2D::get_singleton()->region_set_map(E->get().region, RID()); } q.navpoly_ids.clear(); } for (Map::Element *E = q.occluder_instances.front(); E; E = E->next()) { - VS::get_singleton()->free(E->get().id); + RS::get_singleton()->free(E->get().id); } q.occluder_instances.clear(); @@ -1197,7 +1197,7 @@ void TileMap::_update_all_items_material_state() { void TileMap::_update_item_material_state(const RID &p_canvas_item) { - VS::get_singleton()->canvas_item_set_use_parent_material(p_canvas_item, get_use_parent_material() || get_material().is_valid()); + RS::get_singleton()->canvas_item_set_use_parent_material(p_canvas_item, get_use_parent_material() || get_material().is_valid()); } void TileMap::clear() { @@ -1302,7 +1302,7 @@ void TileMap::set_collision_layer(uint32_t p_layer) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - Physics2DServer::get_singleton()->body_set_collision_layer(q.body, collision_layer); + PhysicsServer2D::get_singleton()->body_set_collision_layer(q.body, collision_layer); } } } @@ -1314,7 +1314,7 @@ void TileMap::set_collision_mask(uint32_t p_mask) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - Physics2DServer::get_singleton()->body_set_collision_mask(q.body, collision_mask); + PhysicsServer2D::get_singleton()->body_set_collision_mask(q.body, collision_mask); } } } @@ -1383,7 +1383,7 @@ void TileMap::set_collision_friction(float p_friction) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_FRICTION, p_friction); + PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_FRICTION, p_friction); } } } @@ -1400,7 +1400,7 @@ void TileMap::set_collision_bounce(float p_bounce) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { Quadrant &q = E->get(); - Physics2DServer::get_singleton()->body_set_param(q.body, Physics2DServer::BODY_PARAM_BOUNCE, p_bounce); + PhysicsServer2D::get_singleton()->body_set_param(q.body, PhysicsServer2D::BODY_PARAM_BOUNCE, p_bounce); } } } @@ -1655,7 +1655,7 @@ void TileMap::set_y_sort_mode(bool p_enable) { _clear_quadrants(); y_sort_mode = p_enable; - VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), y_sort_mode); + RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), y_sort_mode); _recreate_quadrants(); emit_signal("settings_changed"); } @@ -1746,7 +1746,7 @@ void TileMap::set_occluder_light_mask(int p_mask) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { for (Map::Element *F = E->get().occluder_instances.front(); F; F = F->next()) { - VisualServer::get_singleton()->canvas_light_occluder_set_light_mask(F->get().id, occluder_light_mask); + RenderingServer::get_singleton()->canvas_light_occluder_set_light_mask(F->get().id, occluder_light_mask); } } } @@ -1762,7 +1762,7 @@ void TileMap::set_light_mask(int p_light_mask) { for (Map::Element *E = quadrant_map.front(); E; E = E->next()) { for (List::Element *F = E->get().canvas_items.front(); F; F = F->next()) { - VisualServer::get_singleton()->canvas_item_set_light_mask(F->get(), get_light_mask()); + RenderingServer::get_singleton()->canvas_item_set_light_mask(F->get(), get_light_mask()); } } } diff --git a/scene/2d/y_sort.cpp b/scene/2d/y_sort.cpp index 62f10a5c96..15d97eeaa0 100644 --- a/scene/2d/y_sort.cpp +++ b/scene/2d/y_sort.cpp @@ -33,7 +33,7 @@ void YSort::set_sort_enabled(bool p_enabled) { sort_enabled = p_enabled; - VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), sort_enabled); + RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), sort_enabled); } bool YSort::is_sort_enabled() const { @@ -53,5 +53,5 @@ void YSort::_bind_methods() { YSort::YSort() { sort_enabled = true; - VS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), true); + RS::get_singleton()->canvas_item_set_sort_children_by_y(get_canvas_item(), true); } diff --git a/scene/3d/area_3d.cpp b/scene/3d/area_3d.cpp index beeaf7125a..5b02a91793 100644 --- a/scene/3d/area_3d.cpp +++ b/scene/3d/area_3d.cpp @@ -32,12 +32,12 @@ #include "scene/scene_string_names.h" #include "servers/audio_server.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" void Area3D::set_space_override_mode(SpaceOverride p_mode) { space_override = p_mode; - PhysicsServer::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer::AreaSpaceOverrideMode(p_mode)); + PhysicsServer3D::get_singleton()->area_set_space_override_mode(get_rid(), PhysicsServer3D::AreaSpaceOverrideMode(p_mode)); } Area3D::SpaceOverride Area3D::get_space_override_mode() const { @@ -47,7 +47,7 @@ Area3D::SpaceOverride Area3D::get_space_override_mode() const { void Area3D::set_gravity_is_point(bool p_enabled) { gravity_is_point = p_enabled; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT, p_enabled); } bool Area3D::is_gravity_a_point() const { @@ -57,7 +57,7 @@ bool Area3D::is_gravity_a_point() const { void Area3D::set_gravity_distance_scale(real_t p_scale) { gravity_distance_scale = p_scale; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE, p_scale); } real_t Area3D::get_gravity_distance_scale() const { @@ -67,7 +67,7 @@ real_t Area3D::get_gravity_distance_scale() const { void Area3D::set_gravity_vector(const Vector3 &p_vec) { gravity_vec = p_vec; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY_VECTOR, p_vec); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, p_vec); } Vector3 Area3D::get_gravity_vector() const { @@ -77,7 +77,7 @@ Vector3 Area3D::get_gravity_vector() const { void Area3D::set_gravity(real_t p_gravity) { gravity = p_gravity; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_GRAVITY, p_gravity); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_GRAVITY, p_gravity); } real_t Area3D::get_gravity() const { @@ -86,7 +86,7 @@ real_t Area3D::get_gravity() const { void Area3D::set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_LINEAR_DAMP, p_linear_damp); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, p_linear_damp); } real_t Area3D::get_linear_damp() const { @@ -96,7 +96,7 @@ real_t Area3D::get_linear_damp() const { void Area3D::set_angular_damp(real_t p_angular_damp) { angular_damp = p_angular_damp; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_ANGULAR_DAMP, p_angular_damp); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, p_angular_damp); } real_t Area3D::get_angular_damp() const { @@ -107,7 +107,7 @@ real_t Area3D::get_angular_damp() const { void Area3D::set_priority(real_t p_priority) { priority = p_priority; - PhysicsServer::get_singleton()->area_set_param(get_rid(), PhysicsServer::AREA_PARAM_PRIORITY, p_priority); + PhysicsServer3D::get_singleton()->area_set_param(get_rid(), PhysicsServer3D::AREA_PARAM_PRIORITY, p_priority); } real_t Area3D::get_priority() const { @@ -150,7 +150,7 @@ void Area3D::_body_exit_tree(ObjectID p_id) { void Area3D::_body_inout(int p_status, const RID &p_body, ObjectID p_instance, int p_body_shape, int p_area_shape) { - bool body_in = p_status == PhysicsServer::AREA_BODY_ADDED; + bool body_in = p_status == PhysicsServer3D::AREA_BODY_ADDED; ObjectID objid = p_instance; Object *obj = ObjectDB::get_instance(objid); @@ -298,11 +298,11 @@ void Area3D::set_monitoring(bool p_enable) { if (monitoring) { - PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout); - PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout); + PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_body_inout); + PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), this, SceneStringNames::get_singleton()->_area_inout); } else { - PhysicsServer::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); - PhysicsServer::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); + PhysicsServer3D::get_singleton()->area_set_monitor_callback(get_rid(), NULL, StringName()); + PhysicsServer3D::get_singleton()->area_set_area_monitor_callback(get_rid(), NULL, StringName()); _clear_monitoring(); } } @@ -343,7 +343,7 @@ void Area3D::_area_exit_tree(ObjectID p_id) { void Area3D::_area_inout(int p_status, const RID &p_area, ObjectID p_instance, int p_area_shape, int p_self_shape) { - bool area_in = p_status == PhysicsServer::AREA_BODY_ADDED; + bool area_in = p_status == PhysicsServer3D::AREA_BODY_ADDED; ObjectID objid = p_instance; Object *obj = ObjectDB::get_instance(objid); @@ -436,14 +436,14 @@ Array Area3D::get_overlapping_bodies() const { void Area3D::set_monitorable(bool p_enable) { - ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false)."); + ERR_FAIL_COND_MSG(locked || (is_inside_tree() && PhysicsServer3D::get_singleton()->is_flushing_queries()), "Function blocked during in/out signal. Use set_deferred(\"monitorable\", true/false)."); if (p_enable == monitorable) return; monitorable = p_enable; - PhysicsServer::get_singleton()->area_set_monitorable(get_rid(), monitorable); + PhysicsServer3D::get_singleton()->area_set_monitorable(get_rid(), monitorable); } bool Area3D::is_monitorable() const { @@ -489,7 +489,7 @@ bool Area3D::overlaps_body(Node *p_body) const { void Area3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; - PhysicsServer::get_singleton()->area_set_collision_mask(get_rid(), p_mask); + PhysicsServer3D::get_singleton()->area_set_collision_mask(get_rid(), p_mask); } uint32_t Area3D::get_collision_mask() const { @@ -499,7 +499,7 @@ uint32_t Area3D::get_collision_mask() const { void Area3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; - PhysicsServer::get_singleton()->area_set_collision_layer(get_rid(), p_layer); + PhysicsServer3D::get_singleton()->area_set_collision_layer(get_rid(), p_layer); } uint32_t Area3D::get_collision_layer() const { @@ -728,7 +728,7 @@ void Area3D::_bind_methods() { } Area3D::Area3D() : - CollisionObject3D(PhysicsServer::get_singleton()->area_create(), true) { + CollisionObject3D(PhysicsServer3D::get_singleton()->area_create(), true) { space_override = SPACE_OVERRIDE_DISABLED; set_gravity(9.8); diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp index 807515219f..bddf748be7 100644 --- a/scene/3d/audio_stream_player_3d.cpp +++ b/scene/3d/audio_stream_player_3d.cpp @@ -395,9 +395,9 @@ void AudioStreamPlayer3D::_notification(int p_what) { //check if any area is diverting sound into a bus - PhysicsDirectSpaceState *space_state = PhysicsServer::get_singleton()->space_get_direct_state(world->get_space()); + PhysicsDirectSpaceState3D *space_state = PhysicsServer3D::get_singleton()->space_get_direct_state(world->get_space()); - PhysicsDirectSpaceState::ShapeResult sr[MAX_INTERSECT_AREAS]; + PhysicsDirectSpaceState3D::ShapeResult sr[MAX_INTERSECT_AREAS]; int areas = space_state->intersect_point(global_pos, sr, MAX_INTERSECT_AREAS, Set(), area_mask, false, true); Area3D *area = NULL; diff --git a/scene/3d/baked_lightmap.cpp b/scene/3d/baked_lightmap.cpp index 73b1d450f0..05e3f3fefa 100644 --- a/scene/3d/baked_lightmap.cpp +++ b/scene/3d/baked_lightmap.cpp @@ -39,7 +39,7 @@ void BakedLightmapData::set_bounds(const AABB &p_bounds) { bounds = p_bounds; - VS::get_singleton()->lightmap_capture_set_bounds(baked_light, p_bounds); + RS::get_singleton()->lightmap_capture_set_bounds(baked_light, p_bounds); } AABB BakedLightmapData::get_bounds() const { @@ -49,18 +49,18 @@ AABB BakedLightmapData::get_bounds() const { void BakedLightmapData::set_octree(const Vector &p_octree) { - VS::get_singleton()->lightmap_capture_set_octree(baked_light, p_octree); + RS::get_singleton()->lightmap_capture_set_octree(baked_light, p_octree); } Vector BakedLightmapData::get_octree() const { - return VS::get_singleton()->lightmap_capture_get_octree(baked_light); + return RS::get_singleton()->lightmap_capture_get_octree(baked_light); } void BakedLightmapData::set_cell_space_transform(const Transform &p_xform) { cell_space_xform = p_xform; - VS::get_singleton()->lightmap_capture_set_octree_cell_transform(baked_light, p_xform); + RS::get_singleton()->lightmap_capture_set_octree_cell_transform(baked_light, p_xform); } Transform BakedLightmapData::get_cell_space_transform() const { @@ -69,7 +69,7 @@ Transform BakedLightmapData::get_cell_space_transform() const { void BakedLightmapData::set_cell_subdiv(int p_cell_subdiv) { cell_subdiv = p_cell_subdiv; - VS::get_singleton()->lightmap_capture_set_octree_cell_subdiv(baked_light, p_cell_subdiv); + RS::get_singleton()->lightmap_capture_set_octree_cell_subdiv(baked_light, p_cell_subdiv); } int BakedLightmapData::get_cell_subdiv() const { @@ -79,7 +79,7 @@ int BakedLightmapData::get_cell_subdiv() const { void BakedLightmapData::set_energy(float p_energy) { energy = p_energy; - VS::get_singleton()->lightmap_capture_set_energy(baked_light, energy); + RS::get_singleton()->lightmap_capture_set_energy(baked_light, energy); } float BakedLightmapData::get_energy() const { @@ -181,14 +181,14 @@ void BakedLightmapData::_bind_methods() { BakedLightmapData::BakedLightmapData() { - baked_light = VS::get_singleton()->lightmap_capture_create(); + baked_light = RS::get_singleton()->lightmap_capture_create(); energy = 1; cell_subdiv = 1; } BakedLightmapData::~BakedLightmapData() { - VS::get_singleton()->free(baked_light); + RS::get_singleton()->free(baked_light); } /////////////////////////// @@ -425,13 +425,13 @@ BakedLightmap::BakeError BakedLightmap::bake(Node *p_from_node, bool p_create_vi pmc++; PlotLight pl = E->get(); switch (pl.light->get_light_type()) { - case VS::LIGHT_DIRECTIONAL: { + case RS::LIGHT_DIRECTIONAL: { baker.plot_light_directional(-pl.local_xform.basis.get_axis(2), pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_bake_mode() == Light::BAKE_ALL); } break; - case VS::LIGHT_OMNI: { + case RS::LIGHT_OMNI: { baker.plot_light_omni(pl.local_xform.origin, pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_param(Light::PARAM_RANGE), pl.light->get_param(Light::PARAM_ATTENUATION), pl.light->get_bake_mode() == Light::BAKE_ALL); } break; - case VS::LIGHT_SPOT: { + case RS::LIGHT_SPOT: { baker.plot_light_spot(pl.local_xform.origin, pl.local_xform.basis.get_axis(2), pl.light->get_color(), pl.light->get_param(Light::PARAM_ENERGY), pl.light->get_param(Light::PARAM_INDIRECT_ENERGY), pl.light->get_param(Light::PARAM_RANGE), pl.light->get_param(Light::PARAM_ATTENUATION), pl.light->get_param(Light::PARAM_SPOT_ANGLE), pl.light->get_param(Light::PARAM_SPOT_ATTENUATION), pl.light->get_bake_mode() == Light::BAKE_ALL); } break; @@ -675,12 +675,12 @@ void BakedLightmap::_assign_lightmaps() { if (instance_idx >= 0) { RID instance = node->call("get_bake_mesh_instance", instance_idx); if (instance.is_valid()) { - VS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), lightmap->get_rid()); + RS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), lightmap->get_rid()); } } else { VisualInstance *vi = Object::cast_to(node); ERR_CONTINUE(!vi); - VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid()); + RS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), lightmap->get_rid()); } } } @@ -693,12 +693,12 @@ void BakedLightmap::_clear_lightmaps() { if (instance_idx >= 0) { RID instance = node->call("get_bake_mesh_instance", instance_idx); if (instance.is_valid()) { - VS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), RID()); + RS::get_singleton()->instance_set_use_lightmap(instance, get_instance(), RID()); } } else { VisualInstance *vi = Object::cast_to(node); ERR_CONTINUE(!vi); - VS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), RID()); + RS::get_singleton()->instance_set_use_lightmap(vi->get_instance(), get_instance(), RID()); } } } diff --git a/scene/3d/camera_3d.cpp b/scene/3d/camera_3d.cpp index 60cccbeedd..7980c15f89 100644 --- a/scene/3d/camera_3d.cpp +++ b/scene/3d/camera_3d.cpp @@ -82,7 +82,7 @@ void Camera3D::_update_camera() { if (!is_inside_tree()) return; - VisualServer::get_singleton()->camera_set_transform(camera, get_camera_transform()); + RenderingServer::get_singleton()->camera_set_transform(camera, get_camera_transform()); // here goes listener stuff /* @@ -173,7 +173,7 @@ void Camera3D::set_perspective(float p_fovy_degrees, float p_z_near, float p_z_f far = p_z_far; mode = PROJECTION_PERSPECTIVE; - VisualServer::get_singleton()->camera_set_perspective(camera, fov, near, far); + RenderingServer::get_singleton()->camera_set_perspective(camera, fov, near, far); update_gizmo(); force_change = false; } @@ -189,7 +189,7 @@ void Camera3D::set_orthogonal(float p_size, float p_z_near, float p_z_far) { mode = PROJECTION_ORTHOGONAL; force_change = false; - VisualServer::get_singleton()->camera_set_orthogonal(camera, size, near, far); + RenderingServer::get_singleton()->camera_set_orthogonal(camera, size, near, far); update_gizmo(); } @@ -205,7 +205,7 @@ void Camera3D::set_frustum(float p_size, Vector2 p_offset, float p_z_near, float mode = PROJECTION_FRUSTUM; force_change = false; - VisualServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far); + RenderingServer::get_singleton()->camera_set_frustum(camera, size, frustum_offset, near, far); update_gizmo(); } @@ -418,12 +418,12 @@ void Camera::_camera_make_current(Node *p_camera) { if (p_camera==this) { - VisualServer::get_singleton()->viewport_attach_camera(viewport_id,camera); + RenderingServer::get_singleton()->viewport_attach_camera(viewport_id,camera); active=true; } else { if (active && p_camera==NULL) { //detech camera because no one else will claim it - VisualServer::get_singleton()->viewport_attach_camera(viewport_id,RID()); + RenderingServer::get_singleton()->viewport_attach_camera(viewport_id,RID()); } active=false; } @@ -434,9 +434,9 @@ void Camera3D::set_environment(const Ref &p_environment) { environment = p_environment; if (environment.is_valid()) - VS::get_singleton()->camera_set_environment(camera, environment->get_rid()); + RS::get_singleton()->camera_set_environment(camera, environment->get_rid()); else - VS::get_singleton()->camera_set_environment(camera, RID()); + RS::get_singleton()->camera_set_environment(camera, RID()); _update_camera_mode(); } @@ -449,9 +449,9 @@ void Camera3D::set_effects(const Ref &p_effects) { effects = p_effects; if (effects.is_valid()) - VS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid()); + RS::get_singleton()->camera_set_camera_effects(camera, effects->get_rid()); else - VS::get_singleton()->camera_set_camera_effects(camera, RID()); + RS::get_singleton()->camera_set_camera_effects(camera, RID()); _update_camera_mode(); } @@ -462,7 +462,7 @@ Ref Camera3D::get_effects() const { void Camera3D::set_keep_aspect_mode(KeepAspect p_aspect) { keep_aspect = p_aspect; - VisualServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH); + RenderingServer::get_singleton()->camera_set_use_vertical_aspect(camera, p_aspect == KEEP_WIDTH); _update_camera_mode(); _change_notify(); } @@ -628,7 +628,7 @@ void Camera3D::set_zfar(float p_zfar) { void Camera3D::set_cull_mask(uint32_t p_layers) { layers = p_layers; - VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); + RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers); _update_camera_mode(); } @@ -696,7 +696,7 @@ Vector3 Camera3D::get_doppler_tracked_velocity() const { } Camera3D::Camera3D() { - camera = VisualServer::get_singleton()->camera_create(); + camera = RenderingServer::get_singleton()->camera_create(); size = 1; fov = 0; frustum_offset = Vector2(); @@ -711,7 +711,7 @@ Camera3D::Camera3D() { layers = 0xfffff; v_offset = 0; h_offset = 0; - VisualServer::get_singleton()->camera_set_cull_mask(camera, layers); + RenderingServer::get_singleton()->camera_set_cull_mask(camera, layers); //active=false; velocity_tracker.instance(); doppler_tracking = DOPPLER_TRACKING_DISABLED; @@ -721,7 +721,7 @@ Camera3D::Camera3D() { Camera3D::~Camera3D() { - VisualServer::get_singleton()->free(camera); + RenderingServer::get_singleton()->free(camera); } //////////////////////////////////////// @@ -760,7 +760,7 @@ void ClippedCamera3D::_notification(int p_what) { return; } - PhysicsDirectSpaceState *dspace = get_world()->get_direct_space_state(); + PhysicsDirectSpaceState3D *dspace = get_world()->get_direct_space_state(); ERR_FAIL_COND(!dspace); // most likely physics set to threads Vector3 cam_fw = -get_global_transform().basis.get_axis(Vector3::AXIS_Z).normalized(); @@ -791,7 +791,7 @@ void ClippedCamera3D::_notification(int p_what) { } if (!all_equal) { - PhysicsServer::get_singleton()->shape_set_data(pyramid_shape, local_points); + PhysicsServer3D::get_singleton()->shape_set_data(pyramid_shape, local_points); points = local_points; } } @@ -945,10 +945,10 @@ ClippedCamera3D::ClippedCamera3D() { collision_mask = 1; set_notify_local_transform(Engine::get_singleton()->is_editor_hint()); points.resize(5); - pyramid_shape = PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON); + pyramid_shape = PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CONVEX_POLYGON); clip_to_areas = false; clip_to_bodies = true; } ClippedCamera3D::~ClippedCamera3D() { - PhysicsServer::get_singleton()->free(pyramid_shape); + PhysicsServer3D::get_singleton()->free(pyramid_shape); } diff --git a/scene/3d/collision_object_3d.cpp b/scene/3d/collision_object_3d.cpp index 9ae7371b6a..da37ca8ae2 100644 --- a/scene/3d/collision_object_3d.cpp +++ b/scene/3d/collision_object_3d.cpp @@ -31,7 +31,7 @@ #include "collision_object_3d.h" #include "scene/scene_string_names.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" void CollisionObject3D::_notification(int p_what) { @@ -40,15 +40,15 @@ void CollisionObject3D::_notification(int p_what) { case NOTIFICATION_ENTER_WORLD: { if (area) - PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); + PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform()); else - PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); RID space = get_world()->get_space(); if (area) { - PhysicsServer::get_singleton()->area_set_space(rid, space); + PhysicsServer3D::get_singleton()->area_set_space(rid, space); } else - PhysicsServer::get_singleton()->body_set_space(rid, space); + PhysicsServer3D::get_singleton()->body_set_space(rid, space); _update_pickable(); //get space @@ -57,9 +57,9 @@ void CollisionObject3D::_notification(int p_what) { case NOTIFICATION_TRANSFORM_CHANGED: { if (area) - PhysicsServer::get_singleton()->area_set_transform(rid, get_global_transform()); + PhysicsServer3D::get_singleton()->area_set_transform(rid, get_global_transform()); else - PhysicsServer::get_singleton()->body_set_state(rid, PhysicsServer::BODY_STATE_TRANSFORM, get_global_transform()); + PhysicsServer3D::get_singleton()->body_set_state(rid, PhysicsServer3D::BODY_STATE_TRANSFORM, get_global_transform()); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -70,9 +70,9 @@ void CollisionObject3D::_notification(int p_what) { case NOTIFICATION_EXIT_WORLD: { if (area) { - PhysicsServer::get_singleton()->area_set_space(rid, RID()); + PhysicsServer3D::get_singleton()->area_set_space(rid, RID()); } else - PhysicsServer::get_singleton()->body_set_space(rid, RID()); + PhysicsServer3D::get_singleton()->body_set_space(rid, RID()); } break; } @@ -108,9 +108,9 @@ void CollisionObject3D::_update_pickable() { bool pickable = ray_pickable && is_visible_in_tree(); if (area) - PhysicsServer::get_singleton()->area_set_ray_pickable(rid, pickable); + PhysicsServer3D::get_singleton()->area_set_ray_pickable(rid, pickable); else - PhysicsServer::get_singleton()->body_set_ray_pickable(rid, pickable); + PhysicsServer3D::get_singleton()->body_set_ray_pickable(rid, pickable); } void CollisionObject3D::set_ray_pickable(bool p_ray_pickable) { @@ -191,9 +191,9 @@ void CollisionObject3D::shape_owner_set_disabled(uint32_t p_owner, bool p_disabl sd.disabled = p_disabled; for (int i = 0; i < sd.shapes.size(); i++) { if (area) { - PhysicsServer::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + PhysicsServer3D::get_singleton()->area_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); } else { - PhysicsServer::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); + PhysicsServer3D::get_singleton()->body_set_shape_disabled(rid, sd.shapes[i].index, p_disabled); } } } @@ -230,9 +230,9 @@ void CollisionObject3D::shape_owner_set_transform(uint32_t p_owner, const Transf sd.xform = p_transform; for (int i = 0; i < sd.shapes.size(); i++) { if (area) { - PhysicsServer::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); + PhysicsServer3D::get_singleton()->area_set_shape_transform(rid, sd.shapes[i].index, p_transform); } else { - PhysicsServer::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); + PhysicsServer3D::get_singleton()->body_set_shape_transform(rid, sd.shapes[i].index, p_transform); } } } @@ -260,9 +260,9 @@ void CollisionObject3D::shape_owner_add_shape(uint32_t p_owner, const Refarea_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + PhysicsServer3D::get_singleton()->area_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); } else { - PhysicsServer::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); + PhysicsServer3D::get_singleton()->body_add_shape(rid, p_shape->get_rid(), sd.xform, sd.disabled); } sd.shapes.push_back(s); @@ -296,9 +296,9 @@ void CollisionObject3D::shape_owner_remove_shape(uint32_t p_owner, int p_shape) int index_to_remove = shapes[p_owner].shapes[p_shape].index; if (area) { - PhysicsServer::get_singleton()->area_remove_shape(rid, index_to_remove); + PhysicsServer3D::get_singleton()->area_remove_shape(rid, index_to_remove); } else { - PhysicsServer::get_singleton()->body_remove_shape(rid, index_to_remove); + PhysicsServer3D::get_singleton()->body_remove_shape(rid, index_to_remove); } shapes[p_owner].shapes.remove(p_shape); @@ -349,9 +349,9 @@ CollisionObject3D::CollisionObject3D(RID p_rid, bool p_area) { total_subshapes = 0; if (p_area) { - PhysicsServer::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); + PhysicsServer3D::get_singleton()->area_attach_object_instance_id(rid, get_instance_id()); } else { - PhysicsServer::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(rid, get_instance_id()); } //set_transform_notify(true); } @@ -392,5 +392,5 @@ CollisionObject3D::CollisionObject3D() { CollisionObject3D::~CollisionObject3D() { - PhysicsServer::get_singleton()->free(rid); + PhysicsServer3D::get_singleton()->free(rid); } diff --git a/scene/3d/collision_shape_3d.cpp b/scene/3d/collision_shape_3d.cpp index eab09883cd..e736f20614 100644 --- a/scene/3d/collision_shape_3d.cpp +++ b/scene/3d/collision_shape_3d.cpp @@ -36,7 +36,7 @@ #include "scene/resources/ray_shape_3d.h" #include "scene/resources/sphere_shape_3d.h" #include "scene/resources/world_margin_shape_3d.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" //TODO: Implement CylinderShape and HeightMapShape? #include "core/math/quick_hull.h" #include "mesh_instance_3d.h" @@ -196,7 +196,7 @@ bool CollisionShape3D::is_disabled() const { CollisionShape3D::CollisionShape3D() { - //indicator = VisualServer::get_singleton()->mesh_create(); + //indicator = RenderingServer::get_singleton()->mesh_create(); disabled = false; debug_shape = NULL; parent = NULL; @@ -207,7 +207,7 @@ CollisionShape3D::CollisionShape3D() { CollisionShape3D::~CollisionShape3D() { if (!shape.is_null()) shape->unregister_owner(this); - //VisualServer::get_singleton()->free(indicator); + //RenderingServer::get_singleton()->free(indicator); } void CollisionShape3D::_update_debug_shape() { diff --git a/scene/3d/cpu_particles_3d.cpp b/scene/3d/cpu_particles_3d.cpp index 71e869e6e9..4350d4da25 100644 --- a/scene/3d/cpu_particles_3d.cpp +++ b/scene/3d/cpu_particles_3d.cpp @@ -33,7 +33,7 @@ #include "scene/3d/camera_3d.h" #include "scene/3d/gpu_particles_3d.h" #include "scene/resources/particles_material.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" AABB CPUParticles3D::get_aabb() const { @@ -73,7 +73,7 @@ void CPUParticles3D::set_amount(int p_amount) { } particle_data.resize((12 + 4 + 4) * p_amount); - VS::get_singleton()->multimesh_allocate(multimesh, p_amount, VS::MULTIMESH_TRANSFORM_3D, true, true); + RS::get_singleton()->multimesh_allocate(multimesh, p_amount, RS::MULTIMESH_TRANSFORM_3D, true, true); particle_order.resize(p_amount); } @@ -171,9 +171,9 @@ void CPUParticles3D::set_mesh(const Ref &p_mesh) { mesh = p_mesh; if (mesh.is_valid()) { - VS::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); + RS::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); } else { - VS::get_singleton()->multimesh_set_mesh(multimesh, RID()); + RS::get_singleton()->multimesh_set_mesh(multimesh, RID()); } } @@ -1115,15 +1115,15 @@ void CPUParticles3D::_set_redraw(bool p_redraw) { MutexLock lock(update_mutex); if (redraw) { - VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread)); - VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true); - VS::get_singleton()->multimesh_set_visible_instances(multimesh, -1); + RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread)); + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, true); + RS::get_singleton()->multimesh_set_visible_instances(multimesh, -1); } else { - if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread))) { - VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread)); + if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread))) { + RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &CPUParticles3D::_update_render_thread)); } - VS::get_singleton()->instance_geometry_set_flag(get_instance(), VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false); - VS::get_singleton()->multimesh_set_visible_instances(multimesh, 0); + RS::get_singleton()->instance_geometry_set_flag(get_instance(), RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, false); + RS::get_singleton()->multimesh_set_visible_instances(multimesh, 0); } } } @@ -1133,7 +1133,7 @@ void CPUParticles3D::_update_render_thread() { MutexLock lock(update_mutex); if (can_update) { - VS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); + RS::get_singleton()->multimesh_set_buffer(multimesh, particle_data); can_update = false; //wait for next time } } @@ -1488,8 +1488,8 @@ CPUParticles3D::CPUParticles3D() { set_notify_transform(true); - multimesh = VisualServer::get_singleton()->multimesh_create(); - VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0); + multimesh = RenderingServer::get_singleton()->multimesh_create(); + RenderingServer::get_singleton()->multimesh_set_visible_instances(multimesh, 0); set_base(multimesh); set_emitting(true); @@ -1542,5 +1542,5 @@ CPUParticles3D::CPUParticles3D() { } CPUParticles3D::~CPUParticles3D() { - VS::get_singleton()->free(multimesh); + RS::get_singleton()->free(multimesh); } diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp index 413d5a2b1d..a46cd90612 100644 --- a/scene/3d/gi_probe.cpp +++ b/scene/3d/gi_probe.cpp @@ -92,7 +92,7 @@ Dictionary GIProbeData::_get_data() const { } void GIProbeData::allocate(const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3 &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { - VS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts); + RS::get_singleton()->gi_probe_allocate(probe, p_to_cell_xform, p_aabb, p_octree_size, p_octree_cells, p_data_cells, p_distance_field, p_level_counts); bounds = p_aabb; to_cell_xform = p_to_cell_xform; octree_size = p_octree_size; @@ -105,24 +105,24 @@ Vector3 GIProbeData::get_octree_size() const { return octree_size; } Vector GIProbeData::get_octree_cells() const { - return VS::get_singleton()->gi_probe_get_octree_cells(probe); + return RS::get_singleton()->gi_probe_get_octree_cells(probe); } Vector GIProbeData::get_data_cells() const { - return VS::get_singleton()->gi_probe_get_data_cells(probe); + return RS::get_singleton()->gi_probe_get_data_cells(probe); } Vector GIProbeData::get_distance_field() const { - return VS::get_singleton()->gi_probe_get_distance_field(probe); + return RS::get_singleton()->gi_probe_get_distance_field(probe); } Vector GIProbeData::get_level_counts() const { - return VS::get_singleton()->gi_probe_get_level_counts(probe); + return RS::get_singleton()->gi_probe_get_level_counts(probe); } Transform GIProbeData::get_to_cell_xform() const { return to_cell_xform; } void GIProbeData::set_dynamic_range(float p_range) { - VS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range); + RS::get_singleton()->gi_probe_set_dynamic_range(probe, p_range); dynamic_range = p_range; } @@ -131,7 +131,7 @@ float GIProbeData::get_dynamic_range() const { } void GIProbeData::set_propagation(float p_propagation) { - VS::get_singleton()->gi_probe_set_propagation(probe, p_propagation); + RS::get_singleton()->gi_probe_set_propagation(probe, p_propagation); propagation = p_propagation; } @@ -140,7 +140,7 @@ float GIProbeData::get_propagation() const { } void GIProbeData::set_anisotropy_strength(float p_anisotropy_strength) { - VS::get_singleton()->gi_probe_set_anisotropy_strength(probe, p_anisotropy_strength); + RS::get_singleton()->gi_probe_set_anisotropy_strength(probe, p_anisotropy_strength); anisotropy_strength = p_anisotropy_strength; } @@ -149,7 +149,7 @@ float GIProbeData::get_anisotropy_strength() const { } void GIProbeData::set_energy(float p_energy) { - VS::get_singleton()->gi_probe_set_energy(probe, p_energy); + RS::get_singleton()->gi_probe_set_energy(probe, p_energy); energy = p_energy; } @@ -158,7 +158,7 @@ float GIProbeData::get_energy() const { } void GIProbeData::set_ao(float p_ao) { - VS::get_singleton()->gi_probe_set_ao(probe, p_ao); + RS::get_singleton()->gi_probe_set_ao(probe, p_ao); ao = p_ao; } @@ -167,7 +167,7 @@ float GIProbeData::get_ao() const { } void GIProbeData::set_ao_size(float p_ao_size) { - VS::get_singleton()->gi_probe_set_ao_size(probe, p_ao_size); + RS::get_singleton()->gi_probe_set_ao_size(probe, p_ao_size); ao_size = p_ao_size; } @@ -176,7 +176,7 @@ float GIProbeData::get_ao_size() const { } void GIProbeData::set_bias(float p_bias) { - VS::get_singleton()->gi_probe_set_bias(probe, p_bias); + RS::get_singleton()->gi_probe_set_bias(probe, p_bias); bias = p_bias; } @@ -185,7 +185,7 @@ float GIProbeData::get_bias() const { } void GIProbeData::set_normal_bias(float p_normal_bias) { - VS::get_singleton()->gi_probe_set_normal_bias(probe, p_normal_bias); + RS::get_singleton()->gi_probe_set_normal_bias(probe, p_normal_bias); normal_bias = p_normal_bias; } @@ -194,7 +194,7 @@ float GIProbeData::get_normal_bias() const { } void GIProbeData::set_interior(bool p_enable) { - VS::get_singleton()->gi_probe_set_interior(probe, p_enable); + RS::get_singleton()->gi_probe_set_interior(probe, p_enable); interior = p_enable; } @@ -203,7 +203,7 @@ bool GIProbeData::is_interior() const { } void GIProbeData::set_use_two_bounces(bool p_enable) { - VS::get_singleton()->gi_probe_set_use_two_bounces(probe, p_enable); + RS::get_singleton()->gi_probe_set_use_two_bounces(probe, p_enable); use_two_bounces = p_enable; } @@ -294,12 +294,12 @@ GIProbeData::GIProbeData() { anisotropy_strength = 0.5; interior = false; - probe = VS::get_singleton()->gi_probe_create(); + probe = RS::get_singleton()->gi_probe_create(); } GIProbeData::~GIProbeData() { - VS::get_singleton()->free(probe); + RS::get_singleton()->free(probe); } ////////////////////// @@ -308,9 +308,9 @@ GIProbeData::~GIProbeData() { void GIProbe::set_probe_data(const Ref &p_data) { if (p_data.is_valid()) { - VS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid()); + RS::get_singleton()->instance_set_base(get_instance(), p_data->get_rid()); } else { - VS::get_singleton()->instance_set_base(get_instance(), RID()); + RS::get_singleton()->instance_set_base(get_instance(), RID()); } probe_data = p_data; @@ -526,7 +526,7 @@ Vector GIProbe::get_faces(uint32_t p_usage_flags) const { String GIProbe::get_configuration_warning() const { - if (VisualServer::get_singleton()->is_low_end()) { + if (RenderingServer::get_singleton()->is_low_end()) { return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead."); } return String(); @@ -563,10 +563,10 @@ GIProbe::GIProbe() { subdiv = SUBDIV_128; extents = Vector3(10, 10, 10); - gi_probe = VS::get_singleton()->gi_probe_create(); + gi_probe = RS::get_singleton()->gi_probe_create(); set_disable_scale(true); } GIProbe::~GIProbe() { - VS::get_singleton()->free(gi_probe); + RS::get_singleton()->free(gi_probe); } diff --git a/scene/3d/gpu_particles_3d.cpp b/scene/3d/gpu_particles_3d.cpp index a283ec41b2..ad45228ca8 100644 --- a/scene/3d/gpu_particles_3d.cpp +++ b/scene/3d/gpu_particles_3d.cpp @@ -33,7 +33,7 @@ #include "core/os/os.h" #include "scene/resources/particles_material.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" AABB GPUParticles3D::get_aabb() const { @@ -46,7 +46,7 @@ Vector GPUParticles3D::get_faces(uint32_t p_usage_flags) const { void GPUParticles3D::set_emitting(bool p_emitting) { - VS::get_singleton()->particles_set_emitting(particles, p_emitting); + RS::get_singleton()->particles_set_emitting(particles, p_emitting); if (p_emitting && one_shot) { set_process_internal(true); @@ -59,25 +59,25 @@ void GPUParticles3D::set_amount(int p_amount) { ERR_FAIL_COND_MSG(p_amount < 1, "Amount of particles cannot be smaller than 1."); amount = p_amount; - VS::get_singleton()->particles_set_amount(particles, amount); + RS::get_singleton()->particles_set_amount(particles, amount); } void GPUParticles3D::set_lifetime(float p_lifetime) { ERR_FAIL_COND_MSG(p_lifetime <= 0, "Particles lifetime must be greater than 0."); lifetime = p_lifetime; - VS::get_singleton()->particles_set_lifetime(particles, lifetime); + RS::get_singleton()->particles_set_lifetime(particles, lifetime); } void GPUParticles3D::set_one_shot(bool p_one_shot) { one_shot = p_one_shot; - VS::get_singleton()->particles_set_one_shot(particles, one_shot); + RS::get_singleton()->particles_set_one_shot(particles, one_shot); if (is_emitting()) { set_process_internal(true); if (!one_shot) - VisualServer::get_singleton()->particles_restart(particles); + RenderingServer::get_singleton()->particles_restart(particles); } if (!one_shot) @@ -87,29 +87,29 @@ void GPUParticles3D::set_one_shot(bool p_one_shot) { void GPUParticles3D::set_pre_process_time(float p_time) { pre_process_time = p_time; - VS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); + RS::get_singleton()->particles_set_pre_process_time(particles, pre_process_time); } void GPUParticles3D::set_explosiveness_ratio(float p_ratio) { explosiveness_ratio = p_ratio; - VS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); + RS::get_singleton()->particles_set_explosiveness_ratio(particles, explosiveness_ratio); } void GPUParticles3D::set_randomness_ratio(float p_ratio) { randomness_ratio = p_ratio; - VS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); + RS::get_singleton()->particles_set_randomness_ratio(particles, randomness_ratio); } void GPUParticles3D::set_visibility_aabb(const AABB &p_aabb) { visibility_aabb = p_aabb; - VS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb); + RS::get_singleton()->particles_set_custom_aabb(particles, visibility_aabb); update_gizmo(); _change_notify("visibility_aabb"); } void GPUParticles3D::set_use_local_coordinates(bool p_enable) { local_coords = p_enable; - VS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); + RS::get_singleton()->particles_set_use_local_coordinates(particles, local_coords); } void GPUParticles3D::set_process_material(const Ref &p_material) { @@ -117,7 +117,7 @@ void GPUParticles3D::set_process_material(const Ref &p_material) { RID material_rid; if (process_material.is_valid()) material_rid = process_material->get_rid(); - VS::get_singleton()->particles_set_process_material(particles, material_rid); + RS::get_singleton()->particles_set_process_material(particles, material_rid); update_configuration_warning(); } @@ -125,12 +125,12 @@ void GPUParticles3D::set_process_material(const Ref &p_material) { void GPUParticles3D::set_speed_scale(float p_scale) { speed_scale = p_scale; - VS::get_singleton()->particles_set_speed_scale(particles, p_scale); + RS::get_singleton()->particles_set_speed_scale(particles, p_scale); } bool GPUParticles3D::is_emitting() const { - return VS::get_singleton()->particles_get_emitting(particles); + return RS::get_singleton()->particles_get_emitting(particles); } int GPUParticles3D::get_amount() const { @@ -178,7 +178,7 @@ float GPUParticles3D::get_speed_scale() const { void GPUParticles3D::set_draw_order(DrawOrder p_order) { draw_order = p_order; - VS::get_singleton()->particles_set_draw_order(particles, VS::ParticlesDrawOrder(p_order)); + RS::get_singleton()->particles_set_draw_order(particles, RS::ParticlesDrawOrder(p_order)); } GPUParticles3D::DrawOrder GPUParticles3D::get_draw_order() const { @@ -190,7 +190,7 @@ void GPUParticles3D::set_draw_passes(int p_count) { ERR_FAIL_COND(p_count < 1); draw_passes.resize(p_count); - VS::get_singleton()->particles_set_draw_passes(particles, p_count); + RS::get_singleton()->particles_set_draw_passes(particles, p_count); _change_notify(); } int GPUParticles3D::get_draw_passes() const { @@ -208,7 +208,7 @@ void GPUParticles3D::set_draw_pass_mesh(int p_pass, const Ref &p_mesh) { if (p_mesh.is_valid()) mesh_rid = p_mesh->get_rid(); - VS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); + RS::get_singleton()->particles_set_draw_pass_mesh(particles, p_pass, mesh_rid); update_configuration_warning(); } @@ -222,7 +222,7 @@ Ref GPUParticles3D::get_draw_pass_mesh(int p_pass) const { void GPUParticles3D::set_fixed_fps(int p_count) { fixed_fps = p_count; - VS::get_singleton()->particles_set_fixed_fps(particles, p_count); + RS::get_singleton()->particles_set_fixed_fps(particles, p_count); } int GPUParticles3D::get_fixed_fps() const { @@ -231,7 +231,7 @@ int GPUParticles3D::get_fixed_fps() const { void GPUParticles3D::set_fractional_delta(bool p_enable) { fractional_delta = p_enable; - VS::get_singleton()->particles_set_fractional_delta(particles, p_enable); + RS::get_singleton()->particles_set_fractional_delta(particles, p_enable); } bool GPUParticles3D::get_fractional_delta() const { @@ -240,7 +240,7 @@ bool GPUParticles3D::get_fractional_delta() const { String GPUParticles3D::get_configuration_warning() const { - if (VisualServer::get_singleton()->is_low_end()) { + if (RenderingServer::get_singleton()->is_low_end()) { return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose."); } @@ -291,13 +291,13 @@ String GPUParticles3D::get_configuration_warning() const { void GPUParticles3D::restart() { - VisualServer::get_singleton()->particles_restart(particles); - VisualServer::get_singleton()->particles_set_emitting(particles, true); + RenderingServer::get_singleton()->particles_restart(particles); + RenderingServer::get_singleton()->particles_set_emitting(particles, true); } AABB GPUParticles3D::capture_aabb() const { - return VS::get_singleton()->particles_get_current_aabb(particles); + return RS::get_singleton()->particles_get_current_aabb(particles); } void GPUParticles3D::_validate_property(PropertyInfo &property) const { @@ -315,10 +315,10 @@ void GPUParticles3D::_notification(int p_what) { if (p_what == NOTIFICATION_PAUSED || p_what == NOTIFICATION_UNPAUSED) { if (can_process()) { - VS::get_singleton()->particles_set_speed_scale(particles, speed_scale); + RS::get_singleton()->particles_set_speed_scale(particles, speed_scale); } else { - VS::get_singleton()->particles_set_speed_scale(particles, 0); + RS::get_singleton()->particles_set_speed_scale(particles, 0); } } @@ -334,8 +334,8 @@ void GPUParticles3D::_notification(int p_what) { if (p_what == NOTIFICATION_VISIBILITY_CHANGED) { // make sure particles are updated before rendering occurs if they were active before - if (is_visible_in_tree() && !VS::get_singleton()->particles_is_inactive(particles)) { - VS::get_singleton()->particles_request_process(particles); + if (is_visible_in_tree() && !RS::get_singleton()->particles_is_inactive(particles)) { + RS::get_singleton()->particles_request_process(particles); } } } @@ -416,7 +416,7 @@ void GPUParticles3D::_bind_methods() { GPUParticles3D::GPUParticles3D() { - particles = VS::get_singleton()->particles_create(); + particles = RS::get_singleton()->particles_create(); set_base(particles); one_shot = false; // Needed so that set_emitting doesn't access uninitialized values set_emitting(true); @@ -437,5 +437,5 @@ GPUParticles3D::GPUParticles3D() { GPUParticles3D::~GPUParticles3D() { - VS::get_singleton()->free(particles); + RS::get_singleton()->free(particles); } diff --git a/scene/3d/immediate_geometry_3d.cpp b/scene/3d/immediate_geometry_3d.cpp index acc1f407f9..63d4b1ac84 100644 --- a/scene/3d/immediate_geometry_3d.cpp +++ b/scene/3d/immediate_geometry_3d.cpp @@ -32,39 +32,39 @@ void ImmediateGeometry3D::begin(Mesh::PrimitiveType p_primitive, const Ref &p_texture) { - VS::get_singleton()->immediate_begin(im, (VS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID()); + RS::get_singleton()->immediate_begin(im, (RS::PrimitiveType)p_primitive, p_texture.is_valid() ? p_texture->get_rid() : RID()); if (p_texture.is_valid()) cached_textures.push_back(p_texture); } void ImmediateGeometry3D::set_normal(const Vector3 &p_normal) { - VS::get_singleton()->immediate_normal(im, p_normal); + RS::get_singleton()->immediate_normal(im, p_normal); } void ImmediateGeometry3D::set_tangent(const Plane &p_tangent) { - VS::get_singleton()->immediate_tangent(im, p_tangent); + RS::get_singleton()->immediate_tangent(im, p_tangent); } void ImmediateGeometry3D::set_color(const Color &p_color) { - VS::get_singleton()->immediate_color(im, p_color); + RS::get_singleton()->immediate_color(im, p_color); } void ImmediateGeometry3D::set_uv(const Vector2 &p_uv) { - VS::get_singleton()->immediate_uv(im, p_uv); + RS::get_singleton()->immediate_uv(im, p_uv); } void ImmediateGeometry3D::set_uv2(const Vector2 &p_uv2) { - VS::get_singleton()->immediate_uv2(im, p_uv2); + RS::get_singleton()->immediate_uv2(im, p_uv2); } void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) { - VS::get_singleton()->immediate_vertex(im, p_vertex); + RS::get_singleton()->immediate_vertex(im, p_vertex); if (empty) { aabb.position = p_vertex; aabb.size = Vector3(); @@ -76,12 +76,12 @@ void ImmediateGeometry3D::add_vertex(const Vector3 &p_vertex) { void ImmediateGeometry3D::end() { - VS::get_singleton()->immediate_end(im); + RS::get_singleton()->immediate_end(im); } void ImmediateGeometry3D::clear() { - VS::get_singleton()->immediate_clear(im); + RS::get_singleton()->immediate_clear(im); empty = true; cached_textures.clear(); } @@ -158,12 +158,12 @@ void ImmediateGeometry3D::_bind_methods() { ImmediateGeometry3D::ImmediateGeometry3D() { - im = VisualServer::get_singleton()->immediate_create(); + im = RenderingServer::get_singleton()->immediate_create(); set_base(im); empty = true; } ImmediateGeometry3D::~ImmediateGeometry3D() { - VisualServer::get_singleton()->free(im); + RenderingServer::get_singleton()->free(im); } diff --git a/scene/3d/immediate_geometry_3d.h b/scene/3d/immediate_geometry_3d.h index d968187ba3..6e15450a5b 100644 --- a/scene/3d/immediate_geometry_3d.h +++ b/scene/3d/immediate_geometry_3d.h @@ -40,7 +40,7 @@ class ImmediateGeometry3D : public GeometryInstance3D { RID im; //a list of textures drawn need to be kept, to avoid references - // in VisualServer from becoming invalid if the texture is no longer used + // in RenderingServer from becoming invalid if the texture is no longer used List> cached_textures; bool empty; AABB aabb; diff --git a/scene/3d/light_3d.cpp b/scene/3d/light_3d.cpp index 434f35fc57..7fc7fe2bf5 100644 --- a/scene/3d/light_3d.cpp +++ b/scene/3d/light_3d.cpp @@ -44,7 +44,7 @@ void Light3D::set_param(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); param[p_param] = p_value; - VS::get_singleton()->light_set_param(light, VS::LightParam(p_param), p_value); + RS::get_singleton()->light_set_param(light, RS::LightParam(p_param), p_value); if (p_param == PARAM_SPOT_ANGLE || p_param == PARAM_RANGE) { update_gizmo(); @@ -68,9 +68,9 @@ float Light3D::get_param(Param p_param) const { void Light3D::set_shadow(bool p_enable) { shadow = p_enable; - VS::get_singleton()->light_set_shadow(light, p_enable); + RS::get_singleton()->light_set_shadow(light, p_enable); - if (type == VisualServer::LIGHT_SPOT) { + if (type == RenderingServer::LIGHT_SPOT) { update_configuration_warning(); } } @@ -82,7 +82,7 @@ bool Light3D::has_shadow() const { void Light3D::set_negative(bool p_enable) { negative = p_enable; - VS::get_singleton()->light_set_negative(light, p_enable); + RS::get_singleton()->light_set_negative(light, p_enable); } bool Light3D::is_negative() const { @@ -92,7 +92,7 @@ bool Light3D::is_negative() const { void Light3D::set_cull_mask(uint32_t p_cull_mask) { cull_mask = p_cull_mask; - VS::get_singleton()->light_set_cull_mask(light, p_cull_mask); + RS::get_singleton()->light_set_cull_mask(light, p_cull_mask); } uint32_t Light3D::get_cull_mask() const { @@ -102,7 +102,7 @@ uint32_t Light3D::get_cull_mask() const { void Light3D::set_color(const Color &p_color) { color = p_color; - VS::get_singleton()->light_set_color(light, p_color); + RS::get_singleton()->light_set_color(light, p_color); // The gizmo color depends on the light color, so update it. update_gizmo(); } @@ -114,7 +114,7 @@ Color Light3D::get_color() const { void Light3D::set_shadow_color(const Color &p_shadow_color) { shadow_color = p_shadow_color; - VS::get_singleton()->light_set_shadow_color(light, p_shadow_color); + RS::get_singleton()->light_set_shadow_color(light, p_shadow_color); } Color Light3D::get_shadow_color() const { @@ -124,7 +124,7 @@ Color Light3D::get_shadow_color() const { void Light3D::set_shadow_reverse_cull_face(bool p_enable) { reverse_cull = p_enable; - VS::get_singleton()->light_set_reverse_cull_face_mode(light, reverse_cull); + RS::get_singleton()->light_set_reverse_cull_face_mode(light, reverse_cull); } bool Light3D::get_shadow_reverse_cull_face() const { @@ -134,15 +134,15 @@ bool Light3D::get_shadow_reverse_cull_face() const { AABB Light3D::get_aabb() const { - if (type == VisualServer::LIGHT_DIRECTIONAL) { + if (type == RenderingServer::LIGHT_DIRECTIONAL) { return AABB(Vector3(-1, -1, -1), Vector3(2, 2, 2)); - } else if (type == VisualServer::LIGHT_OMNI) { + } else if (type == RenderingServer::LIGHT_OMNI) { return AABB(Vector3(-1, -1, -1) * param[PARAM_RANGE], Vector3(2, 2, 2) * param[PARAM_RANGE]); - } else if (type == VisualServer::LIGHT_SPOT) { + } else if (type == RenderingServer::LIGHT_SPOT) { float len = param[PARAM_RANGE]; float size = Math::tan(Math::deg2rad(param[PARAM_SPOT_ANGLE])) * len; @@ -159,7 +159,7 @@ Vector Light3D::get_faces(uint32_t p_usage_flags) const { void Light3D::set_bake_mode(BakeMode p_mode) { bake_mode = p_mode; - VS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED); + RS::get_singleton()->light_set_use_gi(light, p_mode != BAKE_DISABLED); } Light3D::BakeMode Light3D::get_bake_mode() const { @@ -187,7 +187,7 @@ void Light3D::_update_visibility() { } #endif - VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree() && editor_ok); + RS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree() && editor_ok); _change_notify("geometry/visible"); } @@ -217,7 +217,7 @@ bool Light3D::is_editor_only() const { void Light3D::_validate_property(PropertyInfo &property) const { - if (VisualServer::get_singleton()->is_low_end() && property.name == "shadow_contact") { + if (RenderingServer::get_singleton()->is_low_end() && property.name == "shadow_contact") { property.usage = PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL; } } @@ -292,18 +292,18 @@ void Light3D::_bind_methods() { BIND_ENUM_CONSTANT(BAKE_ALL); } -Light3D::Light3D(VisualServer::LightType p_type) { +Light3D::Light3D(RenderingServer::LightType p_type) { type = p_type; switch (p_type) { - case VS::LIGHT_DIRECTIONAL: light = VisualServer::get_singleton()->directional_light_create(); break; - case VS::LIGHT_OMNI: light = VisualServer::get_singleton()->omni_light_create(); break; - case VS::LIGHT_SPOT: light = VisualServer::get_singleton()->spot_light_create(); break; + case RS::LIGHT_DIRECTIONAL: light = RenderingServer::get_singleton()->directional_light_create(); break; + case RS::LIGHT_OMNI: light = RenderingServer::get_singleton()->omni_light_create(); break; + case RS::LIGHT_SPOT: light = RenderingServer::get_singleton()->spot_light_create(); break; default: { }; } - VS::get_singleton()->instance_set_base(get_instance(), light); + RS::get_singleton()->instance_set_base(get_instance(), light); reverse_cull = false; bake_mode = BAKE_INDIRECT; @@ -335,23 +335,23 @@ Light3D::Light3D(VisualServer::LightType p_type) { Light3D::Light3D() { - type = VisualServer::LIGHT_DIRECTIONAL; + type = RenderingServer::LIGHT_DIRECTIONAL; ERR_PRINT("Light should not be instanced directly; use the DirectionalLight, OmniLight or SpotLight subtypes instead."); } Light3D::~Light3D() { - VS::get_singleton()->instance_set_base(get_instance(), RID()); + RS::get_singleton()->instance_set_base(get_instance(), RID()); if (light.is_valid()) - VisualServer::get_singleton()->free(light); + RenderingServer::get_singleton()->free(light); } ///////////////////////////////////////// void DirectionalLight3D::set_shadow_mode(ShadowMode p_mode) { shadow_mode = p_mode; - VS::get_singleton()->light_directional_set_shadow_mode(light, VS::LightDirectionalShadowMode(p_mode)); + RS::get_singleton()->light_directional_set_shadow_mode(light, RS::LightDirectionalShadowMode(p_mode)); } DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const { @@ -361,7 +361,7 @@ DirectionalLight3D::ShadowMode DirectionalLight3D::get_shadow_mode() const { void DirectionalLight3D::set_shadow_depth_range(ShadowDepthRange p_range) { shadow_depth_range = p_range; - VS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, VS::LightDirectionalShadowDepthRangeMode(p_range)); + RS::get_singleton()->light_directional_set_shadow_depth_range_mode(light, RS::LightDirectionalShadowDepthRangeMode(p_range)); } DirectionalLight3D::ShadowDepthRange DirectionalLight3D::get_shadow_depth_range() const { @@ -372,7 +372,7 @@ DirectionalLight3D::ShadowDepthRange DirectionalLight3D::get_shadow_depth_range( void DirectionalLight3D::set_blend_splits(bool p_enable) { blend_splits = p_enable; - VS::get_singleton()->light_directional_set_blend_splits(light, p_enable); + RS::get_singleton()->light_directional_set_blend_splits(light, p_enable); } bool DirectionalLight3D::is_blend_splits_enabled() const { @@ -412,7 +412,7 @@ void DirectionalLight3D::_bind_methods() { } DirectionalLight3D::DirectionalLight3D() : - Light3D(VisualServer::LIGHT_DIRECTIONAL) { + Light3D(RenderingServer::LIGHT_DIRECTIONAL) { set_param(PARAM_SHADOW_NORMAL_BIAS, 0.8); set_param(PARAM_SHADOW_BIAS, 0.1); @@ -428,7 +428,7 @@ DirectionalLight3D::DirectionalLight3D() : void OmniLight3D::set_shadow_mode(ShadowMode p_mode) { shadow_mode = p_mode; - VS::get_singleton()->light_omni_set_shadow_mode(light, VS::LightOmniShadowMode(p_mode)); + RS::get_singleton()->light_omni_set_shadow_mode(light, RS::LightOmniShadowMode(p_mode)); } OmniLight3D::ShadowMode OmniLight3D::get_shadow_mode() const { @@ -451,7 +451,7 @@ void OmniLight3D::_bind_methods() { } OmniLight3D::OmniLight3D() : - Light3D(VisualServer::LIGHT_OMNI) { + Light3D(RenderingServer::LIGHT_OMNI) { set_shadow_mode(SHADOW_CUBE); } diff --git a/scene/3d/light_3d.h b/scene/3d/light_3d.h index 7b3273e1e4..197e5854ec 100644 --- a/scene/3d/light_3d.h +++ b/scene/3d/light_3d.h @@ -33,7 +33,7 @@ #include "scene/3d/visual_instance_3d.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Light3D : public VisualInstance3D { @@ -42,23 +42,23 @@ class Light3D : public VisualInstance3D { public: enum Param { - PARAM_ENERGY = VS::LIGHT_PARAM_ENERGY, - PARAM_INDIRECT_ENERGY = VS::LIGHT_PARAM_INDIRECT_ENERGY, - PARAM_SPECULAR = VS::LIGHT_PARAM_SPECULAR, - PARAM_RANGE = VS::LIGHT_PARAM_RANGE, - PARAM_ATTENUATION = VS::LIGHT_PARAM_ATTENUATION, - PARAM_SPOT_ANGLE = VS::LIGHT_PARAM_SPOT_ANGLE, - PARAM_SPOT_ATTENUATION = VS::LIGHT_PARAM_SPOT_ATTENUATION, - PARAM_CONTACT_SHADOW_SIZE = VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE, - PARAM_SHADOW_MAX_DISTANCE = VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE, - PARAM_SHADOW_SPLIT_1_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, - PARAM_SHADOW_SPLIT_2_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, - PARAM_SHADOW_SPLIT_3_OFFSET = VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, - PARAM_SHADOW_FADE_START = VS::LIGHT_PARAM_SHADOW_FADE_START, - PARAM_SHADOW_NORMAL_BIAS = VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, - PARAM_SHADOW_BIAS = VS::LIGHT_PARAM_SHADOW_BIAS, - PARAM_SHADOW_BIAS_SPLIT_SCALE = VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, - PARAM_MAX = VS::LIGHT_PARAM_MAX + PARAM_ENERGY = RS::LIGHT_PARAM_ENERGY, + PARAM_INDIRECT_ENERGY = RS::LIGHT_PARAM_INDIRECT_ENERGY, + PARAM_SPECULAR = RS::LIGHT_PARAM_SPECULAR, + PARAM_RANGE = RS::LIGHT_PARAM_RANGE, + PARAM_ATTENUATION = RS::LIGHT_PARAM_ATTENUATION, + PARAM_SPOT_ANGLE = RS::LIGHT_PARAM_SPOT_ANGLE, + PARAM_SPOT_ATTENUATION = RS::LIGHT_PARAM_SPOT_ATTENUATION, + PARAM_CONTACT_SHADOW_SIZE = RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE, + PARAM_SHADOW_MAX_DISTANCE = RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE, + PARAM_SHADOW_SPLIT_1_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, + PARAM_SHADOW_SPLIT_2_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, + PARAM_SHADOW_SPLIT_3_OFFSET = RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, + PARAM_SHADOW_FADE_START = RS::LIGHT_PARAM_SHADOW_FADE_START, + PARAM_SHADOW_NORMAL_BIAS = RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS, + PARAM_SHADOW_BIAS = RS::LIGHT_PARAM_SHADOW_BIAS, + PARAM_SHADOW_BIAS_SPLIT_SCALE = RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, + PARAM_MAX = RS::LIGHT_PARAM_MAX }; enum BakeMode { @@ -75,7 +75,7 @@ private: bool negative; bool reverse_cull; uint32_t cull_mask; - VS::LightType type; + RS::LightType type; bool editor_only; void _update_visibility(); BakeMode bake_mode; @@ -91,10 +91,10 @@ protected: void _notification(int p_what); virtual void _validate_property(PropertyInfo &property) const; - Light3D(VisualServer::LightType p_type); + Light3D(RenderingServer::LightType p_type); public: - VS::LightType get_light_type() const { return type; } + RS::LightType get_light_type() const { return type; } void set_editor_only(bool p_editor_only); bool is_editor_only() const; @@ -145,8 +145,8 @@ public: }; enum ShadowDepthRange { - SHADOW_DEPTH_RANGE_STABLE = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, - SHADOW_DEPTH_RANGE_OPTIMIZED = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, + SHADOW_DEPTH_RANGE_STABLE = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, + SHADOW_DEPTH_RANGE_OPTIMIZED = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, }; private: @@ -210,7 +210,7 @@ public: virtual String get_configuration_warning() const; SpotLight3D() : - Light3D(VisualServer::LIGHT_SPOT) {} + Light3D(RenderingServer::LIGHT_SPOT) {} }; #endif diff --git a/scene/3d/mesh_instance_3d.cpp b/scene/3d/mesh_instance_3d.cpp index 5f826505b4..284bbd7091 100644 --- a/scene/3d/mesh_instance_3d.cpp +++ b/scene/3d/mesh_instance_3d.cpp @@ -47,7 +47,7 @@ bool MeshInstance3D::_set(const StringName &p_name, const Variant &p_value) { Map::Element *E = blend_shape_tracks.find(p_name); if (E) { E->get().value = p_value; - VisualServer::get_singleton()->instance_set_blend_shape_weight(get_instance(), E->get().idx, E->get().value); + RenderingServer::get_singleton()->instance_set_blend_shape_weight(get_instance(), E->get().idx, E->get().value); return true; } @@ -165,9 +165,9 @@ void MeshInstance3D::_resolve_skeleton_path() { skin_ref = new_skin_reference; if (skin_ref.is_valid()) { - VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton()); + RenderingServer::get_singleton()->instance_attach_skeleton(get_instance(), skin_ref->get_skeleton()); } else { - VisualServer::get_singleton()->instance_attach_skeleton(get_instance(), RID()); + RenderingServer::get_singleton()->instance_attach_skeleton(get_instance(), RID()); } } @@ -293,9 +293,9 @@ void MeshInstance3D::set_surface_material(int p_surface, const Ref &p_ materials.write[p_surface] = p_material; if (materials[p_surface].is_valid()) - VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid()); + RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, materials[p_surface]->get_rid()); else - VS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID()); + RS::get_singleton()->instance_set_surface_material(get_instance(), p_surface, RID()); } Ref MeshInstance3D::get_surface_material(int p_surface) const { diff --git a/scene/3d/navigation_3d.cpp b/scene/3d/navigation_3d.cpp index 28da04fcbe..f880f65d37 100644 --- a/scene/3d/navigation_3d.cpp +++ b/scene/3d/navigation_3d.cpp @@ -30,33 +30,33 @@ #include "navigation_3d.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" Vector Navigation3D::get_simple_path(const Vector3 &p_start, const Vector3 &p_end, bool p_optimize) const { - return NavigationServer::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); + return NavigationServer3D::get_singleton()->map_get_path(map, p_start, p_end, p_optimize); } Vector3 Navigation3D::get_closest_point_to_segment(const Vector3 &p_from, const Vector3 &p_to, bool p_use_collision) const { - return NavigationServer::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision); + return NavigationServer3D::get_singleton()->map_get_closest_point_to_segment(map, p_from, p_to, p_use_collision); } Vector3 Navigation3D::get_closest_point(const Vector3 &p_point) const { - return NavigationServer::get_singleton()->map_get_closest_point(map, p_point); + return NavigationServer3D::get_singleton()->map_get_closest_point(map, p_point); } Vector3 Navigation3D::get_closest_point_normal(const Vector3 &p_point) const { - return NavigationServer::get_singleton()->map_get_closest_point_normal(map, p_point); + return NavigationServer3D::get_singleton()->map_get_closest_point_normal(map, p_point); } RID Navigation3D::get_closest_point_owner(const Vector3 &p_point) const { - return NavigationServer::get_singleton()->map_get_closest_point_owner(map, p_point); + return NavigationServer3D::get_singleton()->map_get_closest_point_owner(map, p_point); } void Navigation3D::set_up_vector(const Vector3 &p_up) { up = p_up; - NavigationServer::get_singleton()->map_set_up(map, up); + NavigationServer3D::get_singleton()->map_set_up(map, up); } Vector3 Navigation3D::get_up_vector() const { @@ -66,12 +66,12 @@ Vector3 Navigation3D::get_up_vector() const { void Navigation3D::set_cell_size(float p_cell_size) { cell_size = p_cell_size; - NavigationServer::get_singleton()->map_set_cell_size(map, cell_size); + NavigationServer3D::get_singleton()->map_set_cell_size(map, cell_size); } void Navigation3D::set_edge_connection_margin(float p_edge_connection_margin) { edge_connection_margin = p_edge_connection_margin; - NavigationServer::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); + NavigationServer3D::get_singleton()->map_set_edge_connection_margin(map, edge_connection_margin); } void Navigation3D::_bind_methods() { @@ -101,18 +101,18 @@ void Navigation3D::_bind_methods() { void Navigation3D::_notification(int p_what) { switch (p_what) { case NOTIFICATION_READY: { - NavigationServer::get_singleton()->map_set_active(map, true); + NavigationServer3D::get_singleton()->map_set_active(map, true); } break; case NOTIFICATION_EXIT_TREE: { - NavigationServer::get_singleton()->map_set_active(map, false); + NavigationServer3D::get_singleton()->map_set_active(map, false); } break; } } Navigation3D::Navigation3D() { - map = NavigationServer::get_singleton()->map_create(); + map = NavigationServer3D::get_singleton()->map_create(); set_cell_size(0.3); set_edge_connection_margin(5.0); // Five meters, depends alot on the agents radius @@ -121,5 +121,5 @@ Navigation3D::Navigation3D() { } Navigation3D::~Navigation3D() { - NavigationServer::get_singleton()->free(map); + NavigationServer3D::get_singleton()->free(map); } diff --git a/scene/3d/navigation_agent_3d.cpp b/scene/3d/navigation_agent_3d.cpp index 219e868f29..76f1d4688d 100644 --- a/scene/3d/navigation_agent_3d.cpp +++ b/scene/3d/navigation_agent_3d.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "scene/3d/navigation_3d.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" void NavigationAgent3D::_bind_methods() { @@ -102,7 +102,7 @@ void NavigationAgent3D::_notification(int p_what) { agent_parent = Object::cast_to(get_parent()); - NavigationServer::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); + NavigationServer3D::get_singleton()->agent_set_callback(agent, this, "_avoidance_done"); // Search the navigation node and set it { @@ -129,7 +129,7 @@ void NavigationAgent3D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { if (agent_parent) { - NavigationServer::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); + NavigationServer3D::get_singleton()->agent_set_position(agent, agent_parent->get_global_transform().origin); if (!target_reached) { if (distance_to_target() < target_desired_distance) { emit_signal("target_reached"); @@ -151,7 +151,7 @@ NavigationAgent3D::NavigationAgent3D() : velocity_submitted(false), target_reached(false), navigation_finished(true) { - agent = NavigationServer::get_singleton()->agent_create(); + agent = NavigationServer3D::get_singleton()->agent_create(); set_neighbor_dist(50.0); set_max_neighbors(10); set_time_horizon(5.0); @@ -161,7 +161,7 @@ NavigationAgent3D::NavigationAgent3D() : } NavigationAgent3D::~NavigationAgent3D() { - NavigationServer::get_singleton()->free(agent); + NavigationServer3D::get_singleton()->free(agent); agent = RID(); // Pointless } @@ -170,7 +170,7 @@ void NavigationAgent3D::set_navigation(Navigation3D *p_nav) { return; // Pointless navigation = p_nav; - NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); + NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); } void NavigationAgent3D::set_navigation_node(Node *p_nav) { @@ -189,7 +189,7 @@ void NavigationAgent3D::set_target_desired_distance(real_t p_dd) { void NavigationAgent3D::set_radius(real_t p_radius) { radius = p_radius; - NavigationServer::get_singleton()->agent_set_radius(agent, radius); + NavigationServer3D::get_singleton()->agent_set_radius(agent, radius); } void NavigationAgent3D::set_agent_height_offset(real_t p_hh) { @@ -198,27 +198,27 @@ void NavigationAgent3D::set_agent_height_offset(real_t p_hh) { void NavigationAgent3D::set_ignore_y(bool p_ignore_y) { ignore_y = p_ignore_y; - NavigationServer::get_singleton()->agent_set_ignore_y(agent, ignore_y); + NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, ignore_y); } void NavigationAgent3D::set_neighbor_dist(real_t p_dist) { neighbor_dist = p_dist; - NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); + NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, neighbor_dist); } void NavigationAgent3D::set_max_neighbors(int p_count) { max_neighbors = p_count; - NavigationServer::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); + NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, max_neighbors); } void NavigationAgent3D::set_time_horizon(real_t p_time) { time_horizon = p_time; - NavigationServer::get_singleton()->agent_set_time_horizon(agent, time_horizon); + NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, time_horizon); } void NavigationAgent3D::set_max_speed(real_t p_max_speed) { max_speed = p_max_speed; - NavigationServer::get_singleton()->agent_set_max_speed(agent, max_speed); + NavigationServer3D::get_singleton()->agent_set_max_speed(agent, max_speed); } void NavigationAgent3D::set_path_max_distance(real_t p_pmd) { @@ -279,8 +279,8 @@ Vector3 NavigationAgent3D::get_final_location() { void NavigationAgent3D::set_velocity(Vector3 p_velocity) { target_velocity = p_velocity; - NavigationServer::get_singleton()->agent_set_target_velocity(agent, target_velocity); - NavigationServer::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); + NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, target_velocity); + NavigationServer3D::get_singleton()->agent_set_velocity(agent, prev_safe_velocity); velocity_submitted = true; } @@ -316,7 +316,7 @@ void NavigationAgent3D::update_navigation() { bool reload_path = false; - if (NavigationServer::get_singleton()->agent_is_map_changed(agent)) { + if (NavigationServer3D::get_singleton()->agent_is_map_changed(agent)) { reload_path = true; } else if (navigation_path.size() == 0) { reload_path = true; @@ -337,7 +337,7 @@ void NavigationAgent3D::update_navigation() { } if (reload_path) { - navigation_path = NavigationServer::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); + navigation_path = NavigationServer3D::get_singleton()->map_get_path(navigation->get_rid(), o, target_location, true); navigation_finished = false; nav_path_index = 0; emit_signal("path_changed"); diff --git a/scene/3d/navigation_obstacle_3d.cpp b/scene/3d/navigation_obstacle_3d.cpp index 9eef4a1340..63c273b4ca 100644 --- a/scene/3d/navigation_obstacle_3d.cpp +++ b/scene/3d/navigation_obstacle_3d.cpp @@ -33,7 +33,7 @@ #include "scene/3d/collision_shape_3d.h" #include "scene/3d/navigation_3d.h" #include "scene/3d/physics_body_3d.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" void NavigationObstacle3D::_bind_methods() { @@ -71,15 +71,15 @@ void NavigationObstacle3D::_notification(int p_what) { case NOTIFICATION_INTERNAL_PHYSICS_PROCESS: { Node3D *spatial = Object::cast_to(get_parent()); if (spatial) { - NavigationServer::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin); + NavigationServer3D::get_singleton()->agent_set_position(agent, spatial->get_global_transform().origin); } PhysicsBody3D *rigid = Object::cast_to(get_parent()); if (rigid) { Vector3 v = rigid->get_linear_velocity(); - NavigationServer::get_singleton()->agent_set_velocity(agent, v); - NavigationServer::get_singleton()->agent_set_target_velocity(agent, v); + NavigationServer3D::get_singleton()->agent_set_velocity(agent, v); + NavigationServer3D::get_singleton()->agent_set_target_velocity(agent, v); } } break; @@ -89,11 +89,11 @@ void NavigationObstacle3D::_notification(int p_what) { NavigationObstacle3D::NavigationObstacle3D() : navigation(NULL), agent(RID()) { - agent = NavigationServer::get_singleton()->agent_create(); + agent = NavigationServer3D::get_singleton()->agent_create(); } NavigationObstacle3D::~NavigationObstacle3D() { - NavigationServer::get_singleton()->free(agent); + NavigationServer3D::get_singleton()->free(agent); agent = RID(); // Pointless } @@ -102,7 +102,7 @@ void NavigationObstacle3D::set_navigation(Navigation3D *p_nav) { return; // Pointless navigation = p_nav; - NavigationServer::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); + NavigationServer3D::get_singleton()->agent_set_map(agent, navigation == NULL ? RID() : navigation->get_rid()); } void NavigationObstacle3D::set_navigation_node(Node *p_nav) { @@ -155,9 +155,9 @@ void NavigationObstacle3D::update_agent_shape() { radius = 1.0; // Never a 0 radius // Initialize the Agent as an object - NavigationServer::get_singleton()->agent_set_neighbor_dist(agent, 0.0); - NavigationServer::get_singleton()->agent_set_max_neighbors(agent, 0); - NavigationServer::get_singleton()->agent_set_time_horizon(agent, 0.0); - NavigationServer::get_singleton()->agent_set_radius(agent, radius); - NavigationServer::get_singleton()->agent_set_max_speed(agent, 0.0); + NavigationServer3D::get_singleton()->agent_set_neighbor_dist(agent, 0.0); + NavigationServer3D::get_singleton()->agent_set_max_neighbors(agent, 0); + NavigationServer3D::get_singleton()->agent_set_time_horizon(agent, 0.0); + NavigationServer3D::get_singleton()->agent_set_radius(agent, radius); + NavigationServer3D::get_singleton()->agent_set_max_speed(agent, 0.0); } diff --git a/scene/3d/navigation_region_3d.cpp b/scene/3d/navigation_region_3d.cpp index 8035e6149d..4bb2c72172 100644 --- a/scene/3d/navigation_region_3d.cpp +++ b/scene/3d/navigation_region_3d.cpp @@ -32,7 +32,7 @@ #include "core/os/thread.h" #include "mesh_instance_3d.h" #include "navigation_3d.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" void NavigationRegion3D::set_enabled(bool p_enabled) { @@ -45,12 +45,12 @@ void NavigationRegion3D::set_enabled(bool p_enabled) { if (!enabled) { - NavigationServer::get_singleton()->region_set_map(region, RID()); + NavigationServer3D::get_singleton()->region_set_map(region, RID()); } else { if (navigation) { - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); } } @@ -86,7 +86,7 @@ void NavigationRegion3D::_notification(int p_what) { if (enabled) { - NavigationServer::get_singleton()->region_set_map(region, navigation->get_rid()); + NavigationServer3D::get_singleton()->region_set_map(region, navigation->get_rid()); } break; } @@ -110,14 +110,14 @@ void NavigationRegion3D::_notification(int p_what) { } break; case NOTIFICATION_TRANSFORM_CHANGED: { - NavigationServer::get_singleton()->region_set_transform(region, get_global_transform()); + NavigationServer3D::get_singleton()->region_set_transform(region, get_global_transform()); } break; case NOTIFICATION_EXIT_TREE: { if (navigation) { - NavigationServer::get_singleton()->region_set_map(region, RID()); + NavigationServer3D::get_singleton()->region_set_map(region, RID()); } if (debug_view) { @@ -144,7 +144,7 @@ void NavigationRegion3D::set_navigation_mesh(const Ref &p_navmes navmesh->add_change_receptor(this); } - NavigationServer::get_singleton()->region_set_navmesh(region, p_navmesh); + NavigationServer3D::get_singleton()->region_set_navmesh(region, p_navmesh); if (debug_view && navmesh.is_valid()) { Object::cast_to(debug_view)->set_mesh(navmesh->get_debug_mesh()); @@ -171,7 +171,7 @@ void _bake_navigation_mesh(void *p_user_data) { if (args->nav_region->get_navigation_mesh().is_valid()) { Ref nav_mesh = args->nav_region->get_navigation_mesh()->duplicate(); - NavigationServer::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region); + NavigationServer3D::get_singleton()->region_bake_navmesh(nav_mesh, args->nav_region); args->nav_region->call_deferred("_bake_finished", nav_mesh); memdelete(args); } else { @@ -244,7 +244,7 @@ NavigationRegion3D::NavigationRegion3D() { enabled = true; set_notify_transform(true); - region = NavigationServer::get_singleton()->region_create(); + region = NavigationServer3D::get_singleton()->region_create(); navigation = NULL; debug_view = NULL; @@ -254,5 +254,5 @@ NavigationRegion3D::NavigationRegion3D() { NavigationRegion3D::~NavigationRegion3D() { if (navmesh.is_valid()) navmesh->remove_change_receptor(this); - NavigationServer::get_singleton()->free(region); + NavigationServer3D::get_singleton()->free(region); } diff --git a/scene/3d/physics_body_3d.cpp b/scene/3d/physics_body_3d.cpp index ce1643aa6c..1f3e2b8373 100644 --- a/scene/3d/physics_body_3d.cpp +++ b/scene/3d/physics_body_3d.cpp @@ -38,7 +38,7 @@ #include "core/rid.h" #include "scene/3d/collision_shape_3d.h" #include "scene/scene_string_names.h" -#include "servers/navigation_server.h" +#include "servers/navigation_server_3d.h" #ifdef TOOLS_ENABLED #include "editor/plugins/node_3d_editor_plugin.h" @@ -61,7 +61,7 @@ float PhysicsBody3D::get_inverse_mass() const { void PhysicsBody3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), p_layer); + PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), p_layer); } uint32_t PhysicsBody3D::get_collision_layer() const { @@ -72,7 +72,7 @@ uint32_t PhysicsBody3D::get_collision_layer() const { void PhysicsBody3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), p_mask); + PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), p_mask); } uint32_t PhysicsBody3D::get_collision_mask() const { @@ -112,11 +112,11 @@ bool PhysicsBody3D::get_collision_layer_bit(int p_bit) const { Array PhysicsBody3D::get_collision_exceptions() { List exceptions; - PhysicsServer::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); + PhysicsServer3D::get_singleton()->body_get_collision_exceptions(get_rid(), &exceptions); Array ret; for (List::Element *E = exceptions.front(); E; E = E->next()) { RID body = E->get(); - ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body); Object *obj = ObjectDB::get_instance(instance_id); PhysicsBody3D *physics_body = Object::cast_to(obj); ret.append(physics_body); @@ -129,7 +129,7 @@ void PhysicsBody3D::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid()); + PhysicsServer3D::get_singleton()->body_add_collision_exception(get_rid(), collision_object->get_rid()); } void PhysicsBody3D::remove_collision_exception_with(Node *p_node) { @@ -137,7 +137,7 @@ void PhysicsBody3D::remove_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); + PhysicsServer3D::get_singleton()->body_remove_collision_exception(get_rid(), collision_object->get_rid()); } void PhysicsBody3D::_set_layers(uint32_t p_mask) { @@ -171,8 +171,8 @@ void PhysicsBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); } -PhysicsBody3D::PhysicsBody3D(PhysicsServer::BodyMode p_mode) : - CollisionObject3D(PhysicsServer::get_singleton()->body_create(p_mode), false) { +PhysicsBody3D::PhysicsBody3D(PhysicsServer3D::BodyMode p_mode) : + CollisionObject3D(PhysicsServer3D::get_singleton()->body_create(p_mode), false) { collision_layer = 1; collision_mask = 1; @@ -200,13 +200,13 @@ Ref StaticBody3D::get_physics_material_override() const { void StaticBody3D::set_constant_linear_velocity(const Vector3 &p_vel) { constant_linear_velocity = p_vel; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, constant_linear_velocity); } void StaticBody3D::set_constant_angular_velocity(const Vector3 &p_vel) { constant_angular_velocity = p_vel; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, constant_angular_velocity); } Vector3 StaticBody3D::get_constant_linear_velocity() const { @@ -238,18 +238,18 @@ void StaticBody3D::_bind_methods() { } StaticBody3D::StaticBody3D() : - PhysicsBody3D(PhysicsServer::BODY_MODE_STATIC) { + PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC) { } StaticBody3D::~StaticBody3D() {} void StaticBody3D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1); } else { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } @@ -372,7 +372,7 @@ struct _RigidBodyInOut { void RigidBody3D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED - state = Object::cast_to(p_state); + state = Object::cast_to(p_state); #else state = (PhysicsDirectBodyState *)p_state; //trust it #endif @@ -502,20 +502,20 @@ void RigidBody3D::set_mode(Mode p_mode) { case MODE_RIGID: { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID); } break; case MODE_STATIC: { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC); } break; case MODE_CHARACTER: { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_CHARACTER); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_CHARACTER); } break; case MODE_KINEMATIC: { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC); } break; } update_configuration_warning(); @@ -532,7 +532,7 @@ void RigidBody3D::set_mass(real_t p_mass) { mass = p_mass; _change_notify("mass"); _change_notify("weight"); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass); } real_t RigidBody3D::get_mass() const { @@ -570,7 +570,7 @@ Ref RigidBody3D::get_physics_material_override() const { void RigidBody3D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } real_t RigidBody3D::get_gravity_scale() const { @@ -581,7 +581,7 @@ void RigidBody3D::set_linear_damp(real_t p_linear_damp) { ERR_FAIL_COND(p_linear_damp < -1); linear_damp = p_linear_damp; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_LINEAR_DAMP, linear_damp); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_LINEAR_DAMP, linear_damp); } real_t RigidBody3D::get_linear_damp() const { @@ -592,7 +592,7 @@ void RigidBody3D::set_angular_damp(real_t p_angular_damp) { ERR_FAIL_COND(p_angular_damp < -1); angular_damp = p_angular_damp; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_ANGULAR_DAMP, angular_damp); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP, angular_damp); } real_t RigidBody3D::get_angular_damp() const { @@ -608,7 +608,7 @@ void RigidBody3D::set_axis_velocity(const Vector3 &p_axis) { if (state) { set_linear_velocity(v); } else { - PhysicsServer::get_singleton()->body_set_axis_velocity(get_rid(), p_axis); + PhysicsServer3D::get_singleton()->body_set_axis_velocity(get_rid(), p_axis); linear_velocity = v; } } @@ -619,7 +619,7 @@ void RigidBody3D::set_linear_velocity(const Vector3 &p_velocity) { if (state) state->set_linear_velocity(linear_velocity); else - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_LINEAR_VELOCITY, linear_velocity); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY, linear_velocity); } Vector3 RigidBody3D::get_linear_velocity() const { @@ -633,7 +633,7 @@ void RigidBody3D::set_angular_velocity(const Vector3 &p_velocity) { if (state) state->set_angular_velocity(angular_velocity); else - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY, angular_velocity); } Vector3 RigidBody3D::get_angular_velocity() const { @@ -646,7 +646,7 @@ void RigidBody3D::set_use_custom_integrator(bool p_enable) { return; custom_integrator = p_enable; - PhysicsServer::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); + PhysicsServer3D::get_singleton()->body_set_omit_force_integration(get_rid(), p_enable); } bool RigidBody3D::is_using_custom_integrator() { @@ -656,13 +656,13 @@ bool RigidBody3D::is_using_custom_integrator() { void RigidBody3D::set_sleeping(bool p_sleeping) { sleeping = p_sleeping; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_SLEEPING, sleeping); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_SLEEPING, sleeping); } void RigidBody3D::set_can_sleep(bool p_active) { can_sleep = p_active; - PhysicsServer::get_singleton()->body_set_state(get_rid(), PhysicsServer::BODY_STATE_CAN_SLEEP, p_active); + PhysicsServer3D::get_singleton()->body_set_state(get_rid(), PhysicsServer3D::BODY_STATE_CAN_SLEEP, p_active); } bool RigidBody3D::is_able_to_sleep() const { @@ -678,7 +678,7 @@ bool RigidBody3D::is_sleeping() const { void RigidBody3D::set_max_contacts_reported(int p_amount) { max_contacts_reported = p_amount; - PhysicsServer::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); + PhysicsServer3D::get_singleton()->body_set_max_contacts_reported(get_rid(), p_amount); } int RigidBody3D::get_max_contacts_reported() const { @@ -687,34 +687,34 @@ int RigidBody3D::get_max_contacts_reported() const { } void RigidBody3D::add_central_force(const Vector3 &p_force) { - PhysicsServer::get_singleton()->body_add_central_force(get_rid(), p_force); + PhysicsServer3D::get_singleton()->body_add_central_force(get_rid(), p_force); } void RigidBody3D::add_force(const Vector3 &p_force, const Vector3 &p_pos) { - PhysicsServer::get_singleton()->body_add_force(get_rid(), p_force, p_pos); + PhysicsServer3D::get_singleton()->body_add_force(get_rid(), p_force, p_pos); } void RigidBody3D::add_torque(const Vector3 &p_torque) { - PhysicsServer::get_singleton()->body_add_torque(get_rid(), p_torque); + PhysicsServer3D::get_singleton()->body_add_torque(get_rid(), p_torque); } void RigidBody3D::apply_central_impulse(const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); + PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } void RigidBody3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); + PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); } void RigidBody3D::apply_torque_impulse(const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); + PhysicsServer3D::get_singleton()->body_apply_torque_impulse(get_rid(), p_impulse); } void RigidBody3D::set_use_continuous_collision_detection(bool p_enable) { ccd = p_enable; - PhysicsServer::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable); + PhysicsServer3D::get_singleton()->body_set_enable_continuous_collision_detection(get_rid(), p_enable); } bool RigidBody3D::is_using_continuous_collision_detection() const { @@ -757,12 +757,12 @@ bool RigidBody3D::is_contact_monitor_enabled() const { return contact_monitor != NULL; } -void RigidBody3D::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { - PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); +void RigidBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) { + PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); } -bool RigidBody3D::get_axis_lock(PhysicsServer::BodyAxis p_axis) const { - return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis); +bool RigidBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const { + return PhysicsServer3D::get_singleton()->body_is_axis_locked(get_rid(), p_axis); } Array RigidBody3D::get_colliding_bodies() const { @@ -878,12 +878,12 @@ void RigidBody3D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleeping", "is_sleeping"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "can_sleep"), "set_can_sleep", "is_able_to_sleep"); ADD_GROUP("Axis Lock", "axis_lock_"); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_X); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_ANGULAR_Z); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_linear_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_x"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_y"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "axis_lock_angular_z"), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_ANGULAR_Z); ADD_GROUP("Linear", "linear_"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater"), "set_linear_damp", "get_linear_damp"); @@ -904,7 +904,7 @@ void RigidBody3D::_bind_methods() { } RigidBody3D::RigidBody3D() : - PhysicsBody3D(PhysicsServer::BODY_MODE_RIGID) { + PhysicsBody3D(PhysicsServer3D::BODY_MODE_RIGID) { mode = MODE_RIGID; @@ -924,7 +924,7 @@ RigidBody3D::RigidBody3D() : contact_monitor = NULL; can_sleep = true; - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); } RigidBody3D::~RigidBody3D() { @@ -935,11 +935,11 @@ RigidBody3D::~RigidBody3D() { void RigidBody3D::_reload_physics_characteristics() { if (physics_material_override.is_null()) { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, 0); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, 1); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, 0); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, 1); } else { - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, physics_material_override->computed_bounce()); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, physics_material_override->computed_friction()); } } @@ -974,8 +974,8 @@ Vector3 KinematicBody3D::get_angular_velocity() const { bool KinematicBody3D::move_and_collide(const Vector3 &p_motion, bool p_infinite_inertia, Collision &r_collision, bool p_exclude_raycast_shapes, bool p_test_only) { Transform gt = get_global_transform(); - PhysicsServer::MotionResult result; - bool colliding = PhysicsServer::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes); + PhysicsServer3D::MotionResult result; + bool colliding = PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), gt, p_motion, p_infinite_inertia, &result, p_exclude_raycast_shapes); if (colliding) { r_collision.collider_metadata = result.collider_metadata; @@ -1168,17 +1168,17 @@ bool KinematicBody3D::test_move(const Transform &p_from, const Vector3 &p_motion ERR_FAIL_COND_V(!is_inside_tree(), false); - return PhysicsServer::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia); + return PhysicsServer3D::get_singleton()->body_test_motion(get_rid(), p_from, p_motion, p_infinite_inertia); } bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision) { - PhysicsServer::SeparationResult sep_res[8]; //max 8 rays + PhysicsServer3D::SeparationResult sep_res[8]; //max 8 rays Transform gt = get_global_transform(); Vector3 recover; - int hits = PhysicsServer::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); + int hits = PhysicsServer3D::get_singleton()->body_test_ray_separation(get_rid(), gt, p_infinite_inertia, recover, sep_res, 8, margin); int deepest = -1; float deepest_depth; for (int i = 0; i < hits; i++) { @@ -1208,18 +1208,18 @@ bool KinematicBody3D::separate_raycast_shapes(bool p_infinite_inertia, Collision } } -void KinematicBody3D::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock) { - PhysicsServer::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); +void KinematicBody3D::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock) { + PhysicsServer3D::get_singleton()->body_set_axis_lock(get_rid(), p_axis, p_lock); } -bool KinematicBody3D::get_axis_lock(PhysicsServer::BodyAxis p_axis) const { - return PhysicsServer::get_singleton()->body_is_axis_locked(get_rid(), p_axis); +bool KinematicBody3D::get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const { + return PhysicsServer3D::get_singleton()->body_is_axis_locked(get_rid(), p_axis); } void KinematicBody3D::set_safe_margin(float p_margin) { margin = p_margin; - PhysicsServer::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin); + PhysicsServer3D::get_singleton()->body_set_kinematic_safe_margin(get_rid(), margin); } float KinematicBody3D::get_safe_margin() const { @@ -1289,16 +1289,16 @@ void KinematicBody3D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_slide_count"), &KinematicBody3D::get_slide_count); ClassDB::bind_method(D_METHOD("get_slide_collision", "slide_idx"), &KinematicBody3D::_get_slide_collision); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_X); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Y); - ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer::BODY_AXIS_LINEAR_Z); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_x", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_X); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_y", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Y); + ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "move_lock_z", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR), "set_axis_lock", "get_axis_lock", PhysicsServer3D::BODY_AXIS_LINEAR_Z); ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "collision/safe_margin", PROPERTY_HINT_RANGE, "0.001,256,0.001"), "set_safe_margin", "get_safe_margin"); } void KinematicBody3D::_direct_state_changed(Object *p_state) { #ifdef DEBUG_ENABLED - PhysicsDirectBodyState *state = Object::cast_to(p_state); + PhysicsDirectBodyState3D *state = Object::cast_to(p_state); #else PhysicsDirectBodyState *state = (PhysicsDirectBodyState *)p_state; //trust it #endif @@ -1308,7 +1308,7 @@ void KinematicBody3D::_direct_state_changed(Object *p_state) { } KinematicBody3D::KinematicBody3D() : - PhysicsBody3D(PhysicsServer::BODY_MODE_KINEMATIC) { + PhysicsBody3D(PhysicsServer3D::BODY_MODE_KINEMATIC) { margin = 0.001; locked_axis = 0; @@ -1316,7 +1316,7 @@ KinematicBody3D::KinematicBody3D() : on_ceiling = false; on_wall = false; - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); } KinematicBody3D::~KinematicBody3D() { @@ -1437,11 +1437,11 @@ void PhysicalBone3D::JointData::_get_property_list(List *p_list) c } void PhysicalBone3D::apply_central_impulse(const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); + PhysicsServer3D::get_singleton()->body_apply_central_impulse(get_rid(), p_impulse); } void PhysicalBone3D::apply_impulse(const Vector3 &p_pos, const Vector3 &p_impulse) { - PhysicsServer::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); + PhysicsServer3D::get_singleton()->body_apply_impulse(get_rid(), p_pos, p_impulse); } void PhysicalBone3D::reset_physics_simulation_state() { @@ -1470,17 +1470,17 @@ bool PhysicalBone3D::PinJointData::_set(const StringName &p_name, const Variant if ("joint_constraints/bias" == p_name) { bias = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_BIAS, bias); + PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_BIAS, bias); } else if ("joint_constraints/damping" == p_name) { damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_DAMPING, damping); + PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_DAMPING, damping); } else if ("joint_constraints/impulse_clamp" == p_name) { impulse_clamp = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp); + PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, impulse_clamp); } else { return false; @@ -1523,27 +1523,27 @@ bool PhysicalBone3D::ConeJointData::_set(const StringName &p_name, const Variant if ("joint_constraints/swing_span" == p_name) { swing_span = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, swing_span); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, swing_span); } else if ("joint_constraints/twist_span" == p_name) { twist_span = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, twist_span); } else if ("joint_constraints/bias" == p_name) { bias = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_BIAS, bias); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, bias); } else if ("joint_constraints/softness" == p_name) { softness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, softness); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, softness); } else if ("joint_constraints/relaxation" == p_name) { relaxation = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, relaxation); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, relaxation); } else { return false; @@ -1592,32 +1592,32 @@ bool PhysicalBone3D::HingeJointData::_set(const StringName &p_name, const Varian if ("joint_constraints/angular_limit_enabled" == p_name) { angular_limit_enabled = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled); + PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, angular_limit_enabled); } else if ("joint_constraints/angular_limit_upper" == p_name) { angular_limit_upper = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, angular_limit_upper); } else if ("joint_constraints/angular_limit_lower" == p_name) { angular_limit_lower = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, angular_limit_lower); } else if ("joint_constraints/angular_limit_bias" == p_name) { angular_limit_bias = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, angular_limit_bias); } else if ("joint_constraints/angular_limit_softness" == p_name) { angular_limit_softness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, angular_limit_softness); } else if ("joint_constraints/angular_limit_relaxation" == p_name) { angular_limit_relaxation = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, angular_limit_relaxation); } else { return false; @@ -1669,52 +1669,52 @@ bool PhysicalBone3D::SliderJointData::_set(const StringName &p_name, const Varia if ("joint_constraints/linear_limit_upper" == p_name) { linear_limit_upper = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, linear_limit_upper); } else if ("joint_constraints/linear_limit_lower" == p_name) { linear_limit_lower = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, linear_limit_lower); } else if ("joint_constraints/linear_limit_softness" == p_name) { linear_limit_softness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, linear_limit_softness); } else if ("joint_constraints/linear_limit_restitution" == p_name) { linear_limit_restitution = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, linear_limit_restitution); } else if ("joint_constraints/linear_limit_damping" == p_name) { linear_limit_damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, linear_limit_restitution); } else if ("joint_constraints/angular_limit_upper" == p_name) { angular_limit_upper = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, angular_limit_upper); } else if ("joint_constraints/angular_limit_lower" == p_name) { angular_limit_lower = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, angular_limit_lower); } else if ("joint_constraints/angular_limit_softness" == p_name) { angular_limit_softness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); } else if ("joint_constraints/angular_limit_restitution" == p_name) { angular_limit_restitution = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, angular_limit_softness); } else if ("joint_constraints/angular_limit_damping" == p_name) { angular_limit_damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, angular_limit_damping); } else { return false; @@ -1797,107 +1797,107 @@ bool PhysicalBone3D::SixDOFJointData::_set(const StringName &p_name, const Varia if ("linear_limit_enabled" == var_name) { axis_data[axis].linear_limit_enabled = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, axis_data[axis].linear_limit_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, axis_data[axis].linear_limit_enabled); } else if ("linear_limit_upper" == var_name) { axis_data[axis].linear_limit_upper = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, axis_data[axis].linear_limit_upper); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, axis_data[axis].linear_limit_upper); } else if ("linear_limit_lower" == var_name) { axis_data[axis].linear_limit_lower = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, axis_data[axis].linear_limit_lower); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, axis_data[axis].linear_limit_lower); } else if ("linear_limit_softness" == var_name) { axis_data[axis].linear_limit_softness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, axis_data[axis].linear_limit_softness); } else if ("linear_spring_enabled" == var_name) { axis_data[axis].linear_spring_enabled = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, axis_data[axis].linear_spring_enabled); } else if ("linear_spring_stiffness" == var_name) { axis_data[axis].linear_spring_stiffness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, axis_data[axis].linear_spring_stiffness); } else if ("linear_spring_damping" == var_name) { axis_data[axis].linear_spring_damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, axis_data[axis].linear_spring_damping); } else if ("linear_equilibrium_point" == var_name) { axis_data[axis].linear_equilibrium_point = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].linear_equilibrium_point); } else if ("linear_restitution" == var_name) { axis_data[axis].linear_restitution = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, axis_data[axis].linear_restitution); } else if ("linear_damping" == var_name) { axis_data[axis].linear_damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, axis_data[axis].linear_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, axis_data[axis].linear_damping); } else if ("angular_limit_enabled" == var_name) { axis_data[axis].angular_limit_enabled = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, axis_data[axis].angular_limit_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, axis_data[axis].angular_limit_enabled); } else if ("angular_limit_upper" == var_name) { axis_data[axis].angular_limit_upper = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, axis_data[axis].angular_limit_upper); } else if ("angular_limit_lower" == var_name) { axis_data[axis].angular_limit_lower = Math::deg2rad(real_t(p_value)); if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, axis_data[axis].angular_limit_lower); } else if ("angular_limit_softness" == var_name) { axis_data[axis].angular_limit_softness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, axis_data[axis].angular_limit_softness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, axis_data[axis].angular_limit_softness); } else if ("angular_restitution" == var_name) { axis_data[axis].angular_restitution = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, axis_data[axis].angular_restitution); } else if ("angular_damping" == var_name) { axis_data[axis].angular_damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, axis_data[axis].angular_damping); } else if ("erp" == var_name) { axis_data[axis].erp = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, axis_data[axis].erp); } else if ("angular_spring_enabled" == var_name) { axis_data[axis].angular_spring_enabled = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, axis, PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, axis_data[axis].angular_spring_enabled); } else if ("angular_spring_stiffness" == var_name) { axis_data[axis].angular_spring_stiffness = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, axis_data[axis].angular_spring_stiffness); } else if ("angular_spring_damping" == var_name) { axis_data[axis].angular_spring_damping = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, axis_data[axis].angular_spring_damping); } else if ("angular_equilibrium_point" == var_name) { axis_data[axis].angular_equilibrium_point = p_value; if (j.is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, axis, PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, axis_data[axis].angular_equilibrium_point); } else { return false; @@ -2080,7 +2080,7 @@ void PhysicalBone3D::_notification(int p_what) { } parent_skeleton = NULL; if (joint.is_valid()) { - PhysicsServer::get_singleton()->free(joint); + PhysicsServer3D::get_singleton()->free(joint); joint = RID(); } break; @@ -2101,10 +2101,10 @@ void PhysicalBone3D::_direct_state_changed(Object *p_state) { /// Update bone transform - PhysicsDirectBodyState *state; + PhysicsDirectBodyState3D *state; #ifdef DEBUG_ENABLED - state = Object::cast_to(p_state); + state = Object::cast_to(p_state); #else state = (PhysicsDirectBodyState *)p_state; //trust it #endif @@ -2197,7 +2197,7 @@ void PhysicalBone3D::_fix_joint_offset() { void PhysicalBone3D::_reload_joint() { if (joint.is_valid()) { - PhysicsServer::get_singleton()->free(joint); + PhysicsServer3D::get_singleton()->free(joint); joint = RID(); } @@ -2217,78 +2217,78 @@ void PhysicalBone3D::_reload_joint() { switch (get_joint_type()) { case JOINT_TYPE_PIN: { - joint = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin); + joint = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a.origin, get_rid(), joint_offset.origin); const PinJointData *pjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_BIAS, pjd->bias); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_DAMPING, pjd->damping); - PhysicsServer::get_singleton()->pin_joint_set_param(joint, PhysicsServer::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp); + PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_BIAS, pjd->bias); + PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_DAMPING, pjd->damping); + PhysicsServer3D::get_singleton()->pin_joint_set_param(joint, PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP, pjd->impulse_clamp); } break; case JOINT_TYPE_CONE: { - joint = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset); + joint = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, get_rid(), joint_offset); const ConeJointData *cjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_BIAS, cjd->bias); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_SOFTNESS, cjd->softness); - PhysicsServer::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN, cjd->swing_span); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN, cjd->twist_span); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_BIAS, cjd->bias); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS, cjd->softness); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(joint, PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION, cjd->relaxation); } break; case JOINT_TYPE_HINGE: { - joint = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset); + joint = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, get_rid(), joint_offset); const HingeJointData *hjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness); - PhysicsServer::get_singleton()->hinge_joint_set_param(joint, PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation); + PhysicsServer3D::get_singleton()->hinge_joint_set_flag(joint, PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, hjd->angular_limit_enabled); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, hjd->angular_limit_upper); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, hjd->angular_limit_lower); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, hjd->angular_limit_bias); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, hjd->angular_limit_softness); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(joint, PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, hjd->angular_limit_relaxation); } break; case JOINT_TYPE_SLIDER: { - joint = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset); + joint = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, get_rid(), joint_offset); const SliderJointData *sjd(static_cast(joint_data)); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); - PhysicsServer::get_singleton()->slider_joint_set_param(joint, PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, sjd->linear_limit_upper); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, sjd->linear_limit_lower); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, sjd->linear_limit_softness); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, sjd->linear_limit_restitution); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, sjd->linear_limit_restitution); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, sjd->angular_limit_upper); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, sjd->angular_limit_lower); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, sjd->angular_limit_softness); + PhysicsServer3D::get_singleton()->slider_joint_set_param(joint, PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, sjd->angular_limit_damping); } break; case JOINT_TYPE_6DOF: { - joint = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset); + joint = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, get_rid(), joint_offset); const SixDOFJointData *g6dofjd(static_cast(joint_data)); for (int axis = 0; axis < 3; ++axis) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, g6dofjd->axis_data[axis].linear_limit_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, g6dofjd->axis_data[axis].linear_limit_upper); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, g6dofjd->axis_data[axis].linear_limit_lower); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].linear_limit_softness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, g6dofjd->axis_data[axis].linear_spring_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].linear_spring_stiffness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, g6dofjd->axis_data[axis].linear_spring_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].linear_equilibrium_point); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, g6dofjd->axis_data[axis].linear_restitution); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, g6dofjd->axis_data[axis].linear_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, g6dofjd->axis_data[axis].angular_limit_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, g6dofjd->axis_data[axis].angular_limit_upper); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, g6dofjd->axis_data[axis].angular_limit_lower); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, g6dofjd->axis_data[axis].angular_limit_softness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, g6dofjd->axis_data[axis].angular_restitution); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, g6dofjd->axis_data[axis].angular_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, g6dofjd->axis_data[axis].erp); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, g6dofjd->axis_data[axis].angular_spring_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, g6dofjd->axis_data[axis].angular_spring_stiffness); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, g6dofjd->axis_data[axis].angular_spring_damping); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(joint, static_cast(axis), PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, g6dofjd->axis_data[axis].angular_equilibrium_point); } } break; @@ -2441,7 +2441,7 @@ void PhysicalBone3D::set_mass(real_t p_mass) { ERR_FAIL_COND(p_mass <= 0); mass = p_mass; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_MASS, mass); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_MASS, mass); } real_t PhysicalBone3D::get_mass() const { @@ -2464,7 +2464,7 @@ void PhysicalBone3D::set_friction(real_t p_friction) { ERR_FAIL_COND(p_friction < 0 || p_friction > 1); friction = p_friction; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_FRICTION, friction); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_FRICTION, friction); } real_t PhysicalBone3D::get_friction() const { @@ -2477,7 +2477,7 @@ void PhysicalBone3D::set_bounce(real_t p_bounce) { ERR_FAIL_COND(p_bounce < 0 || p_bounce > 1); bounce = p_bounce; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_BOUNCE, bounce); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_BOUNCE, bounce); } real_t PhysicalBone3D::get_bounce() const { @@ -2488,7 +2488,7 @@ real_t PhysicalBone3D::get_bounce() const { void PhysicalBone3D::set_gravity_scale(real_t p_gravity_scale) { gravity_scale = p_gravity_scale; - PhysicsServer::get_singleton()->body_set_param(get_rid(), PhysicsServer::BODY_PARAM_GRAVITY_SCALE, gravity_scale); + PhysicsServer3D::get_singleton()->body_set_param(get_rid(), PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE, gravity_scale); } real_t PhysicalBone3D::get_gravity_scale() const { @@ -2497,7 +2497,7 @@ real_t PhysicalBone3D::get_gravity_scale() const { } PhysicalBone3D::PhysicalBone3D() : - PhysicsBody3D(PhysicsServer::BODY_MODE_STATIC), + PhysicsBody3D(PhysicsServer3D::BODY_MODE_STATIC), #ifdef TOOLS_ENABLED gizmo_move_joint(false), #endif @@ -2566,10 +2566,10 @@ void PhysicalBone3D::_start_physics_simulation() { return; } reset_to_rest_position(); - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_RIGID); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_RIGID); + PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); set_as_toplevel(true); _internal_simulate_physics = true; } @@ -2579,16 +2579,16 @@ void PhysicalBone3D::_stop_physics_simulation() { return; } if (parent_skeleton->get_animate_physical_bones()) { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_KINEMATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_KINEMATIC); + PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), get_collision_layer()); + PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), get_collision_mask()); } else { - PhysicsServer::get_singleton()->body_set_mode(get_rid(), PhysicsServer::BODY_MODE_STATIC); - PhysicsServer::get_singleton()->body_set_collision_layer(get_rid(), 0); - PhysicsServer::get_singleton()->body_set_collision_mask(get_rid(), 0); + PhysicsServer3D::get_singleton()->body_set_mode(get_rid(), PhysicsServer3D::BODY_MODE_STATIC); + PhysicsServer3D::get_singleton()->body_set_collision_layer(get_rid(), 0); + PhysicsServer3D::get_singleton()->body_set_collision_mask(get_rid(), 0); } if (_internal_simulate_physics) { - PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); + PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), NULL, ""); parent_skeleton->set_bone_global_pose_override(bone_id, Transform(), 0.0, false); set_as_toplevel(false); _internal_simulate_physics = false; diff --git a/scene/3d/physics_body_3d.h b/scene/3d/physics_body_3d.h index e7a403122b..ed7cfa8733 100644 --- a/scene/3d/physics_body_3d.h +++ b/scene/3d/physics_body_3d.h @@ -34,7 +34,7 @@ #include "core/vset.h" #include "scene/3d/collision_object_3d.h" #include "scene/resources/physics_material.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" #include "skeleton_3d.h" class PhysicsBody3D : public CollisionObject3D { @@ -49,7 +49,7 @@ class PhysicsBody3D : public CollisionObject3D { protected: static void _bind_methods(); - PhysicsBody3D(PhysicsServer::BodyMode p_mode); + PhysicsBody3D(PhysicsServer3D::BodyMode p_mode); public: virtual Vector3 get_linear_velocity() const; @@ -118,7 +118,7 @@ public: protected: bool can_sleep; - PhysicsDirectBodyState *state; + PhysicsDirectBodyState3D *state; Mode mode; real_t mass; @@ -234,8 +234,8 @@ public: void set_use_continuous_collision_detection(bool p_enable); bool is_using_continuous_collision_detection() const; - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); - bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; + void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock); + bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const; Array get_colliding_bodies() const; @@ -296,7 +296,7 @@ private: Vector> slide_colliders; Ref motion_cache; - _FORCE_INLINE_ bool _ignores_mode(PhysicsServer::BodyMode) const; + _FORCE_INLINE_ bool _ignores_mode(PhysicsServer3D::BodyMode) const; Ref _move(const Vector3 &p_motion, bool p_infinite_inertia = true, bool p_exclude_raycast_shapes = true, bool p_test_only = false); Ref _get_slide_collision(int p_bounce); @@ -316,8 +316,8 @@ public: bool separate_raycast_shapes(bool p_infinite_inertia, Collision &r_collision); - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool p_lock); - bool get_axis_lock(PhysicsServer::BodyAxis p_axis) const; + void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool p_lock); + bool get_axis_lock(PhysicsServer3D::BodyAxis p_axis) const; void set_safe_margin(float p_margin); float get_safe_margin() const; @@ -381,7 +381,7 @@ public: struct JointData { virtual JointType get_joint_type() { return JOINT_TYPE_NONE; } - /// "j" is used to set the parameter inside the PhysicsServer + /// "j" is used to set the parameter inside the PhysicsServer3D virtual bool _set(const StringName &p_name, const Variant &p_value, RID j = RID()); virtual bool _get(const StringName &p_name, Variant &r_ret) const; virtual void _get_property_list(List *p_list) const; diff --git a/scene/3d/physics_joint_3d.cpp b/scene/3d/physics_joint_3d.cpp index dd7868cb38..f6b3e79300 100644 --- a/scene/3d/physics_joint_3d.cpp +++ b/scene/3d/physics_joint_3d.cpp @@ -34,9 +34,9 @@ void Joint3D::_update_joint(bool p_only_free) { if (joint.is_valid()) { if (ba.is_valid() && bb.is_valid()) - PhysicsServer::get_singleton()->body_remove_collision_exception(ba, bb); + PhysicsServer3D::get_singleton()->body_remove_collision_exception(ba, bb); - PhysicsServer::get_singleton()->free(joint); + PhysicsServer3D::get_singleton()->free(joint); joint = RID(); ba = RID(); bb = RID(); @@ -62,13 +62,13 @@ void Joint3D::_update_joint(bool p_only_free) { if (!joint.is_valid()) return; - PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); + PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority); ba = body_a->get_rid(); if (body_b) bb = body_b->get_rid(); - PhysicsServer::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); + PhysicsServer3D::get_singleton()->joint_disable_collisions_between_bodies(joint, exclude_from_collision); } void Joint3D::set_node_a(const NodePath &p_node_a) { @@ -101,7 +101,7 @@ void Joint3D::set_solver_priority(int p_priority) { solver_priority = p_priority; if (joint.is_valid()) - PhysicsServer::get_singleton()->joint_set_solver_priority(joint, solver_priority); + PhysicsServer3D::get_singleton()->joint_set_solver_priority(joint, solver_priority); } int Joint3D::get_solver_priority() const { @@ -186,7 +186,7 @@ void PinJoint3D::set_param(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, 3); params[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer::PinJointParam(p_param), p_value); + PhysicsServer3D::get_singleton()->pin_joint_set_param(get_joint(), PhysicsServer3D::PinJointParam(p_param), p_value); } float PinJoint3D::get_param(Param p_param) const { @@ -205,9 +205,9 @@ RID PinJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) { else local_b = pinpos; - RID j = PhysicsServer::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + RID j = PhysicsServer3D::get_singleton()->joint_create_pin(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); for (int i = 0; i < 3; i++) { - PhysicsServer::get_singleton()->pin_joint_set_param(j, PhysicsServer::PinJointParam(i), params[i]); + PhysicsServer3D::get_singleton()->pin_joint_set_param(j, PhysicsServer3D::PinJointParam(i), params[i]); } return j; } @@ -290,7 +290,7 @@ void HingeJoint3D::set_param(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer::HingeJointParam(p_param), p_value); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(get_joint(), PhysicsServer3D::HingeJointParam(p_param), p_value); update_gizmo(); } @@ -305,7 +305,7 @@ void HingeJoint3D::set_flag(Flag p_flag, bool p_value) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); flags[p_flag] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer::HingeJointFlag(p_flag), p_value); + PhysicsServer3D::get_singleton()->hinge_joint_set_flag(get_joint(), PhysicsServer3D::HingeJointFlag(p_flag), p_value); update_gizmo(); } @@ -331,13 +331,13 @@ RID HingeJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b) local_b.orthonormalize(); - RID j = PhysicsServer::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + RID j = PhysicsServer3D::get_singleton()->joint_create_hinge(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->hinge_joint_set_param(j, PhysicsServer::HingeJointParam(i), params[i]); + PhysicsServer3D::get_singleton()->hinge_joint_set_param(j, PhysicsServer3D::HingeJointParam(i), params[i]); } for (int i = 0; i < FLAG_MAX; i++) { set_flag(Flag(i), flags[i]); - PhysicsServer::get_singleton()->hinge_joint_set_flag(j, PhysicsServer::HingeJointFlag(i), flags[i]); + PhysicsServer3D::get_singleton()->hinge_joint_set_flag(j, PhysicsServer3D::HingeJointFlag(i), flags[i]); } return j; } @@ -448,7 +448,7 @@ void SliderJoint3D::set_param(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer::SliderJointParam(p_param), p_value); + PhysicsServer3D::get_singleton()->slider_joint_set_param(get_joint(), PhysicsServer3D::SliderJointParam(p_param), p_value); update_gizmo(); } float SliderJoint3D::get_param(Param p_param) const { @@ -473,9 +473,9 @@ RID SliderJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *body_b local_b.orthonormalize(); - RID j = PhysicsServer::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + RID j = PhysicsServer3D::get_singleton()->joint_create_slider(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->slider_joint_set_param(j, PhysicsServer::SliderJointParam(i), params[i]); + PhysicsServer3D::get_singleton()->slider_joint_set_param(j, PhysicsServer3D::SliderJointParam(i), params[i]); } return j; @@ -561,7 +561,7 @@ void ConeTwistJoint3D::set_param(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer::ConeTwistJointParam(p_param), p_value); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(get_joint(), PhysicsServer3D::ConeTwistJointParam(p_param), p_value); update_gizmo(); } @@ -590,9 +590,9 @@ RID ConeTwistJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *bod local_b.orthonormalize(); - RID j = PhysicsServer::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + RID j = PhysicsServer3D::get_singleton()->joint_create_cone_twist(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer::ConeTwistJointParam(i), params[i]); + PhysicsServer3D::get_singleton()->cone_twist_joint_set_param(j, PhysicsServer3D::ConeTwistJointParam(i), params[i]); } return j; @@ -832,7 +832,7 @@ void Generic6DOFJoint3D::set_param_x(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_x[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value); update_gizmo(); } @@ -847,7 +847,7 @@ void Generic6DOFJoint3D::set_param_y(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_y[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value); update_gizmo(); } float Generic6DOFJoint3D::get_param_y(Param p_param) const { @@ -861,7 +861,7 @@ void Generic6DOFJoint3D::set_param_z(Param p_param, float p_value) { ERR_FAIL_INDEX(p_param, PARAM_MAX); params_z[p_param] = p_value; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(p_param), p_value); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(p_param), p_value); update_gizmo(); } float Generic6DOFJoint3D::get_param_z(Param p_param) const { @@ -875,7 +875,7 @@ void Generic6DOFJoint3D::set_flag_x(Flag p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); flags_x[p_flag] = p_enabled; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled); update_gizmo(); } bool Generic6DOFJoint3D::get_flag_x(Flag p_flag) const { @@ -889,7 +889,7 @@ void Generic6DOFJoint3D::set_flag_y(Flag p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); flags_y[p_flag] = p_enabled; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled); update_gizmo(); } bool Generic6DOFJoint3D::get_flag_y(Flag p_flag) const { @@ -903,7 +903,7 @@ void Generic6DOFJoint3D::set_flag_z(Flag p_flag, bool p_enabled) { ERR_FAIL_INDEX(p_flag, FLAG_MAX); flags_z[p_flag] = p_enabled; if (get_joint().is_valid()) - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(p_flag), p_enabled); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(get_joint(), Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(p_flag), p_enabled); update_gizmo(); } bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const { @@ -915,7 +915,7 @@ bool Generic6DOFJoint3D::get_flag_z(Flag p_flag) const { void Generic6DOFJoint3D::set_precision(int p_precision) { precision = p_precision; - PhysicsServer::get_singleton()->generic_6dof_joint_set_precision( + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_precision( get_joint(), precision); } @@ -939,16 +939,16 @@ RID Generic6DOFJoint3D::_configure_joint(PhysicsBody3D *body_a, PhysicsBody3D *b local_b.orthonormalize(); - RID j = PhysicsServer::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); + RID j = PhysicsServer3D::get_singleton()->joint_create_generic_6dof(body_a->get_rid(), local_a, body_b ? body_b->get_rid() : RID(), local_b); for (int i = 0; i < PARAM_MAX; i++) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisParam(i), params_x[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisParam(i), params_y[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisParam(i), params_z[i]); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisParam(i), params_x[i]); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisParam(i), params_y[i]); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_param(j, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisParam(i), params_z[i]); } for (int i = 0; i < FLAG_MAX; i++) { - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_X, PhysicsServer::G6DOFJointAxisFlag(i), flags_x[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Y, PhysicsServer::G6DOFJointAxisFlag(i), flags_y[i]); - PhysicsServer::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Z, PhysicsServer::G6DOFJointAxisFlag(i), flags_z[i]); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_X, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_x[i]); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Y, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_y[i]); + PhysicsServer3D::get_singleton()->generic_6dof_joint_set_flag(j, Vector3::AXIS_Z, PhysicsServer3D::G6DOFJointAxisFlag(i), flags_z[i]); } return j; diff --git a/scene/3d/physics_joint_3d.h b/scene/3d/physics_joint_3d.h index b7c131c666..ce0c7af5d1 100644 --- a/scene/3d/physics_joint_3d.h +++ b/scene/3d/physics_joint_3d.h @@ -82,9 +82,9 @@ class PinJoint3D : public Joint3D { public: enum Param { - PARAM_BIAS = PhysicsServer::PIN_JOINT_BIAS, - PARAM_DAMPING = PhysicsServer::PIN_JOINT_DAMPING, - PARAM_IMPULSE_CLAMP = PhysicsServer::PIN_JOINT_IMPULSE_CLAMP + PARAM_BIAS = PhysicsServer3D::PIN_JOINT_BIAS, + PARAM_DAMPING = PhysicsServer3D::PIN_JOINT_DAMPING, + PARAM_IMPULSE_CLAMP = PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP }; protected: @@ -107,21 +107,21 @@ class HingeJoint3D : public Joint3D { public: enum Param { - PARAM_BIAS = PhysicsServer::HINGE_JOINT_BIAS, - PARAM_LIMIT_UPPER = PhysicsServer::HINGE_JOINT_LIMIT_UPPER, - PARAM_LIMIT_LOWER = PhysicsServer::HINGE_JOINT_LIMIT_LOWER, - PARAM_LIMIT_BIAS = PhysicsServer::HINGE_JOINT_LIMIT_BIAS, - PARAM_LIMIT_SOFTNESS = PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS, - PARAM_LIMIT_RELAXATION = PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION, - PARAM_MOTOR_TARGET_VELOCITY = PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY, - PARAM_MOTOR_MAX_IMPULSE = PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE, - PARAM_MAX = PhysicsServer::HINGE_JOINT_MAX + PARAM_BIAS = PhysicsServer3D::HINGE_JOINT_BIAS, + PARAM_LIMIT_UPPER = PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER, + PARAM_LIMIT_LOWER = PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER, + PARAM_LIMIT_BIAS = PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS, + PARAM_LIMIT_SOFTNESS = PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS, + PARAM_LIMIT_RELAXATION = PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION, + PARAM_MOTOR_TARGET_VELOCITY = PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY, + PARAM_MOTOR_MAX_IMPULSE = PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE, + PARAM_MAX = PhysicsServer3D::HINGE_JOINT_MAX }; enum Flag { - FLAG_USE_LIMIT = PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT, - FLAG_ENABLE_MOTOR = PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR, - FLAG_MAX = PhysicsServer::HINGE_JOINT_FLAG_MAX + FLAG_USE_LIMIT = PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT, + FLAG_ENABLE_MOTOR = PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR, + FLAG_MAX = PhysicsServer3D::HINGE_JOINT_FLAG_MAX }; protected: @@ -155,30 +155,30 @@ class SliderJoint3D : public Joint3D { public: enum Param { - PARAM_LINEAR_LIMIT_UPPER = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER, - PARAM_LINEAR_LIMIT_LOWER = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER, - PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, - PARAM_LINEAR_LIMIT_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, - PARAM_LINEAR_LIMIT_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, - PARAM_LINEAR_MOTION_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, - PARAM_LINEAR_MOTION_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, - PARAM_LINEAR_MOTION_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING, - PARAM_LINEAR_ORTHOGONAL_SOFTNESS = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, - PARAM_LINEAR_ORTHOGONAL_RESTITUTION = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, - PARAM_LINEAR_ORTHOGONAL_DAMPING = PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, - - PARAM_ANGULAR_LIMIT_UPPER = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, - PARAM_ANGULAR_LIMIT_LOWER = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, - PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, - PARAM_ANGULAR_LIMIT_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, - PARAM_ANGULAR_LIMIT_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, - PARAM_ANGULAR_MOTION_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, - PARAM_ANGULAR_MOTION_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, - PARAM_ANGULAR_MOTION_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING, - PARAM_ANGULAR_ORTHOGONAL_SOFTNESS = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, - PARAM_ANGULAR_ORTHOGONAL_RESTITUTION = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, - PARAM_ANGULAR_ORTHOGONAL_DAMPING = PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, - PARAM_MAX = PhysicsServer::SLIDER_JOINT_MAX + PARAM_LINEAR_LIMIT_UPPER = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER, + PARAM_LINEAR_LIMIT_LOWER = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER, + PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, + PARAM_LINEAR_LIMIT_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, + PARAM_LINEAR_LIMIT_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING, + PARAM_LINEAR_MOTION_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, + PARAM_LINEAR_MOTION_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, + PARAM_LINEAR_MOTION_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING, + PARAM_LINEAR_ORTHOGONAL_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, + PARAM_LINEAR_ORTHOGONAL_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, + PARAM_LINEAR_ORTHOGONAL_DAMPING = PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, + + PARAM_ANGULAR_LIMIT_UPPER = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER, + PARAM_ANGULAR_LIMIT_LOWER = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER, + PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, + PARAM_ANGULAR_LIMIT_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, + PARAM_ANGULAR_LIMIT_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, + PARAM_ANGULAR_MOTION_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, + PARAM_ANGULAR_MOTION_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, + PARAM_ANGULAR_MOTION_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING, + PARAM_ANGULAR_ORTHOGONAL_SOFTNESS = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, + PARAM_ANGULAR_ORTHOGONAL_RESTITUTION = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, + PARAM_ANGULAR_ORTHOGONAL_DAMPING = PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, + PARAM_MAX = PhysicsServer3D::SLIDER_JOINT_MAX }; @@ -244,39 +244,39 @@ class Generic6DOFJoint3D : public Joint3D { public: enum Param { - PARAM_LINEAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT, - PARAM_LINEAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT, - PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, - PARAM_LINEAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION, - PARAM_LINEAR_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING, - PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, - PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, - PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, - PARAM_LINEAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING, - PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, - PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, - PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, - PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, - PARAM_ANGULAR_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING, - PARAM_ANGULAR_RESTITUTION = PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION, - PARAM_ANGULAR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT, - PARAM_ANGULAR_ERP = PhysicsServer::G6DOF_JOINT_ANGULAR_ERP, - PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, - PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, - PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, - PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, - PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, - PARAM_MAX = PhysicsServer::G6DOF_JOINT_MAX, + PARAM_LINEAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT, + PARAM_LINEAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT, + PARAM_LINEAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, + PARAM_LINEAR_RESTITUTION = PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION, + PARAM_LINEAR_DAMPING = PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING, + PARAM_LINEAR_MOTOR_TARGET_VELOCITY = PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, + PARAM_LINEAR_MOTOR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, + PARAM_LINEAR_SPRING_STIFFNESS = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, + PARAM_LINEAR_SPRING_DAMPING = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING, + PARAM_LINEAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, + PARAM_ANGULAR_LOWER_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT, + PARAM_ANGULAR_UPPER_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT, + PARAM_ANGULAR_LIMIT_SOFTNESS = PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, + PARAM_ANGULAR_DAMPING = PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING, + PARAM_ANGULAR_RESTITUTION = PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION, + PARAM_ANGULAR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT, + PARAM_ANGULAR_ERP = PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP, + PARAM_ANGULAR_MOTOR_TARGET_VELOCITY = PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, + PARAM_ANGULAR_MOTOR_FORCE_LIMIT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, + PARAM_ANGULAR_SPRING_STIFFNESS = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, + PARAM_ANGULAR_SPRING_DAMPING = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING, + PARAM_ANGULAR_SPRING_EQUILIBRIUM_POINT = PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, + PARAM_MAX = PhysicsServer3D::G6DOF_JOINT_MAX, }; enum Flag { - FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, - FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, - FLAG_ENABLE_LINEAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, - FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, - FLAG_ENABLE_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR, - FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, - FLAG_MAX = PhysicsServer::G6DOF_JOINT_FLAG_MAX + FLAG_ENABLE_LINEAR_LIMIT = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, + FLAG_ENABLE_ANGULAR_LIMIT = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, + FLAG_ENABLE_LINEAR_SPRING = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, + FLAG_ENABLE_ANGULAR_SPRING = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, + FLAG_ENABLE_MOTOR = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR, + FLAG_ENABLE_LINEAR_MOTOR = PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, + FLAG_MAX = PhysicsServer3D::G6DOF_JOINT_FLAG_MAX }; protected: diff --git a/scene/3d/ray_cast_3d.cpp b/scene/3d/ray_cast_3d.cpp index e22c44a3a2..d00af3b128 100644 --- a/scene/3d/ray_cast_3d.cpp +++ b/scene/3d/ray_cast_3d.cpp @@ -33,7 +33,7 @@ #include "collision_object_3d.h" #include "core/engine.h" #include "mesh_instance_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" void RayCast3D::set_cast_to(const Vector3 &p_point) { @@ -199,7 +199,7 @@ void RayCast3D::_update_raycast_state() { Ref w3d = get_world(); ERR_FAIL_COND(w3d.is_null()); - PhysicsDirectSpaceState *dss = PhysicsServer::get_singleton()->space_get_direct_state(w3d->get_space()); + PhysicsDirectSpaceState3D *dss = PhysicsServer3D::get_singleton()->space_get_direct_state(w3d->get_space()); ERR_FAIL_COND(!dss); Transform gt = get_global_transform(); @@ -208,7 +208,7 @@ void RayCast3D::_update_raycast_state() { if (to == Vector3()) to = Vector3(0, 0.01, 0); - PhysicsDirectSpaceState::RayResult rr; + PhysicsDirectSpaceState3D::RayResult rr; if (dss->intersect_ray(gt.get_origin(), gt.xform(to), rr, exclude, collision_mask, collide_with_bodies, collide_with_areas)) { diff --git a/scene/3d/reflection_probe.cpp b/scene/3d/reflection_probe.cpp index 3cf8e43ec2..24bf8b43d1 100644 --- a/scene/3d/reflection_probe.cpp +++ b/scene/3d/reflection_probe.cpp @@ -33,7 +33,7 @@ void ReflectionProbe::set_intensity(float p_intensity) { intensity = p_intensity; - VS::get_singleton()->reflection_probe_set_intensity(probe, p_intensity); + RS::get_singleton()->reflection_probe_set_intensity(probe, p_intensity); } float ReflectionProbe::get_intensity() const { @@ -44,12 +44,12 @@ float ReflectionProbe::get_intensity() const { void ReflectionProbe::set_interior_ambient(Color p_ambient) { interior_ambient = p_ambient; - VS::get_singleton()->reflection_probe_set_interior_ambient(probe, p_ambient); + RS::get_singleton()->reflection_probe_set_interior_ambient(probe, p_ambient); } void ReflectionProbe::set_interior_ambient_energy(float p_energy) { interior_ambient_energy = p_energy; - VS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe, p_energy); + RS::get_singleton()->reflection_probe_set_interior_ambient_energy(probe, p_energy); } float ReflectionProbe::get_interior_ambient_energy() const { @@ -64,7 +64,7 @@ Color ReflectionProbe::get_interior_ambient() const { void ReflectionProbe::set_interior_ambient_probe_contribution(float p_contribution) { interior_ambient_probe_contribution = p_contribution; - VS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe, p_contribution); + RS::get_singleton()->reflection_probe_set_interior_ambient_probe_contribution(probe, p_contribution); } float ReflectionProbe::get_interior_ambient_probe_contribution() const { @@ -75,7 +75,7 @@ float ReflectionProbe::get_interior_ambient_probe_contribution() const { void ReflectionProbe::set_max_distance(float p_distance) { max_distance = p_distance; - VS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance); + RS::get_singleton()->reflection_probe_set_max_distance(probe, p_distance); } float ReflectionProbe::get_max_distance() const { @@ -97,8 +97,8 @@ void ReflectionProbe::set_extents(const Vector3 &p_extents) { } } - VS::get_singleton()->reflection_probe_set_extents(probe, extents); - VS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); + RS::get_singleton()->reflection_probe_set_extents(probe, extents); + RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); _change_notify("extents"); update_gizmo(); } @@ -117,8 +117,8 @@ void ReflectionProbe::set_origin_offset(const Vector3 &p_extents) { origin_offset[i] = SGN(origin_offset[i]) * (extents[i] - 0.01); } } - VS::get_singleton()->reflection_probe_set_extents(probe, extents); - VS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); + RS::get_singleton()->reflection_probe_set_extents(probe, extents); + RS::get_singleton()->reflection_probe_set_origin_offset(probe, origin_offset); _change_notify("origin_offset"); update_gizmo(); @@ -131,7 +131,7 @@ Vector3 ReflectionProbe::get_origin_offset() const { void ReflectionProbe::set_enable_box_projection(bool p_enable) { box_projection = p_enable; - VS::get_singleton()->reflection_probe_set_enable_box_projection(probe, p_enable); + RS::get_singleton()->reflection_probe_set_enable_box_projection(probe, p_enable); } bool ReflectionProbe::is_box_projection_enabled() const { @@ -141,7 +141,7 @@ bool ReflectionProbe::is_box_projection_enabled() const { void ReflectionProbe::set_as_interior(bool p_enable) { interior = p_enable; - VS::get_singleton()->reflection_probe_set_as_interior(probe, interior); + RS::get_singleton()->reflection_probe_set_as_interior(probe, interior); _change_notify(); } @@ -153,7 +153,7 @@ bool ReflectionProbe::is_set_as_interior() const { void ReflectionProbe::set_enable_shadows(bool p_enable) { enable_shadows = p_enable; - VS::get_singleton()->reflection_probe_set_enable_shadows(probe, p_enable); + RS::get_singleton()->reflection_probe_set_enable_shadows(probe, p_enable); } bool ReflectionProbe::are_shadows_enabled() const { @@ -163,7 +163,7 @@ bool ReflectionProbe::are_shadows_enabled() const { void ReflectionProbe::set_cull_mask(uint32_t p_layers) { cull_mask = p_layers; - VS::get_singleton()->reflection_probe_set_cull_mask(probe, p_layers); + RS::get_singleton()->reflection_probe_set_cull_mask(probe, p_layers); } uint32_t ReflectionProbe::get_cull_mask() const { @@ -172,7 +172,7 @@ uint32_t ReflectionProbe::get_cull_mask() const { void ReflectionProbe::set_update_mode(UpdateMode p_mode) { update_mode = p_mode; - VS::get_singleton()->reflection_probe_set_update_mode(probe, VS::ReflectionProbeUpdateMode(p_mode)); + RS::get_singleton()->reflection_probe_set_update_mode(probe, RS::ReflectionProbeUpdateMode(p_mode)); } ReflectionProbe::UpdateMode ReflectionProbe::get_update_mode() const { @@ -272,12 +272,12 @@ ReflectionProbe::ReflectionProbe() { cull_mask = (1 << 20) - 1; update_mode = UPDATE_ONCE; - probe = VisualServer::get_singleton()->reflection_probe_create(); - VS::get_singleton()->instance_set_base(get_instance(), probe); + probe = RenderingServer::get_singleton()->reflection_probe_create(); + RS::get_singleton()->instance_set_base(get_instance(), probe); set_disable_scale(true); } ReflectionProbe::~ReflectionProbe() { - VS::get_singleton()->free(probe); + RS::get_singleton()->free(probe); } diff --git a/scene/3d/reflection_probe.h b/scene/3d/reflection_probe.h index 9cc0c3e8c7..3867d13435 100644 --- a/scene/3d/reflection_probe.h +++ b/scene/3d/reflection_probe.h @@ -34,7 +34,7 @@ #include "scene/3d/visual_instance_3d.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class ReflectionProbe : public VisualInstance3D { GDCLASS(ReflectionProbe, VisualInstance3D); diff --git a/scene/3d/skeleton_3d.cpp b/scene/3d/skeleton_3d.cpp index 1ea6647d61..1b05641c9d 100644 --- a/scene/3d/skeleton_3d.cpp +++ b/scene/3d/skeleton_3d.cpp @@ -62,7 +62,7 @@ SkinReference::~SkinReference() { skeleton_node->skin_bindings.erase(this); } - VS::get_singleton()->free(skeleton); + RS::get_singleton()->free(skeleton); } bool Skeleton3D::_set(const StringName &p_path, const Variant &p_value) { @@ -227,7 +227,7 @@ void Skeleton3D::_notification(int p_what) { case NOTIFICATION_UPDATE_SKELETON: { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); Bone *bonesptr = bones.ptrw(); int len = bones.size(); @@ -320,7 +320,7 @@ void Skeleton3D::_notification(int p_what) { uint32_t bind_count = skin->get_bind_count(); if (E->get()->bind_count != bind_count) { - VS::get_singleton()->skeleton_allocate(skeleton, bind_count); + RS::get_singleton()->skeleton_allocate(skeleton, bind_count); E->get()->bind_count = bind_count; E->get()->skin_bone_indices.resize(bind_count); E->get()->skin_bone_indices_ptrs = E->get()->skin_bone_indices.ptrw(); @@ -802,9 +802,9 @@ void _physical_bones_add_remove_collision_exception(bool p_add, Node *p_node, RI CollisionObject3D *co = Object::cast_to(p_node); if (co) { if (p_add) { - PhysicsServer::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception); + PhysicsServer3D::get_singleton()->body_add_collision_exception(co->get_rid(), p_exception); } else { - PhysicsServer::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception); + PhysicsServer3D::get_singleton()->body_remove_collision_exception(co->get_rid(), p_exception); } } } @@ -871,7 +871,7 @@ Ref Skeleton3D::register_skin(const Ref &p_skin) { skin_ref->skeleton_node = this; skin_ref->bind_count = 0; - skin_ref->skeleton = VisualServer::get_singleton()->skeleton_create(); + skin_ref->skeleton = RenderingServer::get_singleton()->skeleton_create(); skin_ref->skeleton_node = this; skin_ref->skin = skin; diff --git a/scene/3d/soft_body_3d.cpp b/scene/3d/soft_body_3d.cpp index 6c93c3c1c7..ee9ce1dd71 100644 --- a/scene/3d/soft_body_3d.cpp +++ b/scene/3d/soft_body_3d.cpp @@ -36,11 +36,11 @@ #include "scene/3d/collision_object_3d.h" #include "scene/3d/physics_body_3d.h" #include "scene/3d/skeleton_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" -SoftBodyVisualServerHandler::SoftBodyVisualServerHandler() {} +SoftBodyRenderingServerHandler::SoftBodyRenderingServerHandler() {} -void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) { +void SoftBodyRenderingServerHandler::prepare(RID p_mesh, int p_surface) { clear(); ERR_FAIL_COND(!p_mesh.is_valid()); @@ -51,19 +51,19 @@ void SoftBodyVisualServerHandler::prepare(RID p_mesh, int p_surface) { #warning Softbody is not working, needs to be redone considering that these functions no longer exist #endif #if 0 - const uint32_t surface_format = VS::get_singleton()->mesh_surface_get_format(mesh, surface); - const int surface_vertex_len = VS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); - const int surface_index_len = VS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); - uint32_t surface_offsets[VS::ARRAY_MAX]; - - buffer = VS::get_singleton()->mesh_surface_get_array(mesh, surface); - stride = VS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); - offset_vertices = surface_offsets[VS::ARRAY_VERTEX]; - offset_normal = surface_offsets[VS::ARRAY_NORMAL]; + const uint32_t surface_format = RS::get_singleton()->mesh_surface_get_format(mesh, surface); + const int surface_vertex_len = RS::get_singleton()->mesh_surface_get_array_len(mesh, p_surface); + const int surface_index_len = RS::get_singleton()->mesh_surface_get_array_index_len(mesh, p_surface); + uint32_t surface_offsets[RS::ARRAY_MAX]; + + buffer = RS::get_singleton()->mesh_surface_get_array(mesh, surface); + stride = RS::get_singleton()->mesh_surface_make_offsets_from_format(surface_format, surface_vertex_len, surface_index_len, surface_offsets); + offset_vertices = surface_offsets[RS::ARRAY_VERTEX]; + offset_normal = surface_offsets[RS::ARRAY_NORMAL]; #endif } -void SoftBodyVisualServerHandler::clear() { +void SoftBodyRenderingServerHandler::clear() { if (mesh.is_valid()) { buffer.resize(0); @@ -72,28 +72,28 @@ void SoftBodyVisualServerHandler::clear() { mesh = RID(); } -void SoftBodyVisualServerHandler::open() { +void SoftBodyRenderingServerHandler::open() { write_buffer = buffer.ptrw(); } -void SoftBodyVisualServerHandler::close() { +void SoftBodyRenderingServerHandler::close() { //write_buffer.release(); } -void SoftBodyVisualServerHandler::commit_changes() { - VS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); +void SoftBodyRenderingServerHandler::commit_changes() { + RS::get_singleton()->mesh_surface_update_region(mesh, surface, 0, buffer); } -void SoftBodyVisualServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { +void SoftBodyRenderingServerHandler::set_vertex(int p_vertex_id, const void *p_vector3) { copymem(&write_buffer[p_vertex_id * stride + offset_vertices], p_vector3, sizeof(float) * 3); } -void SoftBodyVisualServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { +void SoftBodyRenderingServerHandler::set_normal(int p_vertex_id, const void *p_vector3) { copymem(&write_buffer[p_vertex_id * stride + offset_normal], p_vector3, sizeof(float) * 3); } -void SoftBodyVisualServerHandler::set_aabb(const AABB &p_aabb) { - VS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); +void SoftBodyRenderingServerHandler::set_aabb(const AABB &p_aabb) { + RS::get_singleton()->mesh_set_custom_aabb(mesh, p_aabb); } SoftBody3D::PinnedPoint::PinnedPoint() : @@ -120,7 +120,7 @@ void SoftBody3D::_update_pickable() { if (!is_inside_tree()) return; bool pickable = ray_pickable && is_visible_in_tree(); - PhysicsServer::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); + PhysicsServer3D::get_singleton()->soft_body_set_ray_pickable(physics_rid, pickable); } bool SoftBody3D::_set(const StringName &p_name, const Variant &p_value) { @@ -270,7 +270,7 @@ void SoftBody3D::_notification(int p_what) { } RID space = get_world()->get_space(); - PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, space); + PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, space); prepare_physics_server(); } break; case NOTIFICATION_READY: { @@ -285,10 +285,10 @@ void SoftBody3D::_notification(int p_what) { return; } - PhysicsServer::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); + PhysicsServer3D::get_singleton()->soft_body_set_transform(physics_rid, get_global_transform()); set_notify_transform(false); - // Required to be top level with Transform at center of world in order to modify VisualServer only to support custom Transform + // Required to be top level with Transform at center of world in order to modify RenderingServer only to support custom Transform set_as_toplevel(true); set_transform(Transform()); set_notify_transform(true); @@ -301,7 +301,7 @@ void SoftBody3D::_notification(int p_what) { } break; case NOTIFICATION_EXIT_WORLD: { - PhysicsServer::get_singleton()->soft_body_set_space(physics_rid, RID()); + PhysicsServer3D::get_singleton()->soft_body_set_space(physics_rid, RID()); } break; } @@ -418,7 +418,7 @@ void SoftBody3D::_update_physics_server() { const PinnedPoint *r = pinned_points.ptr(); for (int i = 0; i < pinned_points_indices_size; ++i) { if (r[i].spatial_attachment) { - PhysicsServer::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); + PhysicsServer3D::get_singleton()->soft_body_move_point(physics_rid, r[i].point_index, r[i].spatial_attachment->get_global_transform().xform(r[i].offset)); } } } @@ -427,9 +427,9 @@ void SoftBody3D::_draw_soft_mesh() { if (get_mesh().is_null()) return; - if (!visual_server_handler.is_ready()) { + if (!rendering_server_handler.is_ready()) { - visual_server_handler.prepare(get_mesh()->get_rid(), 0); + rendering_server_handler.prepare(get_mesh()->get_rid(), 0); /// Necessary in order to render the mesh correctly (Soft body nodes are in global space) simulation_started = true; @@ -439,11 +439,11 @@ void SoftBody3D::_draw_soft_mesh() { _update_physics_server(); - visual_server_handler.open(); - PhysicsServer::get_singleton()->soft_body_update_visual_server(physics_rid, &visual_server_handler); - visual_server_handler.close(); + rendering_server_handler.open(); + PhysicsServer3D::get_singleton()->soft_body_update_rendering_server(physics_rid, &rendering_server_handler); + rendering_server_handler.close(); - visual_server_handler.commit_changes(); + rendering_server_handler.commit_changes(); } void SoftBody3D::prepare_physics_server() { @@ -451,9 +451,9 @@ void SoftBody3D::prepare_physics_server() { if (Engine::get_singleton()->is_editor_hint()) { if (get_mesh().is_valid()) - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); else - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, NULL); return; } @@ -461,13 +461,13 @@ void SoftBody3D::prepare_physics_server() { if (get_mesh().is_valid()) { become_mesh_owner(); - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); - VS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, get_mesh()); + RS::get_singleton()->connect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); } else { - PhysicsServer::get_singleton()->soft_body_set_mesh(physics_rid, NULL); - if (VS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) { - VS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); + PhysicsServer3D::get_singleton()->soft_body_set_mesh(physics_rid, NULL); + if (RS::get_singleton()->is_connected("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh))) { + RS::get_singleton()->disconnect("frame_pre_draw", callable_mp(this, &SoftBody3D::_draw_soft_mesh)); } } } @@ -508,7 +508,7 @@ void SoftBody3D::become_mesh_owner() { void SoftBody3D::set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; - PhysicsServer::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); + PhysicsServer3D::get_singleton()->soft_body_set_collision_mask(physics_rid, p_mask); } uint32_t SoftBody3D::get_collision_mask() const { @@ -516,7 +516,7 @@ uint32_t SoftBody3D::get_collision_mask() const { } void SoftBody3D::set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; - PhysicsServer::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); + PhysicsServer3D::get_singleton()->soft_body_set_collision_layer(physics_rid, p_layer); } uint32_t SoftBody3D::get_collision_layer() const { @@ -570,11 +570,11 @@ Vector SoftBody3D::get_pinned_points_indices() { Array SoftBody3D::get_collision_exceptions() { List exceptions; - PhysicsServer::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); + PhysicsServer3D::get_singleton()->soft_body_get_collision_exceptions(physics_rid, &exceptions); Array ret; for (List::Element *E = exceptions.front(); E; E = E->next()) { RID body = E->get(); - ObjectID instance_id = PhysicsServer::get_singleton()->body_get_object_instance_id(body); + ObjectID instance_id = PhysicsServer3D::get_singleton()->body_get_object_instance_id(body); Object *obj = ObjectDB::get_instance(instance_id); PhysicsBody3D *physics_body = Object::cast_to(obj); ret.append(physics_body); @@ -586,90 +586,90 @@ void SoftBody3D::add_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); + PhysicsServer3D::get_singleton()->soft_body_add_collision_exception(physics_rid, collision_object->get_rid()); } void SoftBody3D::remove_collision_exception_with(Node *p_node) { ERR_FAIL_NULL(p_node); CollisionObject3D *collision_object = Object::cast_to(p_node); ERR_FAIL_COND_MSG(!collision_object, "Collision exception only works between two CollisionObject."); - PhysicsServer::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); + PhysicsServer3D::get_singleton()->soft_body_remove_collision_exception(physics_rid, collision_object->get_rid()); } int SoftBody3D::get_simulation_precision() { - return PhysicsServer::get_singleton()->soft_body_get_simulation_precision(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_simulation_precision(physics_rid); } void SoftBody3D::set_simulation_precision(int p_simulation_precision) { - PhysicsServer::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); + PhysicsServer3D::get_singleton()->soft_body_set_simulation_precision(physics_rid, p_simulation_precision); } real_t SoftBody3D::get_total_mass() { - return PhysicsServer::get_singleton()->soft_body_get_total_mass(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_total_mass(physics_rid); } void SoftBody3D::set_total_mass(real_t p_total_mass) { - PhysicsServer::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); + PhysicsServer3D::get_singleton()->soft_body_set_total_mass(physics_rid, p_total_mass); } void SoftBody3D::set_linear_stiffness(real_t p_linear_stiffness) { - PhysicsServer::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); + PhysicsServer3D::get_singleton()->soft_body_set_linear_stiffness(physics_rid, p_linear_stiffness); } real_t SoftBody3D::get_linear_stiffness() { - return PhysicsServer::get_singleton()->soft_body_get_linear_stiffness(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_linear_stiffness(physics_rid); } void SoftBody3D::set_areaAngular_stiffness(real_t p_areaAngular_stiffness) { - PhysicsServer::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness); + PhysicsServer3D::get_singleton()->soft_body_set_areaAngular_stiffness(physics_rid, p_areaAngular_stiffness); } real_t SoftBody3D::get_areaAngular_stiffness() { - return PhysicsServer::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_areaAngular_stiffness(physics_rid); } void SoftBody3D::set_volume_stiffness(real_t p_volume_stiffness) { - PhysicsServer::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); + PhysicsServer3D::get_singleton()->soft_body_set_volume_stiffness(physics_rid, p_volume_stiffness); } real_t SoftBody3D::get_volume_stiffness() { - return PhysicsServer::get_singleton()->soft_body_get_volume_stiffness(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_volume_stiffness(physics_rid); } real_t SoftBody3D::get_pressure_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_pressure_coefficient(physics_rid); } void SoftBody3D::set_pose_matching_coefficient(real_t p_pose_matching_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); + PhysicsServer3D::get_singleton()->soft_body_set_pose_matching_coefficient(physics_rid, p_pose_matching_coefficient); } real_t SoftBody3D::get_pose_matching_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_pose_matching_coefficient(physics_rid); } void SoftBody3D::set_pressure_coefficient(real_t p_pressure_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); + PhysicsServer3D::get_singleton()->soft_body_set_pressure_coefficient(physics_rid, p_pressure_coefficient); } real_t SoftBody3D::get_damping_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_damping_coefficient(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_damping_coefficient(physics_rid); } void SoftBody3D::set_damping_coefficient(real_t p_damping_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); + PhysicsServer3D::get_singleton()->soft_body_set_damping_coefficient(physics_rid, p_damping_coefficient); } real_t SoftBody3D::get_drag_coefficient() { - return PhysicsServer::get_singleton()->soft_body_get_drag_coefficient(physics_rid); + return PhysicsServer3D::get_singleton()->soft_body_get_drag_coefficient(physics_rid); } void SoftBody3D::set_drag_coefficient(real_t p_drag_coefficient) { - PhysicsServer::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); + PhysicsServer3D::get_singleton()->soft_body_set_drag_coefficient(physics_rid, p_drag_coefficient); } Vector3 SoftBody3D::get_point_transform(int p_point_index) { - return PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); + return PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, p_point_index); } void SoftBody3D::pin_point_toggle(int p_point_index) { @@ -701,7 +701,7 @@ bool SoftBody3D::is_ray_pickable() const { } SoftBody3D::SoftBody3D() : - physics_rid(PhysicsServer::get_singleton()->soft_body_create()), + physics_rid(PhysicsServer3D::get_singleton()->soft_body_create()), mesh_owner(false), collision_mask(1), collision_layer(1), @@ -709,18 +709,18 @@ SoftBody3D::SoftBody3D() : pinned_points_cache_dirty(true), ray_pickable(true) { - PhysicsServer::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); + PhysicsServer3D::get_singleton()->body_attach_object_instance_id(physics_rid, get_instance_id()); } SoftBody3D::~SoftBody3D() { - PhysicsServer::get_singleton()->free(physics_rid); + PhysicsServer3D::get_singleton()->free(physics_rid); } void SoftBody3D::reset_softbody_pin() { - PhysicsServer::get_singleton()->soft_body_remove_all_pinned_points(physics_rid); + PhysicsServer3D::get_singleton()->soft_body_remove_all_pinned_points(physics_rid); const PinnedPoint *pps = pinned_points.ptr(); for (int i = pinned_points.size() - 1; 0 < i; --i) { - PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true); + PhysicsServer3D::get_singleton()->soft_body_pin_point(physics_rid, pps[i].point_index, true); } } @@ -747,7 +747,7 @@ void SoftBody3D::_update_cache_pin_points_datas() { } void SoftBody3D::_pin_point_on_physics_server(int p_point_index, bool pin) { - PhysicsServer::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); + PhysicsServer3D::get_singleton()->soft_body_pin_point(physics_rid, p_point_index, pin); } void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_attachment_path) { @@ -761,7 +761,7 @@ void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_ if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) { pp.spatial_attachment = Object::cast_to(get_node(p_spatial_attachment_path)); - pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index)); + pp.offset = (pp.spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, pp.point_index)); } pinned_points.push_back(pp); @@ -773,7 +773,7 @@ void SoftBody3D::_add_pinned_point(int p_point_index, const NodePath &p_spatial_ if (!p_spatial_attachment_path.is_empty() && has_node(p_spatial_attachment_path)) { pinned_point->spatial_attachment = Object::cast_to(get_node(p_spatial_attachment_path)); - pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index)); + pinned_point->offset = (pinned_point->spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, pinned_point->point_index)); } } } @@ -793,7 +793,7 @@ void SoftBody3D::_reset_points_offsets() { if (!r[i].spatial_attachment) continue; - w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index)); + w[i].offset = (r[i].spatial_attachment->get_global_transform().affine_inverse() * get_global_transform()).xform(PhysicsServer3D::get_singleton()->soft_body_get_point_global_position(physics_rid, r[i].point_index)); } } diff --git a/scene/3d/soft_body_3d.h b/scene/3d/soft_body_3d.h index a1a4b4fa2f..7dd5880985 100644 --- a/scene/3d/soft_body_3d.h +++ b/scene/3d/soft_body_3d.h @@ -35,7 +35,7 @@ class SoftBody3D; -class SoftBodyVisualServerHandler { +class SoftBodyRenderingServerHandler { friend class SoftBody3D; @@ -49,7 +49,7 @@ class SoftBodyVisualServerHandler { uint8_t *write_buffer; private: - SoftBodyVisualServerHandler(); + SoftBodyRenderingServerHandler(); bool is_ready() { return mesh.is_valid(); } void prepare(RID p_mesh_rid, int p_surface); void clear(); @@ -79,7 +79,7 @@ public: }; private: - SoftBodyVisualServerHandler visual_server_handler; + SoftBodyRenderingServerHandler rendering_server_handler; RID physics_rid; diff --git a/scene/3d/spring_arm_3d.cpp b/scene/3d/spring_arm_3d.cpp index 1856171539..281be3f7d3 100644 --- a/scene/3d/spring_arm_3d.cpp +++ b/scene/3d/spring_arm_3d.cpp @@ -32,7 +32,7 @@ #include "core/engine.h" #include "scene/3d/collision_object_3d.h" #include "scene/resources/sphere_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" SpringArm3D::SpringArm3D() : spring_length(1), @@ -146,7 +146,7 @@ void SpringArm3D::process_spring() { if (shape.is_null()) { motion = Vector3(cast_direction * (spring_length)); - PhysicsDirectSpaceState::RayResult r; + PhysicsDirectSpaceState3D::RayResult r; bool intersected = get_world()->get_direct_space_state()->intersect_ray(get_global_transform().origin, get_global_transform().origin + motion, r, excluded_objects, mask); if (intersected) { float dist = get_global_transform().origin.distance_to(r.position); diff --git a/scene/3d/sprite_3d.cpp b/scene/3d/sprite_3d.cpp index fd22076091..360e95e76a 100644 --- a/scene/3d/sprite_3d.cpp +++ b/scene/3d/sprite_3d.cpp @@ -377,13 +377,13 @@ SpriteBase3D::SpriteBase3D() { modulate = Color(1, 1, 1, 1); pending_update = false; opacity = 1.0; - immediate = VisualServer::get_singleton()->immediate_create(); + immediate = RenderingServer::get_singleton()->immediate_create(); set_base(immediate); } SpriteBase3D::~SpriteBase3D() { - VisualServer::get_singleton()->free(immediate); + RenderingServer::get_singleton()->free(immediate); } /////////////////////////////////////////// @@ -392,7 +392,7 @@ void Sprite3D::_draw() { RID immediate = get_immediate(); - VS::get_singleton()->immediate_clear(immediate); + RS::get_singleton()->immediate_clear(immediate); if (!texture.is_valid()) return; Vector2 tsize = texture->get_size(); @@ -475,9 +475,9 @@ void Sprite3D::_draw() { } RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y); - VS::get_singleton()->immediate_set_material(immediate, mat); + RS::get_singleton()->immediate_set_material(immediate, mat); - VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLES, texture->get_rid()); + RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid()); int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); @@ -502,15 +502,15 @@ void Sprite3D::_draw() { static const int index[6] = { 0, 1, 2, 0, 2, 3 }; - VS::get_singleton()->immediate_normal(immediate, normal); - VS::get_singleton()->immediate_tangent(immediate, tangent); - VS::get_singleton()->immediate_color(immediate, color); - VS::get_singleton()->immediate_uv(immediate, uvs[i]); + RS::get_singleton()->immediate_normal(immediate, normal); + RS::get_singleton()->immediate_tangent(immediate, tangent); + RS::get_singleton()->immediate_color(immediate, color); + RS::get_singleton()->immediate_uv(immediate, uvs[i]); Vector3 vtx; vtx[x_axis] = vertices[index[i]][0]; vtx[y_axis] = vertices[index[i]][1]; - VS::get_singleton()->immediate_vertex(immediate, vtx); + RS::get_singleton()->immediate_vertex(immediate, vtx); if (i == 0) { aabb.position = vtx; aabb.size = Vector3(); @@ -519,7 +519,7 @@ void Sprite3D::_draw() { } } set_aabb(aabb); - VS::get_singleton()->immediate_end(immediate); + RS::get_singleton()->immediate_end(immediate); } void Sprite3D::_texture_changed() { @@ -717,7 +717,7 @@ Sprite3D::Sprite3D() { void AnimatedSprite3D::_draw() { RID immediate = get_immediate(); - VS::get_singleton()->immediate_clear(immediate); + RS::get_singleton()->immediate_clear(immediate); if (frames.is_null()) { return; @@ -810,9 +810,9 @@ void AnimatedSprite3D::_draw() { RID mat = StandardMaterial3D::get_material_rid_for_2d(get_draw_flag(FLAG_SHADED), get_draw_flag(FLAG_TRANSPARENT), get_draw_flag(FLAG_DOUBLE_SIDED), get_alpha_cut_mode() == ALPHA_CUT_DISCARD, get_alpha_cut_mode() == ALPHA_CUT_OPAQUE_PREPASS, get_billboard_mode() == StandardMaterial3D::BILLBOARD_ENABLED, get_billboard_mode() == StandardMaterial3D::BILLBOARD_FIXED_Y); - VS::get_singleton()->immediate_set_material(immediate, mat); + RS::get_singleton()->immediate_set_material(immediate, mat); - VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_TRIANGLES, texture->get_rid()); + RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_TRIANGLES, texture->get_rid()); int x_axis = ((axis + 1) % 3); int y_axis = ((axis + 2) % 3); @@ -840,15 +840,15 @@ void AnimatedSprite3D::_draw() { 0, 2, 3 }; - VS::get_singleton()->immediate_normal(immediate, normal); - VS::get_singleton()->immediate_tangent(immediate, tangent); - VS::get_singleton()->immediate_color(immediate, color); - VS::get_singleton()->immediate_uv(immediate, uvs[i]); + RS::get_singleton()->immediate_normal(immediate, normal); + RS::get_singleton()->immediate_tangent(immediate, tangent); + RS::get_singleton()->immediate_color(immediate, color); + RS::get_singleton()->immediate_uv(immediate, uvs[i]); Vector3 vtx; vtx[x_axis] = vertices[indices[i]][0]; vtx[y_axis] = vertices[indices[i]][1]; - VS::get_singleton()->immediate_vertex(immediate, vtx); + RS::get_singleton()->immediate_vertex(immediate, vtx); if (i == 0) { aabb.position = vtx; aabb.size = Vector3(); @@ -857,7 +857,7 @@ void AnimatedSprite3D::_draw() { } } set_aabb(aabb); - VS::get_singleton()->immediate_end(immediate); + RS::get_singleton()->immediate_end(immediate); } void AnimatedSprite3D::_validate_property(PropertyInfo &property) const { diff --git a/scene/3d/vehicle_body_3d.cpp b/scene/3d/vehicle_body_3d.cpp index 5d601b0d43..5984b776b2 100644 --- a/scene/3d/vehicle_body_3d.cpp +++ b/scene/3d/vehicle_body_3d.cpp @@ -111,7 +111,7 @@ String VehicleWheel3D::get_configuration_warning() const { return String(); } -void VehicleWheel3D::_update(PhysicsDirectBodyState *s) { +void VehicleWheel3D::_update(PhysicsDirectBodyState3D *s) { if (m_raycastInfo.m_isInContact) @@ -388,7 +388,7 @@ VehicleWheel3D::VehicleWheel3D() { body = NULL; } -void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState *s) { +void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s) { wheel.m_raycastInfo.m_isInContact = false; @@ -405,7 +405,7 @@ void VehicleBody3D::_update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirect wheel.m_raycastInfo.m_wheelAxleWS = chassisTrans.get_basis().xform(wheel.m_wheelAxleCS).normalized(); } -void VehicleBody3D::_update_wheel(int p_idx, PhysicsDirectBodyState *s) { +void VehicleBody3D::_update_wheel(int p_idx, PhysicsDirectBodyState3D *s) { VehicleWheel3D &wheel = *wheels[p_idx]; _update_wheel_transform(wheel, s); @@ -430,7 +430,7 @@ void VehicleBody3D::_update_wheel(int p_idx, PhysicsDirectBodyState *s) { wheel.m_raycastInfo.m_hardPointWS + wheel.m_raycastInfo.m_wheelDirectionWS * wheel.m_raycastInfo.m_suspensionLength); } -real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState *s) { +real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState3D *s) { VehicleWheel3D &wheel = *wheels[p_idx]; @@ -448,9 +448,9 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState *s) { real_t param = real_t(0.); - PhysicsDirectSpaceState::RayResult rr; + PhysicsDirectSpaceState3D::RayResult rr; - PhysicsDirectSpaceState *ss = s->get_space_state(); + PhysicsDirectSpaceState3D *ss = s->get_space_state(); bool col = ss->intersect_ray(source, target, rr, exclude); @@ -513,7 +513,7 @@ real_t VehicleBody3D::_ray_cast(int p_idx, PhysicsDirectBodyState *s) { return depth; } -void VehicleBody3D::_update_suspension(PhysicsDirectBodyState *s) { +void VehicleBody3D::_update_suspension(PhysicsDirectBodyState3D *s) { real_t chassisMass = mass; @@ -558,7 +558,7 @@ void VehicleBody3D::_update_suspension(PhysicsDirectBodyState *s) { } //bilateral constraint between two dynamic objects -void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, +void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState3D *s, const Vector3 &pos1, PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence) { real_t normalLenSqr = normal.length_squared(); @@ -636,7 +636,7 @@ void VehicleBody3D::_resolve_single_bilateral(PhysicsDirectBodyState *s, const V #endif } -VehicleBody3D::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse) : +VehicleBody3D::btVehicleWheelContactPoint::btVehicleWheelContactPoint(PhysicsDirectBodyState3D *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse) : m_s(s), m_body1(body1), m_frictionPositionWorld(frictionPosWorld), @@ -698,7 +698,7 @@ real_t VehicleBody3D::_calc_rolling_friction(btVehicleWheelContactPoint &contact } static const real_t sideFrictionStiffness2 = real_t(1.0); -void VehicleBody3D::_update_friction(PhysicsDirectBodyState *s) { +void VehicleBody3D::_update_friction(PhysicsDirectBodyState3D *s) { //calculate the impulse, so that the wheels don't move sidewards int numWheel = wheels.size(); @@ -854,7 +854,7 @@ void VehicleBody3D::_direct_state_changed(Object *p_state) { RigidBody3D::_direct_state_changed(p_state); - state = Object::cast_to(p_state); + state = Object::cast_to(p_state); float step = state->get_step(); @@ -992,7 +992,7 @@ VehicleBody3D::VehicleBody3D() { ccd = false; exclude.insert(get_rid()); - //PhysicsServer::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); + //PhysicsServer3D::get_singleton()->body_set_force_integration_callback(get_rid(), this, "_direct_state_changed"); set_mass(40); } diff --git a/scene/3d/vehicle_body_3d.h b/scene/3d/vehicle_body_3d.h index 1ca9b6253f..d5e896263d 100644 --- a/scene/3d/vehicle_body_3d.h +++ b/scene/3d/vehicle_body_3d.h @@ -91,7 +91,7 @@ class VehicleWheel3D : public Node3D { PhysicsBody3D *m_groundObject; //could be general void* ptr } m_raycastInfo; - void _update(PhysicsDirectBodyState *s); + void _update(PhysicsDirectBodyState3D *s); protected: void _notification(int p_what); @@ -170,24 +170,24 @@ class VehicleBody3D : public RigidBody3D { Vector m_sideImpulse; struct btVehicleWheelContactPoint { - PhysicsDirectBodyState *m_s; + PhysicsDirectBodyState3D *m_s; PhysicsBody3D *m_body1; Vector3 m_frictionPositionWorld; Vector3 m_frictionDirectionWorld; real_t m_jacDiagABInv; real_t m_maxImpulse; - btVehicleWheelContactPoint(PhysicsDirectBodyState *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse); + btVehicleWheelContactPoint(PhysicsDirectBodyState3D *s, PhysicsBody3D *body1, const Vector3 &frictionPosWorld, const Vector3 &frictionDirectionWorld, real_t maxImpulse); }; - void _resolve_single_bilateral(PhysicsDirectBodyState *s, const Vector3 &pos1, PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence); + void _resolve_single_bilateral(PhysicsDirectBodyState3D *s, const Vector3 &pos1, PhysicsBody3D *body2, const Vector3 &pos2, const Vector3 &normal, real_t &impulse, const real_t p_rollInfluence); real_t _calc_rolling_friction(btVehicleWheelContactPoint &contactPoint); - void _update_friction(PhysicsDirectBodyState *s); - void _update_suspension(PhysicsDirectBodyState *s); - real_t _ray_cast(int p_idx, PhysicsDirectBodyState *s); - void _update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState *s); - void _update_wheel(int p_idx, PhysicsDirectBodyState *s); + void _update_friction(PhysicsDirectBodyState3D *s); + void _update_suspension(PhysicsDirectBodyState3D *s); + real_t _ray_cast(int p_idx, PhysicsDirectBodyState3D *s); + void _update_wheel_transform(VehicleWheel3D &wheel, PhysicsDirectBodyState3D *s); + void _update_wheel(int p_idx, PhysicsDirectBodyState3D *s); friend class VehicleWheel3D; Vector wheels; diff --git a/scene/3d/visual_instance_3d.cpp b/scene/3d/visual_instance_3d.cpp index 14a975c023..775a9b76e2 100644 --- a/scene/3d/visual_instance_3d.cpp +++ b/scene/3d/visual_instance_3d.cpp @@ -31,7 +31,7 @@ #include "visual_instance_3d.h" #include "scene/scene_string_names.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #include "skeleton_3d.h" AABB VisualInstance3D::get_transformed_aabb() const { @@ -45,7 +45,7 @@ void VisualInstance3D::_update_visibility() { return; _change_notify("visible"); - VS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree()); + RS::get_singleton()->instance_set_visible(get_instance(), is_visible_in_tree()); } void VisualInstance3D::_notification(int p_what) { @@ -58,23 +58,23 @@ void VisualInstance3D::_notification(int p_what) { /* Skeleton *skeleton=Object::cast_to(get_parent()); if (skeleton) - VisualServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() ); + RenderingServer::get_singleton()->instance_attach_skeleton( instance, skeleton->get_skeleton() ); */ ERR_FAIL_COND(get_world().is_null()); - VisualServer::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); + RenderingServer::get_singleton()->instance_set_scenario(instance, get_world()->get_scenario()); _update_visibility(); } break; case NOTIFICATION_TRANSFORM_CHANGED: { Transform gt = get_global_transform(); - VisualServer::get_singleton()->instance_set_transform(instance, gt); + RenderingServer::get_singleton()->instance_set_transform(instance, gt); } break; case NOTIFICATION_EXIT_WORLD: { - VisualServer::get_singleton()->instance_set_scenario(instance, RID()); - VisualServer::get_singleton()->instance_attach_skeleton(instance, RID()); - //VS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); + RenderingServer::get_singleton()->instance_set_scenario(instance, RID()); + RenderingServer::get_singleton()->instance_attach_skeleton(instance, RID()); + //RS::get_singleton()->instance_geometry_set_baked_light_sampler(instance, RID() ); } break; case NOTIFICATION_VISIBILITY_CHANGED: { @@ -97,7 +97,7 @@ RID VisualInstance3D::_get_visual_instance_rid() const { void VisualInstance3D::set_layer_mask(uint32_t p_mask) { layers = p_mask; - VisualServer::get_singleton()->instance_set_layer_mask(instance, p_mask); + RenderingServer::get_singleton()->instance_set_layer_mask(instance, p_mask); } uint32_t VisualInstance3D::get_layer_mask() const { @@ -137,7 +137,7 @@ void VisualInstance3D::_bind_methods() { void VisualInstance3D::set_base(const RID &p_base) { - VisualServer::get_singleton()->instance_set_base(instance, p_base); + RenderingServer::get_singleton()->instance_set_base(instance, p_base); base = p_base; } @@ -148,21 +148,21 @@ RID VisualInstance3D::get_base() const { VisualInstance3D::VisualInstance3D() { - instance = VisualServer::get_singleton()->instance_create(); - VisualServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id()); + instance = RenderingServer::get_singleton()->instance_create(); + RenderingServer::get_singleton()->instance_attach_object_instance_id(instance, get_instance_id()); layers = 1; set_notify_transform(true); } VisualInstance3D::~VisualInstance3D() { - VisualServer::get_singleton()->free(instance); + RenderingServer::get_singleton()->free(instance); } void GeometryInstance3D::set_material_override(const Ref &p_material) { material_override = p_material; - VS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID()); + RS::get_singleton()->instance_geometry_set_material_override(get_instance(), p_material.is_valid() ? p_material->get_rid() : RID()); } Ref GeometryInstance3D::get_material_override() const { @@ -173,7 +173,7 @@ Ref GeometryInstance3D::get_material_override() const { void GeometryInstance3D::set_lod_min_distance(float p_dist) { lod_min_distance = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); + RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); } float GeometryInstance3D::get_lod_min_distance() const { @@ -184,7 +184,7 @@ float GeometryInstance3D::get_lod_min_distance() const { void GeometryInstance3D::set_lod_max_distance(float p_dist) { lod_max_distance = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); + RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); } float GeometryInstance3D::get_lod_max_distance() const { @@ -195,7 +195,7 @@ float GeometryInstance3D::get_lod_max_distance() const { void GeometryInstance3D::set_lod_min_hysteresis(float p_dist) { lod_min_hysteresis = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); + RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); } float GeometryInstance3D::get_lod_min_hysteresis() const { @@ -206,7 +206,7 @@ float GeometryInstance3D::get_lod_min_hysteresis() const { void GeometryInstance3D::set_lod_max_hysteresis(float p_dist) { lod_max_hysteresis = p_dist; - VS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); + RS::get_singleton()->instance_geometry_set_draw_range(get_instance(), lod_min_distance, lod_max_distance, lod_min_hysteresis, lod_max_hysteresis); } float GeometryInstance3D::get_lod_max_hysteresis() const { @@ -224,7 +224,7 @@ void GeometryInstance3D::set_flag(Flags p_flag, bool p_value) { return; flags[p_flag] = p_value; - VS::get_singleton()->instance_geometry_set_flag(get_instance(), (VS::InstanceFlags)p_flag, p_value); + RS::get_singleton()->instance_geometry_set_flag(get_instance(), (RS::InstanceFlags)p_flag, p_value); } bool GeometryInstance3D::get_flag(Flags p_flag) const { @@ -238,7 +238,7 @@ void GeometryInstance3D::set_cast_shadows_setting(ShadowCastingSetting p_shadow_ shadow_casting_setting = p_shadow_casting_setting; - VS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (VS::ShadowCastingSetting)p_shadow_casting_setting); + RS::get_singleton()->instance_geometry_set_cast_shadows_setting(get_instance(), (RS::ShadowCastingSetting)p_shadow_casting_setting); } GeometryInstance3D::ShadowCastingSetting GeometryInstance3D::get_cast_shadows_setting() const { @@ -250,7 +250,7 @@ void GeometryInstance3D::set_extra_cull_margin(float p_margin) { ERR_FAIL_COND(p_margin < 0); extra_cull_margin = p_margin; - VS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin); + RS::get_singleton()->instance_set_extra_visibility_margin(get_instance(), extra_cull_margin); } float GeometryInstance3D::get_extra_cull_margin() const { @@ -260,7 +260,7 @@ float GeometryInstance3D::get_extra_cull_margin() const { void GeometryInstance3D::set_custom_aabb(AABB aabb) { - VS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb); + RS::get_singleton()->instance_set_custom_aabb(get_instance(), aabb); } void GeometryInstance3D::_bind_methods() { @@ -331,5 +331,5 @@ GeometryInstance3D::GeometryInstance3D() { shadow_casting_setting = SHADOW_CASTING_SETTING_ON; extra_cull_margin = 0; - //VS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0); + //RS::get_singleton()->instance_geometry_set_baked_light_texture_index(get_instance(),0); } diff --git a/scene/3d/visual_instance_3d.h b/scene/3d/visual_instance_3d.h index 59a935fdee..9476c28848 100644 --- a/scene/3d/visual_instance_3d.h +++ b/scene/3d/visual_instance_3d.h @@ -86,17 +86,17 @@ class GeometryInstance3D : public VisualInstance3D { public: enum Flags { - FLAG_USE_BAKED_LIGHT = VS::INSTANCE_FLAG_USE_BAKED_LIGHT, - FLAG_USE_DYNAMIC_GI = VS::INSTANCE_FLAG_USE_DYNAMIC_GI, - FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, - FLAG_MAX = VS::INSTANCE_FLAG_MAX, + FLAG_USE_BAKED_LIGHT = RS::INSTANCE_FLAG_USE_BAKED_LIGHT, + FLAG_USE_DYNAMIC_GI = RS::INSTANCE_FLAG_USE_DYNAMIC_GI, + FLAG_DRAW_NEXT_FRAME_IF_VISIBLE = RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, + FLAG_MAX = RS::INSTANCE_FLAG_MAX, }; enum ShadowCastingSetting { - SHADOW_CASTING_SETTING_OFF = VS::SHADOW_CASTING_SETTING_OFF, - SHADOW_CASTING_SETTING_ON = VS::SHADOW_CASTING_SETTING_ON, - SHADOW_CASTING_SETTING_DOUBLE_SIDED = VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED, - SHADOW_CASTING_SETTING_SHADOWS_ONLY = VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY + SHADOW_CASTING_SETTING_OFF = RS::SHADOW_CASTING_SETTING_OFF, + SHADOW_CASTING_SETTING_ON = RS::SHADOW_CASTING_SETTING_ON, + SHADOW_CASTING_SETTING_DOUBLE_SIDED = RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED, + SHADOW_CASTING_SETTING_SHADOWS_ONLY = RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY }; private: diff --git a/scene/animation/root_motion_view.cpp b/scene/animation/root_motion_view.cpp index ce9b8bd213..f993127b07 100644 --- a/scene/animation/root_motion_view.cpp +++ b/scene/animation/root_motion_view.cpp @@ -79,7 +79,7 @@ void RootMotionView::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - VS::get_singleton()->immediate_set_material(immediate, StandardMaterial3D::get_material_rid_for_2d(false, true, false, false, false)); + RS::get_singleton()->immediate_set_material(immediate, StandardMaterial3D::get_material_rid_for_2d(false, true, false, false, false)); first = true; } @@ -122,11 +122,11 @@ void RootMotionView::_notification(int p_what) { } accumulated.origin.z = Math::fposmod(accumulated.origin.z, cell_size); - VS::get_singleton()->immediate_clear(immediate); + RS::get_singleton()->immediate_clear(immediate); int cells_in_radius = int((radius / cell_size) + 1.0); - VS::get_singleton()->immediate_begin(immediate, VS::PRIMITIVE_LINES); + RS::get_singleton()->immediate_begin(immediate, RS::PRIMITIVE_LINES); for (int i = -cells_in_radius; i < cells_in_radius; i++) { for (int j = -cells_in_radius; j < cells_in_radius; j++) { @@ -142,21 +142,21 @@ void RootMotionView::_notification(int p_what) { c_i.a *= MAX(0, 1.0 - from_i.length() / radius); c_j.a *= MAX(0, 1.0 - from_j.length() / radius); - VS::get_singleton()->immediate_color(immediate, c); - VS::get_singleton()->immediate_vertex(immediate, from); + RS::get_singleton()->immediate_color(immediate, c); + RS::get_singleton()->immediate_vertex(immediate, from); - VS::get_singleton()->immediate_color(immediate, c_i); - VS::get_singleton()->immediate_vertex(immediate, from_i); + RS::get_singleton()->immediate_color(immediate, c_i); + RS::get_singleton()->immediate_vertex(immediate, from_i); - VS::get_singleton()->immediate_color(immediate, c); - VS::get_singleton()->immediate_vertex(immediate, from); + RS::get_singleton()->immediate_color(immediate, c); + RS::get_singleton()->immediate_vertex(immediate, from); - VS::get_singleton()->immediate_color(immediate, c_j); - VS::get_singleton()->immediate_vertex(immediate, from_j); + RS::get_singleton()->immediate_color(immediate, c_j); + RS::get_singleton()->immediate_vertex(immediate, from_j); } } - VS::get_singleton()->immediate_end(immediate); + RS::get_singleton()->immediate_end(immediate); } } @@ -197,12 +197,12 @@ RootMotionView::RootMotionView() { radius = 10; cell_size = 1; set_process_internal(true); - immediate = VisualServer::get_singleton()->immediate_create(); + immediate = RenderingServer::get_singleton()->immediate_create(); set_base(immediate); color = Color(0.5, 0.5, 1.0); } RootMotionView::~RootMotionView() { set_base(RID()); - VisualServer::get_singleton()->free(immediate); + RenderingServer::get_singleton()->free(immediate); } diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp index f71d322412..1f8487c173 100644 --- a/scene/gui/button.cpp +++ b/scene/gui/button.cpp @@ -31,7 +31,7 @@ #include "button.h" #include "core/translation.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" Size2 Button::get_minimum_size() const { diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp index d68bd4fe4e..470450e3ed 100644 --- a/scene/gui/check_box.cpp +++ b/scene/gui/check_box.cpp @@ -30,7 +30,7 @@ #include "check_box.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" Size2 CheckBox::get_icon_size() const { Ref checked = Control::get_theme_icon("checked"); diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp index ac967a128c..96484424f8 100644 --- a/scene/gui/check_button.cpp +++ b/scene/gui/check_button.cpp @@ -31,7 +31,7 @@ #include "check_button.h" #include "core/print_string.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" Size2 CheckButton::get_icon_size() const { diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index 14bca0e2c8..0d982dbc02 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -40,7 +40,7 @@ #include "scene/main/canvas_layer.h" #include "scene/main/window.h" #include "scene/scene_string_names.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #ifdef TOOLS_ENABLED #include "editor/editor_settings.h" @@ -470,7 +470,7 @@ void Control::_update_canvas_item_transform() { Transform2D xform = _get_internal_transform(); xform[2] += get_position(); - VisualServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); + RenderingServer::get_singleton()->canvas_item_set_transform(get_canvas_item(), xform); } void Control::_notification(int p_notification) { @@ -588,8 +588,8 @@ void Control::_notification(int p_notification) { case NOTIFICATION_DRAW: { _update_canvas_item_transform(); - VisualServer::get_singleton()->canvas_item_set_custom_rect(get_canvas_item(), !data.disable_visibility_clip, Rect2(Point2(), get_size())); - VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), data.clip_contents); + RenderingServer::get_singleton()->canvas_item_set_custom_rect(get_canvas_item(), !data.disable_visibility_clip, Rect2(Point2(), get_size())); + RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), data.clip_contents); //emit_signal(SceneStringNames::get_singleton()->draw); } break; diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp index 2db44d0b66..47a5ac68d2 100644 --- a/scene/gui/item_list.cpp +++ b/scene/gui/item_list.cpp @@ -859,9 +859,9 @@ void ItemList::_notification(int p_what) { } if (has_focus()) { - VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true); draw_style_box(get_theme_stylebox("bg_focus"), Rect2(Point2(), size)); - VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false); } if (shape_changed) { diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp index ef1bb958f6..1ffc9712cc 100644 --- a/scene/gui/label.cpp +++ b/scene/gui/label.cpp @@ -84,7 +84,7 @@ void Label::_notification(int p_what) { if (p_what == NOTIFICATION_DRAW) { if (clip) { - VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); + RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); } if (word_cache_dirty) @@ -105,7 +105,7 @@ void Label::_notification(int p_what) { style->draw(ci, Rect2(Point2(0, 0), get_size())); - VisualServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(), font.is_valid() && font->is_distance_field_hint()); + RenderingServer::get_singleton()->canvas_item_set_distance_field_mode(get_canvas_item(), font.is_valid() && font->is_distance_field_hint()); int font_h = font->get_height() + line_spacing; diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index 734e27b1b6..6c5f77f874 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -815,9 +815,9 @@ void LineEdit::_notification(int p_what) { bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; if (selected) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color); } drawer.draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color); @@ -839,7 +839,7 @@ void LineEdit::_notification(int p_what) { bool selected = selection.enabled && char_ofs >= selection.begin && char_ofs < selection.end; if (selected) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, caret_height)), selection_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(char_width, caret_height)), selection_color); int yofs = y_ofs + (caret_height - font->get_height()) / 2; drawer.draw_char(ci, Point2(x_ofs, yofs + font_ascent), cchar, next, selected ? font_color_selected : font_color); @@ -847,9 +847,9 @@ void LineEdit::_notification(int p_what) { if (char_ofs == cursor_pos && draw_caret && !using_placeholder) { if (ime_text.length() == 0) { #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); #endif } } @@ -874,9 +874,9 @@ void LineEdit::_notification(int p_what) { bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; if (selected) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 3)), font_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(x_ofs, y_ofs + caret_height), Size2(im_char_width, 1)), font_color); } drawer.draw_char(ci, Point2(x_ofs, y_ofs + font_ascent), cchar, next, font_color); @@ -905,9 +905,9 @@ void LineEdit::_notification(int p_what) { } } #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(Math::round(EDSCALE), caret_height)), cursor_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(caret_x_ofs, y_ofs), Size2(1, caret_height)), cursor_color); #endif } } diff --git a/scene/gui/nine_patch_rect.cpp b/scene/gui/nine_patch_rect.cpp index 0ef1f53006..cf10c4cfbd 100644 --- a/scene/gui/nine_patch_rect.cpp +++ b/scene/gui/nine_patch_rect.cpp @@ -30,7 +30,7 @@ #include "nine_patch_rect.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void NinePatchRect::_notification(int p_what) { @@ -45,7 +45,7 @@ void NinePatchRect::_notification(int p_what) { texture->get_rect_region(rect, src_rect, rect, src_rect); RID ci = get_canvas_item(); - VS::get_singleton()->canvas_item_add_nine_patch(ci, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NinePatchAxisMode(axis_h), VS::NinePatchAxisMode(axis_v), draw_center); + RS::get_singleton()->canvas_item_add_nine_patch(ci, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), RS::NinePatchAxisMode(axis_h), RS::NinePatchAxisMode(axis_v), draw_center); } } diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp index df28a4c12f..d17eec4050 100644 --- a/scene/gui/rich_text_label.cpp +++ b/scene/gui/rich_text_label.cpp @@ -603,7 +603,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & #ifdef TOOLS_ENABLED underline_width *= EDSCALE; #endif - VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, underline_width); + RS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, underline_width); } else if (strikethrough) { Color uc = color; uc.a *= 0.5; @@ -612,7 +612,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int & #ifdef TOOLS_ENABLED strikethrough_width *= EDSCALE; #endif - VS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, strikethrough_width); + RS::get_singleton()->canvas_item_add_line(ci, p_ofs + Point2(align_ofs + wofs, uy), p_ofs + Point2(align_ofs + wofs + w, uy), uc, strikethrough_width); } } @@ -991,9 +991,9 @@ void RichTextLabel::_notification(int p_what) { draw_style_box(get_theme_stylebox("normal"), Rect2(Point2(), size)); if (has_focus()) { - VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); draw_style_box(get_theme_stylebox("focus"), Rect2(Point2(), size)); - VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); } int ofs = vscroll->get_value(); diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index fb477ee3b4..7071652f2a 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -728,7 +728,7 @@ void TextEdit::_notification(int p_what) { _update_scrollbars(); RID ci = get_canvas_item(); - VisualServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); + RenderingServer::get_singleton()->canvas_item_set_clip(get_canvas_item(), true); int xmargin_beg = cache.style_normal->get_margin(MARGIN_LEFT) + cache.line_number_w + cache.breakpoint_gutter_width + cache.fold_gutter_width + cache.info_gutter_width; int xmargin_end = size.width - cache.style_normal->get_margin(MARGIN_RIGHT) - cache.minimap_width; @@ -749,14 +749,14 @@ void TextEdit::_notification(int p_what) { if (syntax_coloring) { if (cache.background_color.a > 0.01) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(), get_size()), cache.background_color); } } if (line_length_guidelines) { const int hard_x = xmargin_beg + (int)cache.font->get_char_size('0').width * line_length_guideline_hard_col - cursor.x_ofs; if (hard_x > xmargin_beg && hard_x < xmargin_end) { - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(hard_x, 0), Point2(hard_x, size.height), cache.line_length_guideline_color); + RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(hard_x, 0), Point2(hard_x, size.height), cache.line_length_guideline_color); } // Draw a "Soft" line length guideline, less visible than the hard line length guideline. @@ -764,7 +764,7 @@ void TextEdit::_notification(int p_what) { // Only drawn if its column differs from the hard line length guideline. const int soft_x = xmargin_beg + (int)cache.font->get_char_size('0').width * line_length_guideline_soft_col - cursor.x_ofs; if (hard_x != soft_x && soft_x > xmargin_beg && soft_x < xmargin_end) { - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2(soft_x, 0), Point2(soft_x, size.height), cache.line_length_guideline_color * Color(1, 1, 1, 0.5)); + RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2(soft_x, 0), Point2(soft_x, size.height), cache.line_length_guideline_color * Color(1, 1, 1, 0.5)); } } @@ -955,7 +955,7 @@ void TextEdit::_notification(int p_what) { // draw the minimap Color viewport_color = (cache.background_color.get_v() < 0.5) ? Color(1, 1, 1, 0.1) : Color(0, 0, 0, 0.1); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), viewport_offset_y, cache.minimap_width, viewport_height), viewport_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), viewport_offset_y, cache.minimap_width, viewport_height), viewport_color); for (int i = 0; i < minimap_draw_amount; i++) { minimap_line++; @@ -1008,7 +1008,7 @@ void TextEdit::_notification(int p_what) { } if (minimap_line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, cache.minimap_width, 2), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2((xmargin_end + 2), i * 3, cache.minimap_width, 2), cache.current_line_color); } Color previous_color; @@ -1057,7 +1057,7 @@ void TextEdit::_notification(int p_what) { // take one for zero indexing, and if we hit whitespace / the end of a word. int chars = MAX(0, (j - (characters - 1)) - (is_whitespace ? 1 : 0)) + 1; int char_x_ofs = indent_px + ((xmargin_end + minimap_char_size.x) + (minimap_char_size.x * chars)) + tabs; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_x_ofs, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), previous_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_x_ofs, minimap_line_height * i), Point2(minimap_char_size.x * characters, minimap_char_size.y)), previous_color); } if (out_of_bounds) { @@ -1164,24 +1164,24 @@ void TextEdit::_notification(int p_what) { } if (text.is_marked(line)) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.mark_color); } if (str.length() == 0) { // Draw line background if empty as we won't loop at at all. if (line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, get_row_height()), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(ofs_x, ofs_y, xmargin_end, get_row_height()), cache.current_line_color); } // Give visual indication of empty selected line. if (selection.active && line >= selection.from_line && line <= selection.to_line && char_margin >= xmargin_beg) { int char_w = cache.font->get_char_size(' ').width; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, get_row_height()), cache.selection_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, char_w, get_row_height()), cache.selection_color); } } else { // If it has text, then draw current line marker in the margin, as line number etc will draw over it, draw the rest of line marker later. if (line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_beg + ofs_x, get_row_height()), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(0, ofs_y, xmargin_beg + ofs_x, get_row_height()), cache.current_line_color); } } @@ -1190,9 +1190,9 @@ void TextEdit::_notification(int p_what) { if (text.is_breakpoint(line) && !draw_breakpoint_gutter) { #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.breakpoint_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.breakpoint_color); #endif } @@ -1202,7 +1202,7 @@ void TextEdit::_notification(int p_what) { int vertical_gap = (get_row_height() * 40) / 100; int horizontal_gap = (cache.breakpoint_gutter_width * 30) / 100; int marker_radius = get_row_height() - (vertical_gap * 2); - VisualServer::get_singleton()->canvas_item_add_circle(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2 + marker_radius / 2, ofs_y + vertical_gap + marker_radius / 2), marker_radius, Color(cache.bookmark_color.r, cache.bookmark_color.g, cache.bookmark_color.b)); + RenderingServer::get_singleton()->canvas_item_add_circle(ci, Point2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2 + marker_radius / 2, ofs_y + vertical_gap + marker_radius / 2), marker_radius, Color(cache.bookmark_color.r, cache.bookmark_color.g, cache.bookmark_color.b)); } } @@ -1214,7 +1214,7 @@ void TextEdit::_notification(int p_what) { int marker_height = get_row_height() - (vertical_gap * 2); int marker_width = cache.breakpoint_gutter_width - (horizontal_gap * 2); // No transparency on marker. - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2, ofs_y + vertical_gap, marker_width, marker_height), Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2, ofs_y + vertical_gap, marker_width, marker_height), Color(cache.breakpoint_color.r, cache.breakpoint_color.g, cache.breakpoint_color.b)); } } @@ -1254,9 +1254,9 @@ void TextEdit::_notification(int p_what) { cache.executing_icon->draw_rect(ci, Rect2(cache.style_normal->get_margin(MARGIN_LEFT) + horizontal_gap - 2 - icon_extra_size / 2, ofs_y + vertical_gap - icon_extra_size / 2, marker_width, marker_height), false, Color(cache.executing_line_color.r, cache.executing_line_color.g, cache.executing_line_color.b)); } else { #ifdef TOOLS_ENABLED - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.executing_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y + get_row_height() - EDSCALE, xmargin_end - xmargin_beg, EDSCALE), cache.executing_line_color); #else - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.executing_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - xmargin_beg, get_row_height()), cache.executing_line_color); #endif } } @@ -1315,10 +1315,10 @@ void TextEdit::_notification(int p_what) { if (j == str.length() - 1) { // End of line when last char is skipped. - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); } else if ((char_ofs + char_margin) > xmargin_beg) { // Char next to margin is skipped. - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, (char_ofs + char_margin) - (xmargin_beg + ofs_x), get_row_height()), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(xmargin_beg + ofs_x, ofs_y, (char_ofs + char_margin) - (xmargin_beg + ofs_x), get_row_height()), cache.current_line_color); } } continue; @@ -1338,7 +1338,7 @@ void TextEdit::_notification(int p_what) { in_search_result = j >= search_text_col && j < search_text_col + search_text.length(); if (in_search_result) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.search_result_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin, ofs_y), Size2i(char_w, get_row_height())), cache.search_result_color); } } @@ -1348,32 +1348,32 @@ void TextEdit::_notification(int p_what) { if (line == cursor.line && cursor_wrap_index == line_wrap_index && highlight_current_line) { // Draw the wrap indent offset highlight. if (line_wrap_index != 0 && j == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + ofs_x - indent_px, ofs_y, indent_px, get_row_height()), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + ofs_x - indent_px, ofs_y, indent_px, get_row_height()), cache.current_line_color); } // If its the last char draw to end of the line. if (j == str.length() - 1) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + char_w + ofs_x, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(char_ofs + char_margin + char_w + ofs_x, ofs_y, xmargin_end - (char_ofs + char_margin + char_w), get_row_height()), cache.current_line_color); } // Actual text. if (!in_selection) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.current_line_color); } } if (in_selection) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.selection_color); } if (in_search_result) { Color border_color = (line == search_result_line && j >= search_result_col && j < search_result_col + search_text.length()) ? cache.font_color : cache.search_result_border_color; - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, 1)), border_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y + get_row_height() - 1), Size2i(char_w, 1)), border_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, 1)), border_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y + get_row_height() - 1), Size2i(char_w, 1)), border_color); if (j == search_text_col) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(1, get_row_height())), border_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(1, get_row_height())), border_color); if (j == search_text_col + search_text.length() - 1) - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + char_w + ofs_x - 1, ofs_y), Size2i(1, get_row_height())), border_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + char_w + ofs_x - 1, ofs_y), Size2i(1, get_row_height())), border_color); } if (highlight_all_occurrences && !only_whitespaces_highlighted) { @@ -1392,7 +1392,7 @@ void TextEdit::_notification(int p_what) { } if (in_highlighted_word) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.word_highlighted_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2i(char_ofs + char_margin + ofs_x, ofs_y), Size2i(char_w, get_row_height())), cache.word_highlighted_color); } } } @@ -1449,9 +1449,9 @@ void TextEdit::_notification(int p_what) { bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; if (selected) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); } drawer.draw_char(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + ascent), cchar, next, color); @@ -1468,7 +1468,7 @@ void TextEdit::_notification(int p_what) { #else int caret_h = (block_caret) ? 4 : 2; #endif - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, caret_h)), cache.caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, caret_h)), cache.caret_color); } else { #ifdef TOOLS_ENABLED caret_w = (block_caret) ? caret_w : 2 * EDSCALE; @@ -1476,7 +1476,7 @@ void TextEdit::_notification(int p_what) { caret_w = (block_caret) ? caret_w : 2; #endif - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, cache.font->get_height())), cache.caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, cache.font->get_height())), cache.caret_color); } } } @@ -1544,9 +1544,9 @@ void TextEdit::_notification(int p_what) { bool selected = ofs >= ime_selection.x && ofs < ime_selection.x + ime_selection.y; if (selected) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 3)), color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(char_ofs + char_margin, ofs_y + get_row_height()), Size2(im_char_width, 1)), color); } drawer.draw_char(ci, Point2(char_ofs + char_margin + ofs_x, ofs_y + ascent), cchar, next, color); @@ -1564,7 +1564,7 @@ void TextEdit::_notification(int p_what) { #else int caret_h = (block_caret) ? 4 : 2; #endif - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(char_w, caret_h)), cache.caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(char_w, caret_h)), cache.caret_color); } else { int char_w = cache.font->get_char_size(' ').width; #ifdef TOOLS_ENABLED @@ -1573,7 +1573,7 @@ void TextEdit::_notification(int p_what) { int caret_w = (block_caret) ? char_w : 2; #endif - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, cache.font->get_height())), cache.caret_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(cursor_pos, Size2i(caret_w, cache.font->get_height())), cache.caret_color); } } } @@ -1634,10 +1634,10 @@ void TextEdit::_notification(int p_what) { draw_style_box(csb, Rect2(completion_rect.position - csb->get_offset(), completion_rect.size + csb->get_minimum_size() + Size2(scrollw, 0))); if (cache.completion_background_color.a > 0.01) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.position, completion_rect.size + Size2(scrollw, 0)), cache.completion_background_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(completion_rect.position, completion_rect.size + Size2(scrollw, 0)), cache.completion_background_color); } int line_from = CLAMP(completion_index - lines / 2, 0, completion_options_size - lines); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.position.x, completion_rect.position.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(Point2(completion_rect.position.x, completion_rect.position.y + (completion_index - line_from) * get_row_height()), Size2(completion_rect.size.width, get_row_height())), cache.completion_selected_color); draw_rect(Rect2(completion_rect.position + Vector2(icon_area_size.x + icon_hsep, 0), Size2(MIN(nofs, completion_rect.size.width - (icon_area_size.x + icon_hsep)), completion_rect.size.height)), cache.completion_existing_color); for (int i = 0; i < lines; i++) { diff --git a/scene/gui/texture_progress.cpp b/scene/gui/texture_progress.cpp index abf6b2ed49..0dd43e4a35 100644 --- a/scene/gui/texture_progress.cpp +++ b/scene/gui/texture_progress.cpp @@ -300,7 +300,7 @@ void TextureProgress::draw_nine_patch_stretched(const Ref &p_texture, p_texture->get_rect_region(dst_rect, src_rect, dst_rect, src_rect); RID ci = get_canvas_item(); - VS::get_singleton()->canvas_item_add_nine_patch(ci, dst_rect, src_rect, p_texture->get_rid(), topleft, bottomright, VS::NINE_PATCH_STRETCH, VS::NINE_PATCH_STRETCH, true, p_modulate); + RS::get_singleton()->canvas_item_add_nine_patch(ci, dst_rect, src_rect, p_texture->get_rid(), topleft, bottomright, RS::NINE_PATCH_STRETCH, RS::NINE_PATCH_STRETCH, true, p_modulate); } void TextureProgress::_notification(int p_what) { diff --git a/scene/gui/texture_rect.cpp b/scene/gui/texture_rect.cpp index 6dafd3bf4f..baa138847f 100644 --- a/scene/gui/texture_rect.cpp +++ b/scene/gui/texture_rect.cpp @@ -30,7 +30,7 @@ #include "texture_rect.h" #include "core/core_string_names.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void TextureRect::_notification(int p_what) { diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp index 653ac74164..87425b49cd 100644 --- a/scene/gui/tree.cpp +++ b/scene/gui/tree.cpp @@ -1220,7 +1220,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 } if (cache.draw_guides) { - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); + RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(cell_rect.position.x, cell_rect.position.y + cell_rect.size.height), cell_rect.position + cell_rect.size, cache.guide_color, 1); } if (i == 0) { @@ -1266,12 +1266,12 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 r.size.x += cache.hseparation; } if (p_item->cells[i].custom_bg_outline) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), p_item->cells[i].bg_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y - 1, r.size.x, 1), p_item->cells[i].bg_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), p_item->cells[i].bg_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), p_item->cells[i].bg_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), p_item->cells[i].bg_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y - 1, r.size.x, 1), p_item->cells[i].bg_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), p_item->cells[i].bg_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), p_item->cells[i].bg_color); } else { - VisualServer::get_singleton()->canvas_item_add_rect(ci, r, p_item->cells[i].bg_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, r, p_item->cells[i].bg_color); } } @@ -1280,16 +1280,16 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 Rect2 r = cell_rect; if (drop_mode_section == -1 || drop_mode_section == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, r.size.x, 1), cache.drop_position_color); } if (drop_mode_section == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), cache.drop_position_color); - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), cache.drop_position_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y, 1, r.size.y), cache.drop_position_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x + r.size.x - 1, r.position.y, 1, r.size.y), cache.drop_position_color); } if (drop_mode_section == 1 || drop_mode_section == 0) { - VisualServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), cache.drop_position_color); + RenderingServer::get_singleton()->canvas_item_add_rect(ci, Rect2(r.position.x, r.position.y + r.size.y, r.size.x, 1), cache.drop_position_color); } } @@ -1509,8 +1509,8 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 Point2i parent_pos = Point2i(parent_ofs - cache.arrow->get_width() / 2, p_pos.y + label_h / 2 + cache.arrow->get_height() / 2) - cache.offset + p_draw_ofs; if (root_pos.y + line_width >= 0) { - VisualServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width); - VisualServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width); + RenderingServer::get_singleton()->canvas_item_add_line(ci, root_pos, Point2i(parent_pos.x - Math::floor(line_width / 2), root_pos.y), cache.relationship_line_color, line_width); + RenderingServer::get_singleton()->canvas_item_add_line(ci, Point2i(parent_pos.x, root_pos.y), Point2i(parent_pos.x, prev_ofs), cache.relationship_line_color, line_width); } if (htotal < 0) { @@ -3030,9 +3030,9 @@ void Tree::_notification(int p_what) { bg->draw(ci, Rect2(Point2(), get_size())); if (has_focus()) { - VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, true); bg_focus->draw(ci, Rect2(Point2(), get_size())); - VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); + RenderingServer::get_singleton()->canvas_item_add_clip_ignore(ci, false); } int tbh = _get_title_button_height(); diff --git a/scene/main/canvas_item.cpp b/scene/main/canvas_item.cpp index 7a0fc3352b..4a415415f1 100644 --- a/scene/main/canvas_item.cpp +++ b/scene/main/canvas_item.cpp @@ -40,8 +40,7 @@ #include "scene/resources/style_box.h" #include "scene/resources/texture.h" #include "scene/scene_string_names.h" -#include "servers/visual/visual_server_raster.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" Mutex CanvasItemMaterial::material_mutex; SelfList::List *CanvasItemMaterial::dirty_materials = NULL; @@ -78,7 +77,7 @@ void CanvasItemMaterial::_update_shader() { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } } @@ -87,7 +86,7 @@ void CanvasItemMaterial::_update_shader() { if (shader_map.has(mk)) { - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); shader_map[mk].users++; return; } @@ -138,14 +137,14 @@ void CanvasItemMaterial::_update_shader() { } ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.shader = RS::get_singleton()->shader_create(); shader_data.users = 1; - VS::get_singleton()->shader_set_code(shader_data.shader, code); + RS::get_singleton()->shader_set_code(shader_data.shader, code); shader_map[mk] = shader_data; - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } void CanvasItemMaterial::flush_changes() { @@ -207,7 +206,7 @@ bool CanvasItemMaterial::get_particles_animation() const { void CanvasItemMaterial::set_particles_anim_h_frames(int p_frames) { particles_anim_h_frames = p_frames; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); } int CanvasItemMaterial::get_particles_anim_h_frames() const { @@ -217,7 +216,7 @@ int CanvasItemMaterial::get_particles_anim_h_frames() const { void CanvasItemMaterial::set_particles_anim_v_frames(int p_frames) { particles_anim_v_frames = p_frames; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); } int CanvasItemMaterial::get_particles_anim_v_frames() const { @@ -228,7 +227,7 @@ int CanvasItemMaterial::get_particles_anim_v_frames() const { void CanvasItemMaterial::set_particles_anim_loop(bool p_loop) { particles_anim_loop = p_loop; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); } bool CanvasItemMaterial::get_particles_anim_loop() const { @@ -316,11 +315,11 @@ CanvasItemMaterial::~CanvasItemMaterial() { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } } @@ -388,7 +387,7 @@ void CanvasItem::show() { return; visible = true; - VisualServer::get_singleton()->canvas_item_set_visible(canvas_item, true); + RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, true); if (!is_inside_tree()) return; @@ -403,7 +402,7 @@ void CanvasItem::hide() { return; visible = false; - VisualServer::get_singleton()->canvas_item_set_visible(canvas_item, false); + RenderingServer::get_singleton()->canvas_item_set_visible(canvas_item, false); if (!is_inside_tree()) return; @@ -424,7 +423,7 @@ void CanvasItem::_update_callback() { return; } - VisualServer::get_singleton()->canvas_item_clear(get_canvas_item()); + RenderingServer::get_singleton()->canvas_item_clear(get_canvas_item()); //todo updating = true - only allow drawing here if (is_visible_in_tree()) { //todo optimize this!! if (first_draw) { @@ -494,9 +493,9 @@ void CanvasItem::_toplevel_raise_self() { return; if (canvas_layer) - VisualServer::get_singleton()->canvas_item_set_draw_index(canvas_item, canvas_layer->get_sort_index()); + RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, canvas_layer->get_sort_index()); else - VisualServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_viewport()->gui_get_canvas_sort_index()); + RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_viewport()->gui_get_canvas_sort_index()); } void CanvasItem::_enter_canvas() { @@ -525,7 +524,7 @@ void CanvasItem::_enter_canvas() { else canvas = get_viewport()->find_world_2d()->get_canvas(); - VisualServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas); + RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, canvas); group = "root_canvas" + itos(canvas.get_id()); @@ -541,8 +540,8 @@ void CanvasItem::_enter_canvas() { CanvasItem *parent = get_parent_item(); canvas_layer = parent->canvas_layer; - VisualServer::get_singleton()->canvas_item_set_parent(canvas_item, parent->get_canvas_item()); - VisualServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); + RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, parent->get_canvas_item()); + RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); } pending_update = false; @@ -554,7 +553,7 @@ void CanvasItem::_enter_canvas() { void CanvasItem::_exit_canvas() { notification(NOTIFICATION_EXIT_CANVAS, true); //reverse the notification - VisualServer::get_singleton()->canvas_item_set_parent(canvas_item, RID()); + RenderingServer::get_singleton()->canvas_item_set_parent(canvas_item, RID()); canvas_layer = NULL; group = ""; } @@ -608,7 +607,7 @@ void CanvasItem::_notification(int p_what) { } else { CanvasItem *p = get_parent_item(); ERR_FAIL_COND(!p); - VisualServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); + RenderingServer::get_singleton()->canvas_item_set_draw_index(canvas_item, get_index()); } } break; @@ -674,7 +673,7 @@ void CanvasItem::set_modulate(const Color &p_modulate) { return; modulate = p_modulate; - VisualServer::get_singleton()->canvas_item_set_modulate(canvas_item, modulate); + RenderingServer::get_singleton()->canvas_item_set_modulate(canvas_item, modulate); } Color CanvasItem::get_modulate() const { @@ -715,7 +714,7 @@ void CanvasItem::set_self_modulate(const Color &p_self_modulate) { return; self_modulate = p_self_modulate; - VisualServer::get_singleton()->canvas_item_set_self_modulate(canvas_item, self_modulate); + RenderingServer::get_singleton()->canvas_item_set_self_modulate(canvas_item, self_modulate); } Color CanvasItem::get_self_modulate() const { @@ -728,7 +727,7 @@ void CanvasItem::set_light_mask(int p_light_mask) { return; light_mask = p_light_mask; - VS::get_singleton()->canvas_item_set_light_mask(canvas_item, p_light_mask); + RS::get_singleton()->canvas_item_set_light_mask(canvas_item, p_light_mask); } int CanvasItem::get_light_mask() const { @@ -747,7 +746,7 @@ void CanvasItem::draw_line(const Point2 &p_from, const Point2 &p_to, const Color ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); - VisualServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); + RenderingServer::get_singleton()->canvas_item_add_line(canvas_item, p_from, p_to, p_color, p_width); } void CanvasItem::draw_polyline(const Vector &p_points, const Color &p_color, float p_width) { @@ -756,14 +755,14 @@ void CanvasItem::draw_polyline(const Vector &p_points, const Color &p_co Vector colors; colors.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width); + RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, colors, p_width); } void CanvasItem::draw_polyline_colors(const Vector &p_points, const Vector &p_colors, float p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); - VisualServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width); + RenderingServer::get_singleton()->canvas_item_add_polyline(canvas_item, p_points, p_colors, p_width); } void CanvasItem::draw_arc(const Vector2 &p_center, float p_radius, float p_start_angle, float p_end_angle, int p_point_count, const Color &p_color, float p_width) { @@ -785,14 +784,14 @@ void CanvasItem::draw_multiline(const Vector &p_points, const Color &p_c Vector colors; colors.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width); + RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, colors, p_width); } void CanvasItem::draw_multiline_colors(const Vector &p_points, const Vector &p_colors, float p_width) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); - VisualServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width); + RenderingServer::get_singleton()->canvas_item_add_multiline(canvas_item, p_points, p_colors, p_width); } void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_filled, float p_width) { @@ -804,7 +803,7 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil WARN_PRINT("The draw_rect() \"width\" argument has no effect when \"filled\" is \"true\"."); } - VisualServer::get_singleton()->canvas_item_add_rect(canvas_item, p_rect, p_color); + RenderingServer::get_singleton()->canvas_item_add_rect(canvas_item, p_rect, p_color); } else { // Thick lines are offset depending on their width to avoid partial overlapping. // Thin lines don't require an offset, so don't apply one in this case @@ -815,25 +814,25 @@ void CanvasItem::draw_rect(const Rect2 &p_rect, const Color &p_color, bool p_fil offset = 0.0; } - VisualServer::get_singleton()->canvas_item_add_line( + RenderingServer::get_singleton()->canvas_item_add_line( canvas_item, p_rect.position + Size2(-offset, 0), p_rect.position + Size2(p_rect.size.width + offset, 0), p_color, p_width); - VisualServer::get_singleton()->canvas_item_add_line( + RenderingServer::get_singleton()->canvas_item_add_line( canvas_item, p_rect.position + Size2(p_rect.size.width, offset), p_rect.position + Size2(p_rect.size.width, p_rect.size.height - offset), p_color, p_width); - VisualServer::get_singleton()->canvas_item_add_line( + RenderingServer::get_singleton()->canvas_item_add_line( canvas_item, p_rect.position + Size2(p_rect.size.width + offset, p_rect.size.height), p_rect.position + Size2(-offset, p_rect.size.height), p_color, p_width); - VisualServer::get_singleton()->canvas_item_add_line( + RenderingServer::get_singleton()->canvas_item_add_line( canvas_item, p_rect.position + Size2(0, p_rect.size.height - offset), p_rect.position + Size2(0, offset), @@ -846,7 +845,7 @@ void CanvasItem::draw_circle(const Point2 &p_pos, float p_radius, const Color &p ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); - VisualServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color); + RenderingServer::get_singleton()->canvas_item_add_circle(canvas_item, p_pos, p_radius, p_color); } void CanvasItem::draw_texture(const Ref &p_texture, const Point2 &p_pos, const Color &p_modulate, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { @@ -855,7 +854,7 @@ void CanvasItem::draw_texture(const Ref &p_texture, const Point2 &p_p ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw(canvas_item, p_pos, p_modulate, false, p_normal_map, p_specular_map, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + p_texture->draw(canvas_item, p_pos, p_modulate, false, p_normal_map, p_specular_map, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_texture_rect(const Ref &p_texture, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { @@ -863,13 +862,13 @@ void CanvasItem::draw_texture_rect(const Ref &p_texture, const Rect2 ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + p_texture->draw_rect(canvas_item, p_rect, p_tile, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_texture_rect_region(const Ref &p_texture, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, bool p_clip_uv, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); ERR_FAIL_COND(p_texture.is_null()); - p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat), p_clip_uv); + p_texture->draw_rect_region(canvas_item, p_rect, p_src_rect, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat), p_clip_uv); } void CanvasItem::draw_style_box(const Ref &p_style_box, const Rect2 &p_rect) { @@ -887,7 +886,7 @@ void CanvasItem::draw_primitive(const Vector &p_points, const Vectorget_rid() : RID(); RID rid_specular = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width, rid_normal, rid_specular, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + RenderingServer::get_singleton()->canvas_item_add_primitive(canvas_item, p_points, p_colors, p_uvs, rid, p_width, rid_normal, rid_specular, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_set_transform(const Point2 &p_offset, float p_rot, const Size2 &p_scale) { @@ -895,14 +894,14 @@ void CanvasItem::draw_set_transform(const Point2 &p_offset, float p_rot, const S Transform2D xform(p_rot, p_offset); xform.scale_basis(p_scale); - VisualServer::get_singleton()->canvas_item_add_set_transform(canvas_item, xform); + RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, xform); } void CanvasItem::draw_set_transform_matrix(const Transform2D &p_matrix) { ERR_FAIL_COND_MSG(!drawing, "Drawing is only allowed inside NOTIFICATION_DRAW, _draw() function or 'draw' signal."); - VisualServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix); + RenderingServer::get_singleton()->canvas_item_add_set_transform(canvas_item, p_matrix); } void CanvasItem::draw_polygon(const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, Ref p_texture, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { @@ -913,7 +912,7 @@ void CanvasItem::draw_polygon(const Vector &p_points, const Vectorget_rid() : RID(); RID rid_specular = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, p_uvs, rid, rid_normal, rid_specular, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + RenderingServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, p_colors, p_uvs, rid, rid_normal, rid_specular, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_colored_polygon(const Vector &p_points, const Color &p_color, const Vector &p_uvs, Ref p_texture, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { @@ -926,7 +925,7 @@ void CanvasItem::draw_colored_polygon(const Vector &p_points, const Colo RID rid_normal = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID rid_specular = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid, rid_normal, rid_specular, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + RenderingServer::get_singleton()->canvas_item_add_polygon(canvas_item, p_points, colors, p_uvs, rid, rid_normal, rid_specular, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_mesh(const Ref &p_mesh, const Ref &p_texture, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, const Transform2D &p_transform, const Color &p_modulate, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { @@ -936,7 +935,7 @@ void CanvasItem::draw_mesh(const Ref &p_mesh, const Ref &p_text RID normal_map_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_map_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), p_transform, p_modulate, texture_rid, normal_map_rid, specular_map_rid, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + RenderingServer::get_singleton()->canvas_item_add_mesh(canvas_item, p_mesh->get_rid(), p_transform, p_modulate, texture_rid, normal_map_rid, specular_map_rid, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_multimesh(const Ref &p_multimesh, const Ref &p_texture, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, TextureFilter p_texture_filter, TextureRepeat p_texture_repeat) { @@ -945,7 +944,7 @@ void CanvasItem::draw_multimesh(const Ref &p_multimesh, const Refget_rid() : RID(); RID specular_map_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid, normal_map_rid, specular_map_rid, p_specular_color_shininess, VS::CanvasItemTextureFilter(p_texture_filter), VS::CanvasItemTextureRepeat(p_texture_repeat)); + RenderingServer::get_singleton()->canvas_item_add_multimesh(canvas_item, p_multimesh->get_rid(), texture_rid, normal_map_rid, specular_map_rid, p_specular_color_shininess, RS::CanvasItemTextureFilter(p_texture_filter), RS::CanvasItemTextureRepeat(p_texture_repeat)); } void CanvasItem::draw_string(const Ref &p_font, const Point2 &p_pos, const String &p_text, const Color &p_modulate, int p_clip_w) { @@ -1067,7 +1066,7 @@ void CanvasItem::set_draw_behind_parent(bool p_enable) { if (behind == p_enable) return; behind = p_enable; - VisualServer::get_singleton()->canvas_item_set_draw_behind_parent(canvas_item, behind); + RenderingServer::get_singleton()->canvas_item_set_draw_behind_parent(canvas_item, behind); } bool CanvasItem::is_draw_behind_parent_enabled() const { @@ -1081,14 +1080,14 @@ void CanvasItem::set_material(const Ref &p_material) { RID rid; if (material.is_valid()) rid = material->get_rid(); - VS::get_singleton()->canvas_item_set_material(canvas_item, rid); + RS::get_singleton()->canvas_item_set_material(canvas_item, rid); _change_notify(); //properties for material exposed } void CanvasItem::set_use_parent_material(bool p_use_parent_material) { use_parent_material = p_use_parent_material; - VS::get_singleton()->canvas_item_set_use_parent_material(canvas_item, p_use_parent_material); + RS::get_singleton()->canvas_item_set_use_parent_material(canvas_item, p_use_parent_material); } bool CanvasItem::get_use_parent_material() const { @@ -1373,18 +1372,18 @@ void CanvasItem::_update_texture_filter_changed(bool p_propagate) { } else { //from viewport switch (get_viewport()->get_default_canvas_item_texture_filter()) { - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST: texture_filter_cache = VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST; break; - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR: texture_filter_cache = VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; break; - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: texture_filter_cache = VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; break; - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: texture_filter_cache = VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST: texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR: texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS; break; default: { } } } } else { - texture_filter_cache = VS::CanvasItemTextureFilter(texture_filter); + texture_filter_cache = RS::CanvasItemTextureFilter(texture_filter); } - VS::get_singleton()->canvas_item_set_default_texture_filter(get_canvas_item(), texture_filter_cache); + RS::get_singleton()->canvas_item_set_default_texture_filter(get_canvas_item(), texture_filter_cache); update(); if (p_propagate) { @@ -1422,17 +1421,17 @@ void CanvasItem::_update_texture_repeat_changed(bool p_propagate) { } else { //from viewport switch (get_viewport()->get_default_canvas_item_texture_repeat()) { - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: texture_repeat_cache = VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; break; - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: texture_repeat_cache = VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; break; - case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: texture_repeat_cache = VS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED; break; + case Viewport::DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR; break; default: { } } } } else { - texture_repeat_cache = VS::CanvasItemTextureRepeat(texture_repeat); + texture_repeat_cache = RS::CanvasItemTextureRepeat(texture_repeat); } - VS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), texture_repeat_cache); + RS::get_singleton()->canvas_item_set_default_texture_repeat(get_canvas_item(), texture_repeat_cache); update(); if (p_propagate) { for (List::Element *E = children_items.front(); E; E = E->next()) { @@ -1460,7 +1459,7 @@ CanvasItem::CanvasItem() : xform_change(this) { window = nullptr; - canvas_item = VisualServer::get_singleton()->canvas_item_create(); + canvas_item = RenderingServer::get_singleton()->canvas_item_create(); visible = true; pending_update = false; modulate = Color(1, 1, 1, 1); @@ -1479,13 +1478,13 @@ CanvasItem::CanvasItem() : light_mask = 1; texture_repeat = TEXTURE_REPEAT_PARENT_NODE; texture_filter = TEXTURE_FILTER_PARENT_NODE; - texture_filter_cache = VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - texture_repeat_cache = VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; + texture_filter_cache = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; + texture_repeat_cache = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; C = NULL; } CanvasItem::~CanvasItem() { - VisualServer::get_singleton()->free(canvas_item); + RenderingServer::get_singleton()->free(canvas_item); } diff --git a/scene/main/canvas_item.h b/scene/main/canvas_item.h index 3f176e5f60..dc17c5283b 100644 --- a/scene/main/canvas_item.h +++ b/scene/main/canvas_item.h @@ -213,8 +213,8 @@ private: bool notify_local_transform; bool notify_transform; - VS::CanvasItemTextureFilter texture_filter_cache; - VS::CanvasItemTextureRepeat texture_repeat_cache; + RS::CanvasItemTextureFilter texture_filter_cache; + RS::CanvasItemTextureRepeat texture_repeat_cache; TextureFilter texture_filter; TextureRepeat texture_repeat; diff --git a/scene/main/canvas_layer.cpp b/scene/main/canvas_layer.cpp index 2085fa3a60..e6a665d035 100644 --- a/scene/main/canvas_layer.cpp +++ b/scene/main/canvas_layer.cpp @@ -35,7 +35,7 @@ void CanvasLayer::set_layer(int p_xform) { layer = p_xform; if (viewport.is_valid()) - VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + RenderingServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); } int CanvasLayer::get_layer() const { @@ -48,7 +48,7 @@ void CanvasLayer::set_transform(const Transform2D &p_xform) { transform = p_xform; locrotscale_dirty = true; if (viewport.is_valid()) - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); } Transform2D CanvasLayer::get_transform() const { @@ -61,7 +61,7 @@ void CanvasLayer::_update_xform() { transform.set_rotation_and_scale(rot, scale); transform.set_origin(ofs); if (viewport.is_valid()) - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); } void CanvasLayer::_update_locrotscale() { @@ -150,16 +150,16 @@ void CanvasLayer::_notification(int p_what) { vp->_canvas_layer_add(this); viewport = vp->get_viewport_rid(); - VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas); - VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); + RenderingServer::get_singleton()->viewport_attach_canvas(viewport, canvas); + RenderingServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); _update_follow_viewport(); } break; case NOTIFICATION_EXIT_TREE: { vp->_canvas_layer_remove(this); - VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas); + RenderingServer::get_singleton()->viewport_remove_canvas(viewport, canvas); viewport = RID(); _update_follow_viewport(false); @@ -167,7 +167,7 @@ void CanvasLayer::_notification(int p_what) { case NOTIFICATION_MOVED_IN_PARENT: { if (is_inside_tree()) - VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + RenderingServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); } break; } @@ -191,7 +191,7 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) { ERR_FAIL_NULL(p_viewport); if (is_inside_tree()) { vp->_canvas_layer_remove(this); - VisualServer::get_singleton()->viewport_remove_canvas(viewport, canvas); + RenderingServer::get_singleton()->viewport_remove_canvas(viewport, canvas); viewport = RID(); } @@ -213,9 +213,9 @@ void CanvasLayer::set_custom_viewport(Node *p_viewport) { vp->_canvas_layer_add(this); viewport = vp->get_viewport_rid(); - VisualServer::get_singleton()->viewport_attach_canvas(viewport, canvas); - VisualServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); + RenderingServer::get_singleton()->viewport_attach_canvas(viewport, canvas); + RenderingServer::get_singleton()->viewport_set_canvas_stacking(viewport, canvas, layer, get_position_in_parent()); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, canvas, transform); } } @@ -266,9 +266,9 @@ void CanvasLayer::_update_follow_viewport(bool p_force_exit) { return; } if (p_force_exit || !follow_viewport) { - VS::get_singleton()->canvas_set_parent(canvas, RID(), 1.0); + RS::get_singleton()->canvas_set_parent(canvas, RID(), 1.0); } else { - VS::get_singleton()->canvas_set_parent(canvas, vp->get_world_2d()->get_canvas(), follow_viewport_scale); + RS::get_singleton()->canvas_set_parent(canvas, vp->get_world_2d()->get_canvas(), follow_viewport_scale); } } @@ -325,7 +325,7 @@ CanvasLayer::CanvasLayer() { rot = 0; locrotscale_dirty = false; layer = 1; - canvas = VS::get_singleton()->canvas_create(); + canvas = RS::get_singleton()->canvas_create(); custom_viewport = NULL; sort_index = 0; @@ -335,5 +335,5 @@ CanvasLayer::CanvasLayer() { CanvasLayer::~CanvasLayer() { - VS::get_singleton()->free(canvas); + RS::get_singleton()->free(canvas); } diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index d6c0323f25..15c0a7666e 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -48,9 +48,9 @@ #include "scene/resources/packed_scene.h" #include "scene/scene_string_names.h" #include "servers/display_server.h" -#include "servers/navigation_server.h" -#include "servers/physics_2d_server.h" -#include "servers/physics_server.h" +#include "servers/navigation_server_3d.h" +#include "servers/physics_server_2d.h" +#include "servers/physics_server_3d.h" #include "window.h" #include @@ -435,7 +435,7 @@ bool SceneTree::idle(float p_time) { //print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage())); //print_line("node count: "+itos(get_node_count())); - //print_line("TEXTURE RAM: "+itos(VS::get_singleton()->get_render_info(VS::INFO_TEXTURE_MEM_USED))); + //print_line("TEXTURE RAM: "+itos(RS::get_singleton()->get_render_info(RS::INFO_TEXTURE_MEM_USED))); root_lock++; @@ -796,9 +796,9 @@ void SceneTree::set_pause(bool p_enabled) { if (p_enabled == pause) return; pause = p_enabled; - NavigationServer::get_singleton()->set_active(!p_enabled); - PhysicsServer::get_singleton()->set_active(!p_enabled); - Physics2DServer::get_singleton()->set_active(!p_enabled); + NavigationServer3D::get_singleton()->set_active(!p_enabled); + PhysicsServer3D::get_singleton()->set_active(!p_enabled); + PhysicsServer2D::get_singleton()->set_active(!p_enabled); if (get_root()) get_root()->propagate_notification(p_enabled ? Node::NOTIFICATION_PAUSED : Node::NOTIFICATION_UNPAUSED); } diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index d293a3cd32..b95e81a702 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -53,7 +53,7 @@ #include "scene/resources/mesh.h" #include "scene/scene_string_names.h" #include "servers/display_server.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" void ViewportTexture::setup_local_to_scene() { @@ -78,11 +78,11 @@ void ViewportTexture::setup_local_to_scene() { vp->viewport_textures.insert(this); if (proxy_ph.is_valid()) { - VS::get_singleton()->texture_proxy_update(proxy, vp->texture_rid); - VS::get_singleton()->free(proxy_ph); + RS::get_singleton()->texture_proxy_update(proxy, vp->texture_rid); + RS::get_singleton()->free(proxy_ph); } else { ERR_FAIL_COND(proxy.is_valid()); //should be invalid - proxy = VS::get_singleton()->texture_proxy_create(vp->texture_rid); + proxy = RS::get_singleton()->texture_proxy_create(vp->texture_rid); } } @@ -122,8 +122,8 @@ RID ViewportTexture::get_rid() const { //ERR_FAIL_COND_V_MSG(!vp, RID(), "Viewport Texture must be set to use it."); if (proxy.is_null()) { - proxy_ph = VS::get_singleton()->texture_2d_placeholder_create(); - proxy = VS::get_singleton()->texture_proxy_create(proxy_ph); + proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); + proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); } return proxy; } @@ -135,7 +135,7 @@ bool ViewportTexture::has_alpha() const { Ref ViewportTexture::get_data() const { ERR_FAIL_COND_V_MSG(!vp, Ref(), "Viewport Texture must be set to use it."); - return VS::get_singleton()->texture_2d_get(vp->texture_rid); + return RS::get_singleton()->texture_2d_get(vp->texture_rid); } void ViewportTexture::_bind_methods() { @@ -159,10 +159,10 @@ ViewportTexture::~ViewportTexture() { } if (proxy_ph.is_valid()) { - VS::get_singleton()->free(proxy_ph); + RS::get_singleton()->free(proxy_ph); } if (proxy.is_valid()) { - VS::get_singleton()->free(proxy); + RS::get_singleton()->free(proxy); } } @@ -240,7 +240,7 @@ void Viewport::_collision_object_input_event(CollisionObject3D *p_object, Camera void Viewport::_sub_window_update_order() { for (int i = 0; i < gui.sub_windows.size(); i++) { - VS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i); + RS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i); } } @@ -252,19 +252,19 @@ void Viewport::_sub_window_register(Window *p_window) { } if (gui.sub_windows.size() == 0) { - subwindow_canvas = VS::get_singleton()->canvas_create(); - VS::get_singleton()->viewport_attach_canvas(viewport, subwindow_canvas); - VS::get_singleton()->viewport_set_canvas_stacking(viewport, subwindow_canvas, SUBWINDOW_CANVAS_LAYER, 0); + subwindow_canvas = RS::get_singleton()->canvas_create(); + RS::get_singleton()->viewport_attach_canvas(viewport, subwindow_canvas); + RS::get_singleton()->viewport_set_canvas_stacking(viewport, subwindow_canvas, SUBWINDOW_CANVAS_LAYER, 0); } SubWindow sw; - sw.canvas_item = VS::get_singleton()->canvas_item_create(); - VS::get_singleton()->canvas_item_set_parent(sw.canvas_item, subwindow_canvas); + sw.canvas_item = RS::get_singleton()->canvas_item_create(); + RS::get_singleton()->canvas_item_set_parent(sw.canvas_item, subwindow_canvas); sw.window = p_window; gui.sub_windows.push_back(sw); _sub_window_grab_focus(p_window); - VisualServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, viewport); + RenderingServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, viewport); } void Viewport::_sub_window_update(Window *p_window) { @@ -283,7 +283,7 @@ void Viewport::_sub_window_update(Window *p_window) { Transform2D pos; pos.set_origin(p_window->get_position()); - VS::get_singleton()->canvas_item_clear(sw.canvas_item); + RS::get_singleton()->canvas_item_clear(sw.canvas_item); Rect2i r = Rect2i(p_window->get_position(), sw.window->get_size()); if (!p_window->get_flag(Window::FLAG_BORDERLESS)) { @@ -309,7 +309,7 @@ void Viewport::_sub_window_update(Window *p_window) { close_icon->draw(sw.canvas_item, r.position + Vector2(r.size.width - close_h_ofs, -close_v_ofs)); } - VS::get_singleton()->canvas_item_add_texture_rect(sw.canvas_item, r, sw.window->get_texture()->get_rid()); + RS::get_singleton()->canvas_item_add_texture_rect(sw.canvas_item, r, sw.window->get_texture()->get_rid()); } void Viewport::_sub_window_grab_focus(Window *p_window) { @@ -388,14 +388,14 @@ void Viewport::_sub_window_remove(Window *p_window) { for (int i = 0; i < gui.sub_windows.size(); i++) { if (gui.sub_windows[i].window == p_window) { - VS::get_singleton()->free(gui.sub_windows[i].canvas_item); + RS::get_singleton()->free(gui.sub_windows[i].canvas_item); gui.sub_windows.remove(i); break; } } if (gui.sub_windows.size() == 0) { - VS::get_singleton()->free(subwindow_canvas); + RS::get_singleton()->free(subwindow_canvas); subwindow_canvas = RID(); } @@ -419,7 +419,7 @@ void Viewport::_sub_window_remove(Window *p_window) { } } - VisualServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID()); + RenderingServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID()); } void Viewport::_own_world_changed() { @@ -437,7 +437,7 @@ void Viewport::_own_world_changed() { } if (is_inside_tree()) { - VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); + RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); } _update_listener(); @@ -453,14 +453,14 @@ void Viewport::_notification(int p_what) { if (get_parent()) { parent = get_parent()->get_viewport(); - VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, parent->get_viewport_rid()); + RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, parent->get_viewport_rid()); } else { parent = NULL; } current_canvas = find_world_2d()->get_canvas(); - VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); - VisualServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas); + RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); + RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas); _update_listener(); _update_listener_2d(); @@ -470,19 +470,19 @@ void Viewport::_notification(int p_what) { add_to_group("_viewports"); if (get_tree()->is_debugging_collisions_hint()) { //2D - Physics2DServer::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(), get_tree()->get_collision_debug_contact_count()); - contact_2d_debug = VisualServer::get_singleton()->canvas_item_create(); - VisualServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, find_world_2d()->get_canvas()); + PhysicsServer2D::get_singleton()->space_set_debug_contacts(find_world_2d()->get_space(), get_tree()->get_collision_debug_contact_count()); + contact_2d_debug = RenderingServer::get_singleton()->canvas_item_create(); + RenderingServer::get_singleton()->canvas_item_set_parent(contact_2d_debug, find_world_2d()->get_canvas()); //3D - PhysicsServer::get_singleton()->space_set_debug_contacts(find_world()->get_space(), get_tree()->get_collision_debug_contact_count()); - contact_3d_debug_multimesh = VisualServer::get_singleton()->multimesh_create(); - VisualServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), VS::MULTIMESH_TRANSFORM_3D, true); - VisualServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0); - VisualServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid()); - contact_3d_debug_instance = VisualServer::get_singleton()->instance_create(); - VisualServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh); - VisualServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world()->get_scenario()); - //VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true); + PhysicsServer3D::get_singleton()->space_set_debug_contacts(find_world()->get_space(), get_tree()->get_collision_debug_contact_count()); + contact_3d_debug_multimesh = RenderingServer::get_singleton()->multimesh_create(); + RenderingServer::get_singleton()->multimesh_allocate(contact_3d_debug_multimesh, get_tree()->get_collision_debug_contact_count(), RS::MULTIMESH_TRANSFORM_3D, true); + RenderingServer::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, 0); + RenderingServer::get_singleton()->multimesh_set_mesh(contact_3d_debug_multimesh, get_tree()->get_debug_contact_mesh()->get_rid()); + contact_3d_debug_instance = RenderingServer::get_singleton()->instance_create(); + RenderingServer::get_singleton()->instance_set_base(contact_3d_debug_instance, contact_3d_debug_multimesh); + RenderingServer::get_singleton()->instance_set_scenario(contact_3d_debug_instance, find_world()->get_scenario()); + //RenderingServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, RS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true); } } break; @@ -527,24 +527,24 @@ void Viewport::_notification(int p_what) { if (world_2d.is_valid()) world_2d->_remove_viewport(this); - VisualServer::get_singleton()->viewport_set_scenario(viewport, RID()); - VisualServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); + RenderingServer::get_singleton()->viewport_set_scenario(viewport, RID()); + RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); if (contact_2d_debug.is_valid()) { - VisualServer::get_singleton()->free(contact_2d_debug); + RenderingServer::get_singleton()->free(contact_2d_debug); contact_2d_debug = RID(); } if (contact_3d_debug_multimesh.is_valid()) { - VisualServer::get_singleton()->free(contact_3d_debug_multimesh); - VisualServer::get_singleton()->free(contact_3d_debug_instance); + RenderingServer::get_singleton()->free(contact_3d_debug_multimesh); + RenderingServer::get_singleton()->free(contact_3d_debug_instance); contact_3d_debug_instance = RID(); contact_3d_debug_multimesh = RID(); } remove_from_group("_viewports"); - VS::get_singleton()->viewport_set_active(viewport, false); - VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, RID()); + RS::get_singleton()->viewport_set_active(viewport, false); + RenderingServer::get_singleton()->viewport_set_parent_viewport(viewport, RID()); } break; case NOTIFICATION_INTERNAL_PROCESS: { @@ -561,25 +561,25 @@ void Viewport::_notification(int p_what) { if (get_tree()->is_debugging_collisions_hint() && contact_2d_debug.is_valid()) { - VisualServer::get_singleton()->canvas_item_clear(contact_2d_debug); - VisualServer::get_singleton()->canvas_item_set_draw_index(contact_2d_debug, 0xFFFFF); //very high index + RenderingServer::get_singleton()->canvas_item_clear(contact_2d_debug); + RenderingServer::get_singleton()->canvas_item_set_draw_index(contact_2d_debug, 0xFFFFF); //very high index - Vector points = Physics2DServer::get_singleton()->space_get_contacts(find_world_2d()->get_space()); - int point_count = Physics2DServer::get_singleton()->space_get_contact_count(find_world_2d()->get_space()); + Vector points = PhysicsServer2D::get_singleton()->space_get_contacts(find_world_2d()->get_space()); + int point_count = PhysicsServer2D::get_singleton()->space_get_contact_count(find_world_2d()->get_space()); Color ccol = get_tree()->get_debug_collision_contact_color(); for (int i = 0; i < point_count; i++) { - VisualServer::get_singleton()->canvas_item_add_rect(contact_2d_debug, Rect2(points[i] - Vector2(2, 2), Vector2(5, 5)), ccol); + RenderingServer::get_singleton()->canvas_item_add_rect(contact_2d_debug, Rect2(points[i] - Vector2(2, 2), Vector2(5, 5)), ccol); } } if (get_tree()->is_debugging_collisions_hint() && contact_3d_debug_multimesh.is_valid()) { - Vector points = PhysicsServer::get_singleton()->space_get_contacts(find_world()->get_space()); - int point_count = PhysicsServer::get_singleton()->space_get_contact_count(find_world()->get_space()); + Vector points = PhysicsServer3D::get_singleton()->space_get_contacts(find_world()->get_space()); + int point_count = PhysicsServer3D::get_singleton()->space_get_contact_count(find_world()->get_space()); - VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count); + RS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count); } if (physics_object_picking && (to_screen_rect == Rect2i() || InputFilter::get_singleton()->get_mouse_mode() != InputFilter::MOUSE_MODE_CAPTURED)) { @@ -589,8 +589,8 @@ void Viewport::_notification(int p_what) { CollisionObject3D *last_object = NULL; ObjectID last_id; #endif - PhysicsDirectSpaceState::RayResult result; - Physics2DDirectSpaceState *ss2d = Physics2DServer::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); + PhysicsDirectSpaceState3D::RayResult result; + PhysicsDirectSpaceState2D *ss2d = PhysicsServer2D::get_singleton()->space_get_direct_state(find_world_2d()->get_space()); if (physics_has_last_mousepos) { // if no mouse event exists, create a motion one. This is necessary because objects or camera may have moved. @@ -697,7 +697,7 @@ void Viewport::_notification(int p_what) { uint64_t frame = get_tree()->get_frame(); - Physics2DDirectSpaceState::ShapeResult res[64]; + PhysicsDirectSpaceState2D::ShapeResult res[64]; for (Set::Element *E = canvas_layers.front(); E; E = E->next()) { Transform2D canvas_transform; ObjectID canvas_layer_id; @@ -805,7 +805,7 @@ void Viewport::_notification(int p_what) { Vector3 from = camera->project_ray_origin(pos); Vector3 dir = camera->project_ray_normal(pos); - PhysicsDirectSpaceState *space = PhysicsServer::get_singleton()->space_get_direct_state(find_world()->get_space()); + PhysicsDirectSpaceState3D *space = PhysicsServer3D::get_singleton()->space_get_direct_state(find_world()->get_space()); if (space) { bool col = space->intersect_ray(from, from + dir * 10000, result, Set(), 0xFFFFFFFF, true, true, true); @@ -890,9 +890,9 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_override, co to_screen_rect = p_to_screen_rect; if (p_allocated) { - VS::get_singleton()->viewport_set_size(viewport, size.width, size.height); + RS::get_singleton()->viewport_set_size(viewport, size.width, size.height); } else { - VS::get_singleton()->viewport_set_size(viewport, 0, 0); + RS::get_singleton()->viewport_set_size(viewport, 0, 0); } _update_global_transform(); @@ -974,9 +974,9 @@ void Viewport::enable_canvas_transform_override(bool p_enable) { override_canvas_transform = p_enable; if (p_enable) { - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override); } else { - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform); } } @@ -991,7 +991,7 @@ void Viewport::set_canvas_transform_override(const Transform2D &p_transform) { canvas_transform_override = p_transform; if (override_canvas_transform) { - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform_override); } } @@ -1004,7 +1004,7 @@ void Viewport::set_canvas_transform(const Transform2D &p_transform) { canvas_transform = p_transform; if (!override_canvas_transform) { - VisualServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform); + RenderingServer::get_singleton()->viewport_set_canvas_transform(viewport, find_world_2d()->get_canvas(), canvas_transform); } } @@ -1017,7 +1017,7 @@ void Viewport::_update_global_transform() { Transform2D sxform = stretch_transform * global_canvas_transform; - VisualServer::get_singleton()->viewport_set_global_canvas_transform(viewport, sxform); + RenderingServer::get_singleton()->viewport_set_global_canvas_transform(viewport, sxform); } void Viewport::set_global_canvas_transform(const Transform2D &p_transform) { @@ -1109,9 +1109,9 @@ void Viewport::_camera_set(Camera3D *p_camera) { if (!camera_override) { if (camera) - VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); + RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); else - VisualServer::get_singleton()->viewport_attach_camera(viewport, RID()); + RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID()); } if (camera) { @@ -1168,7 +1168,7 @@ void Viewport::_canvas_layer_remove(CanvasLayer *p_canvas_layer) { void Viewport::set_transparent_background(bool p_enable) { transparent_bg = p_enable; - VS::get_singleton()->viewport_set_transparent_background(viewport, p_enable); + RS::get_singleton()->viewport_set_transparent_background(viewport, p_enable); } bool Viewport::has_transparent_background() const { @@ -1187,7 +1187,7 @@ void Viewport::set_world_2d(const Ref &p_world_2d) { if (is_inside_tree()) { find_world_2d()->_remove_viewport(this); - VisualServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); + RenderingServer::get_singleton()->viewport_remove_canvas(viewport, current_canvas); } if (p_world_2d.is_valid()) @@ -1201,7 +1201,7 @@ void Viewport::set_world_2d(const Ref &p_world_2d) { if (is_inside_tree()) { current_canvas = find_world_2d()->get_canvas(); - VisualServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas); + RenderingServer::get_singleton()->viewport_attach_canvas(viewport, current_canvas); find_world_2d()->_register_viewport(this, Rect2()); } } @@ -1312,7 +1312,7 @@ void Viewport::set_world(const Ref &p_world) { _propagate_enter_world(this); if (is_inside_tree()) { - VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); + RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); } _update_listener(); @@ -1357,18 +1357,18 @@ void Viewport::enable_camera_override(bool p_enable) { } if (p_enable) { - camera_override.rid = VisualServer::get_singleton()->camera_create(); + camera_override.rid = RenderingServer::get_singleton()->camera_create(); } else { - VisualServer::get_singleton()->free(camera_override.rid); + RenderingServer::get_singleton()->free(camera_override.rid); camera_override.rid = RID(); } if (p_enable) { - VisualServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid); + RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera_override.rid); } else if (camera) { - VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); + RenderingServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera()); } else { - VisualServer::get_singleton()->viewport_attach_camera(viewport, RID()); + RenderingServer::get_singleton()->viewport_attach_camera(viewport, RID()); } #endif } @@ -1380,7 +1380,7 @@ bool Viewport::is_camera_override_enabled() const { void Viewport::set_camera_override_transform(const Transform &p_transform) { if (camera_override) { camera_override.transform = p_transform; - VisualServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform); + RenderingServer::get_singleton()->camera_set_transform(camera_override.rid, p_transform); } } @@ -1403,7 +1403,7 @@ void Viewport::set_camera_override_perspective(float p_fovy_degrees, float p_z_n camera_override.z_far = p_z_far; camera_override.projection = CameraOverrideData::PROJECTION_PERSPECTIVE; - VisualServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far); + RenderingServer::get_singleton()->camera_set_perspective(camera_override.rid, camera_override.fov, camera_override.z_near, camera_override.z_far); } } @@ -1418,7 +1418,7 @@ void Viewport::set_camera_override_orthogonal(float p_size, float p_z_near, floa camera_override.z_far = p_z_far; camera_override.projection = CameraOverrideData::PROJECTION_ORTHOGONAL; - VisualServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far); + RenderingServer::get_singleton()->camera_set_orthogonal(camera_override.rid, camera_override.size, camera_override.z_near, camera_override.z_far); } } @@ -1458,7 +1458,7 @@ void Viewport::set_shadow_atlas_size(int p_size) { return; shadow_atlas_size = p_size; - VS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size); + RS::get_singleton()->viewport_set_shadow_atlas_size(viewport, p_size); } int Viewport::get_shadow_atlas_size() const { @@ -1477,7 +1477,7 @@ void Viewport::set_shadow_atlas_quadrant_subdiv(int p_quadrant, ShadowAtlasQuadr shadow_atlas_quadrant_subdiv[p_quadrant] = p_subdiv; static const int subdiv[SHADOW_ATLAS_QUADRANT_SUBDIV_MAX] = { 0, 1, 4, 16, 64, 256, 1024 }; - VS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]); + RS::get_singleton()->viewport_set_shadow_atlas_quadrant_subdivision(viewport, p_quadrant, subdiv[p_subdiv]); } Viewport::ShadowAtlasQuadrantSubdiv Viewport::get_shadow_atlas_quadrant_subdiv(int p_quadrant) const { @@ -3109,7 +3109,7 @@ void Viewport::set_use_own_world(bool p_world) { _propagate_enter_world(this); if (is_inside_tree()) { - VisualServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); + RenderingServer::get_singleton()->viewport_set_scenario(viewport, find_world()->get_scenario()); } _update_listener(); @@ -3183,7 +3183,7 @@ void Viewport::set_msaa(MSAA p_msaa) { if (msaa == p_msaa) return; msaa = p_msaa; - VS::get_singleton()->viewport_set_msaa(viewport, VS::ViewportMSAA(p_msaa)); + RS::get_singleton()->viewport_set_msaa(viewport, RS::ViewportMSAA(p_msaa)); } Viewport::MSAA Viewport::get_msaa() const { @@ -3194,7 +3194,7 @@ Viewport::MSAA Viewport::get_msaa() const { void Viewport::set_debug_draw(DebugDraw p_debug_draw) { debug_draw = p_debug_draw; - VS::get_singleton()->viewport_set_debug_draw(viewport, VS::ViewportDebugDraw(p_debug_draw)); + RS::get_singleton()->viewport_set_debug_draw(viewport, RS::ViewportDebugDraw(p_debug_draw)); } Viewport::DebugDraw Viewport::get_debug_draw() const { @@ -3204,7 +3204,7 @@ Viewport::DebugDraw Viewport::get_debug_draw() const { int Viewport::get_render_info(RenderInfo p_info) { - return VS::get_singleton()->viewport_get_render_info(viewport, VS::ViewportRenderInfo(p_info)); + return RS::get_singleton()->viewport_get_render_info(viewport, RS::ViewportRenderInfo(p_info)); } void Viewport::set_snap_controls_to_pixels(bool p_enable) { @@ -3527,13 +3527,13 @@ Viewport::Viewport() { world_2d = Ref(memnew(World2D)); - viewport = VisualServer::get_singleton()->viewport_create(); - texture_rid = VisualServer::get_singleton()->viewport_get_texture(viewport); + viewport = RenderingServer::get_singleton()->viewport_create(); + texture_rid = RenderingServer::get_singleton()->viewport_get_texture(viewport); default_texture.instance(); default_texture->vp = const_cast(this); viewport_textures.insert(default_texture.ptr()); - default_texture->proxy = VS::get_singleton()->texture_proxy_create(texture_rid); + default_texture->proxy = RS::get_singleton()->texture_proxy_create(texture_rid); audio_listener = false; //internal_listener_2d = SpatialSound2DServer::get_singleton()->listener_create(); @@ -3614,7 +3614,7 @@ Viewport::~Viewport() { for (Set::Element *E = viewport_textures.front(); E; E = E->next()) { E->get()->vp = NULL; } - VisualServer::get_singleton()->free(viewport); + RenderingServer::get_singleton()->free(viewport); } ///////////////////////////////// @@ -3622,7 +3622,7 @@ Viewport::~Viewport() { void SubViewport::set_use_arvr(bool p_use_arvr) { arvr = p_use_arvr; - VS::get_singleton()->viewport_set_use_arvr(get_viewport_rid(), arvr); + RS::get_singleton()->viewport_set_use_arvr(get_viewport_rid(), arvr); } bool SubViewport::is_using_arvr() { @@ -3639,7 +3639,7 @@ Size2i SubViewport::get_size() const { void SubViewport::set_update_mode(UpdateMode p_mode) { update_mode = p_mode; - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::ViewportUpdateMode(p_mode)); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::ViewportUpdateMode(p_mode)); } SubViewport::UpdateMode SubViewport::get_update_mode() const { @@ -3649,7 +3649,7 @@ SubViewport::UpdateMode SubViewport::get_update_mode() const { void SubViewport::set_clear_mode(ClearMode p_mode) { clear_mode = p_mode; - VS::get_singleton()->viewport_set_clear_mode(get_viewport_rid(), VS::ViewportClearMode(p_mode)); + RS::get_singleton()->viewport_set_clear_mode(get_viewport_rid(), RS::ViewportClearMode(p_mode)); } SubViewport::ClearMode SubViewport::get_clear_mode() const { @@ -3664,10 +3664,10 @@ DisplayServer::WindowID SubViewport::get_window_id() const { void SubViewport::_notification(int p_what) { if (p_what == NOTIFICATION_ENTER_TREE) { - VS::get_singleton()->viewport_set_active(get_viewport_rid(), true); + RS::get_singleton()->viewport_set_active(get_viewport_rid(), true); } if (p_what == NOTIFICATION_EXIT_TREE) { - VS::get_singleton()->viewport_set_active(get_viewport_rid(), false); + RS::get_singleton()->viewport_set_active(get_viewport_rid(), false); } } diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 8a56caea52..d0b22b5553 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -36,7 +36,7 @@ #include "scene/resources/texture.h" #include "scene/resources/world_2d.h" #include "servers/display_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Camera3D; class Camera2D; diff --git a/scene/main/window.cpp b/scene/main/window.cpp index b22b99c50c..3a8f7ebb60 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -249,7 +249,7 @@ void Window::_make_window() { } } - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_VISIBLE); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_VISIBLE); } void Window::_update_from_window() { @@ -279,7 +279,7 @@ void Window::_clear_window() { window_id = DisplayServer::INVALID_WINDOW_ID; _update_viewport_size(); - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); } void Window::_rect_changed_callback(const Rect2i &p_callback) { @@ -387,11 +387,11 @@ void Window::set_visible(bool p_visible) { if (visible) { embedder = embedder_vp; embedder->_sub_window_register(this); - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); } else { embedder->_sub_window_remove(this); embedder = nullptr; - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); } _update_window_size(); } @@ -402,7 +402,7 @@ void Window::set_visible(bool p_visible) { notification(NOTIFICATION_VISIBILITY_CHANGED); emit_signal(SceneStringNames::get_singleton()->visibility_changed); - VS::get_singleton()->viewport_set_active(get_viewport_rid(), visible); + RS::get_singleton()->viewport_set_active(get_viewport_rid(), visible); } void Window::_clear_transient() { @@ -606,14 +606,14 @@ void Window::_update_viewport_size() { //black bars and margin if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.x < video_mode.x) { margin.x = Math::round((video_mode.x - screen_size.x) / 2.0); - //VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); + //RenderingServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0); offset.x = Math::round(margin.x * viewport_size.y / screen_size.y); } else if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.y < video_mode.y) { margin.y = Math::round((video_mode.y - screen_size.y) / 2.0); - //VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); + //RenderingServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y); offset.y = Math::round(margin.y * viewport_size.x / screen_size.x); } else { - //VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0); + //RenderingServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0); } switch (content_scale_mode) { @@ -646,9 +646,9 @@ void Window::_update_viewport_size() { _set_size(final_size, final_size_override, attach_to_screen_rect, stretch_transform, allocate); if (window_id != DisplayServer::INVALID_WINDOW_ID) { - VisualServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), attach_to_screen_rect, window_id); + RenderingServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), attach_to_screen_rect, window_id); } else { - VisualServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), Rect2i(), DisplayServer::INVALID_WINDOW_ID); + RenderingServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), Rect2i(), DisplayServer::INVALID_WINDOW_ID); } if (window_id == DisplayServer::MAIN_WINDOW_ID) { @@ -718,7 +718,7 @@ void Window::_notification(int p_what) { //create as embedded if (embedder) { embedder->_sub_window_register(this); - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); _update_window_size(); } @@ -736,7 +736,7 @@ void Window::_notification(int p_what) { } _update_viewport_size(); //then feed back to the viewport _update_window_callbacks(); - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_VISIBLE); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_VISIBLE); } else { //create if (visible) { @@ -752,7 +752,7 @@ void Window::_notification(int p_what) { if (visible) { notification(NOTIFICATION_VISIBILITY_CHANGED); emit_signal(SceneStringNames::get_singleton()->visibility_changed); - VS::get_singleton()->viewport_set_active(get_viewport_rid(), true); + RS::get_singleton()->viewport_set_active(get_viewport_rid(), true); } } @@ -773,7 +773,7 @@ void Window::_notification(int p_what) { if (window_id == DisplayServer::MAIN_WINDOW_ID) { - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); _update_window_callbacks(); } else { _clear_window(); @@ -783,12 +783,12 @@ void Window::_notification(int p_what) { if (embedder) { embedder->_sub_window_remove(this); embedder = nullptr; - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); } _update_viewport_size(); //called by clear and make, which does not happen here } - VS::get_singleton()->viewport_set_active(get_viewport_rid(), false); + RS::get_singleton()->viewport_set_active(get_viewport_rid(), false); } } @@ -1400,7 +1400,7 @@ Window::Window() { } content_scale_mode = CONTENT_SCALE_MODE_DISABLED; content_scale_aspect = CONTENT_SCALE_ASPECT_IGNORE; - VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED); + RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED); } Window::~Window() { } diff --git a/scene/resources/box_shape_3d.cpp b/scene/resources/box_shape_3d.cpp index 3ac29642d7..64c821a011 100644 --- a/scene/resources/box_shape_3d.cpp +++ b/scene/resources/box_shape_3d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "box_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector BoxShape3D::get_debug_mesh_lines() { @@ -54,7 +54,7 @@ real_t BoxShape3D::get_enclosing_radius() const { void BoxShape3D::_update_shape() { - PhysicsServer::get_singleton()->shape_set_data(get_shape(), extents); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), extents); Shape3D::_update_shape(); } @@ -80,7 +80,7 @@ void BoxShape3D::_bind_methods() { } BoxShape3D::BoxShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_BOX)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_BOX)) { set_extents(Vector3(1, 1, 1)); } diff --git a/scene/resources/capsule_shape_2d.cpp b/scene/resources/capsule_shape_2d.cpp index 9b8083de97..ab2657c892 100644 --- a/scene/resources/capsule_shape_2d.cpp +++ b/scene/resources/capsule_shape_2d.cpp @@ -30,8 +30,8 @@ #include "capsule_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" Vector CapsuleShape2D::_get_points() const { @@ -54,7 +54,7 @@ bool CapsuleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_ void CapsuleShape2D::_update_shape() { - Physics2DServer::get_singleton()->shape_set_data(get_rid(), Vector2(radius, height)); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), Vector2(radius, height)); emit_changed(); } @@ -85,7 +85,7 @@ void CapsuleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector points = _get_points(); Vector col; col.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); } Rect2 CapsuleShape2D::get_rect() const { @@ -114,7 +114,7 @@ void CapsuleShape2D::_bind_methods() { } CapsuleShape2D::CapsuleShape2D() : - Shape2D(Physics2DServer::get_singleton()->capsule_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->capsule_shape_create()) { radius = 10; height = 20; diff --git a/scene/resources/capsule_shape_3d.cpp b/scene/resources/capsule_shape_3d.cpp index a929caa275..da3ffcb306 100644 --- a/scene/resources/capsule_shape_3d.cpp +++ b/scene/resources/capsule_shape_3d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "capsule_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector CapsuleShape3D::get_debug_mesh_lines() { @@ -78,7 +78,7 @@ void CapsuleShape3D::_update_shape() { Dictionary d; d["radius"] = radius; d["height"] = height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); Shape3D::_update_shape(); } @@ -120,7 +120,7 @@ void CapsuleShape3D::_bind_methods() { } CapsuleShape3D::CapsuleShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CAPSULE)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CAPSULE)) { radius = 1.0; height = 1.0; diff --git a/scene/resources/circle_shape_2d.cpp b/scene/resources/circle_shape_2d.cpp index 37874e17ef..afb7597280 100644 --- a/scene/resources/circle_shape_2d.cpp +++ b/scene/resources/circle_shape_2d.cpp @@ -30,8 +30,8 @@ #include "circle_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool CircleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { @@ -40,7 +40,7 @@ bool CircleShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_t void CircleShape2D::_update_shape() { - Physics2DServer::get_singleton()->shape_set_data(get_rid(), radius); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), radius); emit_changed(); } @@ -84,11 +84,11 @@ void CircleShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector col; col.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); } CircleShape2D::CircleShape2D() : - Shape2D(Physics2DServer::get_singleton()->circle_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->circle_shape_create()) { radius = 10; _update_shape(); diff --git a/scene/resources/concave_polygon_shape_2d.cpp b/scene/resources/concave_polygon_shape_2d.cpp index c3e9e19721..c8fec3b72d 100644 --- a/scene/resources/concave_polygon_shape_2d.cpp +++ b/scene/resources/concave_polygon_shape_2d.cpp @@ -30,8 +30,8 @@ #include "concave_polygon_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool ConcavePolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { @@ -52,13 +52,13 @@ bool ConcavePolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, do void ConcavePolygonShape2D::set_segments(const Vector &p_segments) { - Physics2DServer::get_singleton()->shape_set_data(get_rid(), p_segments); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), p_segments); emit_changed(); } Vector ConcavePolygonShape2D::get_segments() const { - return Physics2DServer::get_singleton()->shape_get_data(get_rid()); + return PhysicsServer2D::get_singleton()->shape_get_data(get_rid()); } void ConcavePolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) { @@ -70,7 +70,7 @@ void ConcavePolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) { const Vector2 *r = s.ptr(); for (int i = 0; i < len; i += 2) { - VisualServer::get_singleton()->canvas_item_add_line(p_to_rid, r[i], r[i + 1], p_color, 2); + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, r[i], r[i + 1], p_color, 2); } } @@ -113,7 +113,7 @@ void ConcavePolygonShape2D::_bind_methods() { } ConcavePolygonShape2D::ConcavePolygonShape2D() : - Shape2D(Physics2DServer::get_singleton()->concave_polygon_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->concave_polygon_shape_create()) { Vector empty; set_segments(empty); } diff --git a/scene/resources/concave_polygon_shape_3d.cpp b/scene/resources/concave_polygon_shape_3d.cpp index 6be4a087ad..42e06a49b6 100644 --- a/scene/resources/concave_polygon_shape_3d.cpp +++ b/scene/resources/concave_polygon_shape_3d.cpp @@ -30,7 +30,7 @@ #include "concave_polygon_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector ConcavePolygonShape3D::get_debug_mesh_lines() { @@ -80,13 +80,13 @@ void ConcavePolygonShape3D::_update_shape() { void ConcavePolygonShape3D::set_faces(const Vector &p_faces) { - PhysicsServer::get_singleton()->shape_set_data(get_shape(), p_faces); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), p_faces); notify_change_to_owners(); } Vector ConcavePolygonShape3D::get_faces() const { - return PhysicsServer::get_singleton()->shape_get_data(get_shape()); + return PhysicsServer3D::get_singleton()->shape_get_data(get_shape()); } void ConcavePolygonShape3D::_bind_methods() { @@ -97,7 +97,7 @@ void ConcavePolygonShape3D::_bind_methods() { } ConcavePolygonShape3D::ConcavePolygonShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONCAVE_POLYGON)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CONCAVE_POLYGON)) { //set_planes(Vector3(1,1,1)); } diff --git a/scene/resources/convex_polygon_shape_2d.cpp b/scene/resources/convex_polygon_shape_2d.cpp index 95967429c9..6b1ddec507 100644 --- a/scene/resources/convex_polygon_shape_2d.cpp +++ b/scene/resources/convex_polygon_shape_2d.cpp @@ -31,8 +31,8 @@ #include "convex_polygon_shape_2d.h" #include "core/math/geometry.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool ConvexPolygonShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { @@ -45,7 +45,7 @@ void ConvexPolygonShape2D::_update_shape() { if (Geometry::is_polygon_clockwise(final_points)) { //needs to be counter clockwise final_points.invert(); } - Physics2DServer::get_singleton()->shape_set_data(get_rid(), final_points); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), final_points); emit_changed(); } @@ -81,7 +81,7 @@ void ConvexPolygonShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector col; col.push_back(p_color); - VisualServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); + RenderingServer::get_singleton()->canvas_item_add_polygon(p_to_rid, points, col); } Rect2 ConvexPolygonShape2D::get_rect() const { @@ -106,5 +106,5 @@ real_t ConvexPolygonShape2D::get_enclosing_radius() const { } ConvexPolygonShape2D::ConvexPolygonShape2D() : - Shape2D(Physics2DServer::get_singleton()->convex_polygon_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->convex_polygon_shape_create()) { } diff --git a/scene/resources/convex_polygon_shape_3d.cpp b/scene/resources/convex_polygon_shape_3d.cpp index e25301b2eb..ec9ab68015 100644 --- a/scene/resources/convex_polygon_shape_3d.cpp +++ b/scene/resources/convex_polygon_shape_3d.cpp @@ -30,7 +30,7 @@ #include "convex_polygon_shape_3d.h" #include "core/math/quick_hull.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector ConvexPolygonShape3D::get_debug_mesh_lines() { @@ -67,7 +67,7 @@ real_t ConvexPolygonShape3D::get_enclosing_radius() const { void ConvexPolygonShape3D::_update_shape() { - PhysicsServer::get_singleton()->shape_set_data(get_shape(), points); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), points); Shape3D::_update_shape(); } @@ -92,5 +92,5 @@ void ConvexPolygonShape3D::_bind_methods() { } ConvexPolygonShape3D::ConvexPolygonShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CONVEX_POLYGON)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CONVEX_POLYGON)) { } diff --git a/scene/resources/cylinder_shape_3d.cpp b/scene/resources/cylinder_shape_3d.cpp index 7636c55346..19f0542818 100644 --- a/scene/resources/cylinder_shape_3d.cpp +++ b/scene/resources/cylinder_shape_3d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "cylinder_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector CylinderShape3D::get_debug_mesh_lines() { @@ -71,7 +71,7 @@ void CylinderShape3D::_update_shape() { Dictionary d; d["radius"] = radius; d["height"] = height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); Shape3D::_update_shape(); } @@ -113,7 +113,7 @@ void CylinderShape3D::_bind_methods() { } CylinderShape3D::CylinderShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_CYLINDER)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_CYLINDER)) { radius = 1.0; height = 2.0; diff --git a/scene/resources/dynamic_font.cpp b/scene/resources/dynamic_font.cpp index 410c4990a2..107f07ec7d 100644 --- a/scene/resources/dynamic_font.cpp +++ b/scene/resources/dynamic_font.cpp @@ -336,7 +336,7 @@ float DynamicFontAtSize::draw_char(RID p_canvas_item, const Point2 &p_pos, CharT modulate.r = modulate.g = modulate.b = 1.0; } RID texture = font->textures[ch->texture_idx].texture->get_rid(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), texture, ch->rect_uv, modulate, false, RID(), RID(), Color(1, 1, 1, 1), false); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, ch->rect.size), texture, ch->rect_uv, modulate, false, RID(), RID(), Color(1, 1, 1, 1), false); } advance = ch->advance; diff --git a/scene/resources/environment.cpp b/scene/resources/environment.cpp index d407dd3722..89937238c1 100644 --- a/scene/resources/environment.cpp +++ b/scene/resources/environment.cpp @@ -30,7 +30,7 @@ #include "environment.h" #include "core/project_settings.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #include "texture.h" RID Environment::get_rid() const { @@ -41,7 +41,7 @@ RID Environment::get_rid() const { void Environment::set_background(BGMode p_bg) { bg_mode = p_bg; - VS::get_singleton()->environment_set_background(environment, VS::EnvironmentBG(p_bg)); + RS::get_singleton()->environment_set_background(environment, RS::EnvironmentBG(p_bg)); _change_notify(); } @@ -53,56 +53,56 @@ void Environment::set_sky(const Ref &p_sky) { if (bg_sky.is_valid()) sb_rid = bg_sky->get_rid(); - VS::get_singleton()->environment_set_sky(environment, sb_rid); + RS::get_singleton()->environment_set_sky(environment, sb_rid); } void Environment::set_sky_custom_fov(float p_scale) { bg_sky_custom_fov = p_scale; - VS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale); + RS::get_singleton()->environment_set_sky_custom_fov(environment, p_scale); } void Environment::set_bg_color(const Color &p_color) { bg_color = p_color; - VS::get_singleton()->environment_set_bg_color(environment, p_color); + RS::get_singleton()->environment_set_bg_color(environment, p_color); } void Environment::set_bg_energy(float p_energy) { bg_energy = p_energy; - VS::get_singleton()->environment_set_bg_energy(environment, p_energy); + RS::get_singleton()->environment_set_bg_energy(environment, p_energy); } void Environment::set_canvas_max_layer(int p_max_layer) { bg_canvas_max_layer = p_max_layer; - VS::get_singleton()->environment_set_canvas_max_layer(environment, p_max_layer); + RS::get_singleton()->environment_set_canvas_max_layer(environment, p_max_layer); } void Environment::set_ambient_light_color(const Color &p_color) { ambient_color = p_color; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); + RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } void Environment::set_ambient_light_energy(float p_energy) { ambient_energy = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); + RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } void Environment::set_ambient_light_sky_contribution(float p_energy) { ambient_sky_contribution = p_energy; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); + RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } void Environment::set_camera_feed_id(int p_camera_feed_id) { camera_feed_id = p_camera_feed_id; // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 - VS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); + RS::get_singleton()->environment_set_camera_feed_id(environment, camera_feed_id); #endif }; void Environment::set_ambient_source(AmbientSource p_source) { ambient_source = p_source; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); + RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } Environment::AmbientSource Environment::get_ambient_source() const { @@ -110,7 +110,7 @@ Environment::AmbientSource Environment::get_ambient_source() const { } void Environment::set_reflection_source(ReflectionSource p_source) { reflection_source = p_source; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); + RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } Environment::ReflectionSource Environment::get_reflection_source() const { return reflection_source; @@ -132,7 +132,7 @@ float Environment::get_sky_custom_fov() const { void Environment::set_sky_rotation(const Vector3 &p_rotation) { sky_rotation = p_rotation; - VS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); + RS::get_singleton()->environment_set_sky_orientation(environment, Basis(p_rotation)); } Vector3 Environment::get_sky_rotation() const { @@ -172,7 +172,7 @@ int Environment::get_camera_feed_id(void) const { void Environment::set_tonemapper(ToneMapper p_tone_mapper) { tone_mapper = p_tone_mapper; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } Environment::ToneMapper Environment::get_tonemapper() const { @@ -183,7 +183,7 @@ Environment::ToneMapper Environment::get_tonemapper() const { void Environment::set_tonemap_exposure(float p_exposure) { tonemap_exposure = p_exposure; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } float Environment::get_tonemap_exposure() const { @@ -194,7 +194,7 @@ float Environment::get_tonemap_exposure() const { void Environment::set_tonemap_white(float p_white) { tonemap_white = p_white; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } float Environment::get_tonemap_white() const { @@ -204,7 +204,7 @@ float Environment::get_tonemap_white() const { void Environment::set_tonemap_auto_exposure(bool p_enabled) { tonemap_auto_exposure = p_enabled; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); _change_notify(); } bool Environment::get_tonemap_auto_exposure() const { @@ -215,7 +215,7 @@ bool Environment::get_tonemap_auto_exposure() const { void Environment::set_tonemap_auto_exposure_max(float p_auto_exposure_max) { tonemap_auto_exposure_max = p_auto_exposure_max; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_max() const { @@ -225,7 +225,7 @@ float Environment::get_tonemap_auto_exposure_max() const { void Environment::set_tonemap_auto_exposure_min(float p_auto_exposure_min) { tonemap_auto_exposure_min = p_auto_exposure_min; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_min() const { @@ -235,7 +235,7 @@ float Environment::get_tonemap_auto_exposure_min() const { void Environment::set_tonemap_auto_exposure_speed(float p_auto_exposure_speed) { tonemap_auto_exposure_speed = p_auto_exposure_speed; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_speed() const { @@ -245,7 +245,7 @@ float Environment::get_tonemap_auto_exposure_speed() const { void Environment::set_tonemap_auto_exposure_grey(float p_auto_exposure_grey) { tonemap_auto_exposure_grey = p_auto_exposure_grey; - VS::get_singleton()->environment_set_tonemap(environment, VS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); + RS::get_singleton()->environment_set_tonemap(environment, RS::EnvironmentToneMapper(tone_mapper), tonemap_exposure, tonemap_white, tonemap_auto_exposure, tonemap_auto_exposure_min, tonemap_auto_exposure_max, tonemap_auto_exposure_speed, tonemap_auto_exposure_grey); } float Environment::get_tonemap_auto_exposure_grey() const { @@ -255,7 +255,7 @@ float Environment::get_tonemap_auto_exposure_grey() const { void Environment::set_adjustment_enable(bool p_enable) { adjustment_enabled = p_enable; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); _change_notify(); } @@ -267,7 +267,7 @@ bool Environment::is_adjustment_enabled() const { void Environment::set_adjustment_brightness(float p_brightness) { adjustment_brightness = p_brightness; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); } float Environment::get_adjustment_brightness() const { @@ -277,7 +277,7 @@ float Environment::get_adjustment_brightness() const { void Environment::set_adjustment_contrast(float p_contrast) { adjustment_contrast = p_contrast; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); } float Environment::get_adjustment_contrast() const { @@ -287,7 +287,7 @@ float Environment::get_adjustment_contrast() const { void Environment::set_adjustment_saturation(float p_saturation) { adjustment_saturation = p_saturation; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); } float Environment::get_adjustment_saturation() const { @@ -297,7 +297,7 @@ float Environment::get_adjustment_saturation() const { void Environment::set_adjustment_color_correction(const Ref &p_ramp) { adjustment_color_correction = p_ramp; - VS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); + RS::get_singleton()->environment_set_adjustment(environment, adjustment_enabled, adjustment_brightness, adjustment_contrast, adjustment_saturation, adjustment_color_correction.is_valid() ? adjustment_color_correction->get_rid() : RID()); } Ref Environment::get_adjustment_color_correction() const { @@ -371,7 +371,7 @@ void Environment::_validate_property(PropertyInfo &property) const { prefixes++; } - if (VisualServer::get_singleton()->is_low_end()) { + if (RenderingServer::get_singleton()->is_low_end()) { prefixes = high_end_prefixes; while (*prefixes) { String prefix = String(*prefixes); @@ -389,7 +389,7 @@ void Environment::_validate_property(PropertyInfo &property) const { void Environment::set_ssr_enabled(bool p_enable) { ssr_enabled = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); _change_notify(); } @@ -401,7 +401,7 @@ bool Environment::is_ssr_enabled() const { void Environment::set_ssr_max_steps(int p_steps) { ssr_max_steps = p_steps; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } int Environment::get_ssr_max_steps() const { @@ -411,7 +411,7 @@ int Environment::get_ssr_max_steps() const { void Environment::set_ssr_fade_in(float p_fade_in) { ssr_fade_in = p_fade_in; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } float Environment::get_ssr_fade_in() const { @@ -421,7 +421,7 @@ float Environment::get_ssr_fade_in() const { void Environment::set_ssr_fade_out(float p_fade_out) { ssr_fade_out = p_fade_out; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } float Environment::get_ssr_fade_out() const { @@ -431,7 +431,7 @@ float Environment::get_ssr_fade_out() const { void Environment::set_ssr_depth_tolerance(float p_depth_tolerance) { ssr_depth_tolerance = p_depth_tolerance; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } float Environment::get_ssr_depth_tolerance() const { @@ -441,7 +441,7 @@ float Environment::get_ssr_depth_tolerance() const { void Environment::set_ssr_rough(bool p_enable) { ssr_roughness = p_enable; - VS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); + RS::get_singleton()->environment_set_ssr(environment, ssr_enabled, ssr_max_steps, ssr_fade_in, ssr_fade_out, ssr_depth_tolerance, ssr_roughness); } bool Environment::is_ssr_rough() const { @@ -451,7 +451,7 @@ bool Environment::is_ssr_rough() const { void Environment::set_ssao_enabled(bool p_enable) { ssao_enabled = p_enable; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); _change_notify(); } @@ -463,7 +463,7 @@ bool Environment::is_ssao_enabled() const { void Environment::set_ssao_radius(float p_radius) { ssao_radius = p_radius; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_radius() const { @@ -473,7 +473,7 @@ float Environment::get_ssao_radius() const { void Environment::set_ssao_intensity(float p_intensity) { ssao_intensity = p_intensity; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_intensity() const { @@ -484,7 +484,7 @@ float Environment::get_ssao_intensity() const { void Environment::set_ssao_bias(float p_bias) { ssao_bias = p_bias; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_bias() const { @@ -494,7 +494,7 @@ float Environment::get_ssao_bias() const { void Environment::set_ssao_direct_light_affect(float p_direct_light_affect) { ssao_direct_light_affect = p_direct_light_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_direct_light_affect() const { @@ -504,7 +504,7 @@ float Environment::get_ssao_direct_light_affect() const { void Environment::set_ssao_ao_channel_affect(float p_ao_channel_affect) { ssao_ao_channel_affect = p_ao_channel_affect; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_ao_channel_affect() const { @@ -514,7 +514,7 @@ float Environment::get_ssao_ao_channel_affect() const { void Environment::set_ao_color(const Color &p_color) { ao_color = p_color; - VS::get_singleton()->environment_set_ambient_light(environment, ambient_color, VS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, VS::EnvironmentReflectionSource(reflection_source), ao_color); + RS::get_singleton()->environment_set_ambient_light(environment, ambient_color, RS::EnvironmentAmbientSource(ambient_source), ambient_energy, ambient_sky_contribution, RS::EnvironmentReflectionSource(reflection_source), ao_color); } Color Environment::get_ao_color() const { @@ -525,7 +525,7 @@ Color Environment::get_ao_color() const { void Environment::set_ssao_blur(SSAOBlur p_blur) { ssao_blur = p_blur; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } Environment::SSAOBlur Environment::get_ssao_blur() const { @@ -535,7 +535,7 @@ Environment::SSAOBlur Environment::get_ssao_blur() const { void Environment::set_ssao_edge_sharpness(float p_edge_sharpness) { ssao_edge_sharpness = p_edge_sharpness; - VS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, VS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); + RS::get_singleton()->environment_set_ssao(environment, ssao_enabled, ssao_radius, ssao_intensity, ssao_bias, ssao_direct_light_affect, ssao_ao_channel_affect, RS::EnvironmentSSAOBlur(ssao_blur), ssao_edge_sharpness); } float Environment::get_ssao_edge_sharpness() const { @@ -546,7 +546,7 @@ float Environment::get_ssao_edge_sharpness() const { void Environment::set_glow_enabled(bool p_enabled) { glow_enabled = p_enabled; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); _change_notify(); } @@ -557,18 +557,18 @@ bool Environment::is_glow_enabled() const { void Environment::set_glow_level(int p_level, bool p_enabled) { - ERR_FAIL_INDEX(p_level, VS::MAX_GLOW_LEVELS); + ERR_FAIL_INDEX(p_level, RS::MAX_GLOW_LEVELS); if (p_enabled) glow_levels |= (1 << p_level); else glow_levels &= ~(1 << p_level); - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } bool Environment::is_glow_level_enabled(int p_level) const { - ERR_FAIL_INDEX_V(p_level, VS::MAX_GLOW_LEVELS, false); + ERR_FAIL_INDEX_V(p_level, RS::MAX_GLOW_LEVELS, false); return glow_levels & (1 << p_level); } @@ -577,7 +577,7 @@ void Environment::set_glow_intensity(float p_intensity) { glow_intensity = p_intensity; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_intensity() const { @@ -587,7 +587,7 @@ float Environment::get_glow_intensity() const { void Environment::set_glow_strength(float p_strength) { glow_strength = p_strength; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_strength() const { @@ -597,7 +597,7 @@ float Environment::get_glow_strength() const { void Environment::set_glow_mix(float p_mix) { glow_mix = p_mix; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_mix() const { @@ -608,7 +608,7 @@ void Environment::set_glow_bloom(float p_threshold) { glow_bloom = p_threshold; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_bloom() const { @@ -619,7 +619,7 @@ void Environment::set_glow_blend_mode(GlowBlendMode p_mode) { glow_blend_mode = p_mode; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); _change_notify(); } Environment::GlowBlendMode Environment::get_glow_blend_mode() const { @@ -631,7 +631,7 @@ void Environment::set_glow_hdr_bleed_threshold(float p_threshold) { glow_hdr_bleed_threshold = p_threshold; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_hdr_bleed_threshold() const { @@ -642,7 +642,7 @@ void Environment::set_glow_hdr_luminance_cap(float p_amount) { glow_hdr_luminance_cap = p_amount; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_hdr_luminance_cap() const { @@ -653,7 +653,7 @@ void Environment::set_glow_hdr_bleed_scale(float p_scale) { glow_hdr_bleed_scale = p_scale; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } float Environment::get_glow_hdr_bleed_scale() const { @@ -663,7 +663,7 @@ float Environment::get_glow_hdr_bleed_scale() const { void Environment::set_glow_bicubic_upscale(bool p_enable) { glow_bicubic_upscale = p_enable; - VS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, VS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); + RS::get_singleton()->environment_set_glow(environment, glow_enabled, glow_levels, glow_intensity, glow_strength, glow_mix, glow_bloom, RS::EnvironmentGlowBlendMode(glow_blend_mode), glow_hdr_bleed_threshold, glow_hdr_bleed_threshold, glow_hdr_luminance_cap, glow_bicubic_upscale); } bool Environment::is_glow_bicubic_upscale_enabled() const { @@ -674,7 +674,7 @@ bool Environment::is_glow_bicubic_upscale_enabled() const { void Environment::set_fog_enabled(bool p_enabled) { fog_enabled = p_enabled; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); _change_notify(); } @@ -686,7 +686,7 @@ bool Environment::is_fog_enabled() const { void Environment::set_fog_color(const Color &p_color) { fog_color = p_color; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); } Color Environment::get_fog_color() const { @@ -696,7 +696,7 @@ Color Environment::get_fog_color() const { void Environment::set_fog_sun_color(const Color &p_color) { fog_sun_color = p_color; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); } Color Environment::get_fog_sun_color() const { @@ -706,7 +706,7 @@ Color Environment::get_fog_sun_color() const { void Environment::set_fog_sun_amount(float p_amount) { fog_sun_amount = p_amount; - VS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); + RS::get_singleton()->environment_set_fog(environment, fog_enabled, fog_color, fog_sun_color, fog_sun_amount); } float Environment::get_fog_sun_amount() const { @@ -716,7 +716,7 @@ float Environment::get_fog_sun_amount() const { void Environment::set_fog_depth_enabled(bool p_enabled) { fog_depth_enabled = p_enabled; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); } bool Environment::is_fog_depth_enabled() const { @@ -726,7 +726,7 @@ bool Environment::is_fog_depth_enabled() const { void Environment::set_fog_depth_begin(float p_distance) { fog_depth_begin = p_distance; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); } float Environment::get_fog_depth_begin() const { @@ -736,7 +736,7 @@ float Environment::get_fog_depth_begin() const { void Environment::set_fog_depth_end(float p_distance) { fog_depth_end = p_distance; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); } float Environment::get_fog_depth_end() const { @@ -747,7 +747,7 @@ float Environment::get_fog_depth_end() const { void Environment::set_fog_depth_curve(float p_curve) { fog_depth_curve = p_curve; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); } float Environment::get_fog_depth_curve() const { @@ -757,7 +757,7 @@ float Environment::get_fog_depth_curve() const { void Environment::set_fog_transmit_enabled(bool p_enabled) { fog_transmit_enabled = p_enabled; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); } bool Environment::is_fog_transmit_enabled() const { @@ -767,7 +767,7 @@ bool Environment::is_fog_transmit_enabled() const { void Environment::set_fog_transmit_curve(float p_curve) { fog_transmit_curve = p_curve; - VS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); + RS::get_singleton()->environment_set_fog_depth(environment, fog_depth_enabled, fog_depth_begin, fog_depth_end, fog_depth_curve, fog_transmit_enabled, fog_transmit_curve); } float Environment::get_fog_transmit_curve() const { @@ -777,7 +777,7 @@ float Environment::get_fog_transmit_curve() const { void Environment::set_fog_height_enabled(bool p_enabled) { fog_height_enabled = p_enabled; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); } bool Environment::is_fog_height_enabled() const { @@ -787,7 +787,7 @@ bool Environment::is_fog_height_enabled() const { void Environment::set_fog_height_min(float p_distance) { fog_height_min = p_distance; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); } float Environment::get_fog_height_min() const { @@ -797,7 +797,7 @@ float Environment::get_fog_height_min() const { void Environment::set_fog_height_max(float p_distance) { fog_height_max = p_distance; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); } float Environment::get_fog_height_max() const { @@ -807,7 +807,7 @@ float Environment::get_fog_height_max() const { void Environment::set_fog_height_curve(float p_distance) { fog_height_curve = p_distance; - VS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); + RS::get_singleton()->environment_set_fog_height(environment, fog_height_enabled, fog_height_min, fog_height_max, fog_height_curve); } float Environment::get_fog_height_curve() const { @@ -1152,7 +1152,7 @@ Environment::Environment() : ssao_blur(SSAO_BLUR_3x3), glow_blend_mode(GLOW_BLEND_MODE_ADDITIVE) { - environment = VS::get_singleton()->environment_create(); + environment = RS::get_singleton()->environment_create(); bg_mode = BG_CLEAR_COLOR; bg_sky_custom_fov = 0; @@ -1236,7 +1236,7 @@ Environment::Environment() : Environment::~Environment() { - VS::get_singleton()->free(environment); + RS::get_singleton()->free(environment); } ////////////////////// @@ -1244,7 +1244,7 @@ Environment::~Environment() { void CameraEffects::set_dof_blur_far_enabled(bool p_enable) { dof_blur_far_enabled = p_enable; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); } bool CameraEffects::is_dof_blur_far_enabled() const { @@ -1255,7 +1255,7 @@ bool CameraEffects::is_dof_blur_far_enabled() const { void CameraEffects::set_dof_blur_far_distance(float p_distance) { dof_blur_far_distance = p_distance; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); } float CameraEffects::get_dof_blur_far_distance() const { @@ -1265,7 +1265,7 @@ float CameraEffects::get_dof_blur_far_distance() const { void CameraEffects::set_dof_blur_far_transition(float p_distance) { dof_blur_far_transition = p_distance; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); } float CameraEffects::get_dof_blur_far_transition() const { @@ -1275,7 +1275,7 @@ float CameraEffects::get_dof_blur_far_transition() const { void CameraEffects::set_dof_blur_near_enabled(bool p_enable) { dof_blur_near_enabled = p_enable; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); _change_notify(); } @@ -1287,7 +1287,7 @@ bool CameraEffects::is_dof_blur_near_enabled() const { void CameraEffects::set_dof_blur_near_distance(float p_distance) { dof_blur_near_distance = p_distance; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); } float CameraEffects::get_dof_blur_near_distance() const { @@ -1298,7 +1298,7 @@ float CameraEffects::get_dof_blur_near_distance() const { void CameraEffects::set_dof_blur_near_transition(float p_distance) { dof_blur_near_transition = p_distance; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); } float CameraEffects::get_dof_blur_near_transition() const { @@ -1309,7 +1309,7 @@ float CameraEffects::get_dof_blur_near_transition() const { void CameraEffects::set_dof_blur_amount(float p_amount) { dof_blur_amount = p_amount; - VS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); + RS::get_singleton()->camera_effects_set_dof_blur(camera_effects, dof_blur_far_enabled, dof_blur_far_distance, dof_blur_far_transition, dof_blur_near_enabled, dof_blur_near_distance, dof_blur_near_transition, dof_blur_amount); } float CameraEffects::get_dof_blur_amount() const { @@ -1318,7 +1318,7 @@ float CameraEffects::get_dof_blur_amount() const { void CameraEffects::set_override_exposure_enabled(bool p_enabled) { override_exposure_enabled = p_enabled; - VS::get_singleton()->camera_effects_set_custom_exposure(camera_effects, override_exposure_enabled, override_exposure); + RS::get_singleton()->camera_effects_set_custom_exposure(camera_effects, override_exposure_enabled, override_exposure); } bool CameraEffects::is_override_exposure_enabled() const { @@ -1327,7 +1327,7 @@ bool CameraEffects::is_override_exposure_enabled() const { void CameraEffects::set_override_exposure(float p_exposure) { override_exposure = p_exposure; - VS::get_singleton()->camera_effects_set_custom_exposure(camera_effects, override_exposure_enabled, override_exposure); + RS::get_singleton()->camera_effects_set_custom_exposure(camera_effects, override_exposure_enabled, override_exposure); } float CameraEffects::get_override_exposure() const { @@ -1382,7 +1382,7 @@ void CameraEffects::_bind_methods() { CameraEffects::CameraEffects() { - camera_effects = VS::get_singleton()->camera_effects_create(); + camera_effects = RS::get_singleton()->camera_effects_create(); dof_blur_far_enabled = false; dof_blur_far_distance = 10; @@ -1400,5 +1400,5 @@ CameraEffects::CameraEffects() { CameraEffects::~CameraEffects() { - VS::get_singleton()->free(camera_effects); + RS::get_singleton()->free(camera_effects); } diff --git a/scene/resources/environment.h b/scene/resources/environment.h index f9fe26f792..657c7190e5 100644 --- a/scene/resources/environment.h +++ b/scene/resources/environment.h @@ -34,7 +34,7 @@ #include "core/resource.h" #include "scene/resources/sky.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Environment : public Resource { diff --git a/scene/resources/font.cpp b/scene/resources/font.cpp index 1f5e4b647a..8914cf8097 100644 --- a/scene/resources/font.cpp +++ b/scene/resources/font.cpp @@ -556,7 +556,7 @@ float BitmapFont::draw_char(RID p_canvas_item, const Point2 &p_pos, CharType p_c cpos.x += c->h_align; cpos.y -= ascent; cpos.y += c->v_align; - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate, false, RID(), RID(), Color(1, 1, 1, 1), false); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(cpos, c->rect.size), textures[c->texture_idx]->get_rid(), c->rect, p_modulate, false, RID(), RID(), Color(1, 1, 1, 1), false); } return get_char_size(p_char, p_next).width; diff --git a/scene/resources/height_map_shape_3d.cpp b/scene/resources/height_map_shape_3d.cpp index 85c081238d..33b6063299 100644 --- a/scene/resources/height_map_shape_3d.cpp +++ b/scene/resources/height_map_shape_3d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "height_map_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector HeightMapShape3D::get_debug_mesh_lines() { Vector points; @@ -88,7 +88,7 @@ void HeightMapShape3D::_update_shape() { d["heights"] = map_data; d["min_height"] = min_height; d["max_height"] = max_height; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); Shape3D::_update_shape(); } @@ -192,7 +192,7 @@ void HeightMapShape3D::_bind_methods() { } HeightMapShape3D::HeightMapShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_HEIGHTMAP)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_HEIGHTMAP)) { map_width = 2; map_depth = 2; diff --git a/scene/resources/line_shape_2d.cpp b/scene/resources/line_shape_2d.cpp index 3b30b4528a..a1c1b2f9f4 100644 --- a/scene/resources/line_shape_2d.cpp +++ b/scene/resources/line_shape_2d.cpp @@ -30,8 +30,8 @@ #include "line_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool LineShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { @@ -52,7 +52,7 @@ void LineShape2D::_update_shape() { Array arr; arr.push_back(normal); arr.push_back(d); - Physics2DServer::get_singleton()->shape_set_data(get_rid(), arr); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), arr); emit_changed(); } @@ -82,9 +82,9 @@ void LineShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector2 point = get_d() * get_normal(); Vector2 l1[2] = { point - get_normal().tangent() * 100, point + get_normal().tangent() * 100 }; - VS::get_singleton()->canvas_item_add_line(p_to_rid, l1[0], l1[1], p_color, 3); + RS::get_singleton()->canvas_item_add_line(p_to_rid, l1[0], l1[1], p_color, 3); Vector2 l2[2] = { point, point + get_normal() * 30 }; - VS::get_singleton()->canvas_item_add_line(p_to_rid, l2[0], l2[1], p_color, 3); + RS::get_singleton()->canvas_item_add_line(p_to_rid, l2[0], l2[1], p_color, 3); } Rect2 LineShape2D::get_rect() const { @@ -117,7 +117,7 @@ void LineShape2D::_bind_methods() { } LineShape2D::LineShape2D() : - Shape2D(Physics2DServer::get_singleton()->line_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->line_shape_create()) { normal = Vector2(0, 1); d = 0; diff --git a/scene/resources/material.cpp b/scene/resources/material.cpp index d387a39dbe..f52b755ed3 100644 --- a/scene/resources/material.cpp +++ b/scene/resources/material.cpp @@ -51,7 +51,7 @@ void Material::set_next_pass(const Ref &p_pass) { RID next_pass_rid; if (next_pass.is_valid()) next_pass_rid = next_pass->get_rid(); - VS::get_singleton()->material_set_next_pass(material, next_pass_rid); + RS::get_singleton()->material_set_next_pass(material, next_pass_rid); } Ref Material::get_next_pass() const { @@ -64,7 +64,7 @@ void Material::set_render_priority(int p_priority) { ERR_FAIL_COND(p_priority < RENDER_PRIORITY_MIN); ERR_FAIL_COND(p_priority > RENDER_PRIORITY_MAX); render_priority = p_priority; - VS::get_singleton()->material_set_render_priority(material, p_priority); + RS::get_singleton()->material_set_render_priority(material, p_priority); } int Material::get_render_priority() const { @@ -100,13 +100,13 @@ void Material::_bind_methods() { Material::Material() { - material = VisualServer::get_singleton()->material_create(); + material = RenderingServer::get_singleton()->material_create(); render_priority = 0; } Material::~Material() { - VisualServer::get_singleton()->free(material); + RenderingServer::get_singleton()->free(material); } /////////////////////////////////// @@ -126,7 +126,7 @@ bool ShaderMaterial::_set(const StringName &p_name, const Variant &p_value) { } } if (pr) { - VisualServer::get_singleton()->material_set_param(_get_material(), pr, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), pr, p_value); return true; } } @@ -150,7 +150,7 @@ bool ShaderMaterial::_get(const StringName &p_name, Variant &r_ret) const { } if (pr) { - r_ret = VisualServer::get_singleton()->material_get_param(_get_material(), pr); + r_ret = RenderingServer::get_singleton()->material_get_param(_get_material(), pr); return true; } } @@ -171,7 +171,7 @@ bool ShaderMaterial::property_can_revert(const String &p_name) { StringName pr = shader->remap_param(p_name); if (pr) { - Variant default_value = VisualServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); + Variant default_value = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); Variant current_value; _get(p_name, current_value); return default_value.get_type() != Variant::NIL && default_value != current_value; @@ -185,7 +185,7 @@ Variant ShaderMaterial::property_get_revert(const String &p_name) { if (shader.is_valid()) { StringName pr = shader->remap_param(p_name); if (pr) { - r_ret = VisualServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); + r_ret = RenderingServer::get_singleton()->shader_get_param_default(shader->get_rid(), pr); } } return r_ret; @@ -211,7 +211,7 @@ void ShaderMaterial::set_shader(const Ref &p_shader) { } } - VS::get_singleton()->material_set_shader(_get_material(), rid); + RS::get_singleton()->material_set_shader(_get_material(), rid); _change_notify(); //properties for shader exposed emit_changed(); } @@ -223,12 +223,12 @@ Ref ShaderMaterial::get_shader() const { void ShaderMaterial::set_shader_param(const StringName &p_param, const Variant &p_value) { - VS::get_singleton()->material_set_param(_get_material(), p_param, p_value); + RS::get_singleton()->material_set_param(_get_material(), p_param, p_value); } Variant ShaderMaterial::get_shader_param(const StringName &p_param) const { - return VS::get_singleton()->material_get_param(_get_material(), p_param); + return RS::get_singleton()->material_get_param(_get_material(), p_param); } void ShaderMaterial::_shader_changed() { @@ -392,7 +392,7 @@ void BaseMaterial3D::_update_shader() { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } } @@ -401,7 +401,7 @@ void BaseMaterial3D::_update_shader() { if (shader_map.has(mk)) { - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); shader_map[mk].users++; return; } @@ -773,7 +773,7 @@ void BaseMaterial3D::_update_shader() { code += "\tvec2 base_uv2 = UV2;\n"; } - if (!VisualServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //heightmap not supported with triplanar + if (!RenderingServer::get_singleton()->is_low_end() && features[FEATURE_HEIGHT_MAPPING] && !flags[FLAG_UV1_USE_TRIPLANAR]) { //heightmap not supported with triplanar code += "\t{\n"; code += "\t\tvec3 view_dir = normalize(normalize(-VERTEX)*mat3(TANGENT*heightmap_flip.x,-BINORMAL*heightmap_flip.y,NORMAL));\n"; // binormal is negative due to mikktspace, flip 'unflips' it ;-) @@ -953,7 +953,7 @@ void BaseMaterial3D::_update_shader() { if (distance_fade != DISTANCE_FADE_DISABLED) { if ((distance_fade == DISTANCE_FADE_OBJECT_DITHER || distance_fade == DISTANCE_FADE_PIXEL_DITHER)) { - if (!VisualServer::get_singleton()->is_low_end()) { + if (!RenderingServer::get_singleton()->is_low_end()) { code += "\t{\n"; if (distance_fade == DISTANCE_FADE_OBJECT_DITHER) { code += "\t\tfloat fade_distance = abs((INV_CAMERA_MATRIX * WORLD_MATRIX[3]).z);\n"; @@ -1112,14 +1112,14 @@ void BaseMaterial3D::_update_shader() { code += "}\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.shader = RS::get_singleton()->shader_create(); shader_data.users = 1; - VS::get_singleton()->shader_set_code(shader_data.shader, code); + RS::get_singleton()->shader_set_code(shader_data.shader, code); shader_map[mk] = shader_data; - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } void BaseMaterial3D::flush_changes() { @@ -1151,7 +1151,7 @@ void BaseMaterial3D::set_albedo(const Color &p_albedo) { albedo = p_albedo; - VS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); + RS::get_singleton()->material_set_param(_get_material(), shader_names->albedo, p_albedo); } Color BaseMaterial3D::get_albedo() const { @@ -1162,7 +1162,7 @@ Color BaseMaterial3D::get_albedo() const { void BaseMaterial3D::set_specular(float p_specular) { specular = p_specular; - VS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); + RS::get_singleton()->material_set_param(_get_material(), shader_names->specular, p_specular); } float BaseMaterial3D::get_specular() const { @@ -1173,7 +1173,7 @@ float BaseMaterial3D::get_specular() const { void BaseMaterial3D::set_roughness(float p_roughness) { roughness = p_roughness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); + RS::get_singleton()->material_set_param(_get_material(), shader_names->roughness, p_roughness); } float BaseMaterial3D::get_roughness() const { @@ -1184,7 +1184,7 @@ float BaseMaterial3D::get_roughness() const { void BaseMaterial3D::set_metallic(float p_metallic) { metallic = p_metallic; - VS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); + RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic, p_metallic); } float BaseMaterial3D::get_metallic() const { @@ -1195,7 +1195,7 @@ float BaseMaterial3D::get_metallic() const { void BaseMaterial3D::set_emission(const Color &p_emission) { emission = p_emission; - VS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); + RS::get_singleton()->material_set_param(_get_material(), shader_names->emission, p_emission); } Color BaseMaterial3D::get_emission() const { @@ -1205,7 +1205,7 @@ Color BaseMaterial3D::get_emission() const { void BaseMaterial3D::set_emission_energy(float p_emission_energy) { emission_energy = p_emission_energy; - VS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); + RS::get_singleton()->material_set_param(_get_material(), shader_names->emission_energy, p_emission_energy); } float BaseMaterial3D::get_emission_energy() const { @@ -1215,7 +1215,7 @@ float BaseMaterial3D::get_emission_energy() const { void BaseMaterial3D::set_normal_scale(float p_normal_scale) { normal_scale = p_normal_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->normal_scale, p_normal_scale); } float BaseMaterial3D::get_normal_scale() const { @@ -1225,7 +1225,7 @@ float BaseMaterial3D::get_normal_scale() const { void BaseMaterial3D::set_rim(float p_rim) { rim = p_rim; - VS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); + RS::get_singleton()->material_set_param(_get_material(), shader_names->rim, p_rim); } float BaseMaterial3D::get_rim() const { @@ -1235,7 +1235,7 @@ float BaseMaterial3D::get_rim() const { void BaseMaterial3D::set_rim_tint(float p_rim_tint) { rim_tint = p_rim_tint; - VS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); + RS::get_singleton()->material_set_param(_get_material(), shader_names->rim_tint, p_rim_tint); } float BaseMaterial3D::get_rim_tint() const { @@ -1245,7 +1245,7 @@ float BaseMaterial3D::get_rim_tint() const { void BaseMaterial3D::set_ao_light_affect(float p_ao_light_affect) { ao_light_affect = p_ao_light_affect; - VS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); + RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_light_affect, p_ao_light_affect); } float BaseMaterial3D::get_ao_light_affect() const { @@ -1255,7 +1255,7 @@ float BaseMaterial3D::get_ao_light_affect() const { void BaseMaterial3D::set_clearcoat(float p_clearcoat) { clearcoat = p_clearcoat; - VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); + RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat, p_clearcoat); } float BaseMaterial3D::get_clearcoat() const { @@ -1266,7 +1266,7 @@ float BaseMaterial3D::get_clearcoat() const { void BaseMaterial3D::set_clearcoat_gloss(float p_clearcoat_gloss) { clearcoat_gloss = p_clearcoat_gloss; - VS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); + RS::get_singleton()->material_set_param(_get_material(), shader_names->clearcoat_gloss, p_clearcoat_gloss); } float BaseMaterial3D::get_clearcoat_gloss() const { @@ -1277,7 +1277,7 @@ float BaseMaterial3D::get_clearcoat_gloss() const { void BaseMaterial3D::set_anisotropy(float p_anisotropy) { anisotropy = p_anisotropy; - VS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); + RS::get_singleton()->material_set_param(_get_material(), shader_names->anisotropy, p_anisotropy); } float BaseMaterial3D::get_anisotropy() const { @@ -1287,7 +1287,7 @@ float BaseMaterial3D::get_anisotropy() const { void BaseMaterial3D::set_heightmap_scale(float p_heightmap_scale) { heightmap_scale = p_heightmap_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_scale, p_heightmap_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_scale, p_heightmap_scale); } float BaseMaterial3D::get_heightmap_scale() const { @@ -1298,7 +1298,7 @@ float BaseMaterial3D::get_heightmap_scale() const { void BaseMaterial3D::set_subsurface_scattering_strength(float p_subsurface_scattering_strength) { subsurface_scattering_strength = p_subsurface_scattering_strength; - VS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); + RS::get_singleton()->material_set_param(_get_material(), shader_names->subsurface_scattering_strength, subsurface_scattering_strength); } float BaseMaterial3D::get_subsurface_scattering_strength() const { @@ -1309,7 +1309,7 @@ float BaseMaterial3D::get_subsurface_scattering_strength() const { void BaseMaterial3D::set_transmission(const Color &p_transmission) { transmission = p_transmission; - VS::get_singleton()->material_set_param(_get_material(), shader_names->transmission, transmission); + RS::get_singleton()->material_set_param(_get_material(), shader_names->transmission, transmission); } Color BaseMaterial3D::get_transmission() const { @@ -1320,7 +1320,7 @@ Color BaseMaterial3D::get_transmission() const { void BaseMaterial3D::set_refraction(float p_refraction) { refraction = p_refraction; - VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); + RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction, refraction); } float BaseMaterial3D::get_refraction() const { @@ -1488,7 +1488,7 @@ void BaseMaterial3D::set_texture(TextureParam p_param, const Ref &p_t ERR_FAIL_INDEX(p_param, TEXTURE_MAX); textures[p_param] = p_texture; RID rid = p_texture.is_valid() ? p_texture->get_rid() : RID(); - VS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); + RS::get_singleton()->material_set_param(_get_material(), shader_names->texture_names[p_param], rid); _change_notify(); _queue_shader_change(); } @@ -1637,7 +1637,7 @@ void BaseMaterial3D::_validate_property(PropertyInfo &property) const { void BaseMaterial3D::set_point_size(float p_point_size) { point_size = p_point_size; - VS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); + RS::get_singleton()->material_set_param(_get_material(), shader_names->point_size, p_point_size); } float BaseMaterial3D::get_point_size() const { @@ -1648,7 +1648,7 @@ float BaseMaterial3D::get_point_size() const { void BaseMaterial3D::set_uv1_scale(const Vector3 &p_scale) { uv1_scale = p_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_scale, p_scale); } Vector3 BaseMaterial3D::get_uv1_scale() const { @@ -1659,7 +1659,7 @@ Vector3 BaseMaterial3D::get_uv1_scale() const { void BaseMaterial3D::set_uv1_offset(const Vector3 &p_offset) { uv1_offset = p_offset; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_offset, p_offset); } Vector3 BaseMaterial3D::get_uv1_offset() const { @@ -1669,7 +1669,7 @@ Vector3 BaseMaterial3D::get_uv1_offset() const { void BaseMaterial3D::set_uv1_triplanar_blend_sharpness(float p_sharpness) { uv1_triplanar_sharpness = p_sharpness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv1_blend_sharpness, p_sharpness); } float BaseMaterial3D::get_uv1_triplanar_blend_sharpness() const { @@ -1680,7 +1680,7 @@ float BaseMaterial3D::get_uv1_triplanar_blend_sharpness() const { void BaseMaterial3D::set_uv2_scale(const Vector3 &p_scale) { uv2_scale = p_scale; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_scale, p_scale); } Vector3 BaseMaterial3D::get_uv2_scale() const { @@ -1691,7 +1691,7 @@ Vector3 BaseMaterial3D::get_uv2_scale() const { void BaseMaterial3D::set_uv2_offset(const Vector3 &p_offset) { uv2_offset = p_offset; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_offset, p_offset); } Vector3 BaseMaterial3D::get_uv2_offset() const { @@ -1702,7 +1702,7 @@ Vector3 BaseMaterial3D::get_uv2_offset() const { void BaseMaterial3D::set_uv2_triplanar_blend_sharpness(float p_sharpness) { uv2_triplanar_sharpness = p_sharpness; - VS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); + RS::get_singleton()->material_set_param(_get_material(), shader_names->uv2_blend_sharpness, p_sharpness); } float BaseMaterial3D::get_uv2_triplanar_blend_sharpness() const { @@ -1725,7 +1725,7 @@ BaseMaterial3D::BillboardMode BaseMaterial3D::get_billboard_mode() const { void BaseMaterial3D::set_particles_anim_h_frames(int p_frames) { particles_anim_h_frames = p_frames; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_h_frames, p_frames); } int BaseMaterial3D::get_particles_anim_h_frames() const { @@ -1735,7 +1735,7 @@ int BaseMaterial3D::get_particles_anim_h_frames() const { void BaseMaterial3D::set_particles_anim_v_frames(int p_frames) { particles_anim_v_frames = p_frames; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_v_frames, p_frames); } int BaseMaterial3D::get_particles_anim_v_frames() const { @@ -1746,7 +1746,7 @@ int BaseMaterial3D::get_particles_anim_v_frames() const { void BaseMaterial3D::set_particles_anim_loop(bool p_loop) { particles_anim_loop = p_loop; - VS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); + RS::get_singleton()->material_set_param(_get_material(), shader_names->particles_anim_loop, particles_anim_loop); } bool BaseMaterial3D::get_particles_anim_loop() const { @@ -1769,7 +1769,7 @@ bool BaseMaterial3D::is_heightmap_deep_parallax_enabled() const { void BaseMaterial3D::set_heightmap_deep_parallax_min_layers(int p_layer) { deep_parallax_min_layers = p_layer; - VS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_min_layers, p_layer); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_min_layers, p_layer); } int BaseMaterial3D::get_heightmap_deep_parallax_min_layers() const { @@ -1779,7 +1779,7 @@ int BaseMaterial3D::get_heightmap_deep_parallax_min_layers() const { void BaseMaterial3D::set_heightmap_deep_parallax_max_layers(int p_layer) { deep_parallax_max_layers = p_layer; - VS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_max_layers, p_layer); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_max_layers, p_layer); } int BaseMaterial3D::get_heightmap_deep_parallax_max_layers() const { @@ -1789,7 +1789,7 @@ int BaseMaterial3D::get_heightmap_deep_parallax_max_layers() const { void BaseMaterial3D::set_heightmap_deep_parallax_flip_tangent(bool p_flip) { heightmap_parallax_flip_tangent = p_flip; - VS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); } bool BaseMaterial3D::get_heightmap_deep_parallax_flip_tangent() const { @@ -1800,7 +1800,7 @@ bool BaseMaterial3D::get_heightmap_deep_parallax_flip_tangent() const { void BaseMaterial3D::set_heightmap_deep_parallax_flip_binormal(bool p_flip) { heightmap_parallax_flip_binormal = p_flip; - VS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->heightmap_flip, Vector2(heightmap_parallax_flip_tangent ? -1 : 1, heightmap_parallax_flip_binormal ? -1 : 1)); } bool BaseMaterial3D::get_heightmap_deep_parallax_flip_binormal() const { @@ -1820,7 +1820,7 @@ bool BaseMaterial3D::is_grow_enabled() const { void BaseMaterial3D::set_alpha_scissor_threshold(float p_threshold) { alpha_scissor_threshold = p_threshold; - VS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); + RS::get_singleton()->material_set_param(_get_material(), shader_names->alpha_scissor_threshold, p_threshold); } float BaseMaterial3D::get_alpha_scissor_threshold() const { @@ -1830,7 +1830,7 @@ float BaseMaterial3D::get_alpha_scissor_threshold() const { void BaseMaterial3D::set_grow(float p_grow) { grow = p_grow; - VS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); + RS::get_singleton()->material_set_param(_get_material(), shader_names->grow, p_grow); } float BaseMaterial3D::get_grow() const { @@ -1853,7 +1853,7 @@ static Plane _get_texture_mask(BaseMaterial3D::TextureChannel p_channel) { void BaseMaterial3D::set_metallic_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); metallic_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->metallic_texture_channel, _get_texture_mask(p_channel)); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_metallic_texture_channel() const { @@ -1875,7 +1875,7 @@ void BaseMaterial3D::set_ao_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); ao_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->ao_texture_channel, _get_texture_mask(p_channel)); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_ao_texture_channel() const { @@ -1886,7 +1886,7 @@ void BaseMaterial3D::set_refraction_texture_channel(TextureChannel p_channel) { ERR_FAIL_INDEX(p_channel, 5); refraction_texture_channel = p_channel; - VS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); + RS::get_singleton()->material_set_param(_get_material(), shader_names->refraction_texture_channel, _get_texture_mask(p_channel)); } BaseMaterial3D::TextureChannel BaseMaterial3D::get_refraction_texture_channel() const { @@ -1954,7 +1954,7 @@ bool BaseMaterial3D::is_proximity_fade_enabled() const { void BaseMaterial3D::set_proximity_fade_distance(float p_distance) { proximity_fade_distance = p_distance; - VS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance); + RS::get_singleton()->material_set_param(_get_material(), shader_names->proximity_fade_distance, p_distance); } float BaseMaterial3D::get_proximity_fade_distance() const { @@ -1975,7 +1975,7 @@ BaseMaterial3D::DistanceFadeMode BaseMaterial3D::get_distance_fade() const { void BaseMaterial3D::set_distance_fade_max_distance(float p_distance) { distance_fade_max_distance = p_distance; - VS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); + RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_max, distance_fade_max_distance); } float BaseMaterial3D::get_distance_fade_max_distance() const { @@ -1985,7 +1985,7 @@ float BaseMaterial3D::get_distance_fade_max_distance() const { void BaseMaterial3D::set_distance_fade_min_distance(float p_distance) { distance_fade_min_distance = p_distance; - VS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); + RS::get_singleton()->material_set_param(_get_material(), shader_names->distance_fade_min, distance_fade_min_distance); } float BaseMaterial3D::get_distance_fade_min_distance() const { @@ -2561,11 +2561,11 @@ BaseMaterial3D::~BaseMaterial3D() { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } } diff --git a/scene/resources/material.h b/scene/resources/material.h index fc77226fb9..0c9352baf4 100644 --- a/scene/resources/material.h +++ b/scene/resources/material.h @@ -35,8 +35,8 @@ #include "core/self_list.h" #include "scene/resources/shader.h" #include "scene/resources/texture.h" -#include "servers/visual/shader_language.h" -#include "servers/visual_server.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering_server.h" class Material : public Resource { @@ -57,8 +57,8 @@ protected: public: enum { - RENDER_PRIORITY_MAX = VS::MATERIAL_RENDER_PRIORITY_MAX, - RENDER_PRIORITY_MIN = VS::MATERIAL_RENDER_PRIORITY_MIN, + RENDER_PRIORITY_MAX = RS::MATERIAL_RENDER_PRIORITY_MAX, + RENDER_PRIORITY_MIN = RS::MATERIAL_RENDER_PRIORITY_MIN, }; void set_next_pass(const Ref &p_pass); Ref get_next_pass() const; diff --git a/scene/resources/mesh.cpp b/scene/resources/mesh.cpp index 0d32fdb0fa..b37b7f9751 100644 --- a/scene/resources/mesh.cpp +++ b/scene/resources/mesh.cpp @@ -169,20 +169,20 @@ Vector Mesh::get_faces() const { /* for (int i=0;imesh_surface_get_primitive_type( mesh, i ) != VisualServer::PRIMITIVE_TRIANGLES ) + if (RenderingServer::get_singleton()->mesh_surface_get_primitive_type( mesh, i ) != RenderingServer::PRIMITIVE_TRIANGLES ) continue; Vector indices; Vector vertices; - vertices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_VERTEX); + vertices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_VERTEX); - int len=VisualServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); + int len=RenderingServer::get_singleton()->mesh_surface_get_array_index_len(mesh, i); bool has_indices; if (len>0) { - indices=VisualServer::get_singleton()->mesh_surface_get_array(mesh, i,VisualServer::ARRAY_INDEX); + indices=RenderingServer::get_singleton()->mesh_surface_get_array(mesh, i,RenderingServer::ARRAY_INDEX); has_indices=true; } else { @@ -846,7 +846,7 @@ Array ArrayMesh::_get_surfaces() const { Array ret; for (int i = 0; i < surfaces.size(); i++) { - VisualServer::SurfaceData surface = VS::get_singleton()->mesh_get_surface(mesh, i); + RenderingServer::SurfaceData surface = RS::get_singleton()->mesh_get_surface(mesh, i); Dictionary data; data["format"] = surface.format; data["primitive"] = surface.primitive; @@ -902,20 +902,20 @@ Array ArrayMesh::_get_surfaces() const { void ArrayMesh::_create_if_empty() const { if (!mesh.is_valid()) { - mesh = VS::get_singleton()->mesh_create(); - VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)blend_shape_mode); + mesh = RS::get_singleton()->mesh_create(); + RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); } } void ArrayMesh::_set_surfaces(const Array &p_surfaces) { - Vector surface_data; + Vector surface_data; Vector> surface_materials; Vector surface_names; Vector surface_2d; for (int i = 0; i < p_surfaces.size(); i++) { - VS::SurfaceData surface; + RS::SurfaceData surface; Dictionary d = p_surfaces[i]; ERR_FAIL_COND(!d.has("format")); ERR_FAIL_COND(!d.has("primitive")); @@ -923,7 +923,7 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) { ERR_FAIL_COND(!d.has("vertex_count")); ERR_FAIL_COND(!d.has("aabb")); surface.format = d["format"]; - surface.primitive = VS::PrimitiveType(int(d["primitive"])); + surface.primitive = RS::PrimitiveType(int(d["primitive"])); surface.vertex_data = d["vertex_data"]; surface.vertex_count = d["vertex_count"]; surface.aabb = d["aabb"]; @@ -938,7 +938,7 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) { Array lods = d["lods"]; ERR_FAIL_COND(lods.size() & 1); //must be even for (int j = 0; j < lods.size(); j += 2) { - VS::SurfaceData::LOD lod; + RS::SurfaceData::LOD lod; lod.edge_length = lods[j + 0]; lod.index_data = lods[j + 1]; surface.lods.push_back(lod); @@ -993,15 +993,15 @@ void ArrayMesh::_set_surfaces(const Array &p_surfaces) { if (mesh.is_valid()) { //if mesh exists, it needs to be updated - VS::get_singleton()->mesh_clear(mesh); + RS::get_singleton()->mesh_clear(mesh); for (int i = 0; i < surface_data.size(); i++) { - VS::get_singleton()->mesh_add_surface(mesh, surface_data[i]); + RS::get_singleton()->mesh_add_surface(mesh, surface_data[i]); } } else { // if mesh does not exist (first time this is loaded, most likely), // we can create it with a single call, which is a lot more efficient and thread friendly - mesh = VS::get_singleton()->mesh_create_from_surfaces(surface_data); - VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)blend_shape_mode); + mesh = RS::get_singleton()->mesh_create_from_surfaces(surface_data); + RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)blend_shape_mode); } surfaces.clear(); @@ -1102,7 +1102,7 @@ void ArrayMesh::_recompute_aabb() { #ifndef _MSC_VER #warning need to add binding to add_surface using future MeshSurfaceData object #endif -void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes, const Vector &p_bone_aabb, const Vector &p_lods) { +void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes, const Vector &p_bone_aabb, const Vector &p_lods) { _create_if_empty(); @@ -1117,9 +1117,9 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const surfaces.push_back(s); _recompute_aabb(); - VS::SurfaceData sd; + RS::SurfaceData sd; sd.format = p_format; - sd.primitive = VS::PrimitiveType(p_primitive); + sd.primitive = RS::PrimitiveType(p_primitive); sd.aabb = p_aabb; sd.vertex_count = p_vertex_count; sd.vertex_data = p_array; @@ -1129,7 +1129,7 @@ void ArrayMesh::add_surface(uint32_t p_format, PrimitiveType p_primitive, const sd.bone_aabbs = p_bone_aabb; sd.lods = p_lods; - VisualServer::get_singleton()->mesh_add_surface(mesh, sd); + RenderingServer::get_singleton()->mesh_add_surface(mesh, sd); clear_cache(); _change_notify(); @@ -1140,9 +1140,9 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & ERR_FAIL_COND(p_arrays.size() != ARRAY_MAX); - VS::SurfaceData surface; + RS::SurfaceData surface; - Error err = VS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (VisualServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags); + Error err = RS::get_singleton()->mesh_create_surface_data_from_arrays(&surface, (RenderingServer::PrimitiveType)p_primitive, p_arrays, p_blend_shapes, p_lods, p_flags); ERR_FAIL_COND(err != OK); /* print_line("format: " + itos(surface.format)); @@ -1159,16 +1159,16 @@ void ArrayMesh::add_surface_from_arrays(PrimitiveType p_primitive, const Array & Array ArrayMesh::surface_get_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); + return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, p_surface); } Array ArrayMesh::surface_get_blend_shape_arrays(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Array()); - return VisualServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); + return RenderingServer::get_singleton()->mesh_surface_get_blend_shape_arrays(mesh, p_surface); } Dictionary ArrayMesh::surface_get_lods(int p_surface) const { ERR_FAIL_INDEX_V(p_surface, surfaces.size(), Dictionary()); - return VisualServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface); + return RenderingServer::get_singleton()->mesh_surface_get_lods(mesh, p_surface); } int ArrayMesh::get_surface_count() const { @@ -1193,7 +1193,7 @@ void ArrayMesh::add_blend_shape(const StringName &p_name) { } blend_shapes.push_back(name); - //VS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); + //RS::get_singleton()->mesh_set_blend_shape_count(mesh, blend_shapes.size()); } int ArrayMesh::get_blend_shape_count() const { @@ -1215,7 +1215,7 @@ void ArrayMesh::set_blend_shape_mode(BlendShapeMode p_mode) { blend_shape_mode = p_mode; if (mesh.is_valid()) { - VS::get_singleton()->mesh_set_blend_shape_mode(mesh, (VS::BlendShapeMode)p_mode); + RS::get_singleton()->mesh_set_blend_shape_mode(mesh, (RS::BlendShapeMode)p_mode); } } @@ -1254,7 +1254,7 @@ void ArrayMesh::surface_set_material(int p_idx, const Ref &p_material) if (surfaces[p_idx].material == p_material) return; surfaces.write[p_idx].material = p_material; - VisualServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); + RenderingServer::get_singleton()->mesh_surface_set_material(mesh, p_idx, p_material.is_null() ? RID() : p_material->get_rid()); _change_notify("material"); emit_changed(); @@ -1286,7 +1286,7 @@ String ArrayMesh::surface_get_name(int p_idx) const { void ArrayMesh::surface_update_region(int p_surface, int p_offset, const Vector &p_data) { ERR_FAIL_INDEX(p_surface, surfaces.size()); - VS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); + RS::get_singleton()->mesh_surface_update_region(mesh, p_surface, p_offset, p_data); emit_changed(); } @@ -1318,7 +1318,7 @@ void ArrayMesh::clear_surfaces() { if (!mesh.is_valid()) { return; } - VS::get_singleton()->mesh_clear(mesh); + RS::get_singleton()->mesh_clear(mesh); surfaces.clear(); aabb = AABB(); } @@ -1327,7 +1327,7 @@ void ArrayMesh::set_custom_aabb(const AABB &p_custom) { _create_if_empty(); custom_aabb = p_custom; - VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); + RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); } @@ -1609,7 +1609,7 @@ void ArrayMesh::_bind_methods() { } void ArrayMesh::reload_from_file() { - VisualServer::get_singleton()->mesh_clear(mesh); + RenderingServer::get_singleton()->mesh_clear(mesh); surfaces.clear(); clear_blend_shapes(); clear_cache(); @@ -1622,13 +1622,13 @@ void ArrayMesh::reload_from_file() { ArrayMesh::ArrayMesh() { //mesh is now created on demand - //mesh = VisualServer::get_singleton()->mesh_create(); + //mesh = RenderingServer::get_singleton()->mesh_create(); blend_shape_mode = BLEND_SHAPE_MODE_RELATIVE; } ArrayMesh::~ArrayMesh() { if (mesh.is_valid()) { - VisualServer::get_singleton()->free(mesh); + RenderingServer::get_singleton()->free(mesh); } } diff --git a/scene/resources/mesh.h b/scene/resources/mesh.h index e5f87dbbe5..25a9722046 100644 --- a/scene/resources/mesh.h +++ b/scene/resources/mesh.h @@ -36,7 +36,7 @@ #include "core/resource.h" #include "scene/resources/material.h" #include "scene/resources/shape_3d.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Mesh : public Resource { GDCLASS(Mesh, Resource); @@ -51,22 +51,22 @@ protected: public: enum { - NO_INDEX_ARRAY = VisualServer::NO_INDEX_ARRAY, - ARRAY_WEIGHTS_SIZE = VisualServer::ARRAY_WEIGHTS_SIZE + NO_INDEX_ARRAY = RenderingServer::NO_INDEX_ARRAY, + ARRAY_WEIGHTS_SIZE = RenderingServer::ARRAY_WEIGHTS_SIZE }; enum ArrayType { - ARRAY_VERTEX = VisualServer::ARRAY_VERTEX, - ARRAY_NORMAL = VisualServer::ARRAY_NORMAL, - ARRAY_TANGENT = VisualServer::ARRAY_TANGENT, - ARRAY_COLOR = VisualServer::ARRAY_COLOR, - ARRAY_TEX_UV = VisualServer::ARRAY_TEX_UV, - ARRAY_TEX_UV2 = VisualServer::ARRAY_TEX_UV2, - ARRAY_BONES = VisualServer::ARRAY_BONES, - ARRAY_WEIGHTS = VisualServer::ARRAY_WEIGHTS, - ARRAY_INDEX = VisualServer::ARRAY_INDEX, - ARRAY_MAX = VisualServer::ARRAY_MAX + ARRAY_VERTEX = RenderingServer::ARRAY_VERTEX, + ARRAY_NORMAL = RenderingServer::ARRAY_NORMAL, + ARRAY_TANGENT = RenderingServer::ARRAY_TANGENT, + ARRAY_COLOR = RenderingServer::ARRAY_COLOR, + ARRAY_TEX_UV = RenderingServer::ARRAY_TEX_UV, + ARRAY_TEX_UV2 = RenderingServer::ARRAY_TEX_UV2, + ARRAY_BONES = RenderingServer::ARRAY_BONES, + ARRAY_WEIGHTS = RenderingServer::ARRAY_WEIGHTS, + ARRAY_INDEX = RenderingServer::ARRAY_INDEX, + ARRAY_MAX = RenderingServer::ARRAY_MAX }; @@ -98,18 +98,18 @@ public: }; enum PrimitiveType { - PRIMITIVE_POINTS = VisualServer::PRIMITIVE_POINTS, - PRIMITIVE_LINES = VisualServer::PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP = VisualServer::PRIMITIVE_LINE_STRIP, - PRIMITIVE_TRIANGLES = VisualServer::PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP = VisualServer::PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_MAX = VisualServer::PRIMITIVE_MAX, + PRIMITIVE_POINTS = RenderingServer::PRIMITIVE_POINTS, + PRIMITIVE_LINES = RenderingServer::PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP = RenderingServer::PRIMITIVE_LINE_STRIP, + PRIMITIVE_TRIANGLES = RenderingServer::PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP = RenderingServer::PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_MAX = RenderingServer::PRIMITIVE_MAX, }; enum BlendShapeMode { - BLEND_SHAPE_MODE_NORMALIZED = VS::BLEND_SHAPE_MODE_NORMALIZED, - BLEND_SHAPE_MODE_RELATIVE = VS::BLEND_SHAPE_MODE_RELATIVE, + BLEND_SHAPE_MODE_NORMALIZED = RS::BLEND_SHAPE_MODE_NORMALIZED, + BLEND_SHAPE_MODE_RELATIVE = RS::BLEND_SHAPE_MODE_RELATIVE, }; virtual int get_surface_count() const = 0; @@ -193,7 +193,7 @@ protected: public: void add_surface_from_arrays(PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_flags = ARRAY_COMPRESS_DEFAULT); - void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes = Vector>(), const Vector &p_bone_aabbs = Vector(), const Vector &p_lods = Vector()); + void add_surface(uint32_t p_format, PrimitiveType p_primitive, const Vector &p_array, int p_vertex_count, const Vector &p_index_array, int p_index_count, const AABB &p_aabb, const Vector> &p_blend_shapes = Vector>(), const Vector &p_bone_aabbs = Vector(), const Vector &p_lods = Vector()); Array surface_get_arrays(int p_surface) const; Array surface_get_blend_shape_arrays(int p_surface) const; diff --git a/scene/resources/multimesh.cpp b/scene/resources/multimesh.cpp index aa8be326f5..ce561bfaaf 100644 --- a/scene/resources/multimesh.cpp +++ b/scene/resources/multimesh.cpp @@ -30,7 +30,7 @@ #include "multimesh.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" #ifndef DISABLE_DEPRECATED // Kept for compatibility from 3.x to 4.0. @@ -198,20 +198,20 @@ Vector MultiMesh::_get_custom_data_array() const { #endif // DISABLE_DEPRECATED void MultiMesh::set_buffer(const Vector &p_buffer) { - VS::get_singleton()->multimesh_set_buffer(multimesh, p_buffer); + RS::get_singleton()->multimesh_set_buffer(multimesh, p_buffer); } Vector MultiMesh::get_buffer() const { - return VS::get_singleton()->multimesh_get_buffer(multimesh); + return RS::get_singleton()->multimesh_get_buffer(multimesh); } void MultiMesh::set_mesh(const Ref &p_mesh) { mesh = p_mesh; if (!mesh.is_null()) - VisualServer::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); + RenderingServer::get_singleton()->multimesh_set_mesh(multimesh, mesh->get_rid()); else - VisualServer::get_singleton()->multimesh_set_mesh(multimesh, RID()); + RenderingServer::get_singleton()->multimesh_set_mesh(multimesh, RID()); } Ref MultiMesh::get_mesh() const { @@ -221,7 +221,7 @@ Ref MultiMesh::get_mesh() const { void MultiMesh::set_instance_count(int p_count) { ERR_FAIL_COND(p_count < 0); - VisualServer::get_singleton()->multimesh_allocate(multimesh, p_count, VS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data); + RenderingServer::get_singleton()->multimesh_allocate(multimesh, p_count, RS::MultimeshTransformFormat(transform_format), use_colors, use_custom_data); instance_count = p_count; } int MultiMesh::get_instance_count() const { @@ -232,7 +232,7 @@ int MultiMesh::get_instance_count() const { void MultiMesh::set_visible_instance_count(int p_count) { ERR_FAIL_COND(p_count < -1); ERR_FAIL_COND(p_count > instance_count); - VisualServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count); + RenderingServer::get_singleton()->multimesh_set_visible_instances(multimesh, p_count); visible_instance_count = p_count; } int MultiMesh::get_visible_instance_count() const { @@ -242,45 +242,45 @@ int MultiMesh::get_visible_instance_count() const { void MultiMesh::set_instance_transform(int p_instance, const Transform &p_transform) { - VisualServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform); + RenderingServer::get_singleton()->multimesh_instance_set_transform(multimesh, p_instance, p_transform); } void MultiMesh::set_instance_transform_2d(int p_instance, const Transform2D &p_transform) { - VisualServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform); + RenderingServer::get_singleton()->multimesh_instance_set_transform_2d(multimesh, p_instance, p_transform); } Transform MultiMesh::get_instance_transform(int p_instance) const { - return VisualServer::get_singleton()->multimesh_instance_get_transform(multimesh, p_instance); + return RenderingServer::get_singleton()->multimesh_instance_get_transform(multimesh, p_instance); } Transform2D MultiMesh::get_instance_transform_2d(int p_instance) const { - return VisualServer::get_singleton()->multimesh_instance_get_transform_2d(multimesh, p_instance); + return RenderingServer::get_singleton()->multimesh_instance_get_transform_2d(multimesh, p_instance); } void MultiMesh::set_instance_color(int p_instance, const Color &p_color) { - VisualServer::get_singleton()->multimesh_instance_set_color(multimesh, p_instance, p_color); + RenderingServer::get_singleton()->multimesh_instance_set_color(multimesh, p_instance, p_color); } Color MultiMesh::get_instance_color(int p_instance) const { - return VisualServer::get_singleton()->multimesh_instance_get_color(multimesh, p_instance); + return RenderingServer::get_singleton()->multimesh_instance_get_color(multimesh, p_instance); } void MultiMesh::set_instance_custom_data(int p_instance, const Color &p_custom_data) { - VisualServer::get_singleton()->multimesh_instance_set_custom_data(multimesh, p_instance, p_custom_data); + RenderingServer::get_singleton()->multimesh_instance_set_custom_data(multimesh, p_instance, p_custom_data); } Color MultiMesh::get_instance_custom_data(int p_instance) const { - return VisualServer::get_singleton()->multimesh_instance_get_custom_data(multimesh, p_instance); + return RenderingServer::get_singleton()->multimesh_instance_get_custom_data(multimesh, p_instance); } AABB MultiMesh::get_aabb() const { - return VisualServer::get_singleton()->multimesh_get_aabb(multimesh); + return RenderingServer::get_singleton()->multimesh_get_aabb(multimesh); } RID MultiMesh::get_rid() const { @@ -375,7 +375,7 @@ void MultiMesh::_bind_methods() { MultiMesh::MultiMesh() { - multimesh = VisualServer::get_singleton()->multimesh_create(); + multimesh = RenderingServer::get_singleton()->multimesh_create(); use_colors = false; use_custom_data = false; transform_format = TRANSFORM_2D; @@ -385,5 +385,5 @@ MultiMesh::MultiMesh() { MultiMesh::~MultiMesh() { - VisualServer::get_singleton()->free(multimesh); + RenderingServer::get_singleton()->free(multimesh); } diff --git a/scene/resources/multimesh.h b/scene/resources/multimesh.h index 8ca30a5b88..c1e52bc981 100644 --- a/scene/resources/multimesh.h +++ b/scene/resources/multimesh.h @@ -32,7 +32,7 @@ #define MULTIMESH_H #include "scene/resources/mesh.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class MultiMesh : public Resource { @@ -41,8 +41,8 @@ class MultiMesh : public Resource { public: enum TransformFormat { - TRANSFORM_2D = VS::MULTIMESH_TRANSFORM_2D, - TRANSFORM_3D = VS::MULTIMESH_TRANSFORM_3D + TRANSFORM_2D = RS::MULTIMESH_TRANSFORM_2D, + TRANSFORM_3D = RS::MULTIMESH_TRANSFORM_3D }; private: diff --git a/scene/resources/particles_material.cpp b/scene/resources/particles_material.cpp index f18e8956f1..63766c1756 100644 --- a/scene/resources/particles_material.cpp +++ b/scene/resources/particles_material.cpp @@ -121,7 +121,7 @@ void ParticlesMaterial::_update_shader() { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } } @@ -130,7 +130,7 @@ void ParticlesMaterial::_update_shader() { if (shader_map.has(mk)) { - VS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_map[mk].shader); shader_map[mk].users++; return; } @@ -592,14 +592,14 @@ void ParticlesMaterial::_update_shader() { code += "\n"; ShaderData shader_data; - shader_data.shader = VS::get_singleton()->shader_create(); + shader_data.shader = RS::get_singleton()->shader_create(); shader_data.users = 1; - VS::get_singleton()->shader_set_code(shader_data.shader, code); + RS::get_singleton()->shader_set_code(shader_data.shader, code); shader_map[mk] = shader_data; - VS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); + RS::get_singleton()->material_set_shader(_get_material(), shader_data.shader); } void ParticlesMaterial::flush_changes() { @@ -631,7 +631,7 @@ bool ParticlesMaterial::_is_shader_dirty() const { void ParticlesMaterial::set_direction(Vector3 p_direction) { direction = p_direction; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->direction, direction); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->direction, direction); } Vector3 ParticlesMaterial::get_direction() const { @@ -642,7 +642,7 @@ Vector3 ParticlesMaterial::get_direction() const { void ParticlesMaterial::set_spread(float p_spread) { spread = p_spread; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->spread, p_spread); } float ParticlesMaterial::get_spread() const { @@ -653,7 +653,7 @@ float ParticlesMaterial::get_spread() const { void ParticlesMaterial::set_flatness(float p_flatness) { flatness = p_flatness; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->flatness, p_flatness); } float ParticlesMaterial::get_flatness() const { @@ -668,40 +668,40 @@ void ParticlesMaterial::set_param(Parameter p_param, float p_value) { switch (p_param) { case PARAM_INITIAL_LINEAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity, p_value); } break; case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity, p_value); } break; case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity, p_value); } break; case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel, p_value); } break; case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel, p_value); } break; case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel, p_value); } break; case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping, p_value); } break; case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle, p_value); } break; case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale, p_value); } break; case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation, p_value); } break; case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed, p_value); } break; case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset, p_value); } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -721,40 +721,40 @@ void ParticlesMaterial::set_param_randomness(Parameter p_param, float p_value) { switch (p_param) { case PARAM_INITIAL_LINEAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_linear_velocity_random, p_value); } break; case PARAM_ANGULAR_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_random, p_value); } break; case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_random, p_value); } break; case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_random, p_value); } break; case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_random, p_value); } break; case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_random, p_value); } break; case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_random, p_value); } break; case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->initial_angle_random, p_value); } break; case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_random, p_value); } break; case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_random, p_value); } break; case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_random, p_value); } break; case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_random, p_value); } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -786,47 +786,47 @@ void ParticlesMaterial::set_param_texture(Parameter p_param, const Refmaterial_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angular_velocity_texture, p_texture); _adjust_curve_range(p_texture, -360, 360); } break; case PARAM_ORBIT_VELOCITY: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->orbit_velocity_texture, p_texture); _adjust_curve_range(p_texture, -500, 500); } break; case PARAM_LINEAR_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->linear_accel_texture, p_texture); _adjust_curve_range(p_texture, -200, 200); } break; case PARAM_RADIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->radial_accel_texture, p_texture); _adjust_curve_range(p_texture, -200, 200); } break; case PARAM_TANGENTIAL_ACCEL: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->tangent_accel_texture, p_texture); _adjust_curve_range(p_texture, -200, 200); } break; case PARAM_DAMPING: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->damping_texture, p_texture); _adjust_curve_range(p_texture, 0, 100); } break; case PARAM_ANGLE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->angle_texture, p_texture); _adjust_curve_range(p_texture, -360, 360); } break; case PARAM_SCALE: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->scale_texture, p_texture); _adjust_curve_range(p_texture, 0, 1); } break; case PARAM_HUE_VARIATION: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->hue_variation_texture, p_texture); _adjust_curve_range(p_texture, -1, 1); } break; case PARAM_ANIM_SPEED: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_speed_texture, p_texture); _adjust_curve_range(p_texture, 0, 200); } break; case PARAM_ANIM_OFFSET: { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->anim_offset_texture, p_texture); } break; case PARAM_MAX: break; // Can't happen, but silences warning } @@ -842,7 +842,7 @@ Ref ParticlesMaterial::get_param_texture(Parameter p_param) const { void ParticlesMaterial::set_color(const Color &p_color) { - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color, p_color); color = p_color; } @@ -854,7 +854,7 @@ Color ParticlesMaterial::get_color() const { void ParticlesMaterial::set_color_ramp(const Ref &p_texture) { color_ramp = p_texture; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->color_ramp, p_texture); _queue_shader_change(); _change_notify(); } @@ -888,38 +888,38 @@ void ParticlesMaterial::set_emission_shape(EmissionShape p_shape) { void ParticlesMaterial::set_emission_sphere_radius(float p_radius) { emission_sphere_radius = p_radius; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_sphere_radius, p_radius); } void ParticlesMaterial::set_emission_box_extents(Vector3 p_extents) { emission_box_extents = p_extents; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_box_extents, p_extents); } void ParticlesMaterial::set_emission_point_texture(const Ref &p_points) { emission_point_texture = p_points; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_points, p_points); } void ParticlesMaterial::set_emission_normal_texture(const Ref &p_normals) { emission_normal_texture = p_normals; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_normal, p_normals); } void ParticlesMaterial::set_emission_color_texture(const Ref &p_colors) { emission_color_texture = p_colors; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_color, p_colors); _queue_shader_change(); } void ParticlesMaterial::set_emission_point_count(int p_count) { emission_point_count = p_count; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->emission_texture_point_count, p_count); } ParticlesMaterial::EmissionShape ParticlesMaterial::get_emission_shape() const { @@ -957,7 +957,7 @@ int ParticlesMaterial::get_emission_point_count() const { void ParticlesMaterial::set_trail_divisor(int p_divisor) { trail_divisor = p_divisor; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_divisor, p_divisor); } int ParticlesMaterial::get_trail_divisor() const { @@ -974,7 +974,7 @@ void ParticlesMaterial::set_trail_size_modifier(const Ref &p_trail curve->ensure_default_setup(); } - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_size_modifier, curve); _queue_shader_change(); } @@ -986,7 +986,7 @@ Ref ParticlesMaterial::get_trail_size_modifier() const { void ParticlesMaterial::set_trail_color_modifier(const Ref &p_trail_color_modifier) { trail_color_modifier = p_trail_color_modifier; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->trail_color_modifier, p_trail_color_modifier); _queue_shader_change(); } @@ -1002,7 +1002,7 @@ void ParticlesMaterial::set_gravity(const Vector3 &p_gravity) { if (gset == Vector3()) { gset = Vector3(0, -0.000001, 0); //as gravity is used as upvector in some calculations } - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->gravity, gset); } Vector3 ParticlesMaterial::get_gravity() const { @@ -1013,7 +1013,7 @@ Vector3 ParticlesMaterial::get_gravity() const { void ParticlesMaterial::set_lifetime_randomness(float p_lifetime) { lifetime_randomness = p_lifetime; - VisualServer::get_singleton()->material_set_param(_get_material(), shader_names->lifetime_randomness, lifetime_randomness); + RenderingServer::get_singleton()->material_set_param(_get_material(), shader_names->lifetime_randomness, lifetime_randomness); } float ParticlesMaterial::get_lifetime_randomness() const { @@ -1280,10 +1280,10 @@ ParticlesMaterial::~ParticlesMaterial() { shader_map[current_key].users--; if (shader_map[current_key].users == 0) { //deallocate shader, as it's no longer in use - VS::get_singleton()->free(shader_map[current_key].shader); + RS::get_singleton()->free(shader_map[current_key].shader); shader_map.erase(current_key); } - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } } diff --git a/scene/resources/physics_material.h b/scene/resources/physics_material.h index 2f7f4424b2..f4a77d9854 100644 --- a/scene/resources/physics_material.h +++ b/scene/resources/physics_material.h @@ -32,7 +32,7 @@ #define physics_material_override_H #include "core/resource.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" class PhysicsMaterial : public Resource { diff --git a/scene/resources/primitive_meshes.cpp b/scene/resources/primitive_meshes.cpp index 959ee214a2..0792af2143 100644 --- a/scene/resources/primitive_meshes.cpp +++ b/scene/resources/primitive_meshes.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "primitive_meshes.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" /** PrimitiveMesh @@ -37,10 +37,10 @@ void PrimitiveMesh::_update() const { Array arr; - arr.resize(VS::ARRAY_MAX); + arr.resize(RS::ARRAY_MAX); _create_mesh_array(arr); - Vector points = arr[VS::ARRAY_VERTEX]; + Vector points = arr[RS::ARRAY_VERTEX]; aabb = AABB(); @@ -57,10 +57,10 @@ void PrimitiveMesh::_update() const { } } - Vector indices = arr[VS::ARRAY_INDEX]; + Vector indices = arr[RS::ARRAY_INDEX]; if (flip_faces) { - Vector normals = arr[VS::ARRAY_NORMAL]; + Vector normals = arr[RS::ARRAY_NORMAL]; if (normals.size() && indices.size()) { @@ -79,17 +79,17 @@ void PrimitiveMesh::_update() const { SWAP(w[i + 0], w[i + 1]); } } - arr[VS::ARRAY_NORMAL] = normals; - arr[VS::ARRAY_INDEX] = indices; + arr[RS::ARRAY_NORMAL] = normals; + arr[RS::ARRAY_INDEX] = indices; } } array_len = pc; index_array_len = indices.size(); // in with the new - VisualServer::get_singleton()->mesh_clear(mesh); - VisualServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (VisualServer::PrimitiveType)primitive_type, arr); - VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); + RenderingServer::get_singleton()->mesh_clear(mesh); + RenderingServer::get_singleton()->mesh_add_surface_from_arrays(mesh, (RenderingServer::PrimitiveType)primitive_type, arr); + RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); pending_request = false; @@ -136,7 +136,7 @@ Array PrimitiveMesh::surface_get_arrays(int p_surface) const { _update(); } - return VisualServer::get_singleton()->mesh_surface_get_arrays(mesh, 0); + return RenderingServer::get_singleton()->mesh_surface_get_arrays(mesh, 0); } Dictionary PrimitiveMesh::surface_get_lods(int p_surface) const { @@ -150,7 +150,7 @@ Array PrimitiveMesh::surface_get_blend_shape_arrays(int p_surface) const { uint32_t PrimitiveMesh::surface_get_format(int p_idx) const { ERR_FAIL_INDEX_V(p_idx, 1, 0); - return VS::ARRAY_FORMAT_VERTEX | VS::ARRAY_FORMAT_NORMAL | VS::ARRAY_FORMAT_TANGENT | VS::ARRAY_FORMAT_TEX_UV | VS::ARRAY_FORMAT_INDEX | VS::ARRAY_COMPRESS_DEFAULT; + return RS::ARRAY_FORMAT_VERTEX | RS::ARRAY_FORMAT_NORMAL | RS::ARRAY_FORMAT_TANGENT | RS::ARRAY_FORMAT_TEX_UV | RS::ARRAY_FORMAT_INDEX | RS::ARRAY_COMPRESS_DEFAULT; } Mesh::PrimitiveType PrimitiveMesh::surface_get_primitive_type(int p_idx) const { @@ -215,7 +215,7 @@ void PrimitiveMesh::set_material(const Ref &p_material) { material = p_material; if (!pending_request) { // just apply it, else it'll happen when _update is called. - VisualServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); + RenderingServer::get_singleton()->mesh_surface_set_material(mesh, 0, material.is_null() ? RID() : material->get_rid()); _change_notify(); emit_changed(); }; @@ -232,7 +232,7 @@ Array PrimitiveMesh::get_mesh_arrays() const { void PrimitiveMesh::set_custom_aabb(const AABB &p_custom) { custom_aabb = p_custom; - VS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); + RS::get_singleton()->mesh_set_custom_aabb(mesh, custom_aabb); emit_changed(); } @@ -254,7 +254,7 @@ PrimitiveMesh::PrimitiveMesh() { flip_faces = false; // defaults - mesh = VisualServer::get_singleton()->mesh_create(); + mesh = RenderingServer::get_singleton()->mesh_create(); // assume primitive triangles as the type, correct for all but one and it will change this :) primitive_type = Mesh::PRIMITIVE_TRIANGLES; @@ -267,7 +267,7 @@ PrimitiveMesh::PrimitiveMesh() { } PrimitiveMesh::~PrimitiveMesh() { - VisualServer::get_singleton()->free(mesh); + RenderingServer::get_singleton()->free(mesh); } /** @@ -413,11 +413,11 @@ void CapsuleMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void CapsuleMesh::_bind_methods() { @@ -670,11 +670,11 @@ void CubeMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void CubeMesh::_bind_methods() { @@ -871,11 +871,11 @@ void CylinderMesh::_create_mesh_array(Array &p_arr) const { }; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void CylinderMesh::_bind_methods() { @@ -1010,11 +1010,11 @@ void PlaneMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void PlaneMesh::_bind_methods() { @@ -1270,11 +1270,11 @@ void PrismMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void PrismMesh::_bind_methods() { @@ -1401,10 +1401,10 @@ void QuadMesh::_create_mesh_array(Array &p_arr) const { uvs.set(i, quad_uv[j]); } - p_arr[VS::ARRAY_VERTEX] = faces; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_VERTEX] = faces; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; } void QuadMesh::_bind_methods() { @@ -1494,11 +1494,11 @@ void SphereMesh::_create_mesh_array(Array &p_arr) const { thisrow = point; }; - p_arr[VS::ARRAY_VERTEX] = points; - p_arr[VS::ARRAY_NORMAL] = normals; - p_arr[VS::ARRAY_TANGENT] = tangents; - p_arr[VS::ARRAY_TEX_UV] = uvs; - p_arr[VS::ARRAY_INDEX] = indices; + p_arr[RS::ARRAY_VERTEX] = points; + p_arr[RS::ARRAY_NORMAL] = normals; + p_arr[RS::ARRAY_TANGENT] = tangents; + p_arr[RS::ARRAY_TEX_UV] = uvs; + p_arr[RS::ARRAY_INDEX] = indices; } void SphereMesh::_bind_methods() { @@ -1585,7 +1585,7 @@ void PointMesh::_create_mesh_array(Array &p_arr) const { faces.resize(1); faces.set(0, Vector3(0.0, 0.0, 0.0)); - p_arr[VS::ARRAY_VERTEX] = faces; + p_arr[RS::ARRAY_VERTEX] = faces; } PointMesh::PointMesh() { diff --git a/scene/resources/ray_shape_3d.cpp b/scene/resources/ray_shape_3d.cpp index ad927afd58..0211c55f46 100644 --- a/scene/resources/ray_shape_3d.cpp +++ b/scene/resources/ray_shape_3d.cpp @@ -30,7 +30,7 @@ #include "ray_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector RayShape3D::get_debug_mesh_lines() { @@ -50,7 +50,7 @@ void RayShape3D::_update_shape() { Dictionary d; d["length"] = length; d["slips_on_slope"] = slips_on_slope; - PhysicsServer::get_singleton()->shape_set_data(get_shape(), d); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), d); Shape3D::_update_shape(); } @@ -92,7 +92,7 @@ void RayShape3D::_bind_methods() { } RayShape3D::RayShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_RAY)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_RAY)) { length = 1.0; slips_on_slope = false; diff --git a/scene/resources/rectangle_shape_2d.cpp b/scene/resources/rectangle_shape_2d.cpp index f8c8ffb289..19e72a65b0 100644 --- a/scene/resources/rectangle_shape_2d.cpp +++ b/scene/resources/rectangle_shape_2d.cpp @@ -30,11 +30,11 @@ #include "rectangle_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" void RectangleShape2D::_update_shape() { - Physics2DServer::get_singleton()->shape_set_data(get_rid(), extents); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), extents); emit_changed(); } @@ -51,7 +51,7 @@ Vector2 RectangleShape2D::get_extents() const { void RectangleShape2D::draw(const RID &p_to_rid, const Color &p_color) { - VisualServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-extents, extents * 2.0), p_color); + RenderingServer::get_singleton()->canvas_item_add_rect(p_to_rid, Rect2(-extents, extents * 2.0), p_color); } Rect2 RectangleShape2D::get_rect() const { @@ -72,7 +72,7 @@ void RectangleShape2D::_bind_methods() { } RectangleShape2D::RectangleShape2D() : - Shape2D(Physics2DServer::get_singleton()->rectangle_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->rectangle_shape_create()) { extents = Vector2(10, 10); _update_shape(); diff --git a/scene/resources/segment_shape_2d.cpp b/scene/resources/segment_shape_2d.cpp index 2e78a4fccf..814c349784 100644 --- a/scene/resources/segment_shape_2d.cpp +++ b/scene/resources/segment_shape_2d.cpp @@ -30,8 +30,8 @@ #include "segment_shape_2d.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" bool SegmentShape2D::_edit_is_selected_on_click(const Point2 &p_point, double p_tolerance) const { @@ -45,7 +45,7 @@ void SegmentShape2D::_update_shape() { Rect2 r; r.position = a; r.size = b; - Physics2DServer::get_singleton()->shape_set_data(get_rid(), r); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), r); emit_changed(); } @@ -71,7 +71,7 @@ Vector2 SegmentShape2D::get_b() const { void SegmentShape2D::draw(const RID &p_to_rid, const Color &p_color) { - VisualServer::get_singleton()->canvas_item_add_line(p_to_rid, a, b, p_color, 3); + RenderingServer::get_singleton()->canvas_item_add_line(p_to_rid, a, b, p_color, 3); } Rect2 SegmentShape2D::get_rect() const { @@ -99,7 +99,7 @@ void SegmentShape2D::_bind_methods() { } SegmentShape2D::SegmentShape2D() : - Shape2D(Physics2DServer::get_singleton()->segment_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->segment_shape_create()) { a = Vector2(); b = Vector2(0, 10); @@ -113,14 +113,14 @@ void RayShape2D::_update_shape() { Dictionary d; d["length"] = length; d["slips_on_slope"] = slips_on_slope; - Physics2DServer::get_singleton()->shape_set_data(get_rid(), d); + PhysicsServer2D::get_singleton()->shape_set_data(get_rid(), d); emit_changed(); } void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { Vector2 tip = Vector2(0, get_length()); - VS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3); + RS::get_singleton()->canvas_item_add_line(p_to_rid, Vector2(), tip, p_color, 3); Vector pts; float tsize = 4; pts.push_back(tip + Vector2(0, tsize)); @@ -130,7 +130,7 @@ void RayShape2D::draw(const RID &p_to_rid, const Color &p_color) { for (int i = 0; i < 3; i++) cols.push_back(p_color); - VS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector(), RID()); + RS::get_singleton()->canvas_item_add_primitive(p_to_rid, pts, cols, Vector(), RID()); } Rect2 RayShape2D::get_rect() const { @@ -179,7 +179,7 @@ bool RayShape2D::get_slips_on_slope() const { } RayShape2D::RayShape2D() : - Shape2D(Physics2DServer::get_singleton()->ray_shape_create()) { + Shape2D(PhysicsServer2D::get_singleton()->ray_shape_create()) { length = 20; slips_on_slope = false; diff --git a/scene/resources/shader.cpp b/scene/resources/shader.cpp index 47f6d673ae..a62e7ded16 100644 --- a/scene/resources/shader.cpp +++ b/scene/resources/shader.cpp @@ -31,8 +31,8 @@ #include "shader.h" #include "core/os/file_access.h" #include "scene/scene_string_names.h" -#include "servers/visual/shader_language.h" -#include "servers/visual_server.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering_server.h" #include "texture.h" Shader::Mode Shader::get_mode() const { @@ -54,7 +54,7 @@ void Shader::set_code(const String &p_code) { mode = MODE_SPATIAL; } - VisualServer::get_singleton()->shader_set_code(shader, p_code); + RenderingServer::get_singleton()->shader_set_code(shader, p_code); params_cache_dirty = true; emit_changed(); @@ -63,7 +63,7 @@ void Shader::set_code(const String &p_code) { String Shader::get_code() const { _update_shader(); - return VisualServer::get_singleton()->shader_get_code(shader); + return RenderingServer::get_singleton()->shader_get_code(shader); } void Shader::get_param_list(List *p_params) const { @@ -71,7 +71,7 @@ void Shader::get_param_list(List *p_params) const { _update_shader(); List local; - VisualServer::get_singleton()->shader_get_param_list(shader, &local); + RenderingServer::get_singleton()->shader_get_param_list(shader, &local); params_cache.clear(); params_cache_dirty = false; @@ -104,10 +104,10 @@ void Shader::set_default_texture_param(const StringName &p_param, const Refshader_set_default_texture_param(shader, p_param, p_texture->get_rid()); + RS::get_singleton()->shader_set_default_texture_param(shader, p_param, p_texture->get_rid()); } else { default_textures.erase(p_param); - VS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID()); + RS::get_singleton()->shader_set_default_texture_param(shader, p_param, RID()); } emit_changed(); @@ -166,13 +166,13 @@ void Shader::_bind_methods() { Shader::Shader() { mode = MODE_SPATIAL; - shader = VisualServer::get_singleton()->shader_create(); + shader = RenderingServer::get_singleton()->shader_create(); params_cache_dirty = true; } Shader::~Shader() { - VisualServer::get_singleton()->free(shader); + RenderingServer::get_singleton()->free(shader); } //////////// diff --git a/scene/resources/shader.h b/scene/resources/shader.h index 5804fe8fef..e65457ed76 100644 --- a/scene/resources/shader.h +++ b/scene/resources/shader.h @@ -56,7 +56,7 @@ private: Mode mode; // hack the name of performance - // shaders keep a list of ShaderMaterial -> VisualServer name translations, to make + // shaders keep a list of ShaderMaterial -> RenderingServer name translations, to make // conversion fast and save memory. mutable bool params_cache_dirty; mutable Map params_cache; //map a shader param to a material param.. diff --git a/scene/resources/shape_2d.cpp b/scene/resources/shape_2d.cpp index 64930c3117..7984dadbc5 100644 --- a/scene/resources/shape_2d.cpp +++ b/scene/resources/shape_2d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "shape_2d.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" RID Shape2D::get_rid() const { return shape; @@ -38,7 +38,7 @@ RID Shape2D::get_rid() const { void Shape2D::set_custom_solver_bias(real_t p_bias) { custom_bias = p_bias; - Physics2DServer::get_singleton()->shape_set_custom_solver_bias(shape, custom_bias); + PhysicsServer2D::get_singleton()->shape_set_custom_solver_bias(shape, custom_bias); } real_t Shape2D::get_custom_solver_bias() const { @@ -50,13 +50,13 @@ bool Shape2D::collide_with_motion(const Transform2D &p_local_xform, const Vector ERR_FAIL_COND_V(p_shape.is_null(), false); int r; - return Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, NULL, 0, r); + return PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, NULL, 0, r); } bool Shape2D::collide(const Transform2D &p_local_xform, const Ref &p_shape, const Transform2D &p_shape_xform) { ERR_FAIL_COND_V(p_shape.is_null(), false); int r; - return Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), NULL, 0, r); + return PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), NULL, 0, r); } Array Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_xform, const Vector2 &p_local_motion, const Ref &p_shape, const Transform2D &p_shape_xform, const Vector2 &p_shape_motion) { @@ -66,7 +66,7 @@ Array Shape2D::collide_with_motion_and_get_contacts(const Transform2D &p_local_x Vector2 result[max_contacts * 2]; int contacts = 0; - if (!Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, result, max_contacts, contacts)) + if (!PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, p_local_motion, p_shape->get_rid(), p_shape_xform, p_shape_motion, result, max_contacts, contacts)) return Array(); Array results; @@ -84,7 +84,7 @@ Array Shape2D::collide_and_get_contacts(const Transform2D &p_local_xform, const Vector2 result[max_contacts * 2]; int contacts = 0; - if (!Physics2DServer::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), result, max_contacts, contacts)) + if (!PhysicsServer2D::get_singleton()->shape_collide(get_rid(), p_local_xform, Vector2(), p_shape->get_rid(), p_shape_xform, Vector2(), result, max_contacts, contacts)) return Array(); Array results; @@ -115,5 +115,5 @@ Shape2D::Shape2D(const RID &p_rid) { Shape2D::~Shape2D() { - Physics2DServer::get_singleton()->free(shape); + PhysicsServer2D::get_singleton()->free(shape); } diff --git a/scene/resources/shape_3d.cpp b/scene/resources/shape_3d.cpp index c3aeba857a..f4a5d91e52 100644 --- a/scene/resources/shape_3d.cpp +++ b/scene/resources/shape_3d.cpp @@ -33,7 +33,7 @@ #include "core/os/os.h" #include "scene/main/scene_tree.h" #include "scene/resources/mesh.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" void Shape3D::add_vertices_to_array(Vector &array, const Transform &p_xform) { @@ -56,7 +56,7 @@ real_t Shape3D::get_margin() const { void Shape3D::set_margin(real_t p_margin) { margin = p_margin; - PhysicsServer::get_singleton()->shape_set_margin(shape, margin); + PhysicsServer3D::get_singleton()->shape_set_margin(shape, margin); } Ref Shape3D::get_debug_mesh() { @@ -123,5 +123,5 @@ Shape3D::Shape3D(RID p_shape) : Shape3D::~Shape3D() { - PhysicsServer::get_singleton()->free(shape); + PhysicsServer3D::get_singleton()->free(shape); } diff --git a/scene/resources/sky.cpp b/scene/resources/sky.cpp index 1185b693b7..cbe86b16b2 100644 --- a/scene/resources/sky.cpp +++ b/scene/resources/sky.cpp @@ -39,7 +39,7 @@ void Sky::set_radiance_size(RadianceSize p_size) { static const int size[RADIANCE_SIZE_MAX] = { 32, 64, 128, 256, 512, 1024, 2048 }; - VS::get_singleton()->sky_set_radiance_size(sky, size[radiance_size]); + RS::get_singleton()->sky_set_radiance_size(sky, size[radiance_size]); } Sky::RadianceSize Sky::get_radiance_size() const { @@ -49,7 +49,7 @@ Sky::RadianceSize Sky::get_radiance_size() const { void Sky::set_process_mode(ProcessMode p_mode) { mode = p_mode; - VS::get_singleton()->sky_set_mode(sky, VS::SkyMode(mode)); + RS::get_singleton()->sky_set_mode(sky, RS::SkyMode(mode)); } Sky::ProcessMode Sky::get_process_mode() const { @@ -61,7 +61,7 @@ void Sky::set_material(const Ref &p_material) { RID material_rid; if (sky_material.is_valid()) material_rid = sky_material->get_rid(); - VS::get_singleton()->sky_set_material(sky, material_rid); + RS::get_singleton()->sky_set_material(sky, material_rid); } Ref Sky::get_material() const { @@ -104,10 +104,10 @@ void Sky::_bind_methods() { Sky::Sky() { mode = PROCESS_MODE_QUALITY; radiance_size = RADIANCE_SIZE_256; - sky = VS::get_singleton()->sky_create(); + sky = RS::get_singleton()->sky_create(); } Sky::~Sky() { - VS::get_singleton()->free(sky); + RS::get_singleton()->free(sky); } \ No newline at end of file diff --git a/scene/resources/sky_material.cpp b/scene/resources/sky_material.cpp index c3e51460c6..cf11da784d 100644 --- a/scene/resources/sky_material.cpp +++ b/scene/resources/sky_material.cpp @@ -33,7 +33,7 @@ void ProceduralSkyMaterial::set_sky_top_color(const Color &p_sky_top) { sky_top_color = p_sky_top; - VS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "sky_top_color", sky_top_color.to_linear()); } Color ProceduralSkyMaterial::get_sky_top_color() const { @@ -44,7 +44,7 @@ Color ProceduralSkyMaterial::get_sky_top_color() const { void ProceduralSkyMaterial::set_sky_horizon_color(const Color &p_sky_horizon) { sky_horizon_color = p_sky_horizon; - VS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "sky_horizon_color", sky_horizon_color.to_linear()); } Color ProceduralSkyMaterial::get_sky_horizon_color() const { @@ -54,7 +54,7 @@ Color ProceduralSkyMaterial::get_sky_horizon_color() const { void ProceduralSkyMaterial::set_sky_curve(float p_curve) { sky_curve = p_curve; - VS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve); + RS::get_singleton()->material_set_param(_get_material(), "sky_curve", sky_curve); } float ProceduralSkyMaterial::get_sky_curve() const { @@ -64,7 +64,7 @@ float ProceduralSkyMaterial::get_sky_curve() const { void ProceduralSkyMaterial::set_sky_energy(float p_energy) { sky_energy = p_energy; - VS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy); + RS::get_singleton()->material_set_param(_get_material(), "sky_energy", sky_energy); } float ProceduralSkyMaterial::get_sky_energy() const { @@ -74,7 +74,7 @@ float ProceduralSkyMaterial::get_sky_energy() const { void ProceduralSkyMaterial::set_ground_bottom_color(const Color &p_ground_bottom) { ground_bottom_color = p_ground_bottom; - VS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "ground_bottom_color", ground_bottom_color.to_linear()); } Color ProceduralSkyMaterial::get_ground_bottom_color() const { @@ -84,7 +84,7 @@ Color ProceduralSkyMaterial::get_ground_bottom_color() const { void ProceduralSkyMaterial::set_ground_horizon_color(const Color &p_ground_horizon) { ground_horizon_color = p_ground_horizon; - VS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear()); + RS::get_singleton()->material_set_param(_get_material(), "ground_horizon_color", ground_horizon_color.to_linear()); } Color ProceduralSkyMaterial::get_ground_horizon_color() const { @@ -94,7 +94,7 @@ Color ProceduralSkyMaterial::get_ground_horizon_color() const { void ProceduralSkyMaterial::set_ground_curve(float p_curve) { ground_curve = p_curve; - VS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve); + RS::get_singleton()->material_set_param(_get_material(), "ground_curve", ground_curve); } float ProceduralSkyMaterial::get_ground_curve() const { @@ -104,7 +104,7 @@ float ProceduralSkyMaterial::get_ground_curve() const { void ProceduralSkyMaterial::set_ground_energy(float p_energy) { ground_energy = p_energy; - VS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy); + RS::get_singleton()->material_set_param(_get_material(), "ground_energy", ground_energy); } float ProceduralSkyMaterial::get_ground_energy() const { @@ -114,7 +114,7 @@ float ProceduralSkyMaterial::get_ground_energy() const { void ProceduralSkyMaterial::set_sun_angle_min(float p_angle) { sun_angle_min = p_angle; - VS::get_singleton()->material_set_param(_get_material(), "sun_angle_min", Math::deg2rad(sun_angle_min)); + RS::get_singleton()->material_set_param(_get_material(), "sun_angle_min", Math::deg2rad(sun_angle_min)); } float ProceduralSkyMaterial::get_sun_angle_min() const { @@ -124,7 +124,7 @@ float ProceduralSkyMaterial::get_sun_angle_min() const { void ProceduralSkyMaterial::set_sun_angle_max(float p_angle) { sun_angle_max = p_angle; - VS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); + RS::get_singleton()->material_set_param(_get_material(), "sun_angle_max", Math::deg2rad(sun_angle_max)); } float ProceduralSkyMaterial::get_sun_angle_max() const { @@ -134,7 +134,7 @@ float ProceduralSkyMaterial::get_sun_angle_max() const { void ProceduralSkyMaterial::set_sun_curve(float p_curve) { sun_curve = p_curve; - VS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve); + RS::get_singleton()->material_set_param(_get_material(), "sun_curve", sun_curve); } float ProceduralSkyMaterial::get_sun_curve() const { @@ -271,11 +271,11 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() { code += "\tCOLOR = mix(ground, sky, step(0.0, EYEDIR.y));\n"; code += "}\n"; - shader = VS::get_singleton()->shader_create(); + shader = RS::get_singleton()->shader_create(); - VS::get_singleton()->shader_set_code(shader, code); + RS::get_singleton()->shader_set_code(shader, code); - VS::get_singleton()->material_set_shader(_get_material(), shader); + RS::get_singleton()->material_set_shader(_get_material(), shader); set_sky_top_color(Color(0.35, 0.46, 0.71)); set_sky_horizon_color(Color(0.55, 0.69, 0.81)); @@ -293,8 +293,8 @@ ProceduralSkyMaterial::ProceduralSkyMaterial() { } ProceduralSkyMaterial::~ProceduralSkyMaterial() { - VS::get_singleton()->free(shader); - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->free(shader); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } ///////////////////////////////////////// @@ -303,7 +303,7 @@ ProceduralSkyMaterial::~ProceduralSkyMaterial() { void PanoramaSkyMaterial::set_panorama(const Ref &p_panorama) { panorama = p_panorama; - VS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama); + RS::get_singleton()->material_set_param(_get_material(), "source_panorama", panorama); } Ref PanoramaSkyMaterial::get_panorama() const { @@ -341,16 +341,16 @@ PanoramaSkyMaterial::PanoramaSkyMaterial() { code += "\tCOLOR = texture(source_panorama, SKY_COORDS).rgb;\n"; code += "}"; - shader = VS::get_singleton()->shader_create(); + shader = RS::get_singleton()->shader_create(); - VS::get_singleton()->shader_set_code(shader, code); + RS::get_singleton()->shader_set_code(shader, code); - VS::get_singleton()->material_set_shader(_get_material(), shader); + RS::get_singleton()->material_set_shader(_get_material(), shader); } PanoramaSkyMaterial::~PanoramaSkyMaterial() { - VS::get_singleton()->free(shader); - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->free(shader); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } ////////////////////////////////// /* PhysicalSkyMaterial */ @@ -358,7 +358,7 @@ PanoramaSkyMaterial::~PanoramaSkyMaterial() { void PhysicalSkyMaterial::set_rayleigh_coefficient(float p_rayleigh) { rayleigh = p_rayleigh; - VS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh); + RS::get_singleton()->material_set_param(_get_material(), "rayleigh", rayleigh); } float PhysicalSkyMaterial::get_rayleigh_coefficient() const { @@ -368,7 +368,7 @@ float PhysicalSkyMaterial::get_rayleigh_coefficient() const { void PhysicalSkyMaterial::set_rayleigh_color(Color p_rayleigh_color) { rayleigh_color = p_rayleigh_color; - VS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color); + RS::get_singleton()->material_set_param(_get_material(), "rayleigh_color", rayleigh_color); } Color PhysicalSkyMaterial::get_rayleigh_color() const { @@ -378,7 +378,7 @@ Color PhysicalSkyMaterial::get_rayleigh_color() const { void PhysicalSkyMaterial::set_mie_coefficient(float p_mie) { mie = p_mie; - VS::get_singleton()->material_set_param(_get_material(), "mie", mie); + RS::get_singleton()->material_set_param(_get_material(), "mie", mie); } float PhysicalSkyMaterial::get_mie_coefficient() const { @@ -388,7 +388,7 @@ float PhysicalSkyMaterial::get_mie_coefficient() const { void PhysicalSkyMaterial::set_mie_eccentricity(float p_eccentricity) { mie_eccentricity = p_eccentricity; - VS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity); + RS::get_singleton()->material_set_param(_get_material(), "mie_eccentricity", mie_eccentricity); } float PhysicalSkyMaterial::get_mie_eccentricity() const { @@ -398,7 +398,7 @@ float PhysicalSkyMaterial::get_mie_eccentricity() const { void PhysicalSkyMaterial::set_mie_color(Color p_mie_color) { mie_color = p_mie_color; - VS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color); + RS::get_singleton()->material_set_param(_get_material(), "mie_color", mie_color); } Color PhysicalSkyMaterial::get_mie_color() const { return mie_color; @@ -407,7 +407,7 @@ Color PhysicalSkyMaterial::get_mie_color() const { void PhysicalSkyMaterial::set_turbidity(float p_turbidity) { turbidity = p_turbidity; - VS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity); + RS::get_singleton()->material_set_param(_get_material(), "turbidity", turbidity); } float PhysicalSkyMaterial::get_turbidity() const { @@ -417,7 +417,7 @@ float PhysicalSkyMaterial::get_turbidity() const { void PhysicalSkyMaterial::set_sun_disk_scale(float p_sun_disk_scale) { sun_disk_scale = p_sun_disk_scale; - VS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale); + RS::get_singleton()->material_set_param(_get_material(), "sun_disk_scale", sun_disk_scale); } float PhysicalSkyMaterial::get_sun_disk_scale() const { @@ -427,7 +427,7 @@ float PhysicalSkyMaterial::get_sun_disk_scale() const { void PhysicalSkyMaterial::set_ground_color(Color p_ground_color) { ground_color = p_ground_color; - VS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color); + RS::get_singleton()->material_set_param(_get_material(), "ground_color", ground_color); } Color PhysicalSkyMaterial::get_ground_color() const { @@ -437,7 +437,7 @@ Color PhysicalSkyMaterial::get_ground_color() const { void PhysicalSkyMaterial::set_exposure(float p_exposure) { exposure = p_exposure; - VS::get_singleton()->material_set_param(_get_material(), "exposure", exposure); + RS::get_singleton()->material_set_param(_get_material(), "exposure", exposure); } float PhysicalSkyMaterial::get_exposure() const { @@ -447,7 +447,7 @@ float PhysicalSkyMaterial::get_exposure() const { void PhysicalSkyMaterial::set_dither_strength(float p_dither_strength) { dither_strength = p_dither_strength; - VS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength); + RS::get_singleton()->material_set_param(_get_material(), "dither_strength", dither_strength); } float PhysicalSkyMaterial::get_dither_strength() const { @@ -604,11 +604,11 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() { code += "\tCOLOR += (hash(EYEDIR * 1741.9782) * 0.08 - 0.04) * 0.008 * dither_strength;\n"; code += "}\n"; - shader = VS::get_singleton()->shader_create(); + shader = RS::get_singleton()->shader_create(); - VS::get_singleton()->shader_set_code(shader, code); + RS::get_singleton()->shader_set_code(shader, code); - VS::get_singleton()->material_set_shader(_get_material(), shader); + RS::get_singleton()->material_set_shader(_get_material(), shader); set_rayleigh_coefficient(2.0); set_rayleigh_color(Color(0.056, 0.14, 0.3)); @@ -623,6 +623,6 @@ PhysicalSkyMaterial::PhysicalSkyMaterial() { } PhysicalSkyMaterial::~PhysicalSkyMaterial() { - VS::get_singleton()->free(shader); - VS::get_singleton()->material_set_shader(_get_material(), RID()); + RS::get_singleton()->free(shader); + RS::get_singleton()->material_set_shader(_get_material(), RID()); } diff --git a/scene/resources/sphere_shape_3d.cpp b/scene/resources/sphere_shape_3d.cpp index 46f7c96ce1..153db4c291 100644 --- a/scene/resources/sphere_shape_3d.cpp +++ b/scene/resources/sphere_shape_3d.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "sphere_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector SphereShape3D::get_debug_mesh_lines() { @@ -61,7 +61,7 @@ real_t SphereShape3D::get_enclosing_radius() const { void SphereShape3D::_update_shape() { - PhysicsServer::get_singleton()->shape_set_data(get_shape(), radius); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), radius); Shape3D::_update_shape(); } @@ -87,7 +87,7 @@ void SphereShape3D::_bind_methods() { } SphereShape3D::SphereShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_SPHERE)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_SPHERE)) { set_radius(1.0); } diff --git a/scene/resources/style_box.cpp b/scene/resources/style_box.cpp index 0cd2bed71d..56fb5d441f 100644 --- a/scene/resources/style_box.cpp +++ b/scene/resources/style_box.cpp @@ -202,7 +202,7 @@ void StyleBoxTexture::draw(RID p_canvas_item, const Rect2 &p_rect) const { if (normal_map.is_valid()) normal_rid = normal_map->get_rid(); - VisualServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), VS::NinePatchAxisMode(axis_h), VS::NinePatchAxisMode(axis_v), draw_center, modulate, normal_rid); + RenderingServer::get_singleton()->canvas_item_add_nine_patch(p_canvas_item, rect, src_rect, texture->get_rid(), Vector2(margin[MARGIN_LEFT], margin[MARGIN_TOP]), Vector2(margin[MARGIN_RIGHT], margin[MARGIN_BOTTOM]), RS::NinePatchAxisMode(axis_h), RS::NinePatchAxisMode(axis_v), draw_center, modulate, normal_rid); } void StyleBoxTexture::set_draw_center(bool p_enabled) { @@ -853,7 +853,7 @@ void StyleBoxFlat::draw(RID p_canvas_item, const Rect2 &p_rect) const { } //DRAWING - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); vs->canvas_item_add_triangle_array(p_canvas_item, indices, verts, colors, uvs); } @@ -1050,7 +1050,7 @@ Size2 StyleBoxLine::get_center_size() const { } void StyleBoxLine::draw(RID p_canvas_item, const Rect2 &p_rect) const { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); Rect2i r = p_rect; if (vertical) { diff --git a/scene/resources/style_box.h b/scene/resources/style_box.h index 1aa1a00c55..f19b93d00d 100644 --- a/scene/resources/style_box.h +++ b/scene/resources/style_box.h @@ -33,7 +33,7 @@ #include "core/resource.h" #include "scene/resources/texture.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class CanvasItem; diff --git a/scene/resources/surface_tool.cpp b/scene/resources/surface_tool.cpp index fa177d03fb..fee6bd1b54 100644 --- a/scene/resources/surface_tool.cpp +++ b/scene/resources/surface_tool.cpp @@ -519,7 +519,7 @@ void SurfaceTool::deindex() { void SurfaceTool::_create_list(const Ref &p_existing, int p_surface, List *r_vertex, List *r_index, int &lformat) { Array arr = p_existing->surface_get_arrays(p_surface); - ERR_FAIL_COND(arr.size() != VS::ARRAY_MAX); + ERR_FAIL_COND(arr.size() != RS::ARRAY_MAX); _create_list_from_arrays(arr, r_vertex, r_index, lformat); } @@ -527,14 +527,14 @@ Vector SurfaceTool::create_vertex_array_from_triangle_array Vector ret; - Vector varr = p_arrays[VS::ARRAY_VERTEX]; - Vector narr = p_arrays[VS::ARRAY_NORMAL]; - Vector tarr = p_arrays[VS::ARRAY_TANGENT]; - Vector carr = p_arrays[VS::ARRAY_COLOR]; - Vector uvarr = p_arrays[VS::ARRAY_TEX_UV]; - Vector uv2arr = p_arrays[VS::ARRAY_TEX_UV2]; - Vector barr = p_arrays[VS::ARRAY_BONES]; - Vector warr = p_arrays[VS::ARRAY_WEIGHTS]; + Vector varr = p_arrays[RS::ARRAY_VERTEX]; + Vector narr = p_arrays[RS::ARRAY_NORMAL]; + Vector tarr = p_arrays[RS::ARRAY_TANGENT]; + Vector carr = p_arrays[RS::ARRAY_COLOR]; + Vector uvarr = p_arrays[RS::ARRAY_TEX_UV]; + Vector uv2arr = p_arrays[RS::ARRAY_TEX_UV2]; + Vector barr = p_arrays[RS::ARRAY_BONES]; + Vector warr = p_arrays[RS::ARRAY_WEIGHTS]; int vc = varr.size(); if (vc == 0) @@ -542,48 +542,48 @@ Vector SurfaceTool::create_vertex_array_from_triangle_array int lformat = 0; if (varr.size()) { - lformat |= VS::ARRAY_FORMAT_VERTEX; + lformat |= RS::ARRAY_FORMAT_VERTEX; } if (narr.size()) { - lformat |= VS::ARRAY_FORMAT_NORMAL; + lformat |= RS::ARRAY_FORMAT_NORMAL; } if (tarr.size()) { - lformat |= VS::ARRAY_FORMAT_TANGENT; + lformat |= RS::ARRAY_FORMAT_TANGENT; } if (carr.size()) { - lformat |= VS::ARRAY_FORMAT_COLOR; + lformat |= RS::ARRAY_FORMAT_COLOR; } if (uvarr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV; + lformat |= RS::ARRAY_FORMAT_TEX_UV; } if (uv2arr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV2; + lformat |= RS::ARRAY_FORMAT_TEX_UV2; } if (barr.size()) { - lformat |= VS::ARRAY_FORMAT_BONES; + lformat |= RS::ARRAY_FORMAT_BONES; } if (warr.size()) { - lformat |= VS::ARRAY_FORMAT_WEIGHTS; + lformat |= RS::ARRAY_FORMAT_WEIGHTS; } for (int i = 0; i < vc; i++) { Vertex v; - if (lformat & VS::ARRAY_FORMAT_VERTEX) + if (lformat & RS::ARRAY_FORMAT_VERTEX) v.vertex = varr[i]; - if (lformat & VS::ARRAY_FORMAT_NORMAL) + if (lformat & RS::ARRAY_FORMAT_NORMAL) v.normal = narr[i]; - if (lformat & VS::ARRAY_FORMAT_TANGENT) { + if (lformat & RS::ARRAY_FORMAT_TANGENT) { Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]); v.tangent = p.normal; v.binormal = p.normal.cross(v.tangent).normalized() * p.d; } - if (lformat & VS::ARRAY_FORMAT_COLOR) + if (lformat & RS::ARRAY_FORMAT_COLOR) v.color = carr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV) + if (lformat & RS::ARRAY_FORMAT_TEX_UV) v.uv = uvarr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV2) + if (lformat & RS::ARRAY_FORMAT_TEX_UV2) v.uv2 = uv2arr[i]; - if (lformat & VS::ARRAY_FORMAT_BONES) { + if (lformat & RS::ARRAY_FORMAT_BONES) { Vector b; b.resize(4); b.write[0] = barr[i * 4 + 0]; @@ -592,7 +592,7 @@ Vector SurfaceTool::create_vertex_array_from_triangle_array b.write[3] = barr[i * 4 + 3]; v.bones = b; } - if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { + if (lformat & RS::ARRAY_FORMAT_WEIGHTS) { Vector w; w.resize(4); w.write[0] = warr[i * 4 + 0]; @@ -610,14 +610,14 @@ Vector SurfaceTool::create_vertex_array_from_triangle_array void SurfaceTool::_create_list_from_arrays(Array arr, List *r_vertex, List *r_index, int &lformat) { - Vector varr = arr[VS::ARRAY_VERTEX]; - Vector narr = arr[VS::ARRAY_NORMAL]; - Vector tarr = arr[VS::ARRAY_TANGENT]; - Vector carr = arr[VS::ARRAY_COLOR]; - Vector uvarr = arr[VS::ARRAY_TEX_UV]; - Vector uv2arr = arr[VS::ARRAY_TEX_UV2]; - Vector barr = arr[VS::ARRAY_BONES]; - Vector warr = arr[VS::ARRAY_WEIGHTS]; + Vector varr = arr[RS::ARRAY_VERTEX]; + Vector narr = arr[RS::ARRAY_NORMAL]; + Vector tarr = arr[RS::ARRAY_TANGENT]; + Vector carr = arr[RS::ARRAY_COLOR]; + Vector uvarr = arr[RS::ARRAY_TEX_UV]; + Vector uv2arr = arr[RS::ARRAY_TEX_UV2]; + Vector barr = arr[RS::ARRAY_BONES]; + Vector warr = arr[RS::ARRAY_WEIGHTS]; int vc = varr.size(); if (vc == 0) @@ -625,48 +625,48 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List *r_vertex, Li lformat = 0; if (varr.size()) { - lformat |= VS::ARRAY_FORMAT_VERTEX; + lformat |= RS::ARRAY_FORMAT_VERTEX; } if (narr.size()) { - lformat |= VS::ARRAY_FORMAT_NORMAL; + lformat |= RS::ARRAY_FORMAT_NORMAL; } if (tarr.size()) { - lformat |= VS::ARRAY_FORMAT_TANGENT; + lformat |= RS::ARRAY_FORMAT_TANGENT; } if (carr.size()) { - lformat |= VS::ARRAY_FORMAT_COLOR; + lformat |= RS::ARRAY_FORMAT_COLOR; } if (uvarr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV; + lformat |= RS::ARRAY_FORMAT_TEX_UV; } if (uv2arr.size()) { - lformat |= VS::ARRAY_FORMAT_TEX_UV2; + lformat |= RS::ARRAY_FORMAT_TEX_UV2; } if (barr.size()) { - lformat |= VS::ARRAY_FORMAT_BONES; + lformat |= RS::ARRAY_FORMAT_BONES; } if (warr.size()) { - lformat |= VS::ARRAY_FORMAT_WEIGHTS; + lformat |= RS::ARRAY_FORMAT_WEIGHTS; } for (int i = 0; i < vc; i++) { Vertex v; - if (lformat & VS::ARRAY_FORMAT_VERTEX) + if (lformat & RS::ARRAY_FORMAT_VERTEX) v.vertex = varr[i]; - if (lformat & VS::ARRAY_FORMAT_NORMAL) + if (lformat & RS::ARRAY_FORMAT_NORMAL) v.normal = narr[i]; - if (lformat & VS::ARRAY_FORMAT_TANGENT) { + if (lformat & RS::ARRAY_FORMAT_TANGENT) { Plane p(tarr[i * 4 + 0], tarr[i * 4 + 1], tarr[i * 4 + 2], tarr[i * 4 + 3]); v.tangent = p.normal; v.binormal = p.normal.cross(v.tangent).normalized() * p.d; } - if (lformat & VS::ARRAY_FORMAT_COLOR) + if (lformat & RS::ARRAY_FORMAT_COLOR) v.color = carr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV) + if (lformat & RS::ARRAY_FORMAT_TEX_UV) v.uv = uvarr[i]; - if (lformat & VS::ARRAY_FORMAT_TEX_UV2) + if (lformat & RS::ARRAY_FORMAT_TEX_UV2) v.uv2 = uv2arr[i]; - if (lformat & VS::ARRAY_FORMAT_BONES) { + if (lformat & RS::ARRAY_FORMAT_BONES) { Vector b; b.resize(4); b.write[0] = barr[i * 4 + 0]; @@ -675,7 +675,7 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List *r_vertex, Li b.write[3] = barr[i * 4 + 3]; v.bones = b; } - if (lformat & VS::ARRAY_FORMAT_WEIGHTS) { + if (lformat & RS::ARRAY_FORMAT_WEIGHTS) { Vector w; w.resize(4); w.write[0] = warr[i * 4 + 0]; @@ -690,11 +690,11 @@ void SurfaceTool::_create_list_from_arrays(Array arr, List *r_vertex, Li //indices - Vector idx = arr[VS::ARRAY_INDEX]; + Vector idx = arr[RS::ARRAY_INDEX]; int is = idx.size(); if (is) { - lformat |= VS::ARRAY_FORMAT_INDEX; + lformat |= RS::ARRAY_FORMAT_INDEX; const int *iarr = idx.ptr(); for (int i = 0; i < is; i++) { r_index->push_back(iarr[i]); @@ -733,7 +733,7 @@ void SurfaceTool::create_from_blend_shape(const Ref &p_existing, int p_sur ERR_FAIL_COND(shape_idx == -1); ERR_FAIL_COND(shape_idx >= arr.size()); Array mesh = arr[shape_idx]; - ERR_FAIL_COND(mesh.size() != VS::ARRAY_MAX); + ERR_FAIL_COND(mesh.size() != RS::ARRAY_MAX); _create_list_from_arrays(arr[shape_idx], &vertex_array, &index_array, format); } @@ -755,10 +755,10 @@ void SurfaceTool::append_from(const Ref &p_existing, int p_surface, const Vertex v = E->get(); v.vertex = p_xform.xform(v.vertex); - if (nformat & VS::ARRAY_FORMAT_NORMAL) { + if (nformat & RS::ARRAY_FORMAT_NORMAL) { v.normal = p_xform.basis.xform(v.normal); } - if (nformat & VS::ARRAY_FORMAT_TANGENT) { + if (nformat & RS::ARRAY_FORMAT_TANGENT) { v.tangent = p_xform.basis.xform(v.tangent); v.binormal = p_xform.basis.xform(v.binormal); } diff --git a/scene/resources/texture.cpp b/scene/resources/texture.cpp index 1c5b2abad2..74b6a16d41 100644 --- a/scene/resources/texture.cpp +++ b/scene/resources/texture.cpp @@ -47,25 +47,25 @@ bool Texture2D::is_pixel_opaque(int p_x, int p_y) const { return true; } -void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void Texture2D::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, get_size()), get_rid(), false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void Texture2D::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, get_rid(), p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void Texture2D::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, get_rid(), p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } bool Texture2D::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -82,9 +82,9 @@ void Texture2D::_bind_methods() { ClassDB::bind_method(D_METHOD("get_height"), &Texture2D::get_height); ClassDB::bind_method(D_METHOD("get_size"), &Texture2D::get_size); ClassDB::bind_method(D_METHOD("has_alpha"), &Texture2D::has_alpha); - ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); - ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); - ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("draw", "canvas_item", "position", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); + ClassDB::bind_method(D_METHOD("draw_rect", "canvas_item", "rect", "tile", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat"), &Texture2D::draw_rect, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT)); + ClassDB::bind_method(D_METHOD("draw_rect_region", "canvas_item", "rect", "src_rect", "modulate", "transpose", "normal_map", "specular_map", "specular_color_shininess", "texture_filter", "texture_repeat", "clip_uv"), &Texture2D::draw_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(Variant()), DEFVAL(Variant()), DEFVAL(Color(1, 1, 1, 1)), DEFVAL(RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT), DEFVAL(RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT), DEFVAL(true)); ClassDB::bind_method(D_METHOD("get_data"), &Texture2D::get_data); ADD_GROUP("", ""); @@ -121,7 +121,7 @@ bool ImageTexture::_set(const StringName &p_name, const Variant &p_value) { Size2 s = p_value; w = s.width; h = s.height; - VisualServer::get_singleton()->texture_set_size_override(texture, w, h); + RenderingServer::get_singleton()->texture_set_size_override(texture, w, h); } else return false; @@ -158,8 +158,8 @@ void ImageTexture::_reload_hook(const RID &p_hook) { ERR_FAIL_COND_MSG(err != OK, "Cannot load image from path '" + path + "'."); - RID new_texture = VisualServer::get_singleton()->texture_2d_create(img); - VisualServer::get_singleton()->texture_replace(texture, new_texture); + RID new_texture = RenderingServer::get_singleton()->texture_2d_create(img); + RenderingServer::get_singleton()->texture_replace(texture, new_texture); _change_notify(); emit_changed(); @@ -174,10 +174,10 @@ void ImageTexture::create_from_image(const Ref &p_image) { mipmaps = p_image->has_mipmaps(); if (texture.is_null()) { - texture = VisualServer::get_singleton()->texture_2d_create(p_image); + texture = RenderingServer::get_singleton()->texture_2d_create(p_image); } else { - RID new_texture = VisualServer::get_singleton()->texture_2d_create(p_image); - VisualServer::get_singleton()->texture_replace(texture, new_texture); + RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_image); + RenderingServer::get_singleton()->texture_replace(texture, new_texture); } _change_notify(); emit_changed(); @@ -199,9 +199,9 @@ void ImageTexture::update(const Ref &p_image, bool p_immediate) { ERR_FAIL_COND(mipmaps != p_image->has_mipmaps()); if (p_immediate) { - VisualServer::get_singleton()->texture_2d_update_immediate(texture, p_image); + RenderingServer::get_singleton()->texture_2d_update_immediate(texture, p_image); } else { - VisualServer::get_singleton()->texture_2d_update(texture, p_image); + RenderingServer::get_singleton()->texture_2d_update(texture, p_image); } _change_notify(); @@ -219,7 +219,7 @@ void ImageTexture::_resource_path_changed() { Ref ImageTexture::get_data() const { if (image_stored) { - return VisualServer::get_singleton()->texture_2d_get(texture); + return RenderingServer::get_singleton()->texture_2d_get(texture); } else { return Ref(); } @@ -239,7 +239,7 @@ RID ImageTexture::get_rid() const { if (texture.is_null()) { //we are in trouble, create something temporary - texture = VisualServer::get_singleton()->texture_2d_placeholder_create(); + texture = RenderingServer::get_singleton()->texture_2d_placeholder_create(); } return texture; } @@ -249,29 +249,29 @@ bool ImageTexture::has_alpha() const { return (format == Image::FORMAT_LA8 || format == Image::FORMAT_RGBA8); } -void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void ImageTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void ImageTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void ImageTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } bool ImageTexture::is_pixel_opaque(int p_x, int p_y) const { @@ -316,13 +316,13 @@ void ImageTexture::set_size_override(const Size2 &p_size) { w = s.x; if (s.y != 0) h = s.y; - VisualServer::get_singleton()->texture_set_size_override(texture, w, h); + RenderingServer::get_singleton()->texture_set_size_override(texture, w, h); } void ImageTexture::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { - VisualServer::get_singleton()->texture_set_path(texture, p_path); + RenderingServer::get_singleton()->texture_set_path(texture, p_path); } Resource::set_path(p_path, p_take_over); @@ -349,7 +349,7 @@ ImageTexture::ImageTexture() { ImageTexture::~ImageTexture() { if (texture.is_valid()) { - VisualServer::get_singleton()->free(texture); + RenderingServer::get_singleton()->free(texture); } } @@ -495,7 +495,7 @@ Ref StreamTexture::load_image_from_file(FileAccess *f, int p_size_limit) void StreamTexture::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { - VisualServer::get_singleton()->texture_set_path(texture, p_path); + RenderingServer::get_singleton()->texture_set_path(texture, p_path); } Resource::set_path(p_path, p_take_over); @@ -509,7 +509,7 @@ void StreamTexture::_requested_3d(void *p_ud) { request_3d_callback(stex); } -void StreamTexture::_requested_roughness(void *p_ud, const String &p_normal_path, VS::TextureDetectRoughnessChannel p_roughness_channel) { +void StreamTexture::_requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel) { StreamTexture *st = (StreamTexture *)p_ud; Ref stex(st); @@ -611,13 +611,13 @@ Error StreamTexture::load(const String &p_path) { return err; if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(image); - VS::get_singleton()->texture_replace(texture, new_texture); + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(texture, new_texture); } else { - texture = VS::get_singleton()->texture_2d_create(image); + texture = RS::get_singleton()->texture_2d_create(image); } if (lwc || lhc) { - VS::get_singleton()->texture_set_size_override(texture, lwc, lhc); + RS::get_singleton()->texture_set_size_override(texture, lwc, lhc); } w = lwc ? lwc : lw; @@ -627,33 +627,33 @@ Error StreamTexture::load(const String &p_path) { if (get_path() == String()) { //temporarily set path if no path set for resource, helps find errors - VisualServer::get_singleton()->texture_set_path(texture, p_path); + RenderingServer::get_singleton()->texture_set_path(texture, p_path); } #ifdef TOOLS_ENABLED if (request_3d) { //print_line("request detect 3D at " + p_path); - VS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); + RS::get_singleton()->texture_set_detect_3d_callback(texture, _requested_3d, this); } else { //print_line("not requesting detect 3D at " + p_path); - VS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); + RS::get_singleton()->texture_set_detect_3d_callback(texture, NULL, NULL); } if (request_roughness) { //print_line("request detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this); + RS::get_singleton()->texture_set_detect_roughness_callback(texture, _requested_roughness, this); } else { //print_line("not requesting detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_roughness_callback(texture, NULL, NULL); + RS::get_singleton()->texture_set_detect_roughness_callback(texture, NULL, NULL); } if (request_normal) { //print_line("request detect srgb at " + p_path); - VS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); + RS::get_singleton()->texture_set_detect_normal_callback(texture, _requested_normal, this); } else { //print_line("not requesting detect normal at " + p_path); - VS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); + RS::get_singleton()->texture_set_detect_normal_callback(texture, NULL, NULL); } #endif @@ -677,34 +677,34 @@ int StreamTexture::get_height() const { RID StreamTexture::get_rid() const { if (!texture.is_valid()) { - texture = VS::get_singleton()->texture_2d_placeholder_create(); + texture = RS::get_singleton()->texture_2d_placeholder_create(); } return texture; } -void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void StreamTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, Rect2(p_pos, Size2(w, h)), texture, false, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void StreamTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect(p_canvas_item, p_rect, texture, p_tile, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void StreamTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { if ((w | h) == 0) return; RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, p_rect, texture, p_src_rect, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, p_clip_uv, p_texture_filter, p_texture_repeat); } bool StreamTexture::has_alpha() const { @@ -715,7 +715,7 @@ bool StreamTexture::has_alpha() const { Ref StreamTexture::get_data() const { if (texture.is_valid()) { - return VS::get_singleton()->texture_2d_get(texture); + return RS::get_singleton()->texture_2d_get(texture); } else { return Ref(); } @@ -792,7 +792,7 @@ StreamTexture::StreamTexture() { StreamTexture::~StreamTexture() { if (texture.is_valid()) { - VS::get_singleton()->free(texture); + RS::get_singleton()->free(texture); } } @@ -935,7 +935,7 @@ void AtlasTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "filter_clip"), "set_filter_clip", "has_filter_clip"); } -void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if (!atlas.is_valid()) return; @@ -952,10 +952,10 @@ void AtlasTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_m RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, Rect2(p_pos + margin.position, rc.size), atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); } -void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if (!atlas.is_valid()) return; @@ -975,9 +975,9 @@ void AtlasTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), rc, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); } -void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { //this might not necessarily work well if using a rect, needs to be fixed properly if (!atlas.is_valid()) @@ -989,7 +989,7 @@ void AtlasTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, cons RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); + RS::get_singleton()->canvas_item_add_texture_rect_region(p_canvas_item, dr, atlas->get_rid(), src_c, p_modulate, p_transpose, normal_rid, specular_rid, p_specular_color_shininess, filter_clip, p_texture_filter, p_texture_repeat); } bool AtlasTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { @@ -1087,7 +1087,7 @@ Ref MeshTexture::get_base_texture() const { return base_texture; } -void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if (mesh.is_null() || base_texture.is_null()) { return; @@ -1100,9 +1100,9 @@ void MeshTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_mo } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { if (mesh.is_null() || base_texture.is_null()) { return; } @@ -1123,9 +1123,9 @@ void MeshTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } -void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { if (mesh.is_null() || base_texture.is_null()) { return; @@ -1147,7 +1147,7 @@ void MeshTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const } RID normal_rid = p_normal_map.is_valid() ? p_normal_map->get_rid() : RID(); RID specular_rid = p_specular_map.is_valid() ? p_specular_map->get_rid() : RID(); - VisualServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); + RenderingServer::get_singleton()->canvas_item_add_mesh(p_canvas_item, mesh->get_rid(), xform, p_modulate, base_texture->get_rid(), normal_rid, specular_rid, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } bool MeshTexture::get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const { r_rect = p_rect; @@ -1300,7 +1300,7 @@ void LargeTexture::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_data", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_data", "_get_data"); } -void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { for (int i = 0; i < pieces.size(); i++) { @@ -1309,7 +1309,7 @@ void LargeTexture::draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_m } } -void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat) const { +void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat) const { //tiling not supported for this if (size.x == 0 || size.y == 0) @@ -1323,7 +1323,7 @@ void LargeTexture::draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile pieces[i].texture->draw_rect(p_canvas_item, Rect2(pieces[i].offset * scale + p_rect.position, pieces[i].texture->get_size() * scale), false, p_modulate, p_transpose, p_normal_map, p_specular_map, p_specular_color_shininess, p_texture_filter, p_texture_repeat); } } -void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, VS::CanvasItemTextureFilter p_texture_filter, VS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { +void LargeTexture::draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, const Ref &p_normal_map, const Ref &p_specular_map, const Color &p_specular_color_shininess, RS::CanvasItemTextureFilter p_texture_filter, RS::CanvasItemTextureRepeat p_texture_repeat, bool p_clip_uv) const { //tiling not supported for this if (p_src_rect.size.x == 0 || p_src_rect.size.y == 0) @@ -1445,10 +1445,10 @@ void CurveTexture::_update() { Ref image = memnew(Image(_width, 1, false, Image::FORMAT_RF, data)); if (_texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(image); - VS::get_singleton()->texture_replace(_texture, new_texture); + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(_texture, new_texture); } else { - _texture = VS::get_singleton()->texture_2d_create(image); + _texture = RS::get_singleton()->texture_2d_create(image); } emit_changed(); @@ -1462,7 +1462,7 @@ Ref CurveTexture::get_curve() const { RID CurveTexture::get_rid() const { if (!_texture.is_valid()) { - _texture = VS::get_singleton()->texture_2d_placeholder_create(); + _texture = RS::get_singleton()->texture_2d_placeholder_create(); } return _texture; } @@ -1472,7 +1472,7 @@ CurveTexture::CurveTexture() { } CurveTexture::~CurveTexture() { if (_texture.is_valid()) { - VS::get_singleton()->free(_texture); + RS::get_singleton()->free(_texture); } } ////////////////// @@ -1492,7 +1492,7 @@ GradientTexture::GradientTexture() { GradientTexture::~GradientTexture() { if (texture.is_valid()) { - VS::get_singleton()->free(texture); + RS::get_singleton()->free(texture); } } @@ -1564,10 +1564,10 @@ void GradientTexture::_update() { Ref image = memnew(Image(width, 1, false, Image::FORMAT_RGBA8, data)); if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_create(image); - VS::get_singleton()->texture_replace(texture, new_texture); + RID new_texture = RS::get_singleton()->texture_2d_create(image); + RS::get_singleton()->texture_replace(texture, new_texture); } else { - texture = VS::get_singleton()->texture_2d_create(image); + texture = RS::get_singleton()->texture_2d_create(image); } emit_changed(); @@ -1587,7 +1587,7 @@ Ref GradientTexture::get_data() const { if (!texture.is_valid()) { return Ref(); } - return VisualServer::get_singleton()->texture_2d_get(texture); + return RenderingServer::get_singleton()->texture_2d_get(texture); } ////////////////////////////////////// @@ -1607,13 +1607,13 @@ void ProxyTexture::set_base(const Ref &p_texture) { base = p_texture; if (base.is_valid()) { if (proxy_ph.is_valid()) { - VS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); - VS::get_singleton()->free(proxy_ph); + RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); + RS::get_singleton()->free(proxy_ph); proxy_ph = RID(); } else if (proxy.is_valid()) { - VS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); + RS::get_singleton()->texture_proxy_update(proxy, base->get_rid()); } else { - proxy = VS::get_singleton()->texture_proxy_create(base->get_rid()); + proxy = RS::get_singleton()->texture_proxy_create(base->get_rid()); } } } @@ -1638,8 +1638,8 @@ int ProxyTexture::get_height() const { RID ProxyTexture::get_rid() const { if (proxy.is_null()) { - proxy_ph = VS::get_singleton()->texture_2d_placeholder_create(); - proxy = VS::get_singleton()->texture_proxy_create(proxy_ph); + proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); + proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); } return proxy; } @@ -1653,16 +1653,16 @@ bool ProxyTexture::has_alpha() const { ProxyTexture::ProxyTexture() { - //proxy = VS::get_singleton()->texture_create(); + //proxy = RS::get_singleton()->texture_create(); } ProxyTexture::~ProxyTexture() { if (proxy_ph.is_valid()) { - VS::get_singleton()->free(proxy_ph); + RS::get_singleton()->free(proxy_ph); } if (proxy.is_valid()) { - VS::get_singleton()->free(proxy); + RS::get_singleton()->free(proxy); } } ////////////////////////////////////////////// @@ -1708,7 +1708,7 @@ void AnimatedTexture::_update_proxy() { } if (frames[current_frame].texture.is_valid()) { - VisualServer::get_singleton()->texture_proxy_update(proxy, frames[current_frame].texture->get_rid()); + RenderingServer::get_singleton()->texture_proxy_update(proxy, frames[current_frame].texture->get_rid()); } } @@ -1854,17 +1854,17 @@ void AnimatedTexture::_bind_methods() { } AnimatedTexture::AnimatedTexture() { - //proxy = VS::get_singleton()->texture_create(); - proxy_ph = VS::get_singleton()->texture_2d_placeholder_create(); - proxy = VS::get_singleton()->texture_proxy_create(proxy_ph); + //proxy = RS::get_singleton()->texture_create(); + proxy_ph = RS::get_singleton()->texture_2d_placeholder_create(); + proxy = RS::get_singleton()->texture_proxy_create(proxy_ph); - VisualServer::get_singleton()->texture_set_force_redraw_if_visible(proxy, true); + RenderingServer::get_singleton()->texture_set_force_redraw_if_visible(proxy, true); time = 0; frame_count = 1; fps = 4; prev_ticks = 0; current_frame = 0; - VisualServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy)); + RenderingServer::get_singleton()->connect("frame_pre_draw", callable_mp(this, &AnimatedTexture::_update_proxy)); #ifndef NO_THREADS rw_lock = RWLock::create(); @@ -1874,8 +1874,8 @@ AnimatedTexture::AnimatedTexture() { } AnimatedTexture::~AnimatedTexture() { - VS::get_singleton()->free(proxy); - VS::get_singleton()->free(proxy_ph); + RS::get_singleton()->free(proxy); + RS::get_singleton()->free(proxy_ph); if (rw_lock) { memdelete(rw_lock); } @@ -1921,10 +1921,10 @@ Error TextureLayered::create_from_images(Vector> p_images) { int new_layers = p_images.size(); ERR_FAIL_COND_V(new_layers == 0, ERR_INVALID_PARAMETER); - if (layered_type == VS::TEXTURE_LAYERED_CUBEMAP) { + if (layered_type == RS::TEXTURE_LAYERED_CUBEMAP) { ERR_FAIL_COND_V_MSG(new_layers != 6, ERR_INVALID_PARAMETER, "Cubemaps require exactly 6 layers"); - } else if (layered_type == VS::TEXTURE_LAYERED_CUBEMAP_ARRAY) { + } else if (layered_type == RS::TEXTURE_LAYERED_CUBEMAP_ARRAY) { ERR_FAIL_COND_V_MSG((new_layers % 6) != 0, ERR_INVALID_PARAMETER, "Cubemap array layers must be a multiple of 6"); } @@ -1946,11 +1946,11 @@ Error TextureLayered::create_from_images(Vector> p_images) { } if (texture.is_valid()) { - RID new_texture = VS::get_singleton()->texture_2d_layered_create(p_images, layered_type); + RID new_texture = RS::get_singleton()->texture_2d_layered_create(p_images, layered_type); ERR_FAIL_COND_V(!new_texture.is_valid(), ERR_CANT_CREATE); - VS::get_singleton()->texture_replace(texture, new_texture); + RS::get_singleton()->texture_replace(texture, new_texture); } else { - texture = VS::get_singleton()->texture_2d_layered_create(p_images, layered_type); + texture = RS::get_singleton()->texture_2d_layered_create(p_images, layered_type); ERR_FAIL_COND_V(!texture.is_valid(), ERR_CANT_CREATE); } @@ -1969,24 +1969,24 @@ void TextureLayered::update_layer(const Ref &p_image, int p_layer) { ERR_FAIL_COND(p_image->get_width() != width || p_image->get_height() != height); ERR_FAIL_INDEX(p_layer, layers); ERR_FAIL_COND(p_image->has_mipmaps() != mipmaps); - VS::get_singleton()->texture_2d_update(texture, p_image, p_layer); + RS::get_singleton()->texture_2d_update(texture, p_image, p_layer); } Ref TextureLayered::get_layer_data(int p_layer) const { ERR_FAIL_INDEX_V(p_layer, layers, Ref()); - return VS::get_singleton()->texture_2d_layer_get(texture, p_layer); + return RS::get_singleton()->texture_2d_layer_get(texture, p_layer); } RID TextureLayered::get_rid() const { if (texture.is_null()) { - texture = VS::get_singleton()->texture_2d_layered_placeholder_create(); + texture = RS::get_singleton()->texture_2d_layered_placeholder_create(); } return texture; } void TextureLayered::set_path(const String &p_path, bool p_take_over) { if (texture.is_valid()) { - VS::get_singleton()->texture_set_path(texture, p_path); + RS::get_singleton()->texture_set_path(texture, p_path); } Resource::set_path(p_path, p_take_over); @@ -2009,7 +2009,7 @@ void TextureLayered::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "_images", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_INTERNAL), "create_from_images", "_get_images"); } -TextureLayered::TextureLayered(VisualServer::TextureLayeredType p_layered_type) { +TextureLayered::TextureLayered(RenderingServer::TextureLayeredType p_layered_type) { layered_type = p_layered_type; format = Image::FORMAT_MAX; @@ -2020,7 +2020,7 @@ TextureLayered::TextureLayered(VisualServer::TextureLayeredType p_layered_type) TextureLayered::~TextureLayered() { if (texture.is_valid()) { - VS::get_singleton()->free(texture); + RS::get_singleton()->free(texture); } } diff --git a/scene/resources/texture.h b/scene/resources/texture.h index 1fb8742cec..c3bbbd5ee6 100644 --- a/scene/resources/texture.h +++ b/scene/resources/texture.h @@ -41,7 +41,7 @@ #include "scene/resources/curve.h" #include "scene/resources/gradient.h" #include "servers/camera_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" class Texture : public Resource { GDCLASS(Texture, Resource); @@ -68,9 +68,9 @@ public: virtual bool has_alpha() const = 0; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; virtual Ref get_data() const { return Ref(); } @@ -118,9 +118,9 @@ public: virtual RID get_rid() const; bool has_alpha() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; bool is_pixel_opaque(int p_x, int p_y) const; @@ -171,7 +171,7 @@ private: virtual void reload_from_file(); static void _requested_3d(void *p_ud); - static void _requested_roughness(void *p_ud, const String &p_normal_path, VS::TextureDetectRoughnessChannel p_roughness_channel); + static void _requested_roughness(void *p_ud, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); static void _requested_normal(void *p_ud); protected: @@ -182,7 +182,7 @@ public: static Ref load_image_from_file(FileAccess *p_file, int p_size_limit); typedef void (*TextureFormatRequestCallback)(const Ref &); - typedef void (*TextureFormatRoughnessRequestCallback)(const Ref &, const String &p_normal_path, VS::TextureDetectRoughnessChannel p_roughness_channel); + typedef void (*TextureFormatRoughnessRequestCallback)(const Ref &, const String &p_normal_path, RS::TextureDetectRoughnessChannel p_roughness_channel); static TextureFormatRequestCallback request_3d_callback; static TextureFormatRoughnessRequestCallback request_roughness_callback; @@ -198,9 +198,9 @@ public: virtual void set_path(const String &p_path, bool p_take_over); - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; virtual bool has_alpha() const; bool is_pixel_opaque(int p_x, int p_y) const; @@ -251,9 +251,9 @@ public: void set_filter_clip(const bool p_enable); bool has_filter_clip() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; bool is_pixel_opaque(int p_x, int p_y) const; @@ -291,9 +291,9 @@ public: void set_base_texture(const Ref &p_texture); Ref get_base_texture() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; virtual bool get_rect_region(const Rect2 &p_rect, const Rect2 &p_src_rect, Rect2 &r_rect, Rect2 &r_src_rect) const; bool is_pixel_opaque(int p_x, int p_y) const; @@ -339,9 +339,9 @@ public: Ref get_piece_texture(int p_idx) const; Ref to_image() const; - virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; - virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), VS::CanvasItemTextureFilter p_texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; + virtual void draw(RID p_canvas_item, const Point2 &p_pos, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect(RID p_canvas_item, const Rect2 &p_rect, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) const; + virtual void draw_rect_region(RID p_canvas_item, const Rect2 &p_rect, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, const Ref &p_normal_map = Ref(), const Ref &p_specular_map = Ref(), const Color &p_specular_color_shininess = Color(1, 1, 1, 1), RS::CanvasItemTextureFilter p_texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, bool p_clip_uv = true) const; bool is_pixel_opaque(int p_x, int p_y) const; @@ -352,7 +352,7 @@ class TextureLayered : public Texture { GDCLASS(TextureLayered, Texture); - VS::TextureLayeredType layered_type; + RS::TextureLayeredType layered_type; mutable RID texture; Image::Format format; @@ -383,7 +383,7 @@ public: virtual RID get_rid() const; virtual void set_path(const String &p_path, bool p_take_over = false); - TextureLayered(VS::TextureLayeredType p_layered_type); + TextureLayered(RS::TextureLayeredType p_layered_type); ~TextureLayered(); }; @@ -392,7 +392,7 @@ class Texture2DArray : public TextureLayered { GDCLASS(Texture2DArray, TextureLayered) public: Texture2DArray() : - TextureLayered(VS::TEXTURE_LAYERED_2D_ARRAY) {} + TextureLayered(RS::TEXTURE_LAYERED_2D_ARRAY) {} }; class Cubemap : public TextureLayered { @@ -401,7 +401,7 @@ class Cubemap : public TextureLayered { public: Cubemap() : - TextureLayered(VS::TEXTURE_LAYERED_CUBEMAP) {} + TextureLayered(RS::TEXTURE_LAYERED_CUBEMAP) {} }; class CubemapArray : public TextureLayered { @@ -410,7 +410,7 @@ class CubemapArray : public TextureLayered { public: CubemapArray() : - TextureLayered(VS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {} + TextureLayered(RS::TEXTURE_LAYERED_CUBEMAP_ARRAY) {} }; class ResourceFormatLoaderTextureLayered : public ResourceFormatLoader { diff --git a/scene/resources/tile_set.cpp b/scene/resources/tile_set.cpp index b312aa054c..27305cfff1 100644 --- a/scene/resources/tile_set.cpp +++ b/scene/resources/tile_set.cpp @@ -362,7 +362,7 @@ void TileSet::_get_property_list(List *p_list) const { p_list->push_back(PropertyInfo(Variant::BOOL, pre + "shape_one_way", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::FLOAT, pre + "shape_one_way_margin", PROPERTY_HINT_RANGE, "0,128,0.01", PROPERTY_USAGE_NOEDITOR)); p_list->push_back(PropertyInfo(Variant::ARRAY, pre + "shapes", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR)); - p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(VS::CANVAS_ITEM_Z_MIN) + "," + itos(VS::CANVAS_ITEM_Z_MAX) + ",1", PROPERTY_USAGE_NOEDITOR)); + p_list->push_back(PropertyInfo(Variant::INT, pre + "z_index", PROPERTY_HINT_RANGE, itos(RS::CANVAS_ITEM_Z_MIN) + "," + itos(RS::CANVAS_ITEM_Z_MAX) + ",1", PROPERTY_USAGE_NOEDITOR)); } } diff --git a/scene/resources/visual_shader.cpp b/scene/resources/visual_shader.cpp index c4a019c728..c47e80c807 100644 --- a/scene/resources/visual_shader.cpp +++ b/scene/resources/visual_shader.cpp @@ -31,7 +31,7 @@ #include "visual_shader.h" #include "core/vmap.h" -#include "servers/visual/shader_types.h" +#include "servers/rendering/shader_types.h" #include "visual_shader_nodes.h" bool VisualShaderNode::is_simple_decl() const { @@ -1040,8 +1040,8 @@ void VisualShader::_get_property_list(List *p_list) const { Map blend_mode_enums; Set toggles; - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode)).size(); i++) { - String mode = ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode))[i]; + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) { + String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i]; int idx = 0; bool in_enum = false; while (render_mode_enums[idx].string) { @@ -1317,8 +1317,8 @@ void VisualShader::_update_shader() const { int which = modes[render_mode_enums[idx].string]; int count = 0; - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode)).size(); i++) { - String mode = ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode))[i]; + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) { + String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i]; if (mode.begins_with(render_mode_enums[idx].string)) { if (count == which) { if (render_mode != String()) { @@ -1336,9 +1336,9 @@ void VisualShader::_update_shader() const { } //fill render mode flags - for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode)).size(); i++) { + for (int i = 0; i < ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode)).size(); i++) { - String mode = ShaderTypes::get_singleton()->get_modes(VisualServer::ShaderMode(shader_mode))[i]; + String mode = ShaderTypes::get_singleton()->get_modes(RenderingServer::ShaderMode(shader_mode))[i]; if (flags.has(mode)) { if (render_mode != String()) { render_mode += ", "; @@ -1358,7 +1358,7 @@ void VisualShader::_update_shader() const { String global_expressions; for (int i = 0, index = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { continue; } @@ -1378,7 +1378,7 @@ void VisualShader::_update_shader() const { for (int i = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { continue; } @@ -1417,7 +1417,7 @@ void VisualShader::_update_shader() const { final_code += global_expressions; String tcode = code; for (int i = 0; i < TYPE_MAX; i++) { - if (!ShaderTypes::get_singleton()->get_functions(VisualServer::ShaderMode(shader_mode)).has(func_name[i])) { + if (!ShaderTypes::get_singleton()->get_functions(RenderingServer::ShaderMode(shader_mode)).has(func_name[i])) { continue; } tcode = tcode.insert(insertion_pos[i], global_code_per_func[Type(i)]); diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp index 75bdeeac07..ef8067497f 100644 --- a/scene/resources/world_2d.cpp +++ b/scene/resources/world_2d.cpp @@ -34,8 +34,8 @@ #include "scene/2d/camera_2d.h" #include "scene/2d/visibility_notifier_2d.h" #include "scene/main/window.h" -#include "servers/physics_2d_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_2d.h" +#include "servers/rendering_server.h" struct SpatialIndexer2D { @@ -379,30 +379,30 @@ void World2D::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "direct_space_state", PROPERTY_HINT_RESOURCE_TYPE, "Physics2DDirectSpaceState", 0), "", "get_direct_space_state"); } -Physics2DDirectSpaceState *World2D::get_direct_space_state() { +PhysicsDirectSpaceState2D *World2D::get_direct_space_state() { - return Physics2DServer::get_singleton()->space_get_direct_state(space); + return PhysicsServer2D::get_singleton()->space_get_direct_state(space); } World2D::World2D() { - canvas = VisualServer::get_singleton()->canvas_create(); - space = Physics2DServer::get_singleton()->space_create(); + canvas = RenderingServer::get_singleton()->canvas_create(); + space = PhysicsServer2D::get_singleton()->space_create(); //set space2D to be more friendly with pixels than meters, by adjusting some constants - Physics2DServer::get_singleton()->space_set_active(space, true); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98)); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1))); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1)); + PhysicsServer2D::get_singleton()->space_set_active(space, true); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/2d/default_gravity", 98)); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/2d/default_gravity_vector", Vector2(0, 1))); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/2d/default_linear_damp", 0.1)); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); - Physics2DServer::get_singleton()->area_set_param(space, Physics2DServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0)); + PhysicsServer2D::get_singleton()->area_set_param(space, PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/2d/default_angular_damp", 1.0)); ProjectSettings::get_singleton()->set_custom_property_info("physics/2d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/2d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); indexer = memnew(SpatialIndexer2D); } World2D::~World2D() { - VisualServer::get_singleton()->free(canvas); - Physics2DServer::get_singleton()->free(space); + RenderingServer::get_singleton()->free(canvas); + PhysicsServer2D::get_singleton()->free(space); memdelete(indexer); } diff --git a/scene/resources/world_2d.h b/scene/resources/world_2d.h index d837ef58c2..88b4c2594c 100644 --- a/scene/resources/world_2d.h +++ b/scene/resources/world_2d.h @@ -33,7 +33,7 @@ #include "core/project_settings.h" #include "core/resource.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" class VisibilityNotifier2D; class Viewport; @@ -67,7 +67,7 @@ public: RID get_canvas(); RID get_space(); - Physics2DDirectSpaceState *get_direct_space_state(); + PhysicsDirectSpaceState2D *get_direct_space_state(); void get_viewport_list(List *r_viewports); diff --git a/scene/resources/world_3d.cpp b/scene/resources/world_3d.cpp index 0a687af803..8e45b22cbf 100644 --- a/scene/resources/world_3d.cpp +++ b/scene/resources/world_3d.cpp @@ -275,9 +275,9 @@ void World3D::set_environment(const Ref &p_environment) { environment = p_environment; if (environment.is_valid()) - VS::get_singleton()->scenario_set_environment(scenario, environment->get_rid()); + RS::get_singleton()->scenario_set_environment(scenario, environment->get_rid()); else - VS::get_singleton()->scenario_set_environment(scenario, RID()); + RS::get_singleton()->scenario_set_environment(scenario, RID()); emit_changed(); } @@ -294,9 +294,9 @@ void World3D::set_fallback_environment(const Ref &p_environment) { fallback_environment = p_environment; if (fallback_environment.is_valid()) - VS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); + RS::get_singleton()->scenario_set_fallback_environment(scenario, p_environment->get_rid()); else - VS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); + RS::get_singleton()->scenario_set_fallback_environment(scenario, RID()); emit_changed(); } @@ -310,9 +310,9 @@ void World3D::set_camera_effects(const Ref &p_camera_effects) { camera_effects = p_camera_effects; if (camera_effects.is_valid()) - VS::get_singleton()->scenario_set_camera_effects(scenario, camera_effects->get_rid()); + RS::get_singleton()->scenario_set_camera_effects(scenario, camera_effects->get_rid()); else - VS::get_singleton()->scenario_set_camera_effects(scenario, RID()); + RS::get_singleton()->scenario_set_camera_effects(scenario, RID()); } Ref World3D::get_camera_effects() const { @@ -320,9 +320,9 @@ Ref World3D::get_camera_effects() const { return camera_effects; } -PhysicsDirectSpaceState *World3D::get_direct_space_state() { +PhysicsDirectSpaceState3D *World3D::get_direct_space_state() { - return PhysicsServer::get_singleton()->space_get_direct_state(space); + return PhysicsServer3D::get_singleton()->space_get_direct_state(space); } void World3D::get_camera_list(List *r_cameras) { @@ -353,15 +353,15 @@ void World3D::_bind_methods() { World3D::World3D() { - space = PhysicsServer::get_singleton()->space_create(); - scenario = VisualServer::get_singleton()->scenario_create(); + space = PhysicsServer3D::get_singleton()->space_create(); + scenario = RenderingServer::get_singleton()->scenario_create(); - PhysicsServer::get_singleton()->space_set_active(space, true); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8)); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0))); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1)); + PhysicsServer3D::get_singleton()->space_set_active(space, true); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY, GLOBAL_DEF("physics/3d/default_gravity", 9.8)); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR, GLOBAL_DEF("physics/3d/default_gravity_vector", Vector3(0, -1, 0))); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_LINEAR_DAMP, GLOBAL_DEF("physics/3d/default_linear_damp", 0.1)); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_linear_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_linear_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); - PhysicsServer::get_singleton()->area_set_param(space, PhysicsServer::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1)); + PhysicsServer3D::get_singleton()->area_set_param(space, PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP, GLOBAL_DEF("physics/3d/default_angular_damp", 0.1)); ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/default_angular_damp", PropertyInfo(Variant::FLOAT, "physics/3d/default_angular_damp", PROPERTY_HINT_RANGE, "-1,100,0.001,or_greater")); #ifdef _3D_DISABLED @@ -373,8 +373,8 @@ World3D::World3D() { World3D::~World3D() { - PhysicsServer::get_singleton()->free(space); - VisualServer::get_singleton()->free(scenario); + PhysicsServer3D::get_singleton()->free(space); + RenderingServer::get_singleton()->free(scenario); #ifndef _3D_DISABLED memdelete(indexer); diff --git a/scene/resources/world_3d.h b/scene/resources/world_3d.h index 4c18ba9cea..81a27a7349 100644 --- a/scene/resources/world_3d.h +++ b/scene/resources/world_3d.h @@ -33,8 +33,8 @@ #include "core/resource.h" #include "scene/resources/environment.h" -#include "servers/physics_server.h" -#include "servers/visual_server.h" +#include "servers/physics_server_3d.h" +#include "servers/rendering_server.h" class Camera3D; class VisibilityNotifier3D; @@ -82,7 +82,7 @@ public: void get_camera_list(List *r_cameras); - PhysicsDirectSpaceState *get_direct_space_state(); + PhysicsDirectSpaceState3D *get_direct_space_state(); World3D(); ~World3D(); diff --git a/scene/resources/world_margin_shape_3d.cpp b/scene/resources/world_margin_shape_3d.cpp index 3bea3111ef..aa96f8aa68 100644 --- a/scene/resources/world_margin_shape_3d.cpp +++ b/scene/resources/world_margin_shape_3d.cpp @@ -30,7 +30,7 @@ #include "world_margin_shape_3d.h" -#include "servers/physics_server.h" +#include "servers/physics_server_3d.h" Vector WorldMarginShape3D::get_debug_mesh_lines() { @@ -63,7 +63,7 @@ Vector WorldMarginShape3D::get_debug_mesh_lines() { void WorldMarginShape3D::_update_shape() { - PhysicsServer::get_singleton()->shape_set_data(get_shape(), plane); + PhysicsServer3D::get_singleton()->shape_set_data(get_shape(), plane); Shape3D::_update_shape(); } @@ -89,7 +89,7 @@ void WorldMarginShape3D::_bind_methods() { } WorldMarginShape3D::WorldMarginShape3D() : - Shape3D(PhysicsServer::get_singleton()->shape_create(PhysicsServer::SHAPE_PLANE)) { + Shape3D(PhysicsServer3D::get_singleton()->shape_create(PhysicsServer3D::SHAPE_PLANE)) { set_plane(Plane(0, 1, 0, 0)); } diff --git a/servers/SCsub b/servers/SCsub index 34ba70b8cb..7706b99d87 100644 --- a/servers/SCsub +++ b/servers/SCsub @@ -7,9 +7,9 @@ env.add_source_files(env.servers_sources, "*.cpp") SConscript('arvr/SCsub') SConscript('camera/SCsub') -SConscript('physics/SCsub') +SConscript('physics_3d/SCsub') SConscript('physics_2d/SCsub') -SConscript('visual/SCsub') +SConscript('rendering/SCsub') SConscript('audio/SCsub') lib = env.add_library("servers", env.servers_sources) diff --git a/servers/arvr_server.cpp b/servers/arvr_server.cpp index 4b3417db6c..724414ae96 100644 --- a/servers/arvr_server.cpp +++ b/servers/arvr_server.cpp @@ -343,7 +343,7 @@ uint64_t ARVRServer::get_last_frame_usec() { }; void ARVRServer::_process() { - /* called from visual_server_viewport.draw_viewports right before we start drawing our viewports */ + /* called from rendering_server_viewport.draw_viewports right before we start drawing our viewports */ /* mark for our frame timing */ last_process_usec = OS::get_singleton()->get_ticks_usec(); diff --git a/servers/camera/camera_feed.cpp b/servers/camera/camera_feed.cpp index e8537950ec..41f44abae8 100644 --- a/servers/camera/camera_feed.cpp +++ b/servers/camera/camera_feed.cpp @@ -30,7 +30,7 @@ #include "camera_feed.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" void CameraFeed::_bind_methods() { // FIXME: Disabled during Vulkan refactoring, should be ported. @@ -148,7 +148,7 @@ CameraFeed::CameraFeed() { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 // create a texture object - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); texture[CameraServer::FEED_Y_IMAGE] = vs->texture_create(); // also used for RGBA texture[CameraServer::FEED_CBCR_IMAGE] = vs->texture_create(); #endif @@ -168,7 +168,7 @@ CameraFeed::CameraFeed(String p_name, FeedPosition p_position) { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 // create a texture object - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); texture[CameraServer::FEED_Y_IMAGE] = vs->texture_create(); // also used for RGBA texture[CameraServer::FEED_CBCR_IMAGE] = vs->texture_create(); #endif @@ -178,7 +178,7 @@ CameraFeed::~CameraFeed() { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 // Free our textures - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); vs->free(texture[CameraServer::FEED_Y_IMAGE]); vs->free(texture[CameraServer::FEED_CBCR_IMAGE]); #endif @@ -188,7 +188,7 @@ void CameraFeed::set_RGB_img(Ref p_rgb_img) { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 if (active) { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); int new_width = p_rgb_img->get_width(); int new_height = p_rgb_img->get_height(); @@ -198,7 +198,7 @@ void CameraFeed::set_RGB_img(Ref p_rgb_img) { base_width = new_width; base_height = new_height; - vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAGS_DEFAULT); + vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAGS_DEFAULT); } vs->texture_set_data(texture[CameraServer::FEED_RGBA_IMAGE], p_rgb_img); @@ -211,7 +211,7 @@ void CameraFeed::set_YCbCr_img(Ref p_ycbcr_img) { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 if (active) { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); int new_width = p_ycbcr_img->get_width(); int new_height = p_ycbcr_img->get_height(); @@ -221,7 +221,7 @@ void CameraFeed::set_YCbCr_img(Ref p_ycbcr_img) { base_width = new_width; base_height = new_height; - vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAGS_DEFAULT); + vs->texture_allocate(texture[CameraServer::FEED_RGBA_IMAGE], new_width, new_height, 0, Image::FORMAT_RGB8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAGS_DEFAULT); } vs->texture_set_data(texture[CameraServer::FEED_RGBA_IMAGE], p_ycbcr_img); @@ -234,7 +234,7 @@ void CameraFeed::set_YCbCr_imgs(Ref p_y_img, Ref p_cbcr_img) { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 if (active) { - VisualServer *vs = VisualServer::get_singleton(); + RenderingServer *vs = RenderingServer::get_singleton(); ///@TODO investigate whether we can use thirdparty/misc/yuv2rgb.h here to convert our YUV data to RGB, our shader approach is potentially faster though.. // Wondering about including that into multiple projects, may cause issues. @@ -250,10 +250,10 @@ void CameraFeed::set_YCbCr_imgs(Ref p_y_img, Ref p_cbcr_img) { base_width = new_y_width; base_height = new_y_height; - vs->texture_allocate(texture[CameraServer::FEED_Y_IMAGE], new_y_width, new_y_height, 0, Image::FORMAT_R8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_USED_FOR_STREAMING); + vs->texture_allocate(texture[CameraServer::FEED_Y_IMAGE], new_y_width, new_y_height, 0, Image::FORMAT_R8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAG_USED_FOR_STREAMING); ///@TODO GLES2 doesn't support FORMAT_RG8, need to do some form of conversion - vs->texture_allocate(texture[CameraServer::FEED_CBCR_IMAGE], new_cbcr_width, new_cbcr_height, 0, Image::FORMAT_RG8, VS::TEXTURE_TYPE_2D, VS::TEXTURE_FLAG_USED_FOR_STREAMING); + vs->texture_allocate(texture[CameraServer::FEED_CBCR_IMAGE], new_cbcr_width, new_cbcr_height, 0, Image::FORMAT_RG8, RS::TEXTURE_TYPE_2D, RS::TEXTURE_FLAG_USED_FOR_STREAMING); } vs->texture_set_data(texture[CameraServer::FEED_Y_IMAGE], p_y_img); @@ -265,15 +265,15 @@ void CameraFeed::set_YCbCr_imgs(Ref p_y_img, Ref p_cbcr_img) { // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 -void CameraFeed::allocate_texture(int p_width, int p_height, Image::Format p_format, VisualServer::TextureType p_texture_type, FeedDataType p_data_type) { - VisualServer *vs = VisualServer::get_singleton(); +void CameraFeed::allocate_texture(int p_width, int p_height, Image::Format p_format, RenderingServer::TextureType p_texture_type, FeedDataType p_data_type) { + RenderingServer *vs = RenderingServer::get_singleton(); if ((base_width != p_width) || (base_height != p_height)) { // We're assuming here that our camera image doesn't change around formats etc, allocate the whole lot... base_width = p_width; base_height = p_height; - vs->texture_allocate(texture[0], p_width, p_height, 0, p_format, p_texture_type, VS::TEXTURE_FLAGS_DEFAULT); + vs->texture_allocate(texture[0], p_width, p_height, 0, p_format, p_texture_type, RS::TEXTURE_FLAGS_DEFAULT); } datatype = p_data_type; diff --git a/servers/camera/camera_feed.h b/servers/camera/camera_feed.h index b99ded68e4..52a737cd8d 100644 --- a/servers/camera/camera_feed.h +++ b/servers/camera/camera_feed.h @@ -34,7 +34,7 @@ #include "core/image.h" #include "core/math/transform_2d.h" #include "servers/camera_server.h" -#include "servers/visual_server.h" +#include "servers/rendering_server.h" /** @author Bastiaan Olij @@ -105,7 +105,7 @@ public: void set_YCbCr_imgs(Ref p_y_img, Ref p_cbcr_img); // FIXME: Disabled during Vulkan refactoring, should be ported. #if 0 - void allocate_texture(int p_width, int p_height, Image::Format p_format, VisualServer::TextureType p_texture_type, FeedDataType p_data_type); + void allocate_texture(int p_width, int p_height, Image::Format p_format, RenderingServer::TextureType p_texture_type, FeedDataType p_data_type); #endif virtual bool activate_feed(); diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp index fd88d15e58..1a86ff1af4 100644 --- a/servers/camera_server.cpp +++ b/servers/camera_server.cpp @@ -29,8 +29,8 @@ /*************************************************************************/ #include "camera_server.h" +#include "rendering_server.h" #include "servers/camera/camera_feed.h" -#include "visual_server.h" //////////////////////////////////////////////////////// // CameraServer diff --git a/servers/display_server.h b/servers/display_server.h index 4803eeb084..c0e92891a3 100644 --- a/servers/display_server.h +++ b/servers/display_server.h @@ -83,7 +83,7 @@ protected: static DisplayServerCreate server_create_functions[MAX_SERVERS]; static int server_create_count; - friend class VisualServerRaster; + friend class RenderingServerRaster; virtual void _set_use_vsync(bool p_enable); public: diff --git a/servers/navigation_2d_server.cpp b/servers/navigation_2d_server.cpp deleted file mode 100644 index d9b53122e2..0000000000 --- a/servers/navigation_2d_server.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/*************************************************************************/ -/* navigation_2d_server.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "servers/navigation_2d_server.h" -#include "core/math/transform.h" -#include "core/math/transform_2d.h" -#include "servers/navigation_server.h" - -/** - @author AndreaCatania -*/ - -Navigation2DServer *Navigation2DServer::singleton = NULL; - -#define FORWARD_0_C(FUNC_NAME) \ - Navigation2DServer::FUNC_NAME() \ - const { \ - return NavigationServer::get_singleton()->FUNC_NAME(); \ - } - -#define FORWARD_1(FUNC_NAME, T_0, D_0, CONV_0) \ - Navigation2DServer::FUNC_NAME(T_0 D_0) { \ - return NavigationServer::get_singleton_mut()->FUNC_NAME(CONV_0(D_0)); \ - } - -#define FORWARD_1_C(FUNC_NAME, T_0, D_0, CONV_0) \ - Navigation2DServer::FUNC_NAME(T_0 D_0) \ - const { \ - return NavigationServer::get_singleton()->FUNC_NAME(CONV_0(D_0)); \ - } - -#define FORWARD_2_C(FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \ - Navigation2DServer::FUNC_NAME(T_0 D_0, T_1 D_1) \ - const { \ - return NavigationServer::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1)); \ - } - -#define FORWARD_2_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \ - Navigation2DServer::FUNC_NAME(T_0 D_0, T_1 D_1) \ - const { \ - return CONV_R(NavigationServer::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1))); \ - } - -#define FORWARD_4_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \ - Navigation2DServer::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \ - const { \ - return CONV_R(NavigationServer::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3))); \ - } - -#define FORWARD_4_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \ - Navigation2DServer::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \ - const { \ - return NavigationServer::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \ - } - -RID rid_to_rid(const RID d) { - return d; -} -bool bool_to_bool(const bool d) { - return d; -} -int int_to_int(const int d) { - return d; -} -real_t real_to_real(const real_t d) { - return d; -} -Vector3 v2_to_v3(const Vector2 d) { - return Vector3(d.x, 0.0, d.y); -} -Vector2 v3_to_v2(const Vector3 &d) { - return Vector2(d.x, d.z); -} -Vector vector_v3_to_v2(const Vector &d) { - Vector nd; - nd.resize(d.size()); - for (int i(0); i < nd.size(); i++) { - nd.write[i] = v3_to_v2(d[i]); - } - return nd; -} -Transform trf2_to_trf3(const Transform2D &d) { - Vector3 o(v2_to_v3(d.get_origin())); - Basis b; - b.rotate(Vector3(0, 1, 0), d.get_rotation()); - return Transform(b, o); -} -Object *obj_to_obj(Object *d) { - return d; -} -StringName sn_to_sn(StringName &d) { - return d; -} -Variant var_to_var(Variant &d) { - return d; -} -Ref poly_to_mesh(Ref d) { - if (d.is_valid()) { - return d->get_mesh(); - } else { - return Ref(); - } -} - -void Navigation2DServer::_bind_methods() { - ClassDB::bind_method(D_METHOD("map_create"), &Navigation2DServer::map_create); - ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &Navigation2DServer::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &Navigation2DServer::map_is_active); - ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &Navigation2DServer::map_set_cell_size); - ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &Navigation2DServer::map_get_cell_size); - ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &Navigation2DServer::map_set_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &Navigation2DServer::map_get_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &Navigation2DServer::map_get_path); - ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &Navigation2DServer::map_get_closest_point); - ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &Navigation2DServer::map_get_closest_point_owner); - - ClassDB::bind_method(D_METHOD("region_create"), &Navigation2DServer::region_create); - ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &Navigation2DServer::region_set_map); - ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &Navigation2DServer::region_set_transform); - ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &Navigation2DServer::region_set_navpoly); - - ClassDB::bind_method(D_METHOD("agent_create"), &Navigation2DServer::agent_create); - ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &Navigation2DServer::agent_set_map); - ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &Navigation2DServer::agent_set_neighbor_dist); - ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &Navigation2DServer::agent_set_max_neighbors); - ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &Navigation2DServer::agent_set_time_horizon); - ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &Navigation2DServer::agent_set_radius); - ClassDB::bind_method(D_METHOD("agent_set_max_speed", "agent", "max_speed"), &Navigation2DServer::agent_set_max_speed); - ClassDB::bind_method(D_METHOD("agent_set_velocity", "agent", "velocity"), &Navigation2DServer::agent_set_velocity); - ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &Navigation2DServer::agent_set_target_velocity); - ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &Navigation2DServer::agent_set_position); - ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &Navigation2DServer::agent_is_map_changed); - ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &Navigation2DServer::agent_set_callback, DEFVAL(Variant())); - - ClassDB::bind_method(D_METHOD("free", "object"), &Navigation2DServer::free); -} - -Navigation2DServer::Navigation2DServer() { - singleton = this; -} - -Navigation2DServer::~Navigation2DServer() { - singleton = NULL; -} - -RID FORWARD_0_C(map_create); - -void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to_bool); - -bool FORWARD_1_C(map_is_active, RID, p_map, rid_to_rid); - -void FORWARD_2_C(map_set_cell_size, RID, p_map, real_t, p_cell_size, rid_to_rid, real_to_real); -real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid); - -void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real); -real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid); - -Vector FORWARD_4_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool); - -Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); -RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); - -RID FORWARD_0_C(region_create); -void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid); - -void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3); - -void Navigation2DServer::region_set_navpoly(RID p_region, Ref p_nav_mesh) const { - NavigationServer::get_singleton()->region_set_navmesh(p_region, poly_to_mesh(p_nav_mesh)); -} - -RID Navigation2DServer::agent_create() const { - RID agent = NavigationServer::get_singleton()->agent_create(); - NavigationServer::get_singleton()->agent_set_ignore_y(agent, true); - return agent; -} - -void FORWARD_2_C(agent_set_map, RID, p_agent, RID, p_map, rid_to_rid, rid_to_rid); - -void FORWARD_2_C(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real); - -void FORWARD_2_C(agent_set_max_neighbors, RID, p_agent, int, p_count, rid_to_rid, int_to_int); - -void FORWARD_2_C(agent_set_time_horizon, RID, p_agent, real_t, p_time, rid_to_rid, real_to_real); - -void FORWARD_2_C(agent_set_radius, RID, p_agent, real_t, p_radius, rid_to_rid, real_to_real); - -void FORWARD_2_C(agent_set_max_speed, RID, p_agent, real_t, p_max_speed, rid_to_rid, real_to_real); - -void FORWARD_2_C(agent_set_velocity, RID, p_agent, Vector2, p_velocity, rid_to_rid, v2_to_v3); - -void FORWARD_2_C(agent_set_target_velocity, RID, p_agent, Vector2, p_velocity, rid_to_rid, v2_to_v3); - -void FORWARD_2_C(agent_set_position, RID, p_agent, Vector2, p_position, rid_to_rid, v2_to_v3); - -void FORWARD_2_C(agent_set_ignore_y, RID, p_agent, bool, p_ignore, rid_to_rid, bool_to_bool); - -bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid); - -void FORWARD_4_C(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, rid_to_rid, obj_to_obj, sn_to_sn, var_to_var); - -void FORWARD_1_C(free, RID, p_object, rid_to_rid); diff --git a/servers/navigation_2d_server.h b/servers/navigation_2d_server.h deleted file mode 100644 index 35902f83d4..0000000000 --- a/servers/navigation_2d_server.h +++ /dev/null @@ -1,163 +0,0 @@ -/*************************************************************************/ -/* navigation_2d_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/** - @author AndreaCatania -*/ - -#ifndef NAVIGATION_2D_SERVER_H -#define NAVIGATION_2D_SERVER_H - -#include "core/object.h" -#include "core/rid.h" -#include "scene/2d/navigation_region_2d.h" - -// This server exposes the 3D `NavigationServer` features in the 2D world. -class Navigation2DServer : public Object { - GDCLASS(Navigation2DServer, Object); - - static Navigation2DServer *singleton; - -protected: - static void _bind_methods(); - -public: - /// Thread safe, can be used across many threads. - static const Navigation2DServer *get_singleton() { return singleton; } - - /// MUST be used in single thread! - static Navigation2DServer *get_singleton_mut() { return singleton; } - - /// Create a new map. - virtual RID map_create() const; - - /// Set map active. - virtual void map_set_active(RID p_map, bool p_active) const; - - /// Returns true if the map is active. - virtual bool map_is_active(RID p_map) const; - - /// Set the map cell size used to weld the navigation mesh polygons. - virtual void map_set_cell_size(RID p_map, real_t p_cell_size) const; - - /// Returns the map cell size. - virtual real_t map_get_cell_size(RID p_map) const; - - /// Set the map edge connection margin used to weld the compatible region edges. - virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) const; - - /// Returns the edge connection margin of this map. - virtual real_t map_get_edge_connection_margin(RID p_map) const; - - /// Returns the navigation path to reach the destination from the origin. - virtual Vector map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize) const; - - virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; - virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; - - /// Creates a new region. - virtual RID region_create() const; - - /// Set the map of this region. - virtual void region_set_map(RID p_region, RID p_map) const; - - /// Set the global transformation of this region. - virtual void region_set_transform(RID p_region, Transform2D p_transform) const; - - /// Set the navigation poly of this region. - virtual void region_set_navpoly(RID p_region, Ref p_nav_mesh) const; - - /// Creates the agent. - virtual RID agent_create() const; - - /// Put the agent in the map. - virtual void agent_set_map(RID p_agent, RID p_map) const; - - /// The maximum distance (center point to - /// center point) to other agents this agent - /// takes into account in the navigation. The - /// larger this number, the longer the running - /// time of the simulation. If the number is too - /// low, the simulation will not be safe. - /// Must be non-negative. - virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const; - - /// The maximum number of other agents this - /// agent takes into account in the navigation. - /// The larger this number, the longer the - /// running time of the simulation. If the - /// number is too low, the simulation will not - /// be safe. - virtual void agent_set_max_neighbors(RID p_agent, int p_count) const; - - /// The minimal amount of time for which this - /// agent's velocities that are computed by the - /// simulation are safe with respect to other - /// agents. The larger this number, the sooner - /// this agent will respond to the presence of - /// other agents, but the less freedom this - /// agent has in choosing its velocities. - /// Must be positive. - virtual void agent_set_time_horizon(RID p_agent, real_t p_time) const; - - /// The radius of this agent. - /// Must be non-negative. - virtual void agent_set_radius(RID p_agent, real_t p_radius) const; - - /// The maximum speed of this agent. - /// Must be non-negative. - virtual void agent_set_max_speed(RID p_agent, real_t p_max_speed) const; - - /// Current velocity of the agent - virtual void agent_set_velocity(RID p_agent, Vector2 p_velocity) const; - - /// The new target velocity. - virtual void agent_set_target_velocity(RID p_agent, Vector2 p_velocity) const; - - /// Position of the agent in world space. - virtual void agent_set_position(RID p_agent, Vector2 p_position) const; - - /// Agent ignore the Y axis and avoid collisions by moving only on the horizontal plane - virtual void agent_set_ignore_y(RID p_agent, bool p_ignore) const; - - /// Returns true if the map got changed the previous frame. - virtual bool agent_is_map_changed(RID p_agent) const; - - /// Callback called at the end of the RVO process - virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const; - - /// Destroy the `RID` - virtual void free(RID p_object) const; - - Navigation2DServer(); - virtual ~Navigation2DServer(); -}; - -#endif diff --git a/servers/navigation_server.cpp b/servers/navigation_server.cpp deleted file mode 100644 index f2b727ac47..0000000000 --- a/servers/navigation_server.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/*************************************************************************/ -/* navigation_server.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/** - @author AndreaCatania -*/ - -#include "navigation_server.h" - -NavigationServer *NavigationServer::singleton = NULL; - -void NavigationServer::_bind_methods() { - - ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer::map_create); - ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer::map_set_active); - ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer::map_is_active); - ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer::map_set_up); - ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer::map_get_up); - ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer::map_set_cell_size); - ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer::map_get_cell_size); - ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer::map_set_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer::map_get_edge_connection_margin); - ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer::map_get_path); - ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer::map_get_closest_point_to_segment, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer::map_get_closest_point); - ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer::map_get_closest_point_normal); - ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer::map_get_closest_point_owner); - - ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer::region_create); - ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer::region_set_map); - ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer::region_set_transform); - ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer::region_set_navmesh); - ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer::region_bake_navmesh); - - ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer::agent_create); - ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer::agent_set_map); - ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer::agent_set_neighbor_dist); - ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer::agent_set_max_neighbors); - ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer::agent_set_time_horizon); - ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer::agent_set_radius); - ClassDB::bind_method(D_METHOD("agent_set_max_speed", "agent", "max_speed"), &NavigationServer::agent_set_max_speed); - ClassDB::bind_method(D_METHOD("agent_set_velocity", "agent", "velocity"), &NavigationServer::agent_set_velocity); - ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer::agent_set_target_velocity); - ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer::agent_set_position); - ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer::agent_is_map_changed); - ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer::agent_set_callback, DEFVAL(Variant())); - - ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer::free); - - ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer::set_active); - ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer::process); -} - -const NavigationServer *NavigationServer::get_singleton() { - return singleton; -} - -NavigationServer *NavigationServer::get_singleton_mut() { - return singleton; -} - -NavigationServer::NavigationServer() { - ERR_FAIL_COND(singleton != NULL); - singleton = this; -} - -NavigationServer::~NavigationServer() { - singleton = NULL; -} - -NavigationServerCallback NavigationServerManager::create_callback = NULL; - -void NavigationServerManager::set_default_server(NavigationServerCallback p_callback) { - create_callback = p_callback; -} - -NavigationServer *NavigationServerManager::new_default_server() { - ERR_FAIL_COND_V(create_callback == NULL, NULL); - return create_callback(); -} diff --git a/servers/navigation_server.h b/servers/navigation_server.h deleted file mode 100644 index 2ea8e787cf..0000000000 --- a/servers/navigation_server.h +++ /dev/null @@ -1,199 +0,0 @@ -/*************************************************************************/ -/* navigation_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/** - @author AndreaCatania -*/ - -#ifndef NAVIGATION_SERVER_H -#define NAVIGATION_SERVER_H - -#include "core/object.h" -#include "core/rid.h" -#include "scene/3d/navigation_region_3d.h" - -/// This server uses the concept of internal mutability. -/// All the constant functions can be called in multithread because internally -/// the server takes care to schedule the functions access. -/// -/// Note: All the `set` functions are commands executed during the `sync` phase, -/// don't expect that a change is immediately propagated. -class NavigationServer : public Object { - GDCLASS(NavigationServer, Object); - - static NavigationServer *singleton; - -protected: - static void _bind_methods(); - -public: - /// Thread safe, can be used across many threads. - static const NavigationServer *get_singleton(); - - /// MUST be used in single thread! - static NavigationServer *get_singleton_mut(); - - /// Create a new map. - virtual RID map_create() const = 0; - - /// Set map active. - virtual void map_set_active(RID p_map, bool p_active) const = 0; - - /// Returns true if the map is active. - virtual bool map_is_active(RID p_map) const = 0; - - /// Set the map UP direction. - virtual void map_set_up(RID p_map, Vector3 p_up) const = 0; - - /// Returns the map UP direction. - virtual Vector3 map_get_up(RID p_map) const = 0; - - /// Set the map cell size used to weld the navigation mesh polygons. - virtual void map_set_cell_size(RID p_map, real_t p_cell_size) const = 0; - - /// Returns the map cell size. - virtual real_t map_get_cell_size(RID p_map) const = 0; - - /// Set the map edge connection margin used to weld the compatible region edges. - virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) const = 0; - - /// Returns the edge connection margin of this map. - virtual real_t map_get_edge_connection_margin(RID p_map) const = 0; - - /// Returns the navigation path to reach the destination from the origin. - virtual Vector map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const = 0; - - virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0; - virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0; - virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; - virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; - - /// Creates a new region. - virtual RID region_create() const = 0; - - /// Set the map of this region. - virtual void region_set_map(RID p_region, RID p_map) const = 0; - - /// Set the global transformation of this region. - virtual void region_set_transform(RID p_region, Transform p_transform) const = 0; - - /// Set the navigation mesh of this region. - virtual void region_set_navmesh(RID p_region, Ref p_nav_mesh) const = 0; - - /// Bake the navigation mesh - virtual void region_bake_navmesh(Ref r_mesh, Node *p_node) const = 0; - - /// Creates the agent. - virtual RID agent_create() const = 0; - - /// Put the agent in the map. - virtual void agent_set_map(RID p_agent, RID p_map) const = 0; - - /// The maximum distance (center point to - /// center point) to other agents this agent - /// takes into account in the navigation. The - /// larger this number, the longer the running - /// time of the simulation. If the number is too - /// low, the simulation will not be safe. - /// Must be non-negative. - virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const = 0; - - /// The maximum number of other agents this - /// agent takes into account in the navigation. - /// The larger this number, the longer the - /// running time of the simulation. If the - /// number is too low, the simulation will not - /// be safe. - virtual void agent_set_max_neighbors(RID p_agent, int p_count) const = 0; - - /// The minimal amount of time for which this - /// agent's velocities that are computed by the - /// simulation are safe with respect to other - /// agents. The larger this number, the sooner - /// this agent will respond to the presence of - /// other agents, but the less freedom this - /// agent has in choosing its velocities. - /// Must be positive. - virtual void agent_set_time_horizon(RID p_agent, real_t p_time) const = 0; - - /// The radius of this agent. - /// Must be non-negative. - virtual void agent_set_radius(RID p_agent, real_t p_radius) const = 0; - - /// The maximum speed of this agent. - /// Must be non-negative. - virtual void agent_set_max_speed(RID p_agent, real_t p_max_speed) const = 0; - - /// Current velocity of the agent - virtual void agent_set_velocity(RID p_agent, Vector3 p_velocity) const = 0; - - /// The new target velocity. - virtual void agent_set_target_velocity(RID p_agent, Vector3 p_velocity) const = 0; - - /// Position of the agent in world space. - virtual void agent_set_position(RID p_agent, Vector3 p_position) const = 0; - - /// Agent ignore the Y axis and avoid collisions by moving only on the horizontal plane - virtual void agent_set_ignore_y(RID p_agent, bool p_ignore) const = 0; - - /// Returns true if the map got changed the previous frame. - virtual bool agent_is_map_changed(RID p_agent) const = 0; - - /// Callback called at the end of the RVO process - virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const = 0; - - /// Destroy the `RID` - virtual void free(RID p_object) const = 0; - - /// Control activation of this server. - virtual void set_active(bool p_active) const = 0; - - /// Process the collision avoidance agents. - /// The result of this process is needed by the physics server, - /// so this must be called in the main thread. - /// Note: This function is not thread safe. - virtual void process(real_t delta_time) = 0; - - NavigationServer(); - virtual ~NavigationServer(); -}; - -typedef NavigationServer *(*NavigationServerCallback)(); - -/// Manager used for the server singleton registration -class NavigationServerManager { - static NavigationServerCallback create_callback; - -public: - static void set_default_server(NavigationServerCallback p_callback); - static NavigationServer *new_default_server(); -}; - -#endif diff --git a/servers/navigation_server_2d.cpp b/servers/navigation_server_2d.cpp new file mode 100644 index 0000000000..b64ad0e5ab --- /dev/null +++ b/servers/navigation_server_2d.cpp @@ -0,0 +1,229 @@ +/*************************************************************************/ +/* navigation_2d_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "servers/navigation_server_2d.h" +#include "core/math/transform.h" +#include "core/math/transform_2d.h" +#include "servers/navigation_server_3d.h" + +/** + @author AndreaCatania +*/ + +NavigationServer2D *NavigationServer2D::singleton = NULL; + +#define FORWARD_0_C(FUNC_NAME) \ + NavigationServer2D::FUNC_NAME() \ + const { \ + return NavigationServer3D::get_singleton()->FUNC_NAME(); \ + } + +#define FORWARD_1(FUNC_NAME, T_0, D_0, CONV_0) \ + NavigationServer2D::FUNC_NAME(T_0 D_0) { \ + return NavigationServer3D::get_singleton_mut()->FUNC_NAME(CONV_0(D_0)); \ + } + +#define FORWARD_1_C(FUNC_NAME, T_0, D_0, CONV_0) \ + NavigationServer2D::FUNC_NAME(T_0 D_0) \ + const { \ + return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0)); \ + } + +#define FORWARD_2_C(FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \ + const { \ + return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1)); \ + } + +#define FORWARD_2_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, CONV_0, CONV_1) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1) \ + const { \ + return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1))); \ + } + +#define FORWARD_4_R_C(CONV_R, FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \ + const { \ + return CONV_R(NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3))); \ + } + +#define FORWARD_4_C(FUNC_NAME, T_0, D_0, T_1, D_1, T_2, D_2, T_3, D_3, CONV_0, CONV_1, CONV_2, CONV_3) \ + NavigationServer2D::FUNC_NAME(T_0 D_0, T_1 D_1, T_2 D_2, T_3 D_3) \ + const { \ + return NavigationServer3D::get_singleton()->FUNC_NAME(CONV_0(D_0), CONV_1(D_1), CONV_2(D_2), CONV_3(D_3)); \ + } + +static RID rid_to_rid(const RID d) { + return d; +} +static bool bool_to_bool(const bool d) { + return d; +} +static int int_to_int(const int d) { + return d; +} +static real_t real_to_real(const real_t d) { + return d; +} +static Vector3 v2_to_v3(const Vector2 d) { + return Vector3(d.x, 0.0, d.y); +} +static Vector2 v3_to_v2(const Vector3 &d) { + return Vector2(d.x, d.z); +} +static Vector vector_v3_to_v2(const Vector &d) { + Vector nd; + nd.resize(d.size()); + for (int i(0); i < nd.size(); i++) { + nd.write[i] = v3_to_v2(d[i]); + } + return nd; +} +static Transform trf2_to_trf3(const Transform2D &d) { + Vector3 o(v2_to_v3(d.get_origin())); + Basis b; + b.rotate(Vector3(0, 1, 0), d.get_rotation()); + return Transform(b, o); +} +static Object *obj_to_obj(Object *d) { + return d; +} +static StringName sn_to_sn(StringName &d) { + return d; +} +static Variant var_to_var(Variant &d) { + return d; +} +static Ref poly_to_mesh(Ref d) { + if (d.is_valid()) { + return d->get_mesh(); + } else { + return Ref(); + } +} + +void NavigationServer2D::_bind_methods() { + ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer2D::map_create); + ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer2D::map_set_active); + ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer2D::map_is_active); + ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer2D::map_set_cell_size); + ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer2D::map_get_cell_size); + ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer2D::map_set_edge_connection_margin); + ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer2D::map_get_edge_connection_margin); + ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer2D::map_get_path); + ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer2D::map_get_closest_point); + ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer2D::map_get_closest_point_owner); + + ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer2D::region_create); + ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer2D::region_set_map); + ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer2D::region_set_transform); + ClassDB::bind_method(D_METHOD("region_set_navpoly", "region", "nav_poly"), &NavigationServer2D::region_set_navpoly); + + ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer2D::agent_create); + ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer2D::agent_set_map); + ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer2D::agent_set_neighbor_dist); + ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer2D::agent_set_max_neighbors); + ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer2D::agent_set_time_horizon); + ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer2D::agent_set_radius); + ClassDB::bind_method(D_METHOD("agent_set_max_speed", "agent", "max_speed"), &NavigationServer2D::agent_set_max_speed); + ClassDB::bind_method(D_METHOD("agent_set_velocity", "agent", "velocity"), &NavigationServer2D::agent_set_velocity); + ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer2D::agent_set_target_velocity); + ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer2D::agent_set_position); + ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer2D::agent_is_map_changed); + ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer2D::agent_set_callback, DEFVAL(Variant())); + + ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer2D::free); +} + +NavigationServer2D::NavigationServer2D() { + singleton = this; +} + +NavigationServer2D::~NavigationServer2D() { + singleton = NULL; +} + +RID FORWARD_0_C(map_create); + +void FORWARD_2_C(map_set_active, RID, p_map, bool, p_active, rid_to_rid, bool_to_bool); + +bool FORWARD_1_C(map_is_active, RID, p_map, rid_to_rid); + +void FORWARD_2_C(map_set_cell_size, RID, p_map, real_t, p_cell_size, rid_to_rid, real_to_real); +real_t FORWARD_1_C(map_get_cell_size, RID, p_map, rid_to_rid); + +void FORWARD_2_C(map_set_edge_connection_margin, RID, p_map, real_t, p_connection_margin, rid_to_rid, real_to_real); +real_t FORWARD_1_C(map_get_edge_connection_margin, RID, p_map, rid_to_rid); + +Vector FORWARD_4_R_C(vector_v3_to_v2, map_get_path, RID, p_map, Vector2, p_origin, Vector2, p_destination, bool, p_optimize, rid_to_rid, v2_to_v3, v2_to_v3, bool_to_bool); + +Vector2 FORWARD_2_R_C(v3_to_v2, map_get_closest_point, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); +RID FORWARD_2_C(map_get_closest_point_owner, RID, p_map, const Vector2 &, p_point, rid_to_rid, v2_to_v3); + +RID FORWARD_0_C(region_create); +void FORWARD_2_C(region_set_map, RID, p_region, RID, p_map, rid_to_rid, rid_to_rid); + +void FORWARD_2_C(region_set_transform, RID, p_region, Transform2D, p_transform, rid_to_rid, trf2_to_trf3); + +void NavigationServer2D::region_set_navpoly(RID p_region, Ref p_nav_mesh) const { + NavigationServer3D::get_singleton()->region_set_navmesh(p_region, poly_to_mesh(p_nav_mesh)); +} + +RID NavigationServer2D::agent_create() const { + RID agent = NavigationServer3D::get_singleton()->agent_create(); + NavigationServer3D::get_singleton()->agent_set_ignore_y(agent, true); + return agent; +} + +void FORWARD_2_C(agent_set_map, RID, p_agent, RID, p_map, rid_to_rid, rid_to_rid); + +void FORWARD_2_C(agent_set_neighbor_dist, RID, p_agent, real_t, p_dist, rid_to_rid, real_to_real); + +void FORWARD_2_C(agent_set_max_neighbors, RID, p_agent, int, p_count, rid_to_rid, int_to_int); + +void FORWARD_2_C(agent_set_time_horizon, RID, p_agent, real_t, p_time, rid_to_rid, real_to_real); + +void FORWARD_2_C(agent_set_radius, RID, p_agent, real_t, p_radius, rid_to_rid, real_to_real); + +void FORWARD_2_C(agent_set_max_speed, RID, p_agent, real_t, p_max_speed, rid_to_rid, real_to_real); + +void FORWARD_2_C(agent_set_velocity, RID, p_agent, Vector2, p_velocity, rid_to_rid, v2_to_v3); + +void FORWARD_2_C(agent_set_target_velocity, RID, p_agent, Vector2, p_velocity, rid_to_rid, v2_to_v3); + +void FORWARD_2_C(agent_set_position, RID, p_agent, Vector2, p_position, rid_to_rid, v2_to_v3); + +void FORWARD_2_C(agent_set_ignore_y, RID, p_agent, bool, p_ignore, rid_to_rid, bool_to_bool); + +bool FORWARD_1_C(agent_is_map_changed, RID, p_agent, rid_to_rid); + +void FORWARD_4_C(agent_set_callback, RID, p_agent, Object *, p_receiver, StringName, p_method, Variant, p_udata, rid_to_rid, obj_to_obj, sn_to_sn, var_to_var); + +void FORWARD_1_C(free, RID, p_object, rid_to_rid); diff --git a/servers/navigation_server_2d.h b/servers/navigation_server_2d.h new file mode 100644 index 0000000000..272d07667d --- /dev/null +++ b/servers/navigation_server_2d.h @@ -0,0 +1,163 @@ +/*************************************************************************/ +/* navigation_2d_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/** + @author AndreaCatania +*/ + +#ifndef NAVIGATION_2D_SERVER_H +#define NAVIGATION_2D_SERVER_H + +#include "core/object.h" +#include "core/rid.h" +#include "scene/2d/navigation_region_2d.h" + +// This server exposes the 3D `NavigationServer` features in the 2D world. +class NavigationServer2D : public Object { + GDCLASS(NavigationServer2D, Object); + + static NavigationServer2D *singleton; + +protected: + static void _bind_methods(); + +public: + /// Thread safe, can be used across many threads. + static const NavigationServer2D *get_singleton() { return singleton; } + + /// MUST be used in single thread! + static NavigationServer2D *get_singleton_mut() { return singleton; } + + /// Create a new map. + virtual RID map_create() const; + + /// Set map active. + virtual void map_set_active(RID p_map, bool p_active) const; + + /// Returns true if the map is active. + virtual bool map_is_active(RID p_map) const; + + /// Set the map cell size used to weld the navigation mesh polygons. + virtual void map_set_cell_size(RID p_map, real_t p_cell_size) const; + + /// Returns the map cell size. + virtual real_t map_get_cell_size(RID p_map) const; + + /// Set the map edge connection margin used to weld the compatible region edges. + virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) const; + + /// Returns the edge connection margin of this map. + virtual real_t map_get_edge_connection_margin(RID p_map) const; + + /// Returns the navigation path to reach the destination from the origin. + virtual Vector map_get_path(RID p_map, Vector2 p_origin, Vector2 p_destination, bool p_optimize) const; + + virtual Vector2 map_get_closest_point(RID p_map, const Vector2 &p_point) const; + virtual RID map_get_closest_point_owner(RID p_map, const Vector2 &p_point) const; + + /// Creates a new region. + virtual RID region_create() const; + + /// Set the map of this region. + virtual void region_set_map(RID p_region, RID p_map) const; + + /// Set the global transformation of this region. + virtual void region_set_transform(RID p_region, Transform2D p_transform) const; + + /// Set the navigation poly of this region. + virtual void region_set_navpoly(RID p_region, Ref p_nav_mesh) const; + + /// Creates the agent. + virtual RID agent_create() const; + + /// Put the agent in the map. + virtual void agent_set_map(RID p_agent, RID p_map) const; + + /// The maximum distance (center point to + /// center point) to other agents this agent + /// takes into account in the navigation. The + /// larger this number, the longer the running + /// time of the simulation. If the number is too + /// low, the simulation will not be safe. + /// Must be non-negative. + virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const; + + /// The maximum number of other agents this + /// agent takes into account in the navigation. + /// The larger this number, the longer the + /// running time of the simulation. If the + /// number is too low, the simulation will not + /// be safe. + virtual void agent_set_max_neighbors(RID p_agent, int p_count) const; + + /// The minimal amount of time for which this + /// agent's velocities that are computed by the + /// simulation are safe with respect to other + /// agents. The larger this number, the sooner + /// this agent will respond to the presence of + /// other agents, but the less freedom this + /// agent has in choosing its velocities. + /// Must be positive. + virtual void agent_set_time_horizon(RID p_agent, real_t p_time) const; + + /// The radius of this agent. + /// Must be non-negative. + virtual void agent_set_radius(RID p_agent, real_t p_radius) const; + + /// The maximum speed of this agent. + /// Must be non-negative. + virtual void agent_set_max_speed(RID p_agent, real_t p_max_speed) const; + + /// Current velocity of the agent + virtual void agent_set_velocity(RID p_agent, Vector2 p_velocity) const; + + /// The new target velocity. + virtual void agent_set_target_velocity(RID p_agent, Vector2 p_velocity) const; + + /// Position of the agent in world space. + virtual void agent_set_position(RID p_agent, Vector2 p_position) const; + + /// Agent ignore the Y axis and avoid collisions by moving only on the horizontal plane + virtual void agent_set_ignore_y(RID p_agent, bool p_ignore) const; + + /// Returns true if the map got changed the previous frame. + virtual bool agent_is_map_changed(RID p_agent) const; + + /// Callback called at the end of the RVO process + virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const; + + /// Destroy the `RID` + virtual void free(RID p_object) const; + + NavigationServer2D(); + virtual ~NavigationServer2D(); +}; + +#endif diff --git a/servers/navigation_server_3d.cpp b/servers/navigation_server_3d.cpp new file mode 100644 index 0000000000..3cfc47b1e5 --- /dev/null +++ b/servers/navigation_server_3d.cpp @@ -0,0 +1,107 @@ +/*************************************************************************/ +/* navigation_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/** + @author AndreaCatania +*/ + +#include "navigation_server_3d.h" + +NavigationServer3D *NavigationServer3D::singleton = NULL; + +void NavigationServer3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("map_create"), &NavigationServer3D::map_create); + ClassDB::bind_method(D_METHOD("map_set_active", "map", "active"), &NavigationServer3D::map_set_active); + ClassDB::bind_method(D_METHOD("map_is_active", "nap"), &NavigationServer3D::map_is_active); + ClassDB::bind_method(D_METHOD("map_set_up", "map", "up"), &NavigationServer3D::map_set_up); + ClassDB::bind_method(D_METHOD("map_get_up", "map"), &NavigationServer3D::map_get_up); + ClassDB::bind_method(D_METHOD("map_set_cell_size", "map", "cell_size"), &NavigationServer3D::map_set_cell_size); + ClassDB::bind_method(D_METHOD("map_get_cell_size", "map"), &NavigationServer3D::map_get_cell_size); + ClassDB::bind_method(D_METHOD("map_set_edge_connection_margin", "map", "margin"), &NavigationServer3D::map_set_edge_connection_margin); + ClassDB::bind_method(D_METHOD("map_get_edge_connection_margin", "map"), &NavigationServer3D::map_get_edge_connection_margin); + ClassDB::bind_method(D_METHOD("map_get_path", "map", "origin", "destination", "optimize"), &NavigationServer3D::map_get_path); + ClassDB::bind_method(D_METHOD("map_get_closest_point_to_segment", "map", "start", "end", "use_collision"), &NavigationServer3D::map_get_closest_point_to_segment, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("map_get_closest_point", "map", "to_point"), &NavigationServer3D::map_get_closest_point); + ClassDB::bind_method(D_METHOD("map_get_closest_point_normal", "map", "to_point"), &NavigationServer3D::map_get_closest_point_normal); + ClassDB::bind_method(D_METHOD("map_get_closest_point_owner", "map", "to_point"), &NavigationServer3D::map_get_closest_point_owner); + + ClassDB::bind_method(D_METHOD("region_create"), &NavigationServer3D::region_create); + ClassDB::bind_method(D_METHOD("region_set_map", "region", "map"), &NavigationServer3D::region_set_map); + ClassDB::bind_method(D_METHOD("region_set_transform", "region", "transform"), &NavigationServer3D::region_set_transform); + ClassDB::bind_method(D_METHOD("region_set_navmesh", "region", "nav_mesh"), &NavigationServer3D::region_set_navmesh); + ClassDB::bind_method(D_METHOD("region_bake_navmesh", "mesh", "node"), &NavigationServer3D::region_bake_navmesh); + + ClassDB::bind_method(D_METHOD("agent_create"), &NavigationServer3D::agent_create); + ClassDB::bind_method(D_METHOD("agent_set_map", "agent", "map"), &NavigationServer3D::agent_set_map); + ClassDB::bind_method(D_METHOD("agent_set_neighbor_dist", "agent", "dist"), &NavigationServer3D::agent_set_neighbor_dist); + ClassDB::bind_method(D_METHOD("agent_set_max_neighbors", "agent", "count"), &NavigationServer3D::agent_set_max_neighbors); + ClassDB::bind_method(D_METHOD("agent_set_time_horizon", "agent", "time"), &NavigationServer3D::agent_set_time_horizon); + ClassDB::bind_method(D_METHOD("agent_set_radius", "agent", "radius"), &NavigationServer3D::agent_set_radius); + ClassDB::bind_method(D_METHOD("agent_set_max_speed", "agent", "max_speed"), &NavigationServer3D::agent_set_max_speed); + ClassDB::bind_method(D_METHOD("agent_set_velocity", "agent", "velocity"), &NavigationServer3D::agent_set_velocity); + ClassDB::bind_method(D_METHOD("agent_set_target_velocity", "agent", "target_velocity"), &NavigationServer3D::agent_set_target_velocity); + ClassDB::bind_method(D_METHOD("agent_set_position", "agent", "position"), &NavigationServer3D::agent_set_position); + ClassDB::bind_method(D_METHOD("agent_is_map_changed", "agent"), &NavigationServer3D::agent_is_map_changed); + ClassDB::bind_method(D_METHOD("agent_set_callback", "agent", "receiver", "method", "userdata"), &NavigationServer3D::agent_set_callback, DEFVAL(Variant())); + + ClassDB::bind_method(D_METHOD("free", "object"), &NavigationServer3D::free); + + ClassDB::bind_method(D_METHOD("set_active", "active"), &NavigationServer3D::set_active); + ClassDB::bind_method(D_METHOD("process", "delta_time"), &NavigationServer3D::process); +} + +const NavigationServer3D *NavigationServer3D::get_singleton() { + return singleton; +} + +NavigationServer3D *NavigationServer3D::get_singleton_mut() { + return singleton; +} + +NavigationServer3D::NavigationServer3D() { + ERR_FAIL_COND(singleton != NULL); + singleton = this; +} + +NavigationServer3D::~NavigationServer3D() { + singleton = NULL; +} + +NavigationServer3DCallback NavigationServer3DManager::create_callback = NULL; + +void NavigationServer3DManager::set_default_server(NavigationServer3DCallback p_callback) { + create_callback = p_callback; +} + +NavigationServer3D *NavigationServer3DManager::new_default_server() { + ERR_FAIL_COND_V(create_callback == NULL, NULL); + return create_callback(); +} diff --git a/servers/navigation_server_3d.h b/servers/navigation_server_3d.h new file mode 100644 index 0000000000..2e9d078f73 --- /dev/null +++ b/servers/navigation_server_3d.h @@ -0,0 +1,199 @@ +/*************************************************************************/ +/* navigation_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/** + @author AndreaCatania +*/ + +#ifndef NAVIGATION_SERVER_H +#define NAVIGATION_SERVER_H + +#include "core/object.h" +#include "core/rid.h" +#include "scene/3d/navigation_region_3d.h" + +/// This server uses the concept of internal mutability. +/// All the constant functions can be called in multithread because internally +/// the server takes care to schedule the functions access. +/// +/// Note: All the `set` functions are commands executed during the `sync` phase, +/// don't expect that a change is immediately propagated. +class NavigationServer3D : public Object { + GDCLASS(NavigationServer3D, Object); + + static NavigationServer3D *singleton; + +protected: + static void _bind_methods(); + +public: + /// Thread safe, can be used across many threads. + static const NavigationServer3D *get_singleton(); + + /// MUST be used in single thread! + static NavigationServer3D *get_singleton_mut(); + + /// Create a new map. + virtual RID map_create() const = 0; + + /// Set map active. + virtual void map_set_active(RID p_map, bool p_active) const = 0; + + /// Returns true if the map is active. + virtual bool map_is_active(RID p_map) const = 0; + + /// Set the map UP direction. + virtual void map_set_up(RID p_map, Vector3 p_up) const = 0; + + /// Returns the map UP direction. + virtual Vector3 map_get_up(RID p_map) const = 0; + + /// Set the map cell size used to weld the navigation mesh polygons. + virtual void map_set_cell_size(RID p_map, real_t p_cell_size) const = 0; + + /// Returns the map cell size. + virtual real_t map_get_cell_size(RID p_map) const = 0; + + /// Set the map edge connection margin used to weld the compatible region edges. + virtual void map_set_edge_connection_margin(RID p_map, real_t p_connection_margin) const = 0; + + /// Returns the edge connection margin of this map. + virtual real_t map_get_edge_connection_margin(RID p_map) const = 0; + + /// Returns the navigation path to reach the destination from the origin. + virtual Vector map_get_path(RID p_map, Vector3 p_origin, Vector3 p_destination, bool p_optimize) const = 0; + + virtual Vector3 map_get_closest_point_to_segment(RID p_map, const Vector3 &p_from, const Vector3 &p_to, const bool p_use_collision = false) const = 0; + virtual Vector3 map_get_closest_point(RID p_map, const Vector3 &p_point) const = 0; + virtual Vector3 map_get_closest_point_normal(RID p_map, const Vector3 &p_point) const = 0; + virtual RID map_get_closest_point_owner(RID p_map, const Vector3 &p_point) const = 0; + + /// Creates a new region. + virtual RID region_create() const = 0; + + /// Set the map of this region. + virtual void region_set_map(RID p_region, RID p_map) const = 0; + + /// Set the global transformation of this region. + virtual void region_set_transform(RID p_region, Transform p_transform) const = 0; + + /// Set the navigation mesh of this region. + virtual void region_set_navmesh(RID p_region, Ref p_nav_mesh) const = 0; + + /// Bake the navigation mesh + virtual void region_bake_navmesh(Ref r_mesh, Node *p_node) const = 0; + + /// Creates the agent. + virtual RID agent_create() const = 0; + + /// Put the agent in the map. + virtual void agent_set_map(RID p_agent, RID p_map) const = 0; + + /// The maximum distance (center point to + /// center point) to other agents this agent + /// takes into account in the navigation. The + /// larger this number, the longer the running + /// time of the simulation. If the number is too + /// low, the simulation will not be safe. + /// Must be non-negative. + virtual void agent_set_neighbor_dist(RID p_agent, real_t p_dist) const = 0; + + /// The maximum number of other agents this + /// agent takes into account in the navigation. + /// The larger this number, the longer the + /// running time of the simulation. If the + /// number is too low, the simulation will not + /// be safe. + virtual void agent_set_max_neighbors(RID p_agent, int p_count) const = 0; + + /// The minimal amount of time for which this + /// agent's velocities that are computed by the + /// simulation are safe with respect to other + /// agents. The larger this number, the sooner + /// this agent will respond to the presence of + /// other agents, but the less freedom this + /// agent has in choosing its velocities. + /// Must be positive. + virtual void agent_set_time_horizon(RID p_agent, real_t p_time) const = 0; + + /// The radius of this agent. + /// Must be non-negative. + virtual void agent_set_radius(RID p_agent, real_t p_radius) const = 0; + + /// The maximum speed of this agent. + /// Must be non-negative. + virtual void agent_set_max_speed(RID p_agent, real_t p_max_speed) const = 0; + + /// Current velocity of the agent + virtual void agent_set_velocity(RID p_agent, Vector3 p_velocity) const = 0; + + /// The new target velocity. + virtual void agent_set_target_velocity(RID p_agent, Vector3 p_velocity) const = 0; + + /// Position of the agent in world space. + virtual void agent_set_position(RID p_agent, Vector3 p_position) const = 0; + + /// Agent ignore the Y axis and avoid collisions by moving only on the horizontal plane + virtual void agent_set_ignore_y(RID p_agent, bool p_ignore) const = 0; + + /// Returns true if the map got changed the previous frame. + virtual bool agent_is_map_changed(RID p_agent) const = 0; + + /// Callback called at the end of the RVO process + virtual void agent_set_callback(RID p_agent, Object *p_receiver, StringName p_method, Variant p_udata = Variant()) const = 0; + + /// Destroy the `RID` + virtual void free(RID p_object) const = 0; + + /// Control activation of this server. + virtual void set_active(bool p_active) const = 0; + + /// Process the collision avoidance agents. + /// The result of this process is needed by the physics server, + /// so this must be called in the main thread. + /// Note: This function is not thread safe. + virtual void process(real_t delta_time) = 0; + + NavigationServer3D(); + virtual ~NavigationServer3D(); +}; + +typedef NavigationServer3D *(*NavigationServer3DCallback)(); + +/// Manager used for the server singleton registration +class NavigationServer3DManager { + static NavigationServer3DCallback create_callback; + +public: + static void set_default_server(NavigationServer3DCallback p_callback); + static NavigationServer3D *new_default_server(); +}; + +#endif diff --git a/servers/physics/SCsub b/servers/physics/SCsub deleted file mode 100644 index c5cc889112..0000000000 --- a/servers/physics/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -env.add_source_files(env.servers_sources, "*.cpp") - -SConscript("joints/SCsub") diff --git a/servers/physics/area_pair_sw.cpp b/servers/physics/area_pair_sw.cpp deleted file mode 100644 index 966a440930..0000000000 --- a/servers/physics/area_pair_sw.cpp +++ /dev/null @@ -1,159 +0,0 @@ -/*************************************************************************/ -/* area_pair_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "area_pair_sw.h" -#include "collision_solver_sw.h" - -bool AreaPairSW::setup(real_t p_step) { - - bool result = false; - - if (area->is_shape_set_as_disabled(area_shape) || body->is_shape_set_as_disabled(body_shape)) { - result = false; - } else if (area->test_collision_mask(body) && CollisionSolverSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), NULL, this)) { - result = true; - } - - if (result != colliding) { - - if (result) { - - if (area->get_space_override_mode() != PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED) - body->add_area(area); - if (area->has_monitor_callback()) - area->add_body_to_query(body, body_shape, area_shape); - - } else { - - if (area->get_space_override_mode() != PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED) - body->remove_area(area); - if (area->has_monitor_callback()) - area->remove_body_from_query(body, body_shape, area_shape); - } - - colliding = result; - } - - return false; //never do any post solving -} - -void AreaPairSW::solve(real_t p_step) { -} - -AreaPairSW::AreaPairSW(BodySW *p_body, int p_body_shape, AreaSW *p_area, int p_area_shape) { - - body = p_body; - area = p_area; - body_shape = p_body_shape; - area_shape = p_area_shape; - colliding = false; - body->add_constraint(this, 0); - area->add_constraint(this); - if (p_body->get_mode() == PhysicsServer::BODY_MODE_KINEMATIC) - p_body->set_active(true); -} - -AreaPairSW::~AreaPairSW() { - - if (colliding) { - - if (area->get_space_override_mode() != PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED) - body->remove_area(area); - if (area->has_monitor_callback()) - area->remove_body_from_query(body, body_shape, area_shape); - } - body->remove_constraint(this); - area->remove_constraint(this); -} - -//////////////////////////////////////////////////// - -bool Area2PairSW::setup(real_t p_step) { - - bool result = false; - if (area_a->is_shape_set_as_disabled(shape_a) || area_b->is_shape_set_as_disabled(shape_b)) { - result = false; - } else if (area_a->test_collision_mask(area_b) && CollisionSolverSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), NULL, this)) { - result = true; - } - - if (result != colliding) { - - if (result) { - - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) - area_b->add_area_to_query(area_a, shape_a, shape_b); - - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) - area_a->add_area_to_query(area_b, shape_b, shape_a); - - } else { - - if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) - area_b->remove_area_from_query(area_a, shape_a, shape_b); - - if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) - area_a->remove_area_from_query(area_b, shape_b, shape_a); - } - - colliding = result; - } - - return false; //never do any post solving -} - -void Area2PairSW::solve(real_t p_step) { -} - -Area2PairSW::Area2PairSW(AreaSW *p_area_a, int p_shape_a, AreaSW *p_area_b, int p_shape_b) { - - area_a = p_area_a; - area_b = p_area_b; - shape_a = p_shape_a; - shape_b = p_shape_b; - colliding = false; - area_a->add_constraint(this); - area_b->add_constraint(this); -} - -Area2PairSW::~Area2PairSW() { - - if (colliding) { - - if (area_b->has_area_monitor_callback()) - area_b->remove_area_from_query(area_a, shape_a, shape_b); - - if (area_a->has_area_monitor_callback()) - area_a->remove_area_from_query(area_b, shape_b, shape_a); - } - - area_a->remove_constraint(this); - area_b->remove_constraint(this); -} diff --git a/servers/physics/area_pair_sw.h b/servers/physics/area_pair_sw.h deleted file mode 100644 index 97a37ebf90..0000000000 --- a/servers/physics/area_pair_sw.h +++ /dev/null @@ -1,70 +0,0 @@ -/*************************************************************************/ -/* area_pair_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef AREA_PAIR_SW_H -#define AREA_PAIR_SW_H - -#include "area_sw.h" -#include "body_sw.h" -#include "constraint_sw.h" - -class AreaPairSW : public ConstraintSW { - - BodySW *body; - AreaSW *area; - int body_shape; - int area_shape; - bool colliding; - -public: - bool setup(real_t p_step); - void solve(real_t p_step); - - AreaPairSW(BodySW *p_body, int p_body_shape, AreaSW *p_area, int p_area_shape); - ~AreaPairSW(); -}; - -class Area2PairSW : public ConstraintSW { - - AreaSW *area_a; - AreaSW *area_b; - int shape_a; - int shape_b; - bool colliding; - -public: - bool setup(real_t p_step); - void solve(real_t p_step); - - Area2PairSW(AreaSW *p_area_a, int p_shape_a, AreaSW *p_area_b, int p_shape_b); - ~Area2PairSW(); -}; - -#endif // AREA_PAIR__SW_H diff --git a/servers/physics/area_sw.cpp b/servers/physics/area_sw.cpp deleted file mode 100644 index 4b54a56253..0000000000 --- a/servers/physics/area_sw.cpp +++ /dev/null @@ -1,264 +0,0 @@ -/*************************************************************************/ -/* area_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "area_sw.h" -#include "body_sw.h" -#include "space_sw.h" - -AreaSW::BodyKey::BodyKey(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { - rid = p_body->get_self(); - instance_id = p_body->get_instance_id(); - body_shape = p_body_shape; - area_shape = p_area_shape; -} -AreaSW::BodyKey::BodyKey(AreaSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { - rid = p_body->get_self(); - instance_id = p_body->get_instance_id(); - body_shape = p_body_shape; - area_shape = p_area_shape; -} - -void AreaSW::_shapes_changed() { - - if (!moved_list.in_list() && get_space()) - get_space()->area_add_to_moved_list(&moved_list); -} - -void AreaSW::set_transform(const Transform &p_transform) { - - if (!moved_list.in_list() && get_space()) - get_space()->area_add_to_moved_list(&moved_list); - - _set_transform(p_transform); - _set_inv_transform(p_transform.affine_inverse()); -} - -void AreaSW::set_space(SpaceSW *p_space) { - - if (get_space()) { - if (monitor_query_list.in_list()) - get_space()->area_remove_from_monitor_query_list(&monitor_query_list); - if (moved_list.in_list()) - get_space()->area_remove_from_moved_list(&moved_list); - } - - monitored_bodies.clear(); - monitored_areas.clear(); - - _set_space(p_space); -} - -void AreaSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) { - - if (p_id == monitor_callback_id) { - monitor_callback_method = p_method; - return; - } - - _unregister_shapes(); - - monitor_callback_id = p_id; - monitor_callback_method = p_method; - - monitored_bodies.clear(); - monitored_areas.clear(); - - _shape_changed(); - - if (!moved_list.in_list() && get_space()) - get_space()->area_add_to_moved_list(&moved_list); -} - -void AreaSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) { - - if (p_id == area_monitor_callback_id) { - area_monitor_callback_method = p_method; - return; - } - - _unregister_shapes(); - - area_monitor_callback_id = p_id; - area_monitor_callback_method = p_method; - - monitored_bodies.clear(); - monitored_areas.clear(); - - _shape_changed(); - - if (!moved_list.in_list() && get_space()) - get_space()->area_add_to_moved_list(&moved_list); -} - -void AreaSW::set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode) { - bool do_override = p_mode != PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED; - if (do_override == (space_override_mode != PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED)) - return; - _unregister_shapes(); - space_override_mode = p_mode; - _shape_changed(); -} - -void AreaSW::set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value) { - - switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: gravity = p_value; break; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector = p_value; break; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale = p_value; break; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; - case PhysicsServer::AREA_PARAM_PRIORITY: priority = p_value; break; - } -} - -Variant AreaSW::get_param(PhysicsServer::AreaParameter p_param) const { - - switch (p_param) { - case PhysicsServer::AREA_PARAM_GRAVITY: return gravity; - case PhysicsServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; - case PhysicsServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; - case PhysicsServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; - case PhysicsServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; - case PhysicsServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; - case PhysicsServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; - case PhysicsServer::AREA_PARAM_PRIORITY: return priority; - } - - return Variant(); -} - -void AreaSW::_queue_monitor_update() { - - ERR_FAIL_COND(!get_space()); - - if (!monitor_query_list.in_list()) - get_space()->area_add_to_monitor_query_list(&monitor_query_list); -} - -void AreaSW::set_monitorable(bool p_monitorable) { - - if (monitorable == p_monitorable) - return; - - monitorable = p_monitorable; - _set_static(!monitorable); -} - -void AreaSW::call_queries() { - - if (monitor_callback_id.is_valid() && !monitored_bodies.empty()) { - - Variant res[5]; - Variant *resptr[5]; - for (int i = 0; i < 5; i++) - resptr[i] = &res[i]; - - Object *obj = ObjectDB::get_instance(monitor_callback_id); - if (!obj) { - monitored_bodies.clear(); - monitor_callback_id = ObjectID(); - return; - } - - for (Map::Element *E = monitored_bodies.front(); E; E = E->next()) { - - if (E->get().state == 0) - continue; //nothing happened - - res[0] = E->get().state > 0 ? PhysicsServer::AREA_BODY_ADDED : PhysicsServer::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; - - Callable::CallError ce; - obj->call(monitor_callback_method, (const Variant **)resptr, 5, ce); - } - } - - monitored_bodies.clear(); - - if (area_monitor_callback_id.is_valid() && !monitored_areas.empty()) { - - Variant res[5]; - Variant *resptr[5]; - for (int i = 0; i < 5; i++) - resptr[i] = &res[i]; - - Object *obj = ObjectDB::get_instance(area_monitor_callback_id); - if (!obj) { - monitored_areas.clear(); - area_monitor_callback_id = ObjectID(); - return; - } - - for (Map::Element *E = monitored_areas.front(); E; E = E->next()) { - - if (E->get().state == 0) - continue; //nothing happened - - res[0] = E->get().state > 0 ? PhysicsServer::AREA_BODY_ADDED : PhysicsServer::AREA_BODY_REMOVED; - res[1] = E->key().rid; - res[2] = E->key().instance_id; - res[3] = E->key().body_shape; - res[4] = E->key().area_shape; - - Callable::CallError ce; - obj->call(area_monitor_callback_method, (const Variant **)resptr, 5, ce); - } - } - - monitored_areas.clear(); - //get_space()->area_remove_from_monitor_query_list(&monitor_query_list); -} - -AreaSW::AreaSW() : - CollisionObjectSW(TYPE_AREA), - monitor_query_list(this), - moved_list(this) { - - _set_static(true); //areas are never active - space_override_mode = PhysicsServer::AREA_SPACE_OVERRIDE_DISABLED; - gravity = 9.80665; - gravity_vector = Vector3(0, -1, 0); - gravity_is_point = false; - gravity_distance_scale = 0; - point_attenuation = 1; - angular_damp = 0.1; - linear_damp = 0.1; - priority = 0; - set_ray_pickable(false); - monitorable = false; -} - -AreaSW::~AreaSW() { -} diff --git a/servers/physics/area_sw.h b/servers/physics/area_sw.h deleted file mode 100644 index 4da2b00d20..0000000000 --- a/servers/physics/area_sw.h +++ /dev/null @@ -1,203 +0,0 @@ -/*************************************************************************/ -/* area_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef AREA_SW_H -#define AREA_SW_H - -#include "collision_object_sw.h" -#include "core/self_list.h" -#include "servers/physics_server.h" -//#include "servers/physics/query_sw.h" - -class SpaceSW; -class BodySW; -class ConstraintSW; - -class AreaSW : public CollisionObjectSW { - - PhysicsServer::AreaSpaceOverrideMode space_override_mode; - real_t gravity; - Vector3 gravity_vector; - bool gravity_is_point; - real_t gravity_distance_scale; - real_t point_attenuation; - real_t linear_damp; - real_t angular_damp; - int priority; - bool monitorable; - - ObjectID monitor_callback_id; - StringName monitor_callback_method; - - ObjectID area_monitor_callback_id; - StringName area_monitor_callback_method; - - SelfList monitor_query_list; - SelfList moved_list; - - struct BodyKey { - - RID rid; - ObjectID instance_id; - uint32_t body_shape; - uint32_t area_shape; - - _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const { - - if (rid == p_key.rid) { - - if (body_shape == p_key.body_shape) { - - return area_shape < p_key.area_shape; - } else - return body_shape < p_key.body_shape; - } else - return rid < p_key.rid; - } - - _FORCE_INLINE_ BodyKey() {} - BodyKey(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - BodyKey(AreaSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - }; - - struct BodyState { - - int state; - _FORCE_INLINE_ void inc() { state++; } - _FORCE_INLINE_ void dec() { state--; } - _FORCE_INLINE_ BodyState() { state = 0; } - }; - - Map monitored_bodies; - Map monitored_areas; - - //virtual void shape_changed_notify(ShapeSW *p_shape); - //virtual void shape_deleted_notify(ShapeSW *p_shape); - - Set constraints; - - virtual void _shapes_changed(); - void _queue_monitor_update(); - -public: - //_FORCE_INLINE_ const Transform& get_inverse_transform() const { return inverse_transform; } - //_FORCE_INLINE_ SpaceSW* get_owner() { return owner; } - - void set_monitor_callback(ObjectID p_id, const StringName &p_method); - _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); } - - void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); - _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } - - _FORCE_INLINE_ void add_body_to_query(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - _FORCE_INLINE_ void remove_body_from_query(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); - - _FORCE_INLINE_ void add_area_to_query(AreaSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); - _FORCE_INLINE_ void remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); - - void set_param(PhysicsServer::AreaParameter p_param, const Variant &p_value); - Variant get_param(PhysicsServer::AreaParameter p_param) const; - - void set_space_override_mode(PhysicsServer::AreaSpaceOverrideMode p_mode); - PhysicsServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } - - _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } - _FORCE_INLINE_ real_t get_gravity() const { return gravity; } - - _FORCE_INLINE_ void set_gravity_vector(const Vector3 &p_gravity) { gravity_vector = p_gravity; } - _FORCE_INLINE_ Vector3 get_gravity_vector() const { return gravity_vector; } - - _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; } - _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } - - _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale = scale; } - _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; } - - _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation = p_point_attenuation; } - _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; } - - _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; } - _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } - - _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp = p_angular_damp; } - _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } - - _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } - _FORCE_INLINE_ int get_priority() const { return priority; } - - _FORCE_INLINE_ void add_constraint(ConstraintSW *p_constraint) { constraints.insert(p_constraint); } - _FORCE_INLINE_ void remove_constraint(ConstraintSW *p_constraint) { constraints.erase(p_constraint); } - _FORCE_INLINE_ const Set &get_constraints() const { return constraints; } - _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } - - void set_monitorable(bool p_monitorable); - _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } - - void set_transform(const Transform &p_transform); - - void set_space(SpaceSW *p_space); - - void call_queries(); - - AreaSW(); - ~AreaSW(); -}; - -void AreaSW::add_body_to_query(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { - - BodyKey bk(p_body, p_body_shape, p_area_shape); - monitored_bodies[bk].inc(); - if (!monitor_query_list.in_list()) - _queue_monitor_update(); -} -void AreaSW::remove_body_from_query(BodySW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { - - BodyKey bk(p_body, p_body_shape, p_area_shape); - monitored_bodies[bk].dec(); - if (!monitor_query_list.in_list()) - _queue_monitor_update(); -} - -void AreaSW::add_area_to_query(AreaSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { - - BodyKey bk(p_area, p_area_shape, p_self_shape); - monitored_areas[bk].inc(); - if (!monitor_query_list.in_list()) - _queue_monitor_update(); -} -void AreaSW::remove_area_from_query(AreaSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { - - BodyKey bk(p_area, p_area_shape, p_self_shape); - monitored_areas[bk].dec(); - if (!monitor_query_list.in_list()) - _queue_monitor_update(); -} - -#endif // AREA__SW_H diff --git a/servers/physics/body_pair_sw.cpp b/servers/physics/body_pair_sw.cpp deleted file mode 100644 index 31fc1b07d9..0000000000 --- a/servers/physics/body_pair_sw.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/*************************************************************************/ -/* body_pair_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "body_pair_sw.h" - -#include "collision_solver_sw.h" -#include "core/os/os.h" -#include "space_sw.h" - -/* -#define NO_ACCUMULATE_IMPULSES -#define NO_SPLIT_IMPULSES - -#define NO_FRICTION -*/ - -#define NO_TANGENTIALS -/* BODY PAIR */ - -//#define ALLOWED_PENETRATION 0.01 -#define RELAXATION_TIMESTEPS 3 -#define MIN_VELOCITY 0.0001 -#define MAX_BIAS_ROTATION (Math_PI / 8) - -void BodyPairSW::_contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { - - BodyPairSW *pair = (BodyPairSW *)p_userdata; - pair->contact_added_callback(p_point_A, p_point_B); -} - -void BodyPairSW::contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B) { - - // check if we already have the contact - - //Vector3 local_A = A->get_inv_transform().xform(p_point_A); - //Vector3 local_B = B->get_inv_transform().xform(p_point_B); - - Vector3 local_A = A->get_inv_transform().basis.xform(p_point_A); - Vector3 local_B = B->get_inv_transform().basis.xform(p_point_B - offset_B); - - int new_index = contact_count; - - ERR_FAIL_COND(new_index >= (MAX_CONTACTS + 1)); - - Contact contact; - - contact.acc_normal_impulse = 0; - contact.acc_bias_impulse = 0; - contact.acc_bias_impulse_center_of_mass = 0; - contact.acc_tangent_impulse = Vector3(); - contact.local_A = local_A; - contact.local_B = local_B; - contact.normal = (p_point_A - p_point_B).normalized(); - contact.mass_normal = 0; // will be computed in setup() - - // attempt to determine if the contact will be reused - real_t contact_recycle_radius = space->get_contact_recycle_radius(); - - for (int i = 0; i < contact_count; i++) { - - Contact &c = contacts[i]; - if (c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) && - c.local_B.distance_squared_to(local_B) < (contact_recycle_radius * contact_recycle_radius)) { - - contact.acc_normal_impulse = c.acc_normal_impulse; - contact.acc_bias_impulse = c.acc_bias_impulse; - contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass; - contact.acc_tangent_impulse = c.acc_tangent_impulse; - new_index = i; - break; - } - } - - // figure out if the contact amount must be reduced to fit the new contact - - if (new_index == MAX_CONTACTS) { - - // remove the contact with the minimum depth - - int least_deep = -1; - real_t min_depth = 1e10; - - for (int i = 0; i <= contact_count; i++) { - - Contact &c = (i == contact_count) ? contact : contacts[i]; - Vector3 global_A = A->get_transform().basis.xform(c.local_A); - Vector3 global_B = B->get_transform().basis.xform(c.local_B) + offset_B; - - Vector3 axis = global_A - global_B; - real_t depth = axis.dot(c.normal); - - if (depth < min_depth) { - - min_depth = depth; - least_deep = i; - } - } - - ERR_FAIL_COND(least_deep == -1); - - if (least_deep < contact_count) { //replace the last deep contact by the new one - - contacts[least_deep] = contact; - } - - return; - } - - contacts[new_index] = contact; - - if (new_index == contact_count) { - - contact_count++; - } -} - -void BodyPairSW::validate_contacts() { - - //make sure to erase contacts that are no longer valid - - real_t contact_max_separation = space->get_contact_max_separation(); - for (int i = 0; i < contact_count; i++) { - - Contact &c = contacts[i]; - - Vector3 global_A = A->get_transform().basis.xform(c.local_A); - Vector3 global_B = B->get_transform().basis.xform(c.local_B) + offset_B; - Vector3 axis = global_A - global_B; - real_t depth = axis.dot(c.normal); - - if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) { - // contact no longer needed, remove - - if ((i + 1) < contact_count) { - // swap with the last one - SWAP(contacts[i], contacts[contact_count - 1]); - } - - i--; - contact_count--; - } - } -} - -bool BodyPairSW::_test_ccd(real_t p_step, BodySW *p_A, int p_shape_A, const Transform &p_xform_A, BodySW *p_B, int p_shape_B, const Transform &p_xform_B) { - - Vector3 motion = p_A->get_linear_velocity() * p_step; - real_t mlen = motion.length(); - if (mlen < CMP_EPSILON) - return false; - - Vector3 mnormal = motion / mlen; - - real_t min, max; - p_A->get_shape(p_shape_A)->project_range(mnormal, p_xform_A, min, max); - bool fast_object = mlen > (max - min) * 0.3; //going too fast in that direction - - if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis - return false; - } - - //cast a segment from support in motion normal, in the same direction of motion by motion length - //support is the worst case collision point, so real collision happened before - Vector3 s = p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform(mnormal).normalized()); - Vector3 from = p_xform_A.xform(s); - Vector3 to = from + motion; - - Transform from_inv = p_xform_B.affine_inverse(); - - Vector3 local_from = from_inv.xform(from - mnormal * mlen * 0.1); //start from a little inside the bounding box - Vector3 local_to = from_inv.xform(to); - - Vector3 rpos, rnorm; - if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) { - return false; - } - - //shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough - Vector3 hitpos = p_xform_B.xform(rpos); - - real_t newlen = hitpos.distance_to(from) - (max - min) * 0.01; - p_A->set_linear_velocity((mnormal * newlen) / p_step); - - return true; -} - -real_t combine_bounce(BodySW *A, BodySW *B) { - return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1); -} - -real_t combine_friction(BodySW *A, BodySW *B) { - return ABS(MIN(A->get_friction(), B->get_friction())); -} - -bool BodyPairSW::setup(real_t p_step) { - - //cannot collide - if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) { - collided = false; - return false; - } - - if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) { - collided = false; - return false; - } - - offset_B = B->get_transform().get_origin() - A->get_transform().get_origin(); - - validate_contacts(); - - Vector3 offset_A = A->get_transform().get_origin(); - Transform xform_Au = Transform(A->get_transform().basis, Vector3()); - Transform xform_A = xform_Au * A->get_shape_transform(shape_A); - - Transform xform_Bu = B->get_transform(); - xform_Bu.origin -= offset_A; - Transform xform_B = xform_Bu * B->get_shape_transform(shape_B); - - ShapeSW *shape_A_ptr = A->get_shape(shape_A); - ShapeSW *shape_B_ptr = B->get_shape(shape_B); - - bool collided = CollisionSolverSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); - this->collided = collided; - - if (!collided) { - - //test ccd (currently just a raycast) - - if (A->is_continuous_collision_detection_enabled() && A->get_mode() > PhysicsServer::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC) { - _test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B); - } - - if (B->is_continuous_collision_detection_enabled() && B->get_mode() > PhysicsServer::BODY_MODE_KINEMATIC && A->get_mode() <= PhysicsServer::BODY_MODE_KINEMATIC) { - _test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A); - } - - return false; - } - - real_t max_penetration = space->get_contact_max_allowed_penetration(); - - real_t bias = (real_t)0.3; - - if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) { - - if (shape_A_ptr->get_custom_bias() == 0) - bias = shape_B_ptr->get_custom_bias(); - else if (shape_B_ptr->get_custom_bias() == 0) - bias = shape_A_ptr->get_custom_bias(); - else - bias = (shape_B_ptr->get_custom_bias() + shape_A_ptr->get_custom_bias()) * 0.5; - } - - real_t inv_dt = 1.0 / p_step; - - for (int i = 0; i < contact_count; i++) { - - Contact &c = contacts[i]; - c.active = false; - - Vector3 global_A = xform_Au.xform(c.local_A); - Vector3 global_B = xform_Bu.xform(c.local_B); - - real_t depth = c.normal.dot(global_A - global_B); - - if (depth <= 0) { - c.active = false; - continue; - } - - c.active = true; - -#ifdef DEBUG_ENABLED - - if (space->is_debugging_contacts()) { - space->add_debug_contact(global_A + offset_A); - space->add_debug_contact(global_B + offset_A); - } -#endif - - c.rA = global_A - A->get_center_of_mass(); - c.rB = global_B - B->get_center_of_mass() - offset_B; - - // contact query reporting... - - if (A->can_report_contacts()) { - Vector3 crA = A->get_angular_velocity().cross(c.rA) + A->get_linear_velocity(); - A->add_contact(global_A, -c.normal, depth, shape_A, global_B, shape_B, B->get_instance_id(), B->get_self(), crA); - } - - if (B->can_report_contacts()) { - Vector3 crB = B->get_angular_velocity().cross(c.rB) + B->get_linear_velocity(); - B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crB); - } - - c.active = true; - - // Precompute normal mass, tangent mass, and bias. - Vector3 inertia_A = A->get_inv_inertia_tensor().xform(c.rA.cross(c.normal)); - Vector3 inertia_B = B->get_inv_inertia_tensor().xform(c.rB.cross(c.normal)); - real_t kNormal = A->get_inv_mass() + B->get_inv_mass(); - kNormal += c.normal.dot(inertia_A.cross(c.rA)) + c.normal.dot(inertia_B.cross(c.rB)); - c.mass_normal = 1.0f / kNormal; - - c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration); - c.depth = depth; - - Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; - A->apply_impulse(c.rA + A->get_center_of_mass(), -j_vec); - B->apply_impulse(c.rB + B->get_center_of_mass(), j_vec); - c.acc_bias_impulse = 0; - c.acc_bias_impulse_center_of_mass = 0; - - c.bounce = combine_bounce(A, B); - if (c.bounce) { - - Vector3 crA = A->get_angular_velocity().cross(c.rA); - Vector3 crB = B->get_angular_velocity().cross(c.rB); - Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; - //normal impule - c.bounce = c.bounce * dv.dot(c.normal); - } - } - - return true; -} - -void BodyPairSW::solve(real_t p_step) { - - if (!collided) - return; - - for (int i = 0; i < contact_count; i++) { - - Contact &c = contacts[i]; - if (!c.active) - continue; - - c.active = false; //try to deactivate, will activate itself if still needed - - //bias impulse - - Vector3 crbA = A->get_biased_angular_velocity().cross(c.rA); - Vector3 crbB = B->get_biased_angular_velocity().cross(c.rB); - Vector3 dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA; - - real_t vbn = dbv.dot(c.normal); - - if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { - - real_t jbn = (-vbn + c.bias) * c.mass_normal; - real_t jbnOld = c.acc_bias_impulse; - c.acc_bias_impulse = MAX(jbnOld + jbn, 0.0f); - - Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); - - A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb, MAX_BIAS_ROTATION / p_step); - B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb, MAX_BIAS_ROTATION / p_step); - - crbA = A->get_biased_angular_velocity().cross(c.rA); - crbB = B->get_biased_angular_velocity().cross(c.rB); - dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA; - - vbn = dbv.dot(c.normal); - - if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { - - real_t jbn_com = (-vbn + c.bias) / (A->get_inv_mass() + B->get_inv_mass()); - real_t jbnOld_com = c.acc_bias_impulse_center_of_mass; - c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f); - - Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com); - - A->apply_bias_impulse(A->get_center_of_mass(), -jb_com, 0.0f); - B->apply_bias_impulse(B->get_center_of_mass(), jb_com, 0.0f); - } - - c.active = true; - } - - Vector3 crA = A->get_angular_velocity().cross(c.rA); - Vector3 crB = B->get_angular_velocity().cross(c.rB); - Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; - - //normal impulse - real_t vn = dv.dot(c.normal); - - if (Math::abs(vn) > MIN_VELOCITY) { - - real_t jn = -(c.bounce + vn) * c.mass_normal; - real_t jnOld = c.acc_normal_impulse; - c.acc_normal_impulse = MAX(jnOld + jn, 0.0f); - - Vector3 j = c.normal * (c.acc_normal_impulse - jnOld); - - A->apply_impulse(c.rA + A->get_center_of_mass(), -j); - B->apply_impulse(c.rB + B->get_center_of_mass(), j); - - c.active = true; - } - - //friction impulse - - real_t friction = combine_friction(A, B); - - Vector3 lvA = A->get_linear_velocity() + A->get_angular_velocity().cross(c.rA); - Vector3 lvB = B->get_linear_velocity() + B->get_angular_velocity().cross(c.rB); - - Vector3 dtv = lvB - lvA; - real_t tn = c.normal.dot(dtv); - - // tangential velocity - Vector3 tv = dtv - c.normal * tn; - real_t tvl = tv.length(); - - if (tvl > MIN_VELOCITY) { - - tv /= tvl; - - Vector3 temp1 = A->get_inv_inertia_tensor().xform(c.rA.cross(tv)); - Vector3 temp2 = B->get_inv_inertia_tensor().xform(c.rB.cross(tv)); - - real_t t = -tvl / - (A->get_inv_mass() + B->get_inv_mass() + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB))); - - Vector3 jt = t * tv; - - Vector3 jtOld = c.acc_tangent_impulse; - c.acc_tangent_impulse += jt; - - real_t fi_len = c.acc_tangent_impulse.length(); - real_t jtMax = c.acc_normal_impulse * friction; - - if (fi_len > CMP_EPSILON && fi_len > jtMax) { - - c.acc_tangent_impulse *= jtMax / fi_len; - } - - jt = c.acc_tangent_impulse - jtOld; - - A->apply_impulse(c.rA + A->get_center_of_mass(), -jt); - B->apply_impulse(c.rB + B->get_center_of_mass(), jt); - - c.active = true; - } - } -} - -BodyPairSW::BodyPairSW(BodySW *p_A, int p_shape_A, BodySW *p_B, int p_shape_B) : - ConstraintSW(_arr, 2) { - - A = p_A; - B = p_B; - shape_A = p_shape_A; - shape_B = p_shape_B; - space = A->get_space(); - A->add_constraint(this, 0); - B->add_constraint(this, 1); - contact_count = 0; - collided = false; -} - -BodyPairSW::~BodyPairSW() { - - A->remove_constraint(this); - B->remove_constraint(this); -} diff --git a/servers/physics/body_pair_sw.h b/servers/physics/body_pair_sw.h deleted file mode 100644 index 235aab23b5..0000000000 --- a/servers/physics/body_pair_sw.h +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************/ -/* body_pair_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BODY_PAIR_SW_H -#define BODY_PAIR_SW_H - -#include "body_sw.h" -#include "constraint_sw.h" - -class BodyPairSW : public ConstraintSW { - enum { - - MAX_CONTACTS = 4 - }; - - union { - struct { - BodySW *A; - BodySW *B; - }; - - BodySW *_arr[2]; - }; - - int shape_A; - int shape_B; - - struct Contact { - - Vector3 position; - Vector3 normal; - Vector3 local_A, local_B; - real_t acc_normal_impulse; // accumulated normal impulse (Pn) - Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt) - real_t acc_bias_impulse; // accumulated normal impulse for position bias (Pnb) - real_t acc_bias_impulse_center_of_mass; // accumulated normal impulse for position bias applied to com - real_t mass_normal; - real_t bias; - real_t bounce; - - real_t depth; - bool active; - Vector3 rA, rB; // Offset in world orientation with respect to center of mass - }; - - Vector3 offset_B; //use local A coordinates to avoid numerical issues on collision detection - - Vector3 sep_axis; - Contact contacts[MAX_CONTACTS]; - int contact_count; - bool collided; - - static void _contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); - - void contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B); - - void validate_contacts(); - bool _test_ccd(real_t p_step, BodySW *p_A, int p_shape_A, const Transform &p_xform_A, BodySW *p_B, int p_shape_B, const Transform &p_xform_B); - - SpaceSW *space; - -public: - bool setup(real_t p_step); - void solve(real_t p_step); - - BodyPairSW(BodySW *p_A, int p_shape_A, BodySW *p_B, int p_shape_B); - ~BodyPairSW(); -}; - -#endif // BODY_PAIR__SW_H diff --git a/servers/physics/body_sw.cpp b/servers/physics/body_sw.cpp deleted file mode 100644 index 8819941f04..0000000000 --- a/servers/physics/body_sw.cpp +++ /dev/null @@ -1,814 +0,0 @@ -/*************************************************************************/ -/* body_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "body_sw.h" -#include "area_sw.h" -#include "space_sw.h" - -void BodySW::_update_inertia() { - - if (get_space() && !inertia_update_list.in_list()) - get_space()->body_add_to_inertia_update_list(&inertia_update_list); -} - -void BodySW::_update_transform_dependant() { - - center_of_mass = get_transform().basis.xform(center_of_mass_local); - principal_inertia_axes = get_transform().basis * principal_inertia_axes_local; - - // update inertia tensor - Basis tb = principal_inertia_axes; - Basis tbt = tb.transposed(); - Basis diag; - diag.scale(_inv_inertia); - _inv_inertia_tensor = tb * diag * tbt; -} - -void BodySW::update_inertias() { - - //update shapes and motions - - switch (mode) { - - case PhysicsServer::BODY_MODE_RIGID: { - - //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet) - real_t total_area = 0; - - for (int i = 0; i < get_shape_count(); i++) { - - total_area += get_shape_area(i); - } - - // We have to recompute the center of mass - center_of_mass_local.zero(); - - for (int i = 0; i < get_shape_count(); i++) { - real_t area = get_shape_area(i); - - real_t mass = area * this->mass / total_area; - - // NOTE: we assume that the shape origin is also its center of mass - center_of_mass_local += mass * get_shape_transform(i).origin; - } - - center_of_mass_local /= mass; - - // Recompute the inertia tensor - Basis inertia_tensor; - inertia_tensor.set_zero(); - - for (int i = 0; i < get_shape_count(); i++) { - - if (is_shape_disabled(i)) { - continue; - } - - const ShapeSW *shape = get_shape(i); - - real_t area = get_shape_area(i); - - real_t mass = area * this->mass / total_area; - - Basis shape_inertia_tensor = shape->get_moment_of_inertia(mass).to_diagonal_matrix(); - Transform shape_transform = get_shape_transform(i); - Basis shape_basis = shape_transform.basis.orthonormalized(); - - // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor! - shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed(); - - Vector3 shape_origin = shape_transform.origin - center_of_mass_local; - inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass; - } - - // Compute the principal axes of inertia - principal_inertia_axes_local = inertia_tensor.diagonalize().transposed(); - _inv_inertia = inertia_tensor.get_main_diagonal().inverse(); - - if (mass) - _inv_mass = 1.0 / mass; - else - _inv_mass = 0; - - } break; - - case PhysicsServer::BODY_MODE_KINEMATIC: - case PhysicsServer::BODY_MODE_STATIC: { - - _inv_inertia_tensor.set_zero(); - _inv_mass = 0; - } break; - case PhysicsServer::BODY_MODE_CHARACTER: { - - _inv_inertia_tensor.set_zero(); - _inv_mass = 1.0 / mass; - - } break; - } - - //_update_shapes(); - - _update_transform_dependant(); -} - -void BodySW::set_active(bool p_active) { - - if (active == p_active) - return; - - active = p_active; - if (!p_active) { - if (get_space()) - get_space()->body_remove_from_active_list(&active_list); - } else { - if (mode == PhysicsServer::BODY_MODE_STATIC) - return; //static bodies can't become active - if (get_space()) - get_space()->body_add_to_active_list(&active_list); - - //still_time=0; - } - /* - if (!space) - return; - - for(int i=0;i0) { - get_space()->get_broadphase()->set_active(s.bpid,active); - } - } -*/ -} - -void BodySW::set_param(PhysicsServer::BodyParameter p_param, real_t p_value) { - - switch (p_param) { - case PhysicsServer::BODY_PARAM_BOUNCE: { - - bounce = p_value; - } break; - case PhysicsServer::BODY_PARAM_FRICTION: { - - friction = p_value; - } break; - case PhysicsServer::BODY_PARAM_MASS: { - ERR_FAIL_COND(p_value <= 0); - mass = p_value; - _update_inertia(); - - } break; - case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: { - gravity_scale = p_value; - } break; - case PhysicsServer::BODY_PARAM_LINEAR_DAMP: { - - linear_damp = p_value; - } break; - case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: { - - angular_damp = p_value; - } break; - default: { - } - } -} - -real_t BodySW::get_param(PhysicsServer::BodyParameter p_param) const { - - switch (p_param) { - case PhysicsServer::BODY_PARAM_BOUNCE: { - - return bounce; - } break; - case PhysicsServer::BODY_PARAM_FRICTION: { - - return friction; - } break; - case PhysicsServer::BODY_PARAM_MASS: { - return mass; - } break; - case PhysicsServer::BODY_PARAM_GRAVITY_SCALE: { - return gravity_scale; - } break; - case PhysicsServer::BODY_PARAM_LINEAR_DAMP: { - - return linear_damp; - } break; - case PhysicsServer::BODY_PARAM_ANGULAR_DAMP: { - - return angular_damp; - } break; - - default: { - } - } - - return 0; -} - -void BodySW::set_mode(PhysicsServer::BodyMode p_mode) { - - PhysicsServer::BodyMode prev = mode; - mode = p_mode; - - switch (p_mode) { - //CLEAR UP EVERYTHING IN CASE IT NOT WORKS! - case PhysicsServer::BODY_MODE_STATIC: - case PhysicsServer::BODY_MODE_KINEMATIC: { - - _set_inv_transform(get_transform().affine_inverse()); - _inv_mass = 0; - _set_static(p_mode == PhysicsServer::BODY_MODE_STATIC); - //set_active(p_mode==PhysicsServer::BODY_MODE_KINEMATIC); - set_active(p_mode == PhysicsServer::BODY_MODE_KINEMATIC && contacts.size()); - linear_velocity = Vector3(); - angular_velocity = Vector3(); - if (mode == PhysicsServer::BODY_MODE_KINEMATIC && prev != mode) { - first_time_kinematic = true; - } - - } break; - case PhysicsServer::BODY_MODE_RIGID: { - - _inv_mass = mass > 0 ? (1.0 / mass) : 0; - _set_static(false); - set_active(true); - - } break; - case PhysicsServer::BODY_MODE_CHARACTER: { - - _inv_mass = mass > 0 ? (1.0 / mass) : 0; - _set_static(false); - set_active(true); - angular_velocity = Vector3(); - } break; - } - - _update_inertia(); - /* - if (get_space()) - _update_queries(); - */ -} -PhysicsServer::BodyMode BodySW::get_mode() const { - - return mode; -} - -void BodySW::_shapes_changed() { - - _update_inertia(); -} - -void BodySW::set_state(PhysicsServer::BodyState p_state, const Variant &p_variant) { - - switch (p_state) { - case PhysicsServer::BODY_STATE_TRANSFORM: { - - if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { - new_transform = p_variant; - //wakeup_neighbours(); - set_active(true); - if (first_time_kinematic) { - _set_transform(p_variant); - _set_inv_transform(get_transform().affine_inverse()); - first_time_kinematic = false; - } - - } else if (mode == PhysicsServer::BODY_MODE_STATIC) { - _set_transform(p_variant); - _set_inv_transform(get_transform().affine_inverse()); - wakeup_neighbours(); - } else { - Transform t = p_variant; - t.orthonormalize(); - new_transform = get_transform(); //used as old to compute motion - if (new_transform == t) - break; - _set_transform(t); - _set_inv_transform(get_transform().inverse()); - } - wakeup(); - - } break; - case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: { - - /* - if (mode==PhysicsServer::BODY_MODE_STATIC) - break; - */ - linear_velocity = p_variant; - wakeup(); - } break; - case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: { - /* - if (mode!=PhysicsServer::BODY_MODE_RIGID) - break; - */ - angular_velocity = p_variant; - wakeup(); - - } break; - case PhysicsServer::BODY_STATE_SLEEPING: { - //? - if (mode == PhysicsServer::BODY_MODE_STATIC || mode == PhysicsServer::BODY_MODE_KINEMATIC) - break; - bool do_sleep = p_variant; - if (do_sleep) { - linear_velocity = Vector3(); - //biased_linear_velocity=Vector3(); - angular_velocity = Vector3(); - //biased_angular_velocity=Vector3(); - set_active(false); - } else { - set_active(true); - } - } break; - case PhysicsServer::BODY_STATE_CAN_SLEEP: { - can_sleep = p_variant; - if (mode == PhysicsServer::BODY_MODE_RIGID && !active && !can_sleep) - set_active(true); - - } break; - } -} -Variant BodySW::get_state(PhysicsServer::BodyState p_state) const { - - switch (p_state) { - case PhysicsServer::BODY_STATE_TRANSFORM: { - return get_transform(); - } break; - case PhysicsServer::BODY_STATE_LINEAR_VELOCITY: { - return linear_velocity; - } break; - case PhysicsServer::BODY_STATE_ANGULAR_VELOCITY: { - return angular_velocity; - } break; - case PhysicsServer::BODY_STATE_SLEEPING: { - return !is_active(); - } break; - case PhysicsServer::BODY_STATE_CAN_SLEEP: { - return can_sleep; - } break; - } - - return Variant(); -} - -void BodySW::set_space(SpaceSW *p_space) { - - if (get_space()) { - - if (inertia_update_list.in_list()) - get_space()->body_remove_from_inertia_update_list(&inertia_update_list); - if (active_list.in_list()) - get_space()->body_remove_from_active_list(&active_list); - if (direct_state_query_list.in_list()) - get_space()->body_remove_from_state_query_list(&direct_state_query_list); - } - - _set_space(p_space); - - if (get_space()) { - - _update_inertia(); - if (active) - get_space()->body_add_to_active_list(&active_list); - /* - _update_queries(); - if (is_active()) { - active=false; - set_active(true); - } - */ - } - - first_integration = true; -} - -void BodySW::_compute_area_gravity_and_dampenings(const AreaSW *p_area) { - - if (p_area->is_gravity_point()) { - if (p_area->get_gravity_distance_scale() > 0) { - Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); - gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale() + 1, 2)); - } else { - gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); - } - } else { - gravity += p_area->get_gravity_vector() * p_area->get_gravity(); - } - - area_linear_damp += p_area->get_linear_damp(); - area_angular_damp += p_area->get_angular_damp(); -} - -void BodySW::set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock) { - if (lock) { - locked_axis |= p_axis; - } else { - locked_axis &= ~p_axis; - } -} - -bool BodySW::is_axis_locked(PhysicsServer::BodyAxis p_axis) const { - return locked_axis & p_axis; -} - -void BodySW::integrate_forces(real_t p_step) { - - if (mode == PhysicsServer::BODY_MODE_STATIC) - return; - - AreaSW *def_area = get_space()->get_default_area(); - // AreaSW *damp_area = def_area; - - ERR_FAIL_COND(!def_area); - - int ac = areas.size(); - bool stopped = false; - gravity = Vector3(0, 0, 0); - area_linear_damp = 0; - area_angular_damp = 0; - if (ac) { - areas.sort(); - const AreaCMP *aa = &areas[0]; - // damp_area = aa[ac-1].area; - for (int i = ac - 1; i >= 0 && !stopped; i--) { - PhysicsServer::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); - switch (mode) { - case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE: - case PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { - _compute_area_gravity_and_dampenings(aa[i].area); - stopped = mode == PhysicsServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; - } break; - case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE: - case PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { - gravity = Vector3(0, 0, 0); - area_angular_damp = 0; - area_linear_damp = 0; - _compute_area_gravity_and_dampenings(aa[i].area); - stopped = mode == PhysicsServer::AREA_SPACE_OVERRIDE_REPLACE; - } break; - default: { - } - } - } - } - - if (!stopped) { - _compute_area_gravity_and_dampenings(def_area); - } - - gravity *= gravity_scale; - - // If less than 0, override dampenings with that of the Body - if (angular_damp >= 0) - area_angular_damp = angular_damp; - /* - else - area_angular_damp=damp_area->get_angular_damp(); - */ - - if (linear_damp >= 0) - area_linear_damp = linear_damp; - /* - else - area_linear_damp=damp_area->get_linear_damp(); - */ - - Vector3 motion; - bool do_motion = false; - - if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { - - //compute motion, angular and etc. velocities from prev transform - linear_velocity = (new_transform.origin - get_transform().origin) / p_step; - - //compute a FAKE angular velocity, not so easy - Basis rot = new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized(); - Vector3 axis; - real_t angle; - - rot.get_axis_angle(axis, angle); - axis.normalize(); - angular_velocity = axis.normalized() * (angle / p_step); - - motion = new_transform.origin - get_transform().origin; - do_motion = true; - - } else { - if (!omit_force_integration && !first_integration) { - //overridden by direct state query - - Vector3 force = gravity * mass; - force += applied_force; - Vector3 torque = applied_torque; - - real_t damp = 1.0 - p_step * area_linear_damp; - - if (damp < 0) // reached zero in the given time - damp = 0; - - real_t angular_damp = 1.0 - p_step * area_angular_damp; - - if (angular_damp < 0) // reached zero in the given time - angular_damp = 0; - - linear_velocity *= damp; - angular_velocity *= angular_damp; - - linear_velocity += _inv_mass * force * p_step; - angular_velocity += _inv_inertia_tensor.xform(torque) * p_step; - } - - if (continuous_cd) { - motion = linear_velocity * p_step; - do_motion = true; - } - } - - applied_force = Vector3(); - applied_torque = Vector3(); - first_integration = false; - - //motion=linear_velocity*p_step; - - biased_angular_velocity = Vector3(); - biased_linear_velocity = Vector3(); - - if (do_motion) { //shapes temporarily extend for raycast - _update_shapes_with_motion(motion); - } - - def_area = NULL; // clear the area, so it is set in the next frame - contact_count = 0; -} - -void BodySW::integrate_velocities(real_t p_step) { - - if (mode == PhysicsServer::BODY_MODE_STATIC) - return; - - if (fi_callback) - get_space()->body_add_to_state_query_list(&direct_state_query_list); - - //apply axis lock linear - for (int i = 0; i < 3; i++) { - if (is_axis_locked((PhysicsServer::BodyAxis)(1 << i))) { - linear_velocity[i] = 0; - biased_linear_velocity[i] = 0; - new_transform.origin[i] = get_transform().origin[i]; - } - } - //apply axis lock angular - for (int i = 0; i < 3; i++) { - if (is_axis_locked((PhysicsServer::BodyAxis)(1 << (i + 3)))) { - angular_velocity[i] = 0; - biased_angular_velocity[i] = 0; - } - } - - if (mode == PhysicsServer::BODY_MODE_KINEMATIC) { - - _set_transform(new_transform, false); - _set_inv_transform(new_transform.affine_inverse()); - if (contacts.size() == 0 && linear_velocity == Vector3() && angular_velocity == Vector3()) - set_active(false); //stopped moving, deactivate - - return; - } - - Vector3 total_angular_velocity = angular_velocity + biased_angular_velocity; - - real_t ang_vel = total_angular_velocity.length(); - Transform transform = get_transform(); - - if (ang_vel != 0.0) { - Vector3 ang_vel_axis = total_angular_velocity / ang_vel; - Basis rot(ang_vel_axis, ang_vel * p_step); - Basis identity3(1, 0, 0, 0, 1, 0, 0, 0, 1); - transform.origin += ((identity3 - rot) * transform.basis).xform(center_of_mass_local); - transform.basis = rot * transform.basis; - transform.orthonormalize(); - } - - Vector3 total_linear_velocity = linear_velocity + biased_linear_velocity; - /*for(int i=0;i<3;i++) { - if (axis_lock&(1<body_add_to_state_query_list(&direct_state_query_list); - */ -} - -/* -void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) { - - Transform inv_xform = p_xform.affine_inverse(); - if (!get_space()) { - _set_transform(p_xform); - _set_inv_transform(inv_xform); - - return; - } - - //compute a FAKE linear velocity - this is easy - - linear_velocity=(p_xform.origin - get_transform().origin)/p_step; - - //compute a FAKE angular velocity, not so easy - Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized(); - Vector3 axis; - real_t angle; - - rot.get_axis_angle(axis,angle); - axis.normalize(); - angular_velocity=axis.normalized() * (angle/p_step); - linear_velocity = (p_xform.origin - get_transform().origin)/p_step; - - if (!direct_state_query_list.in_list())// - callalways, so lv and av are cleared && (state_query || direct_state_query)) - get_space()->body_add_to_state_query_list(&direct_state_query_list); - simulated_motion=true; - _set_transform(p_xform); - - -} -*/ - -void BodySW::wakeup_neighbours() { - - for (Map::Element *E = constraint_map.front(); E; E = E->next()) { - - const ConstraintSW *c = E->key(); - BodySW **n = c->get_body_ptr(); - int bc = c->get_body_count(); - - for (int i = 0; i < bc; i++) { - - if (i == E->get()) - continue; - BodySW *b = n[i]; - if (b->mode != PhysicsServer::BODY_MODE_RIGID) - continue; - - if (!b->is_active()) - b->set_active(true); - } - } -} - -void BodySW::call_queries() { - - if (fi_callback) { - - PhysicsDirectBodyStateSW *dbs = PhysicsDirectBodyStateSW::singleton; - dbs->body = this; - - Variant v = dbs; - - Object *obj = ObjectDB::get_instance(fi_callback->id); - if (!obj) { - - set_force_integration_callback(ObjectID(), StringName()); - } else { - const Variant *vp[2] = { &v, &fi_callback->udata }; - - Callable::CallError ce; - int argc = (fi_callback->udata.get_type() == Variant::NIL) ? 1 : 2; - obj->call(fi_callback->method, vp, argc, ce); - } - } -} - -bool BodySW::sleep_test(real_t p_step) { - - if (mode == PhysicsServer::BODY_MODE_STATIC || mode == PhysicsServer::BODY_MODE_KINEMATIC) - return true; // - else if (mode == PhysicsServer::BODY_MODE_CHARACTER) - return !active; // characters don't sleep unless asked to sleep - else if (!can_sleep) - return false; - - if (Math::abs(angular_velocity.length()) < get_space()->get_body_angular_velocity_sleep_threshold() && Math::abs(linear_velocity.length_squared()) < get_space()->get_body_linear_velocity_sleep_threshold() * get_space()->get_body_linear_velocity_sleep_threshold()) { - - still_time += p_step; - - return still_time > get_space()->get_body_time_to_sleep(); - } else { - - still_time = 0; //maybe this should be set to 0 on set_active? - return false; - } -} - -void BodySW::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { - - if (fi_callback) { - - memdelete(fi_callback); - fi_callback = NULL; - } - - if (p_id.is_valid()) { - - fi_callback = memnew(ForceIntegrationCallback); - fi_callback->id = p_id; - fi_callback->method = p_method; - fi_callback->udata = p_udata; - } -} - -void BodySW::set_kinematic_margin(real_t p_margin) { - kinematic_safe_margin = p_margin; -} - -BodySW::BodySW() : - CollisionObjectSW(TYPE_BODY), - locked_axis(0), - active_list(this), - inertia_update_list(this), - direct_state_query_list(this) { - - mode = PhysicsServer::BODY_MODE_RIGID; - active = true; - - mass = 1; - kinematic_safe_margin = 0.01; - //_inv_inertia=Transform(); - _inv_mass = 1; - bounce = 0; - friction = 1; - omit_force_integration = false; - //applied_torque=0; - island_step = 0; - island_next = NULL; - island_list_next = NULL; - first_time_kinematic = false; - first_integration = false; - _set_static(false); - - contact_count = 0; - gravity_scale = 1.0; - linear_damp = -1; - angular_damp = -1; - area_angular_damp = 0; - area_linear_damp = 0; - - still_time = 0; - continuous_cd = false; - can_sleep = true; - fi_callback = NULL; -} - -BodySW::~BodySW() { - - if (fi_callback) - memdelete(fi_callback); -} - -PhysicsDirectBodyStateSW *PhysicsDirectBodyStateSW::singleton = NULL; - -PhysicsDirectSpaceState *PhysicsDirectBodyStateSW::get_space_state() { - - return body->get_space()->get_direct_state(); -} diff --git a/servers/physics/body_sw.h b/servers/physics/body_sw.h deleted file mode 100644 index d712b09878..0000000000 --- a/servers/physics/body_sw.h +++ /dev/null @@ -1,475 +0,0 @@ -/*************************************************************************/ -/* body_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BODY_SW_H -#define BODY_SW_H - -#include "area_sw.h" -#include "collision_object_sw.h" -#include "core/vset.h" - -class ConstraintSW; - -class BodySW : public CollisionObjectSW { - - PhysicsServer::BodyMode mode; - - Vector3 linear_velocity; - Vector3 angular_velocity; - - Vector3 biased_linear_velocity; - Vector3 biased_angular_velocity; - real_t mass; - real_t bounce; - real_t friction; - - real_t linear_damp; - real_t angular_damp; - real_t gravity_scale; - - uint16_t locked_axis; - - real_t kinematic_safe_margin; - real_t _inv_mass; - Vector3 _inv_inertia; // Relative to the principal axes of inertia - - // Relative to the local frame of reference - Basis principal_inertia_axes_local; - Vector3 center_of_mass_local; - - // In world orientation with local origin - Basis _inv_inertia_tensor; - Basis principal_inertia_axes; - Vector3 center_of_mass; - - Vector3 gravity; - - real_t still_time; - - Vector3 applied_force; - Vector3 applied_torque; - - real_t area_angular_damp; - real_t area_linear_damp; - - SelfList active_list; - SelfList inertia_update_list; - SelfList direct_state_query_list; - - VSet exceptions; - bool omit_force_integration; - bool active; - - bool first_integration; - - bool continuous_cd; - bool can_sleep; - bool first_time_kinematic; - void _update_inertia(); - virtual void _shapes_changed(); - Transform new_transform; - - Map constraint_map; - - struct AreaCMP { - - AreaSW *area; - int refCount; - _FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); } - _FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); } - _FORCE_INLINE_ AreaCMP() {} - _FORCE_INLINE_ AreaCMP(AreaSW *p_area) { - area = p_area; - refCount = 1; - } - }; - - Vector areas; - - struct Contact { - - Vector3 local_pos; - Vector3 local_normal; - real_t depth; - int local_shape; - Vector3 collider_pos; - int collider_shape; - ObjectID collider_instance_id; - RID collider; - Vector3 collider_velocity_at_pos; - }; - - Vector contacts; //no contacts by default - int contact_count; - - struct ForceIntegrationCallback { - - ObjectID id; - StringName method; - Variant udata; - }; - - ForceIntegrationCallback *fi_callback; - - uint64_t island_step; - BodySW *island_next; - BodySW *island_list_next; - - _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const AreaSW *p_area); - - _FORCE_INLINE_ void _update_transform_dependant(); - - friend class PhysicsDirectBodyStateSW; // i give up, too many functions to expose - -public: - void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); - - void set_kinematic_margin(real_t p_margin); - _FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; } - - _FORCE_INLINE_ void add_area(AreaSW *p_area) { - int index = areas.find(AreaCMP(p_area)); - if (index > -1) { - areas.write[index].refCount += 1; - } else { - areas.ordered_insert(AreaCMP(p_area)); - } - } - - _FORCE_INLINE_ void remove_area(AreaSW *p_area) { - int index = areas.find(AreaCMP(p_area)); - if (index > -1) { - areas.write[index].refCount -= 1; - if (areas[index].refCount < 1) - areas.remove(index); - } - } - - _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { - contacts.resize(p_size); - contact_count = 0; - if (mode == PhysicsServer::BODY_MODE_KINEMATIC && p_size) set_active(true); - } - _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } - - _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } - _FORCE_INLINE_ void add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos); - - _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); } - _FORCE_INLINE_ void remove_exception(const RID &p_exception) { exceptions.erase(p_exception); } - _FORCE_INLINE_ bool has_exception(const RID &p_exception) const { return exceptions.has(p_exception); } - _FORCE_INLINE_ const VSet &get_exceptions() const { return exceptions; } - - _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } - _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - - _FORCE_INLINE_ BodySW *get_island_next() const { return island_next; } - _FORCE_INLINE_ void set_island_next(BodySW *p_next) { island_next = p_next; } - - _FORCE_INLINE_ BodySW *get_island_list_next() const { return island_list_next; } - _FORCE_INLINE_ void set_island_list_next(BodySW *p_next) { island_list_next = p_next; } - - _FORCE_INLINE_ void add_constraint(ConstraintSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } - _FORCE_INLINE_ void remove_constraint(ConstraintSW *p_constraint) { constraint_map.erase(p_constraint); } - const Map &get_constraint_map() const { return constraint_map; } - _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } - - _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } - _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; } - - _FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; } - _FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; } - _FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3 &p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); } - - _FORCE_INLINE_ void set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; } - _FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; } - - _FORCE_INLINE_ void set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; } - _FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; } - - _FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; } - _FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; } - - _FORCE_INLINE_ void apply_central_impulse(const Vector3 &p_j) { - linear_velocity += p_j * _inv_mass; - } - - _FORCE_INLINE_ void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { - - linear_velocity += p_j * _inv_mass; - angular_velocity += _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); - } - - _FORCE_INLINE_ void apply_torque_impulse(const Vector3 &p_j) { - - angular_velocity += _inv_inertia_tensor.xform(p_j); - } - - _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j, real_t p_max_delta_av = -1.0) { - - biased_linear_velocity += p_j * _inv_mass; - if (p_max_delta_av != 0.0) { - Vector3 delta_av = _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); - if (p_max_delta_av > 0 && delta_av.length() > p_max_delta_av) { - delta_av = delta_av.normalized() * p_max_delta_av; - } - biased_angular_velocity += delta_av; - } - } - - _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_j) { - - biased_angular_velocity += _inv_inertia_tensor.xform(p_j); - } - - _FORCE_INLINE_ void add_central_force(const Vector3 &p_force) { - - applied_force += p_force; - } - - _FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_pos) { - - applied_force += p_force; - applied_torque += p_pos.cross(p_force); - } - - _FORCE_INLINE_ void add_torque(const Vector3 &p_torque) { - applied_torque += p_torque; - } - - void set_active(bool p_active); - _FORCE_INLINE_ bool is_active() const { return active; } - - _FORCE_INLINE_ void wakeup() { - if ((!get_space()) || mode == PhysicsServer::BODY_MODE_STATIC || mode == PhysicsServer::BODY_MODE_KINEMATIC) - return; - set_active(true); - } - - void set_param(PhysicsServer::BodyParameter p_param, real_t); - real_t get_param(PhysicsServer::BodyParameter p_param) const; - - void set_mode(PhysicsServer::BodyMode p_mode); - PhysicsServer::BodyMode get_mode() const; - - void set_state(PhysicsServer::BodyState p_state, const Variant &p_variant); - Variant get_state(PhysicsServer::BodyState p_state) const; - - void set_applied_force(const Vector3 &p_force) { applied_force = p_force; } - Vector3 get_applied_force() const { return applied_force; } - - void set_applied_torque(const Vector3 &p_torque) { applied_torque = p_torque; } - Vector3 get_applied_torque() const { return applied_torque; } - - _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; } - _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; } - - void set_space(SpaceSW *p_space); - - void update_inertias(); - - _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; } - _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; } - _FORCE_INLINE_ Basis get_inv_inertia_tensor() const { return _inv_inertia_tensor; } - _FORCE_INLINE_ real_t get_friction() const { return friction; } - _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } - _FORCE_INLINE_ real_t get_bounce() const { return bounce; } - - void set_axis_lock(PhysicsServer::BodyAxis p_axis, bool lock); - bool is_axis_locked(PhysicsServer::BodyAxis p_axis) const; - - void integrate_forces(real_t p_step); - void integrate_velocities(real_t p_step); - - _FORCE_INLINE_ Vector3 get_velocity_in_local_point(const Vector3 &rel_pos) const { - - return linear_velocity + angular_velocity.cross(rel_pos - center_of_mass); - } - - _FORCE_INLINE_ real_t compute_impulse_denominator(const Vector3 &p_pos, const Vector3 &p_normal) const { - - Vector3 r0 = p_pos - get_transform().origin - center_of_mass; - - Vector3 c0 = (r0).cross(p_normal); - - Vector3 vec = (_inv_inertia_tensor.xform_inv(c0)).cross(r0); - - return _inv_mass + p_normal.dot(vec); - } - - _FORCE_INLINE_ real_t compute_angular_impulse_denominator(const Vector3 &p_axis) const { - - return p_axis.dot(_inv_inertia_tensor.xform_inv(p_axis)); - } - - //void simulate_motion(const Transform& p_xform,real_t p_step); - void call_queries(); - void wakeup_neighbours(); - - bool sleep_test(real_t p_step); - - BodySW(); - ~BodySW(); -}; - -//add contact inline - -void BodySW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos) { - - int c_max = contacts.size(); - - if (c_max == 0) - return; - - Contact *c = contacts.ptrw(); - - int idx = -1; - - if (contact_count < c_max) { - idx = contact_count++; - } else { - - real_t least_depth = 1e20; - int least_deep = -1; - for (int i = 0; i < c_max; i++) { - - if (i == 0 || c[i].depth < least_depth) { - least_deep = i; - least_depth = c[i].depth; - } - } - - if (least_deep >= 0 && least_depth < p_depth) { - - idx = least_deep; - } - if (idx == -1) - return; //none least deepe than this - } - - c[idx].local_pos = p_local_pos; - c[idx].local_normal = p_local_normal; - c[idx].depth = p_depth; - c[idx].local_shape = p_local_shape; - c[idx].collider_pos = p_collider_pos; - c[idx].collider_shape = p_collider_shape; - c[idx].collider_instance_id = p_collider_instance_id; - c[idx].collider = p_collider; - c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos; -} - -class PhysicsDirectBodyStateSW : public PhysicsDirectBodyState { - - GDCLASS(PhysicsDirectBodyStateSW, PhysicsDirectBodyState); - -public: - static PhysicsDirectBodyStateSW *singleton; - BodySW *body; - real_t step; - - virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area - virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area - virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area - - virtual Vector3 get_center_of_mass() const { return body->get_center_of_mass(); } - virtual Basis get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); } - - virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass - virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space - virtual Basis get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space - - virtual void set_linear_velocity(const Vector3 &p_velocity) { body->set_linear_velocity(p_velocity); } - virtual Vector3 get_linear_velocity() const { return body->get_linear_velocity(); } - - virtual void set_angular_velocity(const Vector3 &p_velocity) { body->set_angular_velocity(p_velocity); } - virtual Vector3 get_angular_velocity() const { return body->get_angular_velocity(); } - - virtual void set_transform(const Transform &p_transform) { body->set_state(PhysicsServer::BODY_STATE_TRANSFORM, p_transform); } - virtual Transform get_transform() const { return body->get_transform(); } - - virtual void add_central_force(const Vector3 &p_force) { body->add_central_force(p_force); } - virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->add_force(p_force, p_pos); } - virtual void add_torque(const Vector3 &p_torque) { body->add_torque(p_torque); } - virtual void apply_central_impulse(const Vector3 &p_j) { body->apply_central_impulse(p_j); } - virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); } - virtual void apply_torque_impulse(const Vector3 &p_j) { body->apply_torque_impulse(p_j); } - - virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); } - virtual bool is_sleeping() const { return !body->is_active(); } - - virtual int get_contact_count() const { return body->contact_count; } - - virtual Vector3 get_contact_local_position(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); - return body->contacts[p_contact_idx].local_pos; - } - virtual Vector3 get_contact_local_normal(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); - return body->contacts[p_contact_idx].local_normal; - } - virtual float get_contact_impulse(int p_contact_idx) const { - return 0.0f; // Only implemented for bullet - } - virtual int get_contact_local_shape(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1); - return body->contacts[p_contact_idx].local_shape; - } - - virtual RID get_contact_collider(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID()); - return body->contacts[p_contact_idx].collider; - } - virtual Vector3 get_contact_collider_position(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); - return body->contacts[p_contact_idx].collider_pos; - } - virtual ObjectID get_contact_collider_id(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID()); - return body->contacts[p_contact_idx].collider_instance_id; - } - virtual int get_contact_collider_shape(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); - return body->contacts[p_contact_idx].collider_shape; - } - virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const { - ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); - return body->contacts[p_contact_idx].collider_velocity_at_pos; - } - - virtual PhysicsDirectSpaceState *get_space_state(); - - virtual real_t get_step() const { return step; } - PhysicsDirectBodyStateSW() { - singleton = this; - body = NULL; - } -}; - -#endif // BODY__SW_H diff --git a/servers/physics/broad_phase_basic.cpp b/servers/physics/broad_phase_basic.cpp deleted file mode 100644 index f49bf9d4cc..0000000000 --- a/servers/physics/broad_phase_basic.cpp +++ /dev/null @@ -1,225 +0,0 @@ -/*************************************************************************/ -/* broad_phase_basic.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "broad_phase_basic.h" -#include "core/list.h" -#include "core/print_string.h" - -BroadPhaseSW::ID BroadPhaseBasic::create(CollisionObjectSW *p_object, int p_subindex) { - - ERR_FAIL_COND_V(p_object == NULL, 0); - - current++; - - Element e; - e.owner = p_object; - e._static = false; - e.subindex = p_subindex; - - element_map[current] = e; - return current; -} - -void BroadPhaseBasic::move(ID p_id, const AABB &p_aabb) { - - Map::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - E->get().aabb = p_aabb; -} -void BroadPhaseBasic::set_static(ID p_id, bool p_static) { - - Map::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - E->get()._static = p_static; -} -void BroadPhaseBasic::remove(ID p_id) { - - Map::Element *E = element_map.find(p_id); - ERR_FAIL_COND(!E); - List to_erase; - //unpair must be done immediately on removal to avoid potential invalid pointers - for (Map::Element *F = pair_map.front(); F; F = F->next()) { - - if (F->key().a == p_id || F->key().b == p_id) { - - if (unpair_callback) { - Element *elem_A = &element_map[F->key().a]; - Element *elem_B = &element_map[F->key().b]; - unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, F->get(), unpair_userdata); - } - to_erase.push_back(F->key()); - } - } - while (to_erase.size()) { - - pair_map.erase(to_erase.front()->get()); - to_erase.pop_front(); - } - element_map.erase(E); -} - -CollisionObjectSW *BroadPhaseBasic::get_object(ID p_id) const { - - const Map::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, NULL); - return E->get().owner; -} -bool BroadPhaseBasic::is_static(ID p_id) const { - - const Map::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, false); - return E->get()._static; -} -int BroadPhaseBasic::get_subindex(ID p_id) const { - - const Map::Element *E = element_map.find(p_id); - ERR_FAIL_COND_V(!E, -1); - return E->get().subindex; -} - -int BroadPhaseBasic::cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) { - - int rc = 0; - - for (Map::Element *E = element_map.front(); E; E = E->next()) { - - const AABB aabb = E->get().aabb; - if (aabb.has_point(p_point)) { - - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) - break; - } - } - - return rc; -} - -int BroadPhaseBasic::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) { - - int rc = 0; - - for (Map::Element *E = element_map.front(); E; E = E->next()) { - - const AABB aabb = E->get().aabb; - if (aabb.intersects_segment(p_from, p_to)) { - - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) - break; - } - } - - return rc; -} -int BroadPhaseBasic::cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) { - - int rc = 0; - - for (Map::Element *E = element_map.front(); E; E = E->next()) { - - const AABB aabb = E->get().aabb; - if (aabb.intersects(p_aabb)) { - - p_results[rc] = E->get().owner; - p_result_indices[rc] = E->get().subindex; - rc++; - if (rc >= p_max_results) - break; - } - } - - return rc; -} - -void BroadPhaseBasic::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { - - pair_userdata = p_userdata; - pair_callback = p_pair_callback; -} -void BroadPhaseBasic::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { - - unpair_userdata = p_userdata; - unpair_callback = p_unpair_callback; -} - -void BroadPhaseBasic::update() { - - // recompute pairs - for (Map::Element *I = element_map.front(); I; I = I->next()) { - - for (Map::Element *J = I->next(); J; J = J->next()) { - - Element *elem_A = &I->get(); - Element *elem_B = &J->get(); - - if (elem_A->owner == elem_B->owner) - continue; - - bool pair_ok = elem_A->aabb.intersects(elem_B->aabb) && (!elem_A->_static || !elem_B->_static); - - PairKey key(I->key(), J->key()); - - Map::Element *E = pair_map.find(key); - - if (!pair_ok && E) { - if (unpair_callback) - unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, E->get(), unpair_userdata); - pair_map.erase(key); - } - - if (pair_ok && !E) { - - void *data = NULL; - if (pair_callback) - data = pair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, unpair_userdata); - pair_map.insert(key, data); - } - } - } -} - -BroadPhaseSW *BroadPhaseBasic::_create() { - - return memnew(BroadPhaseBasic); -} - -BroadPhaseBasic::BroadPhaseBasic() { - - current = 1; - unpair_callback = NULL; - unpair_userdata = NULL; - pair_callback = NULL; - pair_userdata = NULL; -} diff --git a/servers/physics/broad_phase_basic.h b/servers/physics/broad_phase_basic.h deleted file mode 100644 index 424889d8aa..0000000000 --- a/servers/physics/broad_phase_basic.h +++ /dev/null @@ -1,108 +0,0 @@ -/*************************************************************************/ -/* broad_phase_basic.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BROAD_PHASE_BASIC_H -#define BROAD_PHASE_BASIC_H - -#include "broad_phase_sw.h" -#include "core/map.h" - -class BroadPhaseBasic : public BroadPhaseSW { - - struct Element { - - CollisionObjectSW *owner; - bool _static; - AABB aabb; - int subindex; - }; - - Map element_map; - - ID current; - - struct PairKey { - - union { - struct { - ID a; - ID b; - }; - uint64_t key; - }; - - _FORCE_INLINE_ bool operator<(const PairKey &p_key) const { - return key < p_key.key; - } - - PairKey() { key = 0; } - PairKey(ID p_a, ID p_b) { - if (p_a > p_b) { - a = p_b; - b = p_a; - } else { - a = p_a; - b = p_b; - } - } - }; - - Map pair_map; - - PairCallback pair_callback; - void *pair_userdata; - UnpairCallback unpair_callback; - void *unpair_userdata; - -public: - // 0 is an invalid ID - virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0); - virtual void move(ID p_id, const AABB &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); - - virtual CollisionObjectSW *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; - - virtual int cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL); - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL); - virtual int cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL); - - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); - - virtual void update(); - - static BroadPhaseSW *_create(); - BroadPhaseBasic(); -}; - -#endif // BROAD_PHASE_BASIC_H diff --git a/servers/physics/broad_phase_octree.cpp b/servers/physics/broad_phase_octree.cpp deleted file mode 100644 index a9aa662abf..0000000000 --- a/servers/physics/broad_phase_octree.cpp +++ /dev/null @@ -1,129 +0,0 @@ -/*************************************************************************/ -/* broad_phase_octree.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "broad_phase_octree.h" -#include "collision_object_sw.h" - -BroadPhaseSW::ID BroadPhaseOctree::create(CollisionObjectSW *p_object, int p_subindex) { - - ID oid = octree.create(p_object, AABB(), p_subindex, false, 1 << p_object->get_type(), 0); - return oid; -} - -void BroadPhaseOctree::move(ID p_id, const AABB &p_aabb) { - - octree.move(p_id, p_aabb); -} - -void BroadPhaseOctree::set_static(ID p_id, bool p_static) { - - CollisionObjectSW *it = octree.get(p_id); - octree.set_pairable(p_id, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF); //pair everything, don't care 1? -} -void BroadPhaseOctree::remove(ID p_id) { - - octree.erase(p_id); -} - -CollisionObjectSW *BroadPhaseOctree::get_object(ID p_id) const { - - CollisionObjectSW *it = octree.get(p_id); - ERR_FAIL_COND_V(!it, NULL); - return it; -} -bool BroadPhaseOctree::is_static(ID p_id) const { - - return !octree.is_pairable(p_id); -} -int BroadPhaseOctree::get_subindex(ID p_id) const { - - return octree.get_subindex(p_id); -} - -int BroadPhaseOctree::cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) { - - return octree.cull_point(p_point, p_results, p_max_results, p_result_indices); -} - -int BroadPhaseOctree::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) { - - return octree.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); -} - -int BroadPhaseOctree::cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices) { - - return octree.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); -} - -void *BroadPhaseOctree::_pair_callback(void *self, OctreeElementID p_A, CollisionObjectSW *p_object_A, int subindex_A, OctreeElementID p_B, CollisionObjectSW *p_object_B, int subindex_B) { - - BroadPhaseOctree *bpo = (BroadPhaseOctree *)(self); - if (!bpo->pair_callback) - return NULL; - - return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata); -} - -void BroadPhaseOctree::_unpair_callback(void *self, OctreeElementID p_A, CollisionObjectSW *p_object_A, int subindex_A, OctreeElementID p_B, CollisionObjectSW *p_object_B, int subindex_B, void *pairdata) { - - BroadPhaseOctree *bpo = (BroadPhaseOctree *)(self); - if (!bpo->unpair_callback) - return; - - bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata); -} - -void BroadPhaseOctree::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { - - pair_callback = p_pair_callback; - pair_userdata = p_userdata; -} -void BroadPhaseOctree::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { - - unpair_callback = p_unpair_callback; - unpair_userdata = p_userdata; -} - -void BroadPhaseOctree::update() { - // does.. not? -} - -BroadPhaseSW *BroadPhaseOctree::_create() { - - return memnew(BroadPhaseOctree); -} - -BroadPhaseOctree::BroadPhaseOctree() { - octree.set_pair_callback(_pair_callback, this); - octree.set_unpair_callback(_unpair_callback, this); - pair_callback = NULL; - pair_userdata = NULL; - unpair_userdata = NULL; -} diff --git a/servers/physics/broad_phase_octree.h b/servers/physics/broad_phase_octree.h deleted file mode 100644 index e2a1d82b69..0000000000 --- a/servers/physics/broad_phase_octree.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************/ -/* broad_phase_octree.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BROAD_PHASE_OCTREE_H -#define BROAD_PHASE_OCTREE_H - -#include "broad_phase_sw.h" -#include "core/math/octree.h" - -class BroadPhaseOctree : public BroadPhaseSW { - - Octree octree; - - static void *_pair_callback(void *, OctreeElementID, CollisionObjectSW *, int, OctreeElementID, CollisionObjectSW *, int); - static void _unpair_callback(void *, OctreeElementID, CollisionObjectSW *, int, OctreeElementID, CollisionObjectSW *, int, void *); - - PairCallback pair_callback; - void *pair_userdata; - UnpairCallback unpair_callback; - void *unpair_userdata; - -public: - // 0 is an invalid ID - virtual ID create(CollisionObjectSW *p_object, int p_subindex = 0); - virtual void move(ID p_id, const AABB &p_aabb); - virtual void set_static(ID p_id, bool p_static); - virtual void remove(ID p_id); - - virtual CollisionObjectSW *get_object(ID p_id) const; - virtual bool is_static(ID p_id) const; - virtual int get_subindex(ID p_id) const; - - virtual int cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL); - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL); - virtual int cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL); - - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); - - virtual void update(); - - static BroadPhaseSW *_create(); - BroadPhaseOctree(); -}; - -#endif // BROAD_PHASE_OCTREE_H diff --git a/servers/physics/broad_phase_sw.cpp b/servers/physics/broad_phase_sw.cpp deleted file mode 100644 index a6fc253b1b..0000000000 --- a/servers/physics/broad_phase_sw.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************/ -/* broad_phase_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "broad_phase_sw.h" - -BroadPhaseSW::CreateFunction BroadPhaseSW::create_func = NULL; - -BroadPhaseSW::~BroadPhaseSW() { -} diff --git a/servers/physics/broad_phase_sw.h b/servers/physics/broad_phase_sw.h deleted file mode 100644 index e69a2d24ed..0000000000 --- a/servers/physics/broad_phase_sw.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************/ -/* broad_phase_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef BROAD_PHASE_SW_H -#define BROAD_PHASE_SW_H - -#include "core/math/aabb.h" -#include "core/math/math_funcs.h" - -class CollisionObjectSW; - -class BroadPhaseSW { - -public: - typedef BroadPhaseSW *(*CreateFunction)(); - - static CreateFunction create_func; - - typedef uint32_t ID; - - typedef void *(*PairCallback)(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_userdata); - typedef void (*UnpairCallback)(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_data, void *p_userdata); - - // 0 is an invalid ID - virtual ID create(CollisionObjectSW *p_object_, int p_subindex = 0) = 0; - virtual void move(ID p_id, const AABB &p_aabb) = 0; - virtual void set_static(ID p_id, bool p_static) = 0; - virtual void remove(ID p_id) = 0; - - virtual CollisionObjectSW *get_object(ID p_id) const = 0; - virtual bool is_static(ID p_id) const = 0; - virtual int get_subindex(ID p_id) const = 0; - - virtual int cull_point(const Vector3 &p_point, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0; - virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0; - virtual int cull_aabb(const AABB &p_aabb, CollisionObjectSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0; - - virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0; - virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0; - - virtual void update() = 0; - - virtual ~BroadPhaseSW(); -}; - -#endif // BROAD_PHASE__SW_H diff --git a/servers/physics/collision_object_sw.cpp b/servers/physics/collision_object_sw.cpp deleted file mode 100644 index 3cabf75ab6..0000000000 --- a/servers/physics/collision_object_sw.cpp +++ /dev/null @@ -1,239 +0,0 @@ -/*************************************************************************/ -/* collision_object_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "collision_object_sw.h" -#include "servers/physics/physics_server_sw.h" -#include "space_sw.h" - -void CollisionObjectSW::add_shape(ShapeSW *p_shape, const Transform &p_transform, bool p_disabled) { - - Shape s; - s.shape = p_shape; - s.xform = p_transform; - s.xform_inv = s.xform.affine_inverse(); - s.bpid = 0; //needs update - s.disabled = p_disabled; - shapes.push_back(s); - p_shape->add_owner(this); - - if (!pending_shape_update_list.in_list()) { - PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); - } - //_update_shapes(); - //_shapes_changed(); -} - -void CollisionObjectSW::set_shape(int p_index, ShapeSW *p_shape) { - - ERR_FAIL_INDEX(p_index, shapes.size()); - shapes[p_index].shape->remove_owner(this); - shapes.write[p_index].shape = p_shape; - - p_shape->add_owner(this); - if (!pending_shape_update_list.in_list()) { - PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); - } - //_update_shapes(); - //_shapes_changed(); -} -void CollisionObjectSW::set_shape_transform(int p_index, const Transform &p_transform) { - - ERR_FAIL_INDEX(p_index, shapes.size()); - - shapes.write[p_index].xform = p_transform; - shapes.write[p_index].xform_inv = p_transform.affine_inverse(); - if (!pending_shape_update_list.in_list()) { - PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); - } - //_update_shapes(); - //_shapes_changed(); -} - -void CollisionObjectSW::set_shape_as_disabled(int p_idx, bool p_enable) { - shapes.write[p_idx].disabled = p_enable; - if (!pending_shape_update_list.in_list()) { - PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); - } -} - -void CollisionObjectSW::remove_shape(ShapeSW *p_shape) { - - //remove a shape, all the times it appears - for (int i = 0; i < shapes.size(); i++) { - - if (shapes[i].shape == p_shape) { - remove_shape(i); - i--; - } - } -} - -void CollisionObjectSW::remove_shape(int p_index) { - - //remove anything from shape to be erased to end, so subindices don't change - ERR_FAIL_INDEX(p_index, shapes.size()); - for (int i = p_index; i < shapes.size(); i++) { - - if (shapes[i].bpid == 0) - continue; - //should never get here with a null owner - space->get_broadphase()->remove(shapes[i].bpid); - shapes.write[i].bpid = 0; - } - shapes[p_index].shape->remove_owner(this); - shapes.remove(p_index); - - if (!pending_shape_update_list.in_list()) { - PhysicsServerSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); - } - //_update_shapes(); - //_shapes_changed(); -} - -void CollisionObjectSW::_set_static(bool p_static) { - if (_static == p_static) - return; - _static = p_static; - - if (!space) - return; - for (int i = 0; i < get_shape_count(); i++) { - const Shape &s = shapes[i]; - if (s.bpid > 0) { - space->get_broadphase()->set_static(s.bpid, _static); - } - } -} - -void CollisionObjectSW::_unregister_shapes() { - - for (int i = 0; i < shapes.size(); i++) { - - Shape &s = shapes.write[i]; - if (s.bpid > 0) { - space->get_broadphase()->remove(s.bpid); - s.bpid = 0; - } - } -} - -void CollisionObjectSW::_update_shapes() { - - if (!space) - return; - - for (int i = 0; i < shapes.size(); i++) { - - Shape &s = shapes.write[i]; - if (s.bpid == 0) { - s.bpid = space->get_broadphase()->create(this, i); - space->get_broadphase()->set_static(s.bpid, _static); - } - - //not quite correct, should compute the next matrix.. - AABB shape_aabb = s.shape->get_aabb(); - Transform xform = transform * s.xform; - shape_aabb = xform.xform(shape_aabb); - s.aabb_cache = shape_aabb; - s.aabb_cache = s.aabb_cache.grow((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05); - - Vector3 scale = xform.get_basis().get_scale(); - s.area_cache = s.shape->get_area() * scale.x * scale.y * scale.z; - - space->get_broadphase()->move(s.bpid, s.aabb_cache); - } -} - -void CollisionObjectSW::_update_shapes_with_motion(const Vector3 &p_motion) { - - if (!space) - return; - - for (int i = 0; i < shapes.size(); i++) { - - Shape &s = shapes.write[i]; - if (s.bpid == 0) { - s.bpid = space->get_broadphase()->create(this, i); - space->get_broadphase()->set_static(s.bpid, _static); - } - - //not quite correct, should compute the next matrix.. - AABB shape_aabb = s.shape->get_aabb(); - Transform xform = transform * s.xform; - shape_aabb = xform.xform(shape_aabb); - shape_aabb = shape_aabb.merge(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion - s.aabb_cache = shape_aabb; - - space->get_broadphase()->move(s.bpid, shape_aabb); - } -} - -void CollisionObjectSW::_set_space(SpaceSW *p_space) { - - if (space) { - - space->remove_object(this); - - for (int i = 0; i < shapes.size(); i++) { - - Shape &s = shapes.write[i]; - if (s.bpid) { - space->get_broadphase()->remove(s.bpid); - s.bpid = 0; - } - } - } - - space = p_space; - - if (space) { - - space->add_object(this); - _update_shapes(); - } -} - -void CollisionObjectSW::_shape_changed() { - - _update_shapes(); - _shapes_changed(); -} - -CollisionObjectSW::CollisionObjectSW(Type p_type) : - pending_shape_update_list(this) { - - _static = true; - type = p_type; - space = NULL; - - collision_layer = 1; - collision_mask = 1; - ray_pickable = true; -} diff --git a/servers/physics/collision_object_sw.h b/servers/physics/collision_object_sw.h deleted file mode 100644 index 7c0e66ff90..0000000000 --- a/servers/physics/collision_object_sw.h +++ /dev/null @@ -1,164 +0,0 @@ -/*************************************************************************/ -/* collision_object_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef COLLISION_OBJECT_SW_H -#define COLLISION_OBJECT_SW_H - -#include "broad_phase_sw.h" -#include "core/self_list.h" -#include "servers/physics_server.h" -#include "shape_sw.h" - -#ifdef DEBUG_ENABLED -#define MAX_OBJECT_DISTANCE 3.1622776601683791e+18 - -#define MAX_OBJECT_DISTANCE_X2 (MAX_OBJECT_DISTANCE * MAX_OBJECT_DISTANCE) -#endif - -class SpaceSW; - -class CollisionObjectSW : public ShapeOwnerSW { -public: - enum Type { - TYPE_AREA, - TYPE_BODY - }; - -private: - Type type; - RID self; - ObjectID instance_id; - uint32_t collision_layer; - uint32_t collision_mask; - - struct Shape { - - Transform xform; - Transform xform_inv; - BroadPhaseSW::ID bpid; - AABB aabb_cache; //for rayqueries - real_t area_cache; - ShapeSW *shape; - bool disabled; - - Shape() { disabled = false; } - }; - - Vector shapes; - SpaceSW *space; - Transform transform; - Transform inv_transform; - bool _static; - - SelfList pending_shape_update_list; - - void _update_shapes(); - -protected: - void _update_shapes_with_motion(const Vector3 &p_motion); - void _unregister_shapes(); - - _FORCE_INLINE_ void _set_transform(const Transform &p_transform, bool p_update_shapes = true) { -#ifdef DEBUG_ENABLED - - ERR_FAIL_COND_MSG(p_transform.origin.length_squared() > MAX_OBJECT_DISTANCE_X2, "Object went too far away (more than '" + itos(MAX_OBJECT_DISTANCE) + "' units from origin)."); -#endif - - transform = p_transform; - if (p_update_shapes) _update_shapes(); - } - _FORCE_INLINE_ void _set_inv_transform(const Transform &p_transform) { inv_transform = p_transform; } - void _set_static(bool p_static); - - virtual void _shapes_changed() = 0; - void _set_space(SpaceSW *p_space); - - bool ray_pickable; - - CollisionObjectSW(Type p_type); - -public: - _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } - _FORCE_INLINE_ RID get_self() const { return self; } - - _FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; } - _FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; } - - void _shape_changed(); - - _FORCE_INLINE_ Type get_type() const { return type; } - void add_shape(ShapeSW *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); - void set_shape(int p_index, ShapeSW *p_shape); - void set_shape_transform(int p_index, const Transform &p_transform); - _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } - _FORCE_INLINE_ bool is_shape_disabled(int p_index) const { - CRASH_BAD_INDEX(p_index, shapes.size()); - return shapes[p_index].disabled; - } - _FORCE_INLINE_ ShapeSW *get_shape(int p_index) const { return shapes[p_index].shape; } - _FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; } - _FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } - _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } - _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; } - - _FORCE_INLINE_ Transform get_transform() const { return transform; } - _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } - _FORCE_INLINE_ SpaceSW *get_space() const { return space; } - - _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; } - _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; } - - void set_shape_as_disabled(int p_idx, bool p_enable); - _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { - CRASH_BAD_INDEX(p_idx, shapes.size()); - return shapes[p_idx].disabled; - } - - _FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; } - _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } - - _FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; } - _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } - - _FORCE_INLINE_ bool test_collision_mask(CollisionObjectSW *p_other) const { - return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; - } - - void remove_shape(ShapeSW *p_shape); - void remove_shape(int p_index); - - virtual void set_space(SpaceSW *p_space) = 0; - - _FORCE_INLINE_ bool is_static() const { return _static; } - - virtual ~CollisionObjectSW() {} -}; - -#endif // COLLISION_OBJECT_SW_H diff --git a/servers/physics/collision_solver_sat.cpp b/servers/physics/collision_solver_sat.cpp deleted file mode 100644 index 0e0dfd3cf2..0000000000 --- a/servers/physics/collision_solver_sat.cpp +++ /dev/null @@ -1,1591 +0,0 @@ -/*************************************************************************/ -/* collision_solver_sat.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "collision_solver_sat.h" -#include "core/math/geometry.h" - -#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.02 - -struct _CollectorCallback { - - CollisionSolverSW::CallbackResult callback; - void *userdata; - bool swap; - bool collided; - Vector3 normal; - Vector3 *prev_axis; - - _FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B) { - - if (swap) - callback(p_point_B, p_point_A, userdata); - else - callback(p_point_A, p_point_B, userdata); - } -}; - -typedef void (*GenerateContactsFunc)(const Vector3 *, int, const Vector3 *, int, _CollectorCallback *); - -static void _generate_contacts_point_point(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(p_point_count_A != 1); - ERR_FAIL_COND(p_point_count_B != 1); -#endif - - p_callback->call(*p_points_A, *p_points_B); -} - -static void _generate_contacts_point_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(p_point_count_A != 1); - ERR_FAIL_COND(p_point_count_B != 2); -#endif - - Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(*p_points_A, p_points_B); - p_callback->call(*p_points_A, closest_B); -} - -static void _generate_contacts_point_face(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(p_point_count_A != 1); - ERR_FAIL_COND(p_point_count_B < 3); -#endif - - Vector3 closest_B = Plane(p_points_B[0], p_points_B[1], p_points_B[2]).project(*p_points_A); - - p_callback->call(*p_points_A, closest_B); -} - -static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(p_point_count_A != 2); - ERR_FAIL_COND(p_point_count_B != 2); // circle is actually a 4x3 matrix -#endif - - Vector3 rel_A = p_points_A[1] - p_points_A[0]; - Vector3 rel_B = p_points_B[1] - p_points_B[0]; - - Vector3 c = rel_A.cross(rel_B).cross(rel_B); - - if (Math::is_zero_approx(rel_A.dot(c))) { - - // should handle somehow.. - //ERR_PRINT("TODO FIX"); - //return; - - Vector3 axis = rel_A.normalized(); //make an axis - Vector3 base_A = p_points_A[0] - axis * axis.dot(p_points_A[0]); - Vector3 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]); - - //sort all 4 points in axis - real_t dvec[4] = { axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; - - SortArray sa; - sa.sort(dvec, 4); - - //use the middle ones as contacts - p_callback->call(base_A + axis * dvec[1], base_B + axis * dvec[1]); - p_callback->call(base_A + axis * dvec[2], base_B + axis * dvec[2]); - - return; - } - - real_t d = (c.dot(p_points_B[0]) - p_points_A[0].dot(c)) / rel_A.dot(c); - - if (d < 0.0) - d = 0.0; - else if (d > 1.0) - d = 1.0; - - Vector3 closest_A = p_points_A[0] + rel_A * d; - Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(closest_A, p_points_B); - p_callback->call(closest_A, closest_B); -} - -static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(p_point_count_A < 2); - ERR_FAIL_COND(p_point_count_B < 3); -#endif - - static const int max_clip = 32; - - Vector3 _clipbuf1[max_clip]; - Vector3 _clipbuf2[max_clip]; - Vector3 *clipbuf_src = _clipbuf1; - Vector3 *clipbuf_dst = _clipbuf2; - int clipbuf_len = p_point_count_A; - - // copy A points to clipbuf_src - for (int i = 0; i < p_point_count_A; i++) { - - clipbuf_src[i] = p_points_A[i]; - } - - Plane plane_B(p_points_B[0], p_points_B[1], p_points_B[2]); - - // go through all of B points - for (int i = 0; i < p_point_count_B; i++) { - - int i_n = (i + 1) % p_point_count_B; - - Vector3 edge0_B = p_points_B[i]; - Vector3 edge1_B = p_points_B[i_n]; - - Vector3 clip_normal = (edge0_B - edge1_B).cross(plane_B.normal).normalized(); - // make a clip plane - - Plane clip(edge0_B, clip_normal); - // avoid double clip if A is edge - int dst_idx = 0; - bool edge = clipbuf_len == 2; - for (int j = 0; j < clipbuf_len; j++) { - - int j_n = (j + 1) % clipbuf_len; - - Vector3 edge0_A = clipbuf_src[j]; - Vector3 edge1_A = clipbuf_src[j_n]; - - real_t dist0 = clip.distance_to(edge0_A); - real_t dist1 = clip.distance_to(edge1_A); - - if (dist0 <= 0) { // behind plane - - ERR_FAIL_COND(dst_idx >= max_clip); - clipbuf_dst[dst_idx++] = clipbuf_src[j]; - } - - // check for different sides and non coplanar - //if ( (dist0*dist1) < -CMP_EPSILON && !(edge && j)) { - if ((dist0 * dist1) < 0 && !(edge && j)) { - - // calculate intersection - Vector3 rel = edge1_A - edge0_A; - real_t den = clip.normal.dot(rel); - real_t dist = -(clip.normal.dot(edge0_A) - clip.d) / den; - Vector3 inters = edge0_A + rel * dist; - - ERR_FAIL_COND(dst_idx >= max_clip); - clipbuf_dst[dst_idx] = inters; - dst_idx++; - } - } - - clipbuf_len = dst_idx; - SWAP(clipbuf_src, clipbuf_dst); - } - - // generate contacts - //Plane plane_A(p_points_A[0],p_points_A[1],p_points_A[2]); - - for (int i = 0; i < clipbuf_len; i++) { - - real_t d = plane_B.distance_to(clipbuf_src[i]); - /* - if (d>CMP_EPSILON) - continue; - */ - - Vector3 closest_B = clipbuf_src[i] - plane_B.normal * d; - - if (p_callback->normal.dot(clipbuf_src[i]) >= p_callback->normal.dot(closest_B)) - continue; - - p_callback->call(clipbuf_src[i], closest_B); - } -} - -static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { - -#ifdef DEBUG_ENABLED - ERR_FAIL_COND(p_point_count_A < 1); - ERR_FAIL_COND(p_point_count_B < 1); -#endif - - static const GenerateContactsFunc generate_contacts_func_table[3][3] = { - { - _generate_contacts_point_point, - _generate_contacts_point_edge, - _generate_contacts_point_face, - }, - { - 0, - _generate_contacts_edge_edge, - _generate_contacts_face_face, - }, - { - 0, - 0, - _generate_contacts_face_face, - } - }; - - int pointcount_B; - int pointcount_A; - const Vector3 *points_A; - const Vector3 *points_B; - - if (p_point_count_A > p_point_count_B) { - //swap - p_callback->swap = !p_callback->swap; - p_callback->normal = -p_callback->normal; - - pointcount_B = p_point_count_A; - pointcount_A = p_point_count_B; - points_A = p_points_B; - points_B = p_points_A; - } else { - - pointcount_B = p_point_count_B; - pointcount_A = p_point_count_A; - points_A = p_points_A; - points_B = p_points_B; - } - - int version_A = (pointcount_A > 3 ? 3 : pointcount_A) - 1; - int version_B = (pointcount_B > 3 ? 3 : pointcount_B) - 1; - - GenerateContactsFunc contacts_func = generate_contacts_func_table[version_A][version_B]; - ERR_FAIL_COND(!contacts_func); - contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_callback); -} - -template -class SeparatorAxisTest { - - const ShapeA *shape_A; - const ShapeB *shape_B; - const Transform *transform_A; - const Transform *transform_B; - real_t best_depth; - Vector3 best_axis; - _CollectorCallback *callback; - real_t margin_A; - real_t margin_B; - Vector3 separator_axis; - -public: - _FORCE_INLINE_ bool test_previous_axis() { - - if (callback && callback->prev_axis && *callback->prev_axis != Vector3()) - return test_axis(*callback->prev_axis); - else - return true; - } - - _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) { - - Vector3 axis = p_axis; - - if (Math::abs(axis.x) < CMP_EPSILON && - Math::abs(axis.y) < CMP_EPSILON && - Math::abs(axis.z) < CMP_EPSILON) { - // strange case, try an upwards separator - axis = Vector3(0.0, 1.0, 0.0); - } - - real_t min_A, max_A, min_B, max_B; - - shape_A->project_range(axis, *transform_A, min_A, max_A); - shape_B->project_range(axis, *transform_B, min_B, max_B); - - if (withMargin) { - min_A -= margin_A; - max_A += margin_A; - min_B -= margin_B; - max_B += margin_B; - } - - min_B -= (max_A - min_A) * 0.5; - max_B += (max_A - min_A) * 0.5; - - min_B -= (min_A + max_A) * 0.5; - max_B -= (min_A + max_A) * 0.5; - - if (min_B > 0.0 || max_B < 0.0) { - separator_axis = axis; - return false; // doesn't contain 0 - } - - //use the smallest depth - - if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0 - min_B = -min_B; - } - - if (max_B < min_B) { - if (max_B < best_depth) { - best_depth = max_B; - best_axis = axis; - } - } else { - if (min_B < best_depth) { - best_depth = min_B; - best_axis = -axis; // keep it as A axis - } - } - - return true; - } - - _FORCE_INLINE_ void generate_contacts() { - - // nothing to do, don't generate - if (best_axis == Vector3(0.0, 0.0, 0.0)) - return; - - if (!callback->callback) { - //just was checking intersection? - callback->collided = true; - if (callback->prev_axis) - *callback->prev_axis = best_axis; - return; - } - - static const int max_supports = 16; - - Vector3 supports_A[max_supports]; - int support_count_A; - shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A); - for (int i = 0; i < support_count_A; i++) { - supports_A[i] = transform_A->xform(supports_A[i]); - } - - if (withMargin) { - - for (int i = 0; i < support_count_A; i++) { - supports_A[i] += -best_axis * margin_A; - } - } - - Vector3 supports_B[max_supports]; - int support_count_B; - shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B); - for (int i = 0; i < support_count_B; i++) { - supports_B[i] = transform_B->xform(supports_B[i]); - } - - if (withMargin) { - - for (int i = 0; i < support_count_B; i++) { - supports_B[i] += best_axis * margin_B; - } - } - - callback->normal = best_axis; - if (callback->prev_axis) - *callback->prev_axis = best_axis; - _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback); - - callback->collided = true; - } - - _FORCE_INLINE_ SeparatorAxisTest(const ShapeA *p_shape_A, const Transform &p_transform_A, const ShapeB *p_shape_B, const Transform &p_transform_B, _CollectorCallback *p_callback, real_t p_margin_A = 0, real_t p_margin_B = 0) { - best_depth = 1e15; - shape_A = p_shape_A; - shape_B = p_shape_B; - transform_A = &p_transform_A; - transform_B = &p_transform_B; - callback = p_callback; - margin_A = p_margin_A; - margin_B = p_margin_B; - } -}; - -/****** SAT TESTS *******/ - -typedef void (*CollisionFunc)(const ShapeSW *, const Transform &, const ShapeSW *, const Transform &, _CollectorCallback *p_callback, real_t, real_t); - -template -static void _collision_sphere_sphere(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const SphereShapeSW *sphere_A = static_cast(p_a); - const SphereShapeSW *sphere_B = static_cast(p_b); - - SeparatorAxisTest separator(sphere_A, p_transform_a, sphere_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - // previous axis - - if (!separator.test_previous_axis()) - return; - - if (!separator.test_axis((p_transform_a.origin - p_transform_b.origin).normalized())) - return; - - separator.generate_contacts(); -} - -template -static void _collision_sphere_box(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const SphereShapeSW *sphere_A = static_cast(p_a); - const BoxShapeSW *box_B = static_cast(p_b); - - SeparatorAxisTest separator(sphere_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - // test faces - - for (int i = 0; i < 3; i++) { - - Vector3 axis = p_transform_b.basis.get_axis(i).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // calculate closest point to sphere - - Vector3 cnormal = p_transform_b.xform_inv(p_transform_a.origin); - - Vector3 cpoint = p_transform_b.xform(Vector3( - - (cnormal.x < 0) ? -box_B->get_half_extents().x : box_B->get_half_extents().x, - (cnormal.y < 0) ? -box_B->get_half_extents().y : box_B->get_half_extents().y, - (cnormal.z < 0) ? -box_B->get_half_extents().z : box_B->get_half_extents().z)); - - // use point to test axis - Vector3 point_axis = (p_transform_a.origin - cpoint).normalized(); - - if (!separator.test_axis(point_axis)) - return; - - // test edges - - for (int i = 0; i < 3; i++) { - - Vector3 axis = point_axis.cross(p_transform_b.basis.get_axis(i)).cross(p_transform_b.basis.get_axis(i)).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - separator.generate_contacts(); -} - -template -static void _collision_sphere_capsule(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const SphereShapeSW *sphere_A = static_cast(p_a); - const CapsuleShapeSW *capsule_B = static_cast(p_b); - - SeparatorAxisTest separator(sphere_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - //capsule sphere 1, sphere - - Vector3 capsule_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5); - - Vector3 capsule_ball_1 = p_transform_b.origin + capsule_axis; - - if (!separator.test_axis((capsule_ball_1 - p_transform_a.origin).normalized())) - return; - - //capsule sphere 2, sphere - - Vector3 capsule_ball_2 = p_transform_b.origin - capsule_axis; - - if (!separator.test_axis((capsule_ball_2 - p_transform_a.origin).normalized())) - return; - - //capsule edge, sphere - - Vector3 b2a = p_transform_a.origin - p_transform_b.origin; - - Vector3 axis = b2a.cross(capsule_axis).cross(capsule_axis).normalized(); - - if (!separator.test_axis(axis)) - return; - - separator.generate_contacts(); -} - -template -static void _collision_sphere_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { -} - -template -static void _collision_sphere_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const SphereShapeSW *sphere_A = static_cast(p_a); - const ConvexPolygonShapeSW *convex_polygon_B = static_cast(p_b); - - SeparatorAxisTest separator(sphere_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - const Geometry::MeshData &mesh = convex_polygon_B->get_mesh(); - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int face_count = mesh.faces.size(); - const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); - int edge_count = mesh.edges.size(); - const Vector3 *vertices = mesh.vertices.ptr(); - int vertex_count = mesh.vertices.size(); - - // faces of B - for (int i = 0; i < face_count; i++) { - - Vector3 axis = p_transform_b.xform(faces[i].plane).normal; - - if (!separator.test_axis(axis)) - return; - } - - // edges of B - for (int i = 0; i < edge_count; i++) { - - Vector3 v1 = p_transform_b.xform(vertices[edges[i].a]); - Vector3 v2 = p_transform_b.xform(vertices[edges[i].b]); - Vector3 v3 = p_transform_a.origin; - - Vector3 n1 = v2 - v1; - Vector3 n2 = v2 - v3; - - Vector3 axis = n1.cross(n2).cross(n1).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // vertices of B - for (int i = 0; i < vertex_count; i++) { - - Vector3 v1 = p_transform_b.xform(vertices[i]); - Vector3 v2 = p_transform_a.origin; - - Vector3 axis = (v2 - v1).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - separator.generate_contacts(); -} - -template -static void _collision_sphere_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const SphereShapeSW *sphere_A = static_cast(p_a); - const FaceShapeSW *face_B = static_cast(p_b); - - SeparatorAxisTest separator(sphere_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - Vector3 vertex[3] = { - p_transform_b.xform(face_B->vertex[0]), - p_transform_b.xform(face_B->vertex[1]), - p_transform_b.xform(face_B->vertex[2]), - }; - - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) - return; - - // edges and points of B - for (int i = 0; i < 3; i++) { - - Vector3 n1 = vertex[i] - p_transform_a.origin; - - if (!separator.test_axis(n1.normalized())) { - return; - } - - Vector3 n2 = vertex[(i + 1) % 3] - vertex[i]; - - Vector3 axis = n1.cross(n2).cross(n2).normalized(); - - if (!separator.test_axis(axis)) { - return; - } - } - - separator.generate_contacts(); -} - -template -static void _collision_box_box(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const BoxShapeSW *box_A = static_cast(p_a); - const BoxShapeSW *box_B = static_cast(p_b); - - SeparatorAxisTest separator(box_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - // test faces of A - - for (int i = 0; i < 3; i++) { - - Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // test faces of B - - for (int i = 0; i < 3; i++) { - - Vector3 axis = p_transform_b.basis.get_axis(i).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // test combined edges - for (int i = 0; i < 3; i++) { - - for (int j = 0; j < 3; j++) { - - Vector3 axis = p_transform_a.basis.get_axis(i).cross(p_transform_b.basis.get_axis(j)); - - if (Math::is_zero_approx(axis.length_squared())) - continue; - axis.normalize(); - - if (!separator.test_axis(axis)) { - return; - } - } - } - - if (withMargin) { - //add endpoint test between closest vertices and edges - - // calculate closest point to sphere - - Vector3 ab_vec = p_transform_b.origin - p_transform_a.origin; - - Vector3 cnormal_a = p_transform_a.basis.xform_inv(ab_vec); - - Vector3 support_a = p_transform_a.xform(Vector3( - - (cnormal_a.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, - (cnormal_a.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, - (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); - - Vector3 cnormal_b = p_transform_b.basis.xform_inv(-ab_vec); - - Vector3 support_b = p_transform_b.xform(Vector3( - - (cnormal_b.x < 0) ? -box_B->get_half_extents().x : box_B->get_half_extents().x, - (cnormal_b.y < 0) ? -box_B->get_half_extents().y : box_B->get_half_extents().y, - (cnormal_b.z < 0) ? -box_B->get_half_extents().z : box_B->get_half_extents().z)); - - Vector3 axis_ab = (support_a - support_b); - - if (!separator.test_axis(axis_ab.normalized())) { - return; - } - - //now try edges, which become cylinders! - - for (int i = 0; i < 3; i++) { - - //a ->b - Vector3 axis_a = p_transform_a.basis.get_axis(i); - - if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) - return; - - //b ->a - Vector3 axis_b = p_transform_b.basis.get_axis(i); - - if (!separator.test_axis(axis_ab.cross(axis_b).cross(axis_b).normalized())) - return; - } - } - - separator.generate_contacts(); -} - -template -static void _collision_box_capsule(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const BoxShapeSW *box_A = static_cast(p_a); - const CapsuleShapeSW *capsule_B = static_cast(p_b); - - SeparatorAxisTest separator(box_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - // faces of A - for (int i = 0; i < 3; i++) { - - Vector3 axis = p_transform_a.basis.get_axis(i); - - if (!separator.test_axis(axis)) - return; - } - - Vector3 cyl_axis = p_transform_b.basis.get_axis(2).normalized(); - - // edges of A, capsule cylinder - - for (int i = 0; i < 3; i++) { - - // cylinder - Vector3 box_axis = p_transform_a.basis.get_axis(i); - Vector3 axis = box_axis.cross(cyl_axis); - if (Math::is_zero_approx(axis.length_squared())) - continue; - - if (!separator.test_axis(axis.normalized())) - return; - } - - // points of A, capsule cylinder - // this sure could be made faster somehow.. - - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - Vector3 he = box_A->get_half_extents(); - he.x *= (i * 2 - 1); - he.y *= (j * 2 - 1); - he.z *= (k * 2 - 1); - Vector3 point = p_transform_a.origin; - for (int l = 0; l < 3; l++) - point += p_transform_a.basis.get_axis(l) * he[l]; - - //Vector3 axis = (point - cyl_axis * cyl_axis.dot(point)).normalized(); - Vector3 axis = Plane(cyl_axis, 0).project(point).normalized(); - - if (!separator.test_axis(axis)) - return; - } - } - } - - // capsule balls, edges of A - - for (int i = 0; i < 2; i++) { - - Vector3 capsule_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5); - - Vector3 sphere_pos = p_transform_b.origin + ((i == 0) ? capsule_axis : -capsule_axis); - - Vector3 cnormal = p_transform_a.xform_inv(sphere_pos); - - Vector3 cpoint = p_transform_a.xform(Vector3( - - (cnormal.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, - (cnormal.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, - (cnormal.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); - - // use point to test axis - Vector3 point_axis = (sphere_pos - cpoint).normalized(); - - if (!separator.test_axis(point_axis)) - return; - - // test edges of A - - for (int j = 0; j < 3; j++) { - - Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(j)).cross(p_transform_a.basis.get_axis(j)).normalized(); - - if (!separator.test_axis(axis)) - return; - } - } - - separator.generate_contacts(); -} - -template -static void _collision_box_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { -} - -template -static void _collision_box_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const BoxShapeSW *box_A = static_cast(p_a); - const ConvexPolygonShapeSW *convex_polygon_B = static_cast(p_b); - - SeparatorAxisTest separator(box_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - const Geometry::MeshData &mesh = convex_polygon_B->get_mesh(); - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int face_count = mesh.faces.size(); - const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); - int edge_count = mesh.edges.size(); - const Vector3 *vertices = mesh.vertices.ptr(); - int vertex_count = mesh.vertices.size(); - - // faces of A - for (int i = 0; i < 3; i++) { - - Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // faces of B - for (int i = 0; i < face_count; i++) { - - Vector3 axis = p_transform_b.xform(faces[i].plane).normal; - - if (!separator.test_axis(axis)) - return; - } - - // A<->B edges - for (int i = 0; i < 3; i++) { - - Vector3 e1 = p_transform_a.basis.get_axis(i); - - for (int j = 0; j < edge_count; j++) { - - Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]); - - Vector3 axis = e1.cross(e2).normalized(); - - if (!separator.test_axis(axis)) - return; - } - } - - if (withMargin) { - - // calculate closest points between vertices and box edges - for (int v = 0; v < vertex_count; v++) { - - Vector3 vtxb = p_transform_b.xform(vertices[v]); - Vector3 ab_vec = vtxb - p_transform_a.origin; - - Vector3 cnormal_a = p_transform_a.basis.xform_inv(ab_vec); - - Vector3 support_a = p_transform_a.xform(Vector3( - - (cnormal_a.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, - (cnormal_a.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, - (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); - - Vector3 axis_ab = support_a - vtxb; - - if (!separator.test_axis(axis_ab.normalized())) { - return; - } - - //now try edges, which become cylinders! - - for (int i = 0; i < 3; i++) { - - //a ->b - Vector3 axis_a = p_transform_a.basis.get_axis(i); - - if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) - return; - } - } - - //convex edges and box points - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - Vector3 he = box_A->get_half_extents(); - he.x *= (i * 2 - 1); - he.y *= (j * 2 - 1); - he.z *= (k * 2 - 1); - Vector3 point = p_transform_a.origin; - for (int l = 0; l < 3; l++) - point += p_transform_a.basis.get_axis(l) * he[l]; - - for (int e = 0; e < edge_count; e++) { - - Vector3 p1 = p_transform_b.xform(vertices[edges[e].a]); - Vector3 p2 = p_transform_b.xform(vertices[edges[e].b]); - Vector3 n = (p2 - p1); - - if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) - return; - } - } - } - } - } - - separator.generate_contacts(); -} - -template -static void _collision_box_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const BoxShapeSW *box_A = static_cast(p_a); - const FaceShapeSW *face_B = static_cast(p_b); - - SeparatorAxisTest separator(box_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - Vector3 vertex[3] = { - p_transform_b.xform(face_B->vertex[0]), - p_transform_b.xform(face_B->vertex[1]), - p_transform_b.xform(face_B->vertex[2]), - }; - - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) - return; - - // faces of A - for (int i = 0; i < 3; i++) { - - Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // combined edges - - for (int i = 0; i < 3; i++) { - - Vector3 e = vertex[i] - vertex[(i + 1) % 3]; - - for (int j = 0; j < 3; j++) { - - Vector3 axis = p_transform_a.basis.get_axis(j); - - if (!separator.test_axis(e.cross(axis).normalized())) - return; - } - } - - if (withMargin) { - - // calculate closest points between vertices and box edges - for (int v = 0; v < 3; v++) { - - Vector3 ab_vec = vertex[v] - p_transform_a.origin; - - Vector3 cnormal_a = p_transform_a.basis.xform_inv(ab_vec); - - Vector3 support_a = p_transform_a.xform(Vector3( - - (cnormal_a.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, - (cnormal_a.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, - (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); - - Vector3 axis_ab = support_a - vertex[v]; - - if (!separator.test_axis(axis_ab.normalized())) { - return; - } - - //now try edges, which become cylinders! - - for (int i = 0; i < 3; i++) { - - //a ->b - Vector3 axis_a = p_transform_a.basis.get_axis(i); - - if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) - return; - } - } - - //convex edges and box points, there has to be a way to speed up this (get closest point?) - for (int i = 0; i < 2; i++) { - for (int j = 0; j < 2; j++) { - for (int k = 0; k < 2; k++) { - Vector3 he = box_A->get_half_extents(); - he.x *= (i * 2 - 1); - he.y *= (j * 2 - 1); - he.z *= (k * 2 - 1); - Vector3 point = p_transform_a.origin; - for (int l = 0; l < 3; l++) - point += p_transform_a.basis.get_axis(l) * he[l]; - - for (int e = 0; e < 3; e++) { - - Vector3 p1 = vertex[e]; - Vector3 p2 = vertex[(e + 1) % 3]; - - Vector3 n = (p2 - p1); - - if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) - return; - } - } - } - } - } - - separator.generate_contacts(); -} - -template -static void _collision_capsule_capsule(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const CapsuleShapeSW *capsule_A = static_cast(p_a); - const CapsuleShapeSW *capsule_B = static_cast(p_b); - - SeparatorAxisTest separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - // some values - - Vector3 capsule_A_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5); - Vector3 capsule_B_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5); - - Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis; - Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis; - Vector3 capsule_B_ball_1 = p_transform_b.origin + capsule_B_axis; - Vector3 capsule_B_ball_2 = p_transform_b.origin - capsule_B_axis; - - //balls-balls - - if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_1).normalized())) - return; - if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_2).normalized())) - return; - - if (!separator.test_axis((capsule_A_ball_2 - capsule_B_ball_1).normalized())) - return; - if (!separator.test_axis((capsule_A_ball_2 - capsule_B_ball_2).normalized())) - return; - - // edges-balls - - if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_1).cross(capsule_A_axis).cross(capsule_A_axis).normalized())) - return; - - if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_2).cross(capsule_A_axis).cross(capsule_A_axis).normalized())) - return; - - if (!separator.test_axis((capsule_B_ball_1 - capsule_A_ball_1).cross(capsule_B_axis).cross(capsule_B_axis).normalized())) - return; - - if (!separator.test_axis((capsule_B_ball_1 - capsule_A_ball_2).cross(capsule_B_axis).cross(capsule_B_axis).normalized())) - return; - - // edges - - if (!separator.test_axis(capsule_A_axis.cross(capsule_B_axis).normalized())) - return; - - separator.generate_contacts(); -} - -template -static void _collision_capsule_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { -} - -template -static void _collision_capsule_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const CapsuleShapeSW *capsule_A = static_cast(p_a); - const ConvexPolygonShapeSW *convex_polygon_B = static_cast(p_b); - - SeparatorAxisTest separator(capsule_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - const Geometry::MeshData &mesh = convex_polygon_B->get_mesh(); - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int face_count = mesh.faces.size(); - const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); - int edge_count = mesh.edges.size(); - const Vector3 *vertices = mesh.vertices.ptr(); - - // faces of B - for (int i = 0; i < face_count; i++) { - - Vector3 axis = p_transform_b.xform(faces[i].plane).normal; - - if (!separator.test_axis(axis)) - return; - } - - // edges of B, capsule cylinder - - for (int i = 0; i < edge_count; i++) { - - // cylinder - Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].a]) - p_transform_b.basis.xform(vertices[edges[i].b]); - Vector3 axis = edge_axis.cross(p_transform_a.basis.get_axis(2)).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // capsule balls, edges of B - - for (int i = 0; i < 2; i++) { - - // edges of B, capsule cylinder - - Vector3 capsule_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5); - - Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis); - - for (int j = 0; j < edge_count; j++) { - - Vector3 n1 = sphere_pos - p_transform_b.xform(vertices[edges[j].a]); - Vector3 n2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]); - - Vector3 axis = n1.cross(n2).cross(n2).normalized(); - - if (!separator.test_axis(axis)) - return; - } - } - - separator.generate_contacts(); -} - -template -static void _collision_capsule_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const CapsuleShapeSW *capsule_A = static_cast(p_a); - const FaceShapeSW *face_B = static_cast(p_b); - - SeparatorAxisTest separator(capsule_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - Vector3 vertex[3] = { - p_transform_b.xform(face_B->vertex[0]), - p_transform_b.xform(face_B->vertex[1]), - p_transform_b.xform(face_B->vertex[2]), - }; - - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) - return; - - // edges of B, capsule cylinder - - Vector3 capsule_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5); - - for (int i = 0; i < 3; i++) { - - // edge-cylinder - Vector3 edge_axis = vertex[i] - vertex[(i + 1) % 3]; - Vector3 axis = edge_axis.cross(capsule_axis).normalized(); - - if (!separator.test_axis(axis)) - return; - - if (!separator.test_axis((p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized())) - return; - - for (int j = 0; j < 2; j++) { - - // point-spheres - Vector3 sphere_pos = p_transform_a.origin + ((j == 0) ? capsule_axis : -capsule_axis); - - Vector3 n1 = sphere_pos - vertex[i]; - - if (!separator.test_axis(n1.normalized())) - return; - - Vector3 n2 = edge_axis; - - axis = n1.cross(n2).cross(n2); - - if (!separator.test_axis(axis.normalized())) - return; - } - } - - separator.generate_contacts(); -} - -template -static void _collision_cylinder_cylinder(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { -} - -template -static void _collision_cylinder_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { -} - -template -static void _collision_cylinder_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { -} - -template -static void _collision_convex_polygon_convex_polygon(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const ConvexPolygonShapeSW *convex_polygon_A = static_cast(p_a); - const ConvexPolygonShapeSW *convex_polygon_B = static_cast(p_b); - - SeparatorAxisTest separator(convex_polygon_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - if (!separator.test_previous_axis()) - return; - - const Geometry::MeshData &mesh_A = convex_polygon_A->get_mesh(); - - const Geometry::MeshData::Face *faces_A = mesh_A.faces.ptr(); - int face_count_A = mesh_A.faces.size(); - const Geometry::MeshData::Edge *edges_A = mesh_A.edges.ptr(); - int edge_count_A = mesh_A.edges.size(); - const Vector3 *vertices_A = mesh_A.vertices.ptr(); - int vertex_count_A = mesh_A.vertices.size(); - - const Geometry::MeshData &mesh_B = convex_polygon_B->get_mesh(); - - const Geometry::MeshData::Face *faces_B = mesh_B.faces.ptr(); - int face_count_B = mesh_B.faces.size(); - const Geometry::MeshData::Edge *edges_B = mesh_B.edges.ptr(); - int edge_count_B = mesh_B.edges.size(); - const Vector3 *vertices_B = mesh_B.vertices.ptr(); - int vertex_count_B = mesh_B.vertices.size(); - - // faces of A - for (int i = 0; i < face_count_A; i++) { - - Vector3 axis = p_transform_a.xform(faces_A[i].plane).normal; - //Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // faces of B - for (int i = 0; i < face_count_B; i++) { - - Vector3 axis = p_transform_b.xform(faces_B[i].plane).normal; - //Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // A<->B edges - for (int i = 0; i < edge_count_A; i++) { - - Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]) - p_transform_a.basis.xform(vertices_A[edges_A[i].b]); - - for (int j = 0; j < edge_count_B; j++) { - - Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[j].a]) - p_transform_b.basis.xform(vertices_B[edges_B[j].b]); - - Vector3 axis = e1.cross(e2).normalized(); - - if (!separator.test_axis(axis)) - return; - } - } - - if (withMargin) { - - //vertex-vertex - for (int i = 0; i < vertex_count_A; i++) { - - Vector3 va = p_transform_a.xform(vertices_A[i]); - - for (int j = 0; j < vertex_count_B; j++) { - - if (!separator.test_axis((va - p_transform_b.xform(vertices_B[j])).normalized())) - return; - } - } - //edge-vertex (shell) - - for (int i = 0; i < edge_count_A; i++) { - - Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]); - Vector3 e2 = p_transform_a.basis.xform(vertices_A[edges_A[i].b]); - Vector3 n = (e2 - e1); - - for (int j = 0; j < vertex_count_B; j++) { - - Vector3 e3 = p_transform_b.xform(vertices_B[j]); - - if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) - return; - } - } - - for (int i = 0; i < edge_count_B; i++) { - - Vector3 e1 = p_transform_b.basis.xform(vertices_B[edges_B[i].a]); - Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[i].b]); - Vector3 n = (e2 - e1); - - for (int j = 0; j < vertex_count_A; j++) { - - Vector3 e3 = p_transform_a.xform(vertices_A[j]); - - if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) - return; - } - } - } - - separator.generate_contacts(); -} - -template -static void _collision_convex_polygon_face(const ShapeSW *p_a, const Transform &p_transform_a, const ShapeSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { - - const ConvexPolygonShapeSW *convex_polygon_A = static_cast(p_a); - const FaceShapeSW *face_B = static_cast(p_b); - - SeparatorAxisTest separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); - - const Geometry::MeshData &mesh = convex_polygon_A->get_mesh(); - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int face_count = mesh.faces.size(); - const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); - int edge_count = mesh.edges.size(); - const Vector3 *vertices = mesh.vertices.ptr(); - int vertex_count = mesh.vertices.size(); - - Vector3 vertex[3] = { - p_transform_b.xform(face_B->vertex[0]), - p_transform_b.xform(face_B->vertex[1]), - p_transform_b.xform(face_B->vertex[2]), - }; - - if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) - return; - - // faces of A - for (int i = 0; i < face_count; i++) { - - //Vector3 axis = p_transform_a.xform( faces[i].plane ).normal; - Vector3 axis = p_transform_a.basis.xform(faces[i].plane.normal).normalized(); - - if (!separator.test_axis(axis)) - return; - } - - // A<->B edges - for (int i = 0; i < edge_count; i++) { - - Vector3 e1 = p_transform_a.xform(vertices[edges[i].a]) - p_transform_a.xform(vertices[edges[i].b]); - - for (int j = 0; j < 3; j++) { - - Vector3 e2 = vertex[j] - vertex[(j + 1) % 3]; - - Vector3 axis = e1.cross(e2).normalized(); - - if (!separator.test_axis(axis)) - return; - } - } - - if (withMargin) { - - //vertex-vertex - for (int i = 0; i < vertex_count; i++) { - - Vector3 va = p_transform_a.xform(vertices[i]); - - for (int j = 0; j < 3; j++) { - - if (!separator.test_axis((va - vertex[j]).normalized())) - return; - } - } - //edge-vertex (shell) - - for (int i = 0; i < edge_count; i++) { - - Vector3 e1 = p_transform_a.basis.xform(vertices[edges[i].a]); - Vector3 e2 = p_transform_a.basis.xform(vertices[edges[i].b]); - Vector3 n = (e2 - e1); - - for (int j = 0; j < 3; j++) { - - Vector3 e3 = vertex[j]; - - if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) - return; - } - } - - for (int i = 0; i < 3; i++) { - - Vector3 e1 = vertex[i]; - Vector3 e2 = vertex[(i + 1) % 3]; - Vector3 n = (e2 - e1); - - for (int j = 0; j < vertex_count; j++) { - - Vector3 e3 = p_transform_a.xform(vertices[j]); - - if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) - return; - } - } - } - - separator.generate_contacts(); -} - -bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CollisionSolverSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) { - - PhysicsServer::ShapeType type_A = p_shape_A->get_type(); - - ERR_FAIL_COND_V(type_A == PhysicsServer::SHAPE_PLANE, false); - ERR_FAIL_COND_V(type_A == PhysicsServer::SHAPE_RAY, false); - ERR_FAIL_COND_V(p_shape_A->is_concave(), false); - - PhysicsServer::ShapeType type_B = p_shape_B->get_type(); - - ERR_FAIL_COND_V(type_B == PhysicsServer::SHAPE_PLANE, false); - ERR_FAIL_COND_V(type_B == PhysicsServer::SHAPE_RAY, false); - ERR_FAIL_COND_V(p_shape_B->is_concave(), false); - - static const CollisionFunc collision_table[6][6] = { - { _collision_sphere_sphere, - _collision_sphere_box, - _collision_sphere_capsule, - _collision_sphere_cylinder, - _collision_sphere_convex_polygon, - _collision_sphere_face }, - { 0, - _collision_box_box, - _collision_box_capsule, - _collision_box_cylinder, - _collision_box_convex_polygon, - _collision_box_face }, - { 0, - 0, - _collision_capsule_capsule, - _collision_capsule_cylinder, - _collision_capsule_convex_polygon, - _collision_capsule_face }, - { 0, - 0, - 0, - _collision_cylinder_cylinder, - _collision_cylinder_convex_polygon, - _collision_cylinder_face }, - { 0, - 0, - 0, - 0, - _collision_convex_polygon_convex_polygon, - _collision_convex_polygon_face }, - { 0, - 0, - 0, - 0, - 0, - 0 }, - }; - - static const CollisionFunc collision_table_margin[6][6] = { - { _collision_sphere_sphere, - _collision_sphere_box, - _collision_sphere_capsule, - _collision_sphere_cylinder, - _collision_sphere_convex_polygon, - _collision_sphere_face }, - { 0, - _collision_box_box, - _collision_box_capsule, - _collision_box_cylinder, - _collision_box_convex_polygon, - _collision_box_face }, - { 0, - 0, - _collision_capsule_capsule, - _collision_capsule_cylinder, - _collision_capsule_convex_polygon, - _collision_capsule_face }, - { 0, - 0, - 0, - _collision_cylinder_cylinder, - _collision_cylinder_convex_polygon, - _collision_cylinder_face }, - { 0, - 0, - 0, - 0, - _collision_convex_polygon_convex_polygon, - _collision_convex_polygon_face }, - { 0, - 0, - 0, - 0, - 0, - 0 }, - }; - - _CollectorCallback callback; - callback.callback = p_result_callback; - callback.swap = p_swap; - callback.userdata = p_userdata; - callback.collided = false; - callback.prev_axis = r_prev_axis; - - const ShapeSW *A = p_shape_A; - const ShapeSW *B = p_shape_B; - const Transform *transform_A = &p_transform_A; - const Transform *transform_B = &p_transform_B; - real_t margin_A = p_margin_a; - real_t margin_B = p_margin_b; - - if (type_A > type_B) { - SWAP(A, B); - SWAP(transform_A, transform_B); - SWAP(type_A, type_B); - SWAP(margin_A, margin_B); - callback.swap = !callback.swap; - } - - CollisionFunc collision_func; - if (margin_A != 0.0 || margin_B != 0.0) { - collision_func = collision_table_margin[type_A - 2][type_B - 2]; - - } else { - collision_func = collision_table[type_A - 2][type_B - 2]; - } - ERR_FAIL_COND_V(!collision_func, false); - - collision_func(A, *transform_A, B, *transform_B, &callback, margin_A, margin_B); - - return callback.collided; -} diff --git a/servers/physics/collision_solver_sat.h b/servers/physics/collision_solver_sat.h deleted file mode 100644 index 31895231f0..0000000000 --- a/servers/physics/collision_solver_sat.h +++ /dev/null @@ -1,38 +0,0 @@ -/*************************************************************************/ -/* collision_solver_sat.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef COLLISION_SOLVER_SAT_H -#define COLLISION_SOLVER_SAT_H - -#include "collision_solver_sw.h" - -bool sat_calculate_penetration(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CollisionSolverSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = NULL, real_t p_margin_a = 0, real_t p_margin_b = 0); - -#endif // COLLISION_SOLVER_SAT_H diff --git a/servers/physics/collision_solver_sw.cpp b/servers/physics/collision_solver_sw.cpp deleted file mode 100644 index ce24ba6bca..0000000000 --- a/servers/physics/collision_solver_sw.cpp +++ /dev/null @@ -1,372 +0,0 @@ -/*************************************************************************/ -/* collision_solver_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "collision_solver_sw.h" -#include "collision_solver_sat.h" - -#include "gjk_epa.h" - -#define collision_solver sat_calculate_penetration -//#define collision_solver gjk_epa_calculate_penetration - -bool CollisionSolverSW::solve_static_plane(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { - - const PlaneShapeSW *plane = static_cast(p_shape_A); - if (p_shape_B->get_type() == PhysicsServer::SHAPE_PLANE) - return false; - Plane p = p_transform_A.xform(plane->get_plane()); - - static const int max_supports = 16; - Vector3 supports[max_supports]; - int support_count; - - p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count); - - bool found = false; - - for (int i = 0; i < support_count; i++) { - - supports[i] = p_transform_B.xform(supports[i]); - if (p.distance_to(supports[i]) >= 0) - continue; - found = true; - - Vector3 support_A = p.project(supports[i]); - - if (p_result_callback) { - if (p_swap_result) - p_result_callback(supports[i], support_A, p_userdata); - else - p_result_callback(support_A, supports[i], p_userdata); - } - } - - return found; -} - -bool CollisionSolverSW::solve_ray(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { - - const RayShapeSW *ray = static_cast(p_shape_A); - - Vector3 from = p_transform_A.origin; - Vector3 to = from + p_transform_A.basis.get_axis(2) * ray->get_length(); - Vector3 support_A = to; - - Transform ai = p_transform_B.affine_inverse(); - - from = ai.xform(from); - to = ai.xform(to); - - Vector3 p, n; - if (!p_shape_B->intersect_segment(from, to, p, n)) - return false; - - Vector3 support_B = p_transform_B.xform(p); - if (ray->get_slips_on_slope()) { - Vector3 global_n = ai.basis.xform_inv(n).normalized(); - support_B = support_A + (support_B - support_A).length() * global_n; - } - - if (p_result_callback) { - if (p_swap_result) - p_result_callback(support_B, support_A, p_userdata); - else - p_result_callback(support_A, support_B, p_userdata); - } - return true; -} - -struct _ConcaveCollisionInfo { - - const Transform *transform_A; - const ShapeSW *shape_A; - const Transform *transform_B; - CollisionSolverSW::CallbackResult result_callback; - void *userdata; - bool swap_result; - bool collided; - int aabb_tests; - int collisions; - bool tested; - real_t margin_A; - real_t margin_B; - Vector3 close_A, close_B; -}; - -void CollisionSolverSW::concave_callback(void *p_userdata, ShapeSW *p_convex) { - - _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); - cinfo.aabb_tests++; - - bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, NULL, cinfo.margin_A, cinfo.margin_B); - if (!collided) - return; - - cinfo.collided = true; - cinfo.collisions++; -} - -bool CollisionSolverSW::solve_concave(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) { - - const ConcaveShapeSW *concave_B = static_cast(p_shape_B); - - _ConcaveCollisionInfo cinfo; - cinfo.transform_A = &p_transform_A; - cinfo.shape_A = p_shape_A; - cinfo.transform_B = &p_transform_B; - cinfo.result_callback = p_result_callback; - cinfo.userdata = p_userdata; - cinfo.swap_result = p_swap_result; - cinfo.collided = false; - cinfo.collisions = 0; - cinfo.margin_A = p_margin_A; - cinfo.margin_B = p_margin_B; - - cinfo.aabb_tests = 0; - - Transform rel_transform = p_transform_A; - rel_transform.origin -= p_transform_B.origin; - - //quickly compute a local AABB - - AABB local_aabb; - for (int i = 0; i < 3; i++) { - - Vector3 axis(p_transform_B.basis.get_axis(i)); - real_t axis_scale = 1.0 / axis.length(); - axis *= axis_scale; - - real_t smin, smax; - p_shape_A->project_range(axis, rel_transform, smin, smax); - smin -= p_margin_A; - smax += p_margin_A; - smin *= axis_scale; - smax *= axis_scale; - - local_aabb.position[i] = smin; - local_aabb.size[i] = smax - smin; - } - - concave_B->cull(local_aabb, concave_callback, &cinfo); - - return cinfo.collided; -} - -bool CollisionSolverSW::solve_static(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { - - PhysicsServer::ShapeType type_A = p_shape_A->get_type(); - PhysicsServer::ShapeType type_B = p_shape_B->get_type(); - bool concave_A = p_shape_A->is_concave(); - bool concave_B = p_shape_B->is_concave(); - - bool swap = false; - - if (type_A > type_B) { - SWAP(type_A, type_B); - SWAP(concave_A, concave_B); - swap = true; - } - - if (type_A == PhysicsServer::SHAPE_PLANE) { - - if (type_B == PhysicsServer::SHAPE_PLANE) - return false; - if (type_B == PhysicsServer::SHAPE_RAY) { - return false; - } - - if (swap) { - return solve_static_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); - } else { - return solve_static_plane(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); - } - - } else if (type_A == PhysicsServer::SHAPE_RAY) { - - if (type_B == PhysicsServer::SHAPE_RAY) - return false; - - if (swap) { - return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); - } else { - return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); - } - - } else if (concave_B) { - - if (concave_A) - return false; - - if (!swap) - return solve_concave(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_A, p_margin_B); - else - return solve_concave(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_A, p_margin_B); - - } else { - - return collision_solver(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A, p_margin_B); - } -} - -void CollisionSolverSW::concave_distance_callback(void *p_userdata, ShapeSW *p_convex) { - - _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); - cinfo.aabb_tests++; - if (cinfo.collided) - return; - - Vector3 close_A, close_B; - cinfo.collided = !gjk_epa_calculate_distance(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, close_A, close_B); - - if (cinfo.collided) - return; - if (!cinfo.tested || close_A.distance_squared_to(close_B) < cinfo.close_A.distance_squared_to(cinfo.close_B)) { - - cinfo.close_A = close_A; - cinfo.close_B = close_B; - cinfo.tested = true; - } - - cinfo.collisions++; -} - -bool CollisionSolverSW::solve_distance_plane(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) { - - const PlaneShapeSW *plane = static_cast(p_shape_A); - if (p_shape_B->get_type() == PhysicsServer::SHAPE_PLANE) - return false; - Plane p = p_transform_A.xform(plane->get_plane()); - - static const int max_supports = 16; - Vector3 supports[max_supports]; - int support_count; - - p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count); - - bool collided = false; - Vector3 closest; - real_t closest_d = 0; - - for (int i = 0; i < support_count; i++) { - - supports[i] = p_transform_B.xform(supports[i]); - real_t d = p.distance_to(supports[i]); - if (i == 0 || d < closest_d) { - closest = supports[i]; - closest_d = d; - if (d <= 0) - collided = true; - } - } - - r_point_A = p.project(closest); - r_point_B = closest; - - return collided; -} - -bool CollisionSolverSW::solve_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) { - - if (p_shape_A->is_concave()) - return false; - - if (p_shape_B->get_type() == PhysicsServer::SHAPE_PLANE) { - - Vector3 a, b; - bool col = solve_distance_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, a, b); - r_point_A = b; - r_point_B = a; - return !col; - - } else if (p_shape_B->is_concave()) { - - if (p_shape_A->is_concave()) - return false; - - const ConcaveShapeSW *concave_B = static_cast(p_shape_B); - - _ConcaveCollisionInfo cinfo; - cinfo.transform_A = &p_transform_A; - cinfo.shape_A = p_shape_A; - cinfo.transform_B = &p_transform_B; - cinfo.result_callback = NULL; - cinfo.userdata = NULL; - cinfo.swap_result = false; - cinfo.collided = false; - cinfo.collisions = 0; - cinfo.aabb_tests = 0; - cinfo.tested = false; - - Transform rel_transform = p_transform_A; - rel_transform.origin -= p_transform_B.origin; - - //quickly compute a local AABB - - bool use_cc_hint = p_concave_hint != AABB(); - AABB cc_hint_aabb; - if (use_cc_hint) { - cc_hint_aabb = p_concave_hint; - cc_hint_aabb.position -= p_transform_B.origin; - } - - AABB local_aabb; - for (int i = 0; i < 3; i++) { - - Vector3 axis(p_transform_B.basis.get_axis(i)); - real_t axis_scale = ((real_t)1.0) / axis.length(); - axis *= axis_scale; - - real_t smin, smax; - - if (use_cc_hint) { - cc_hint_aabb.project_range_in_plane(Plane(axis, 0), smin, smax); - } else { - p_shape_A->project_range(axis, rel_transform, smin, smax); - } - - smin *= axis_scale; - smax *= axis_scale; - - local_aabb.position[i] = smin; - local_aabb.size[i] = smax - smin; - } - - concave_B->cull(local_aabb, concave_distance_callback, &cinfo); - if (!cinfo.collided) { - r_point_A = cinfo.close_A; - r_point_B = cinfo.close_B; - } - - return !cinfo.collided; - } else { - - return gjk_epa_calculate_distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, r_point_A, r_point_B); //should pass sepaxis.. - } -} diff --git a/servers/physics/collision_solver_sw.h b/servers/physics/collision_solver_sw.h deleted file mode 100644 index d4dc1ac2a2..0000000000 --- a/servers/physics/collision_solver_sw.h +++ /dev/null @@ -1,53 +0,0 @@ -/*************************************************************************/ -/* collision_solver_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef COLLISION_SOLVER_SW_H -#define COLLISION_SOLVER_SW_H - -#include "shape_sw.h" - -class CollisionSolverSW { -public: - typedef void (*CallbackResult)(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); - -private: - static void concave_callback(void *p_userdata, ShapeSW *p_convex); - static bool solve_static_plane(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); - static bool solve_ray(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); - static bool solve_concave(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0); - static void concave_distance_callback(void *p_userdata, ShapeSW *p_convex); - static bool solve_distance_plane(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B); - -public: - static bool solve_static(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0); - static bool solve_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = NULL); -}; - -#endif // COLLISION_SOLVER__SW_H diff --git a/servers/physics/constraint_sw.h b/servers/physics/constraint_sw.h deleted file mode 100644 index 22f31b411b..0000000000 --- a/servers/physics/constraint_sw.h +++ /dev/null @@ -1,85 +0,0 @@ -/*************************************************************************/ -/* constraint_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef CONSTRAINT_SW_H -#define CONSTRAINT_SW_H - -#include "body_sw.h" - -class ConstraintSW { - - BodySW **_body_ptr; - int _body_count; - uint64_t island_step; - ConstraintSW *island_next; - ConstraintSW *island_list_next; - int priority; - bool disabled_collisions_between_bodies; - - RID self; - -protected: - ConstraintSW(BodySW **p_body_ptr = NULL, int p_body_count = 0) { - _body_ptr = p_body_ptr; - _body_count = p_body_count; - island_step = 0; - priority = 1; - disabled_collisions_between_bodies = true; - } - -public: - _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } - _FORCE_INLINE_ RID get_self() const { return self; } - - _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } - _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } - - _FORCE_INLINE_ ConstraintSW *get_island_next() const { return island_next; } - _FORCE_INLINE_ void set_island_next(ConstraintSW *p_next) { island_next = p_next; } - - _FORCE_INLINE_ ConstraintSW *get_island_list_next() const { return island_list_next; } - _FORCE_INLINE_ void set_island_list_next(ConstraintSW *p_next) { island_list_next = p_next; } - - _FORCE_INLINE_ BodySW **get_body_ptr() const { return _body_ptr; } - _FORCE_INLINE_ int get_body_count() const { return _body_count; } - - _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } - _FORCE_INLINE_ int get_priority() const { return priority; } - - _FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; } - _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } - - virtual bool setup(real_t p_step) = 0; - virtual void solve(real_t p_step) = 0; - - virtual ~ConstraintSW() {} -}; - -#endif // CONSTRAINT__SW_H diff --git a/servers/physics/gjk_epa.cpp b/servers/physics/gjk_epa.cpp deleted file mode 100644 index abf0c0dc15..0000000000 --- a/servers/physics/gjk_epa.cpp +++ /dev/null @@ -1,946 +0,0 @@ -/*************************************************************************/ -/* gjk_epa.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "gjk_epa.h" - -/* Disabling formatting for thirdparty code snippet */ -/* clang-format off */ - -/*************** Bullet's GJK-EPA2 IMPLEMENTATION *******************/ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the -use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not -claim that you wrote the original software. If you use this software in a -product, an acknowledgment in the product documentation would be appreciated -but is not required. -2. Altered source versions must be plainly marked as such, and must not be -misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -GJK-EPA collision solver by Nathanael Presson, 2008 -*/ - - // Config - -/* GJK */ -#define GJK_MAX_ITERATIONS 128 -#define GJK_ACCURARY ((real_t)0.0001) -#define GJK_MIN_DISTANCE ((real_t)0.0001) -#define GJK_DUPLICATED_EPS ((real_t)0.0001) -#define GJK_SIMPLEX2_EPS ((real_t)0.0) -#define GJK_SIMPLEX3_EPS ((real_t)0.0) -#define GJK_SIMPLEX4_EPS ((real_t)0.0) - -/* EPA */ -#define EPA_MAX_VERTICES 64 -#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) -#define EPA_MAX_ITERATIONS 255 -#define EPA_ACCURACY ((real_t)0.0001) -#define EPA_FALLBACK (10*EPA_ACCURACY) -#define EPA_PLANE_EPS ((real_t)0.00001) -#define EPA_INSIDE_EPS ((real_t)0.01) - -namespace GjkEpa2 { - - -struct sResults { - enum eStatus { - Separated, /* Shapes doesn't penetrate */ - Penetrating, /* Shapes are penetrating */ - GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ - EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ - } status; - - Vector3 witnesses[2]; - Vector3 normal; - real_t distance; -}; - -// Shorthands -typedef unsigned int U; -typedef unsigned char U1; - -// MinkowskiDiff -struct MinkowskiDiff { - - const ShapeSW* m_shapes[2]; - - Transform transform_A; - Transform transform_B; - - // i wonder how this could be sped up... if it can - _FORCE_INLINE_ Vector3 Support0 ( const Vector3& d ) const { - return transform_A.xform( m_shapes[0]->get_support( transform_A.basis.xform_inv(d).normalized() ) ); - } - - _FORCE_INLINE_ Vector3 Support1 ( const Vector3& d ) const { - return transform_B.xform( m_shapes[1]->get_support( transform_B.basis.xform_inv(d).normalized() ) ); - } - - _FORCE_INLINE_ Vector3 Support ( const Vector3& d ) const { - return ( Support0 ( d )-Support1 ( -d ) ); - } - - _FORCE_INLINE_ Vector3 Support ( const Vector3& d,U index ) const - { - if ( index ) - return ( Support1 ( d ) ); - else - return ( Support0 ( d ) ); - } -}; - -typedef MinkowskiDiff tShape; - - -// GJK -struct GJK -{ - /* Types */ - struct sSV - { - Vector3 d,w; - }; - struct sSimplex - { - sSV* c[4]; - real_t p[4]; - U rank; - }; - struct eStatus { enum _ { - Valid, - Inside, - Failed };}; - /* Fields */ - tShape m_shape; - Vector3 m_ray; - real_t m_distance; - sSimplex m_simplices[2]; - sSV m_store[4]; - sSV* m_free[4]; - U m_nfree; - U m_current; - sSimplex* m_simplex; - eStatus::_ m_status; - /* Methods */ - GJK() - { - Initialize(); - } - void Initialize() - { - m_ray = Vector3(0,0,0); - m_nfree = 0; - m_status = eStatus::Failed; - m_current = 0; - m_distance = 0; - } - eStatus::_ Evaluate(const tShape& shapearg,const Vector3& guess) - { - U iterations=0; - real_t sqdist=0; - real_t alpha=0; - Vector3 lastw[4]; - U clastw=0; - /* Initialize solver */ - m_free[0] = &m_store[0]; - m_free[1] = &m_store[1]; - m_free[2] = &m_store[2]; - m_free[3] = &m_store[3]; - m_nfree = 4; - m_current = 0; - m_status = eStatus::Valid; - m_shape = shapearg; - m_distance = 0; - /* Initialize simplex */ - m_simplices[0].rank = 0; - m_ray = guess; - const real_t sqrl= m_ray.length_squared(); - appendvertice(m_simplices[0],sqrl>0?-m_ray:Vector3(1,0,0)); - m_simplices[0].p[0] = 1; - m_ray = m_simplices[0].c[0]->w; - sqdist = sqrl; - lastw[0] = - lastw[1] = - lastw[2] = - lastw[3] = m_ray; - /* Loop */ - do { - const U next=1-m_current; - sSimplex& cs=m_simplices[m_current]; - sSimplex& ns=m_simplices[next]; - /* Check zero */ - const real_t rl=m_ray.length(); - if(rlw; - bool found=false; - for(U i=0;i<4;++i) - { - if((w-lastw[i]).length_squared()w, - cs.c[1]->w, - weights,mask);break; - case 3: sqdist=projectorigin( cs.c[0]->w, - cs.c[1]->w, - cs.c[2]->w, - weights,mask);break; - case 4: sqdist=projectorigin( cs.c[0]->w, - cs.c[1]->w, - cs.c[2]->w, - cs.c[3]->w, - weights,mask);break; - } - if(sqdist>=0) - {/* Valid */ - ns.rank = 0; - m_ray = Vector3(0,0,0); - m_current = next; - for(U i=0,ni=cs.rank;iw*weights[i]; - } - else - { - m_free[m_nfree++] = cs.c[i]; - } - } - if(mask==15) m_status=eStatus::Inside; - } - else - {/* Return old simplex */ - removevertice(m_simplices[m_current]); - break; - } - m_status=((++iterations)rank) - { - case 1: - { - for(U i=0;i<3;++i) - { - Vector3 axis=Vector3(0,0,0); - axis[i]=1; - appendvertice(*m_simplex, axis); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-axis); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - } - } - break; - case 2: - { - const Vector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; - for(U i=0;i<3;++i) - { - Vector3 axis=Vector3(0,0,0); - axis[i]=1; - const Vector3 p=vec3_cross(d,axis); - if(p.length_squared()>0) - { - appendvertice(*m_simplex, p); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-p); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - } - } - } - break; - case 3: - { - const Vector3 n=vec3_cross(m_simplex->c[1]->w-m_simplex->c[0]->w, - m_simplex->c[2]->w-m_simplex->c[0]->w); - if(n.length_squared()>0) - { - appendvertice(*m_simplex,n); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - appendvertice(*m_simplex,-n); - if(EncloseOrigin()) return(true); - removevertice(*m_simplex); - } - } - break; - case 4: - { - if(Math::abs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, - m_simplex->c[1]->w-m_simplex->c[3]->w, - m_simplex->c[2]->w-m_simplex->c[3]->w))>0) - return(true); - } - break; - } - return(false); - } - /* Internals */ - void getsupport(const Vector3& d,sSV& sv) const - { - sv.d = d/d.length(); - sv.w = m_shape.Support(sv.d); - } - void removevertice(sSimplex& simplex) - { - m_free[m_nfree++]=simplex.c[--simplex.rank]; - } - void appendvertice(sSimplex& simplex,const Vector3& v) - { - simplex.p[simplex.rank]=0; - simplex.c[simplex.rank]=m_free[--m_nfree]; - getsupport(v,*simplex.c[simplex.rank++]); - } - static real_t det(const Vector3& a,const Vector3& b,const Vector3& c) - { - return( a.y*b.z*c.x+a.z*b.x*c.y- - a.x*b.z*c.y-a.y*b.x*c.z+ - a.x*b.y*c.z-a.z*b.y*c.x); - } - static real_t projectorigin( const Vector3& a, - const Vector3& b, - real_t* w,U& m) - { - const Vector3 d=b-a; - const real_t l=d.length_squared(); - if(l>GJK_SIMPLEX2_EPS) - { - const real_t t(l>0?-vec3_dot(a,d)/l:0); - if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length_squared()); } - else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length_squared()); } - else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length_squared()); } - } - return(-1); - } - static real_t projectorigin( const Vector3& a, - const Vector3& b, - const Vector3& c, - real_t* w,U& m) - { - static const U imd3[]={1,2,0}; - const Vector3* vt[]={&a,&b,&c}; - const Vector3 dl[]={a-b,b-c,c-a}; - const Vector3 n=vec3_cross(dl[0],dl[1]); - const real_t l=n.length_squared(); - if(l>GJK_SIMPLEX3_EPS) - { - real_t mindist=-1; - real_t subw[2] = { 0 , 0}; - U subm = 0; - for(U i=0;i<3;++i) - { - if(vec3_dot(*vt[i],vec3_cross(dl[i],n))>0) - { - const U j=imd3[i]; - const real_t subd(projectorigin(*vt[i],*vt[j],subw,subm)); - if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) - { - real_t mindist=-1; - real_t subw[3]; - U subm=0; - for(U i=0;i<3;++i) - { - const U j=imd3[i]; - const real_t s=vl*vec3_dot(d,vec3_cross(dl[i],dl[j])); - if(s>0) - { - const real_t subd=projectorigin(*vt[i],*vt[j],d,subw,subm); - if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; - fb->e[eb]=(U1)ea;fb->f[eb]=fa; - } - static inline void append(sList& list,sFace* face) - { - face->l[0] = 0; - face->l[1] = list.root; - if(list.root) list.root->l[0]=face; - list.root = face; - ++list.count; - } - static inline void remove(sList& list,sFace* face) - { - if(face->l[1]) face->l[1]->l[0]=face->l[0]; - if(face->l[0]) face->l[0]->l[1]=face->l[1]; - if(face==list.root) list.root=face->l[1]; - --list.count; - } - - - void Initialize() - { - m_status = eStatus::Failed; - m_normal = Vector3(0,0,0); - m_depth = 0; - m_nextsv = 0; - for(U i=0;i1)&&gjk.EncloseOrigin()) - { - - /* Clean up */ - while(m_hull.root) - { - sFace* f = m_hull.root; - remove(m_hull,f); - append(m_stock,f); - } - m_status = eStatus::Valid; - m_nextsv = 0; - /* Orient simplex */ - if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, - simplex.c[1]->w-simplex.c[3]->w, - simplex.c[2]->w-simplex.c[3]->w)<0) - { - SWAP(simplex.c[0],simplex.c[1]); - SWAP(simplex.p[0],simplex.p[1]); - } - /* Build initial hull */ - sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), - newface(simplex.c[1],simplex.c[0],simplex.c[3],true), - newface(simplex.c[2],simplex.c[1],simplex.c[3],true), - newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; - if(m_hull.count==4) - { - sFace* best=findbest(); - sFace outer=*best; - U pass=0; - U iterations=0; - bind(tetra[0],0,tetra[1],0); - bind(tetra[0],1,tetra[2],0); - bind(tetra[0],2,tetra[3],0); - bind(tetra[1],1,tetra[3],2); - bind(tetra[1],2,tetra[2],1); - bind(tetra[2],2,tetra[3],1); - m_status=eStatus::Valid; - for(;iterationspass = (U1)(++pass); - gjk.getsupport(best->n,*w); - const real_t wdist=vec3_dot(best->n,w->w)-best->d; - if(wdist>EPA_ACCURACY) - { - for(U j=0;(j<3)&&valid;++j) - { - valid&=expand( pass,w, - best->f[j],best->e[j], - horizon); - } - if(valid&&(horizon.nf>=3)) - { - bind(horizon.cf,1,horizon.ff,2); - remove(m_hull,best); - append(m_stock,best); - best=findbest(); - if(best->p>=outer.p) outer=*best; - } else { m_status=eStatus::InvalidHull;break; } - } else { m_status=eStatus::AccuraryReached;break; } - } else { m_status=eStatus::OutOfVertices;break; } - } - const Vector3 projection=outer.n*outer.d; - m_normal = outer.n; - m_depth = outer.d; - m_result.rank = 3; - m_result.c[0] = outer.c[0]; - m_result.c[1] = outer.c[1]; - m_result.c[2] = outer.c[2]; - m_result.p[0] = vec3_cross( outer.c[1]->w-projection, - outer.c[2]->w-projection).length(); - m_result.p[1] = vec3_cross( outer.c[2]->w-projection, - outer.c[0]->w-projection).length(); - m_result.p[2] = vec3_cross( outer.c[0]->w-projection, - outer.c[1]->w-projection).length(); - const real_t sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; - m_result.p[0] /= sum; - m_result.p[1] /= sum; - m_result.p[2] /= sum; - return(m_status); - } - } - /* Fallback */ - m_status = eStatus::FallBack; - m_normal = -guess; - const real_t nl=m_normal.length(); - if(nl>0) - m_normal = m_normal/nl; - else - m_normal = Vector3(1,0,0); - m_depth = 0; - m_result.rank=1; - m_result.c[0]=simplex.c[0]; - m_result.p[0]=1; - return(m_status); - } - sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) - { - if(m_stock.root) - { - sFace* face=m_stock.root; - remove(m_stock,face); - append(m_hull,face); - face->pass = 0; - face->c[0] = a; - face->c[1] = b; - face->c[2] = c; - face->n = vec3_cross(b->w-a->w,c->w-a->w); - const real_t l=face->n.length(); - const bool v=l>EPA_ACCURACY; - face->p = MIN(MIN( - vec3_dot(a->w,vec3_cross(face->n,a->w-b->w)), - vec3_dot(b->w,vec3_cross(face->n,b->w-c->w))), - vec3_dot(c->w,vec3_cross(face->n,c->w-a->w))) / - (v?l:1); - face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; - if(v) - { - face->d = vec3_dot(a->w,face->n)/l; - face->n /= l; - if(forced||(face->d>=-EPA_PLANE_EPS)) - { - return(face); - } else m_status=eStatus::NonConvex; - } else m_status=eStatus::Degenerated; - remove(m_hull,face); - append(m_stock,face); - return(0); - } - // -- GODOT start -- - //m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; - m_status=eStatus::OutOfFaces; - // -- GODOT end -- - return(0); - } - sFace* findbest() - { - sFace* minf=m_hull.root; - real_t mind=minf->d*minf->d; - real_t maxp=minf->p; - for(sFace* f=minf->l[1];f;f=f->l[1]) - { - const real_t sqd=f->d*f->d; - if((f->p>=maxp)&&(sqdp; - } - } - return(minf); - } - bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon) - { - static const U i1m3[]={1,2,0}; - static const U i2m3[]={2,0,1}; - if(f->pass!=pass) - { - const U e1=i1m3[e]; - if((vec3_dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) - { - sFace* nf=newface(f->c[e1],f->c[e],w,false); - if(nf) - { - bind(nf,0,f,e); - if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; - horizon.cf=nf; - ++horizon.nf; - return(true); - } - } - else - { - const U e2=i2m3[e]; - f->pass = (U1)pass; - if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& - expand(pass,w,f->f[e2],f->e[e2],horizon)) - { - remove(m_hull,f); - append(m_stock,f); - return(true); - } - } - } - return(false); - } - - }; - - // - static void Initialize( const ShapeSW* shape0,const Transform& wtrs0, - const ShapeSW* shape1,const Transform& wtrs1, - sResults& results, - tShape& shape, - bool withmargins) - { - /* Results */ - results.witnesses[0] = - results.witnesses[1] = Vector3(0,0,0); - results.status = sResults::Separated; - /* Shape */ - shape.m_shapes[0] = shape0; - shape.m_shapes[1] = shape1; - shape.transform_A = wtrs0; - shape.transform_B = wtrs1; - - } - - - -// -// Api -// - -// - -// -bool Distance( const ShapeSW* shape0, - const Transform& wtrs0, - const ShapeSW* shape1, - const Transform& wtrs1, - const Vector3& guess, - sResults& results) -{ - tShape shape; - Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); - GJK gjk; - GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); - if(gjk_status==GJK::eStatus::Valid) - { - Vector3 w0=Vector3(0,0,0); - Vector3 w1=Vector3(0,0,0); - for(U i=0;irank;++i) - { - const real_t p=gjk.m_simplex->p[i]; - w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; - w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; - } - results.witnesses[0] = w0; - results.witnesses[1] = w1; - results.normal = w0-w1; - results.distance = results.normal.length(); - results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; - return(true); - } - else - { - results.status = gjk_status==GJK::eStatus::Inside? - sResults::Penetrating : - sResults::GJK_Failed ; - return(false); - } -} - -// -bool Penetration( const ShapeSW* shape0, - const Transform& wtrs0, - const ShapeSW* shape1, - const Transform& wtrs1, - const Vector3& guess, - sResults& results - ) -{ - tShape shape; - Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); - GJK gjk; - GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); - switch(gjk_status) - { - case GJK::eStatus::Inside: - { - EPA epa; - EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); - if(epa_status!=EPA::eStatus::Failed) - { - Vector3 w0=Vector3(0,0,0); - for(U i=0;id,0)*epa.m_result.p[i]; - } - results.status = sResults::Penetrating; - results.witnesses[0] = w0; - results.witnesses[1] = w0-epa.m_normal*epa.m_depth; - results.normal = -epa.m_normal; - results.distance = -epa.m_depth; - return(true); - } else results.status=sResults::EPA_Failed; - } - break; - case GJK::eStatus::Failed: - results.status=sResults::GJK_Failed; - break; - default: {} - } - return(false); -} - - -/* Symbols cleanup */ - -#undef GJK_MAX_ITERATIONS -#undef GJK_ACCURARY -#undef GJK_MIN_DISTANCE -#undef GJK_DUPLICATED_EPS -#undef GJK_SIMPLEX2_EPS -#undef GJK_SIMPLEX3_EPS -#undef GJK_SIMPLEX4_EPS - -#undef EPA_MAX_VERTICES -#undef EPA_MAX_FACES -#undef EPA_MAX_ITERATIONS -#undef EPA_ACCURACY -#undef EPA_FALLBACK -#undef EPA_PLANE_EPS -#undef EPA_INSIDE_EPS - - -} // end of namespace - -/* clang-format on */ - -bool gjk_epa_calculate_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) { - - GjkEpa2::sResults res; - - if (GjkEpa2::Distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) { - - r_result_A = res.witnesses[0]; - r_result_B = res.witnesses[1]; - return true; - } - - return false; -} - -bool gjk_epa_calculate_penetration(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CollisionSolverSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap) { - - GjkEpa2::sResults res; - - if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) { - if (p_result_callback) { - if (p_swap) - p_result_callback(res.witnesses[1], res.witnesses[0], p_userdata); - else - p_result_callback(res.witnesses[0], res.witnesses[1], p_userdata); - } - return true; - } - - return false; -} diff --git a/servers/physics/gjk_epa.h b/servers/physics/gjk_epa.h deleted file mode 100644 index 38c616cde0..0000000000 --- a/servers/physics/gjk_epa.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* gjk_epa.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef GJK_EPA_H -#define GJK_EPA_H - -#include "collision_solver_sw.h" -#include "shape_sw.h" - -bool gjk_epa_calculate_penetration(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, CollisionSolverSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false); -bool gjk_epa_calculate_distance(const ShapeSW *p_shape_A, const Transform &p_transform_A, const ShapeSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B); - -#endif diff --git a/servers/physics/joints/SCsub b/servers/physics/joints/SCsub deleted file mode 100644 index d730144861..0000000000 --- a/servers/physics/joints/SCsub +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/physics/joints/cone_twist_joint_sw.cpp b/servers/physics/joints/cone_twist_joint_sw.cpp deleted file mode 100644 index 58f66f7ea2..0000000000 --- a/servers/physics/joints/cone_twist_joint_sw.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/*************************************************************************/ -/* cone_twist_joint_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -/* -Bullet Continuous Collision Detection and Physics Library -ConeTwistJointSW is Copyright (c) 2007 Starbreeze Studios - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Written by: Marcus Hennix -*/ - -#include "cone_twist_joint_sw.h" - -static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { - - if (Math::abs(n.z) > Math_SQRT12) { - // choose p in y-z plane - real_t a = n[1] * n[1] + n[2] * n[2]; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(0, -n[2] * k, n[1] * k); - // set q = n x p - q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); - } else { - // choose p in x-y plane - real_t a = n.x * n.x + n.y * n.y; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(-n.y * k, n.x * k, 0); - // set q = n x p - q = Vector3(-n.z * p.y, n.z * p.x, a * k); - } -} - -static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { - real_t coeff_1 = Math_PI / 4.0f; - real_t coeff_2 = 3.0f * coeff_1; - real_t abs_y = Math::abs(y); - real_t angle; - if (x >= 0.0f) { - real_t r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - real_t r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - -ConeTwistJointSW::ConeTwistJointSW(BodySW *rbA, BodySW *rbB, const Transform &rbAFrame, const Transform &rbBFrame) : - JointSW(_arr, 2) { - - A = rbA; - B = rbB; - - m_rbAFrame = rbAFrame; - m_rbBFrame = rbBFrame; - - m_swingSpan1 = Math_PI / 4.0; - m_swingSpan2 = Math_PI / 4.0; - m_twistSpan = Math_PI * 2; - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - - m_angularOnly = false; - m_solveTwistLimit = false; - m_solveSwingLimit = false; - - A->add_constraint(this, 0); - B->add_constraint(this, 1); - - m_appliedImpulse = 0; -} - -bool ConeTwistJointSW::setup(real_t p_timestep) { - m_appliedImpulse = real_t(0.); - - //set bias, sign, clear accumulator - m_swingCorrection = real_t(0.); - m_twistLimitSign = real_t(0.); - m_solveTwistLimit = false; - m_solveSwingLimit = false; - m_accTwistLimitImpulse = real_t(0.); - m_accSwingLimitImpulse = real_t(0.); - - if (!m_angularOnly) { - Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); - Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); - Vector3 relPos = pivotBInW - pivotAInW; - - Vector3 normal[3]; - if (Math::is_zero_approx(relPos.length_squared())) { - normal[0] = Vector3(real_t(1.0), 0, 0); - } else { - normal[0] = relPos.normalized(); - } - - plane_space(normal[0], normal[1], normal[2]); - - for (int i = 0; i < 3; i++) { - memnew_placement(&m_jac[i], JacobianEntrySW( - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - pivotAInW - A->get_transform().origin - A->get_center_of_mass(), - pivotBInW - B->get_transform().origin - B->get_center_of_mass(), - normal[i], - A->get_inv_inertia(), - A->get_inv_mass(), - B->get_inv_inertia(), - B->get_inv_mass())); - } - } - - Vector3 b1Axis1, b1Axis2, b1Axis3; - Vector3 b2Axis1, b2Axis2; - - b1Axis1 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(0)); - b2Axis1 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(0)); - - real_t swing1 = real_t(0.), swing2 = real_t(0.); - - real_t swx = real_t(0.), swy = real_t(0.); - real_t thresh = real_t(10.); - real_t fact; - - // Get Frame into world space - if (m_swingSpan1 >= real_t(0.05f)) { - b1Axis2 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(1)); - //swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); - swx = b2Axis1.dot(b1Axis1); - swy = b2Axis1.dot(b1Axis2); - swing1 = atan2fast(swy, swx); - fact = (swy * swy + swx * swx) * thresh * thresh; - fact = fact / (fact + real_t(1.0)); - swing1 *= fact; - } - - if (m_swingSpan2 >= real_t(0.05f)) { - b1Axis3 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(2)); - //swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); - swx = b2Axis1.dot(b1Axis1); - swy = b2Axis1.dot(b1Axis3); - swing2 = atan2fast(swy, swx); - fact = (swy * swy + swx * swx) * thresh * thresh; - fact = fact / (fact + real_t(1.0)); - swing2 *= fact; - } - - real_t RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1); - real_t RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2); - real_t EllipseAngle = Math::abs(swing1 * swing1) * RMaxAngle1Sq + Math::abs(swing2 * swing2) * RMaxAngle2Sq; - - if (EllipseAngle > 1.0f) { - m_swingCorrection = EllipseAngle - 1.0f; - m_solveSwingLimit = true; - - // Calculate necessary axis & factors - m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3)); - m_swingAxis.normalize(); - - real_t swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; - m_swingAxis *= swingAxisSign; - - m_kSwing = real_t(1.) / (A->compute_angular_impulse_denominator(m_swingAxis) + - B->compute_angular_impulse_denominator(m_swingAxis)); - } - - // Twist limits - if (m_twistSpan >= real_t(0.)) { - Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1)); - Quat rotationArc = Quat(b2Axis1, b1Axis1); - Vector3 TwistRef = rotationArc.xform(b2Axis22); - real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2)); - - real_t lockedFreeFactor = (m_twistSpan > real_t(0.05f)) ? m_limitSoftness : real_t(0.); - if (twist <= -m_twistSpan * lockedFreeFactor) { - m_twistCorrection = -(twist + m_twistSpan); - m_solveTwistLimit = true; - - m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; - m_twistAxis.normalize(); - m_twistAxis *= -1.0f; - - m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) + - B->compute_angular_impulse_denominator(m_twistAxis)); - - } else if (twist > m_twistSpan * lockedFreeFactor) { - m_twistCorrection = (twist - m_twistSpan); - m_solveTwistLimit = true; - - m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; - m_twistAxis.normalize(); - - m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) + - B->compute_angular_impulse_denominator(m_twistAxis)); - } - } - - return true; -} - -void ConeTwistJointSW::solve(real_t p_timestep) { - - Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); - Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); - - real_t tau = real_t(0.3); - - //linear part - if (!m_angularOnly) { - Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; - Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; - - Vector3 vel1 = A->get_velocity_in_local_point(rel_pos1); - Vector3 vel2 = B->get_velocity_in_local_point(rel_pos2); - Vector3 vel = vel1 - vel2; - - for (int i = 0; i < 3; i++) { - const Vector3 &normal = m_jac[i].m_linearJointAxis; - real_t jacDiagABInv = real_t(1.) / m_jac[i].getDiagonal(); - - real_t rel_vel; - rel_vel = normal.dot(vel); - //positional error (zeroth order error) - real_t depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - real_t impulse = depth * tau / p_timestep * jacDiagABInv - rel_vel * jacDiagABInv; - m_appliedImpulse += impulse; - Vector3 impulse_vector = normal * impulse; - A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); - B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); - } - } - - { - ///solve angular part - const Vector3 &angVelA = A->get_angular_velocity(); - const Vector3 &angVelB = B->get_angular_velocity(); - - // solve swing limit - if (m_solveSwingLimit) { - real_t amplitude = ((angVelB - angVelA).dot(m_swingAxis) * m_relaxationFactor * m_relaxationFactor + m_swingCorrection * (real_t(1.) / p_timestep) * m_biasFactor); - real_t impulseMag = amplitude * m_kSwing; - - // Clamp the accumulated impulse - real_t temp = m_accSwingLimitImpulse; - m_accSwingLimitImpulse = MAX(m_accSwingLimitImpulse + impulseMag, real_t(0.0)); - impulseMag = m_accSwingLimitImpulse - temp; - - Vector3 impulse = m_swingAxis * impulseMag; - - A->apply_torque_impulse(impulse); - B->apply_torque_impulse(-impulse); - } - - // solve twist limit - if (m_solveTwistLimit) { - real_t amplitude = ((angVelB - angVelA).dot(m_twistAxis) * m_relaxationFactor * m_relaxationFactor + m_twistCorrection * (real_t(1.) / p_timestep) * m_biasFactor); - real_t impulseMag = amplitude * m_kTwist; - - // Clamp the accumulated impulse - real_t temp = m_accTwistLimitImpulse; - m_accTwistLimitImpulse = MAX(m_accTwistLimitImpulse + impulseMag, real_t(0.0)); - impulseMag = m_accTwistLimitImpulse - temp; - - Vector3 impulse = m_twistAxis * impulseMag; - - A->apply_torque_impulse(impulse); - B->apply_torque_impulse(-impulse); - } - } -} - -void ConeTwistJointSW::set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value) { - - switch (p_param) { - case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: { - - m_swingSpan1 = p_value; - m_swingSpan2 = p_value; - } break; - case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN: { - - m_twistSpan = p_value; - } break; - case PhysicsServer::CONE_TWIST_JOINT_BIAS: { - - m_biasFactor = p_value; - } break; - case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS: { - - m_limitSoftness = p_value; - } break; - case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: { - - m_relaxationFactor = p_value; - } break; - case PhysicsServer::CONE_TWIST_MAX: break; // Can't happen, but silences warning - } -} - -real_t ConeTwistJointSW::get_param(PhysicsServer::ConeTwistJointParam p_param) const { - - switch (p_param) { - case PhysicsServer::CONE_TWIST_JOINT_SWING_SPAN: { - - return m_swingSpan1; - } break; - case PhysicsServer::CONE_TWIST_JOINT_TWIST_SPAN: { - - return m_twistSpan; - } break; - case PhysicsServer::CONE_TWIST_JOINT_BIAS: { - - return m_biasFactor; - } break; - case PhysicsServer::CONE_TWIST_JOINT_SOFTNESS: { - - return m_limitSoftness; - } break; - case PhysicsServer::CONE_TWIST_JOINT_RELAXATION: { - - return m_relaxationFactor; - } break; - case PhysicsServer::CONE_TWIST_MAX: break; // Can't happen, but silences warning - } - - return 0; -} diff --git a/servers/physics/joints/cone_twist_joint_sw.h b/servers/physics/joints/cone_twist_joint_sw.h deleted file mode 100644 index 857aaa0d86..0000000000 --- a/servers/physics/joints/cone_twist_joint_sw.h +++ /dev/null @@ -1,142 +0,0 @@ -/*************************************************************************/ -/* cone_twist_joint_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -/* -Bullet Continuous Collision Detection and Physics Library -ConeTwistJointSW is Copyright (c) 2007 Starbreeze Studios - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. - -Written by: Marcus Hennix -*/ - -#ifndef CONE_TWIST_JOINT_SW_H -#define CONE_TWIST_JOINT_SW_H - -#include "servers/physics/joints/jacobian_entry_sw.h" -#include "servers/physics/joints_sw.h" - -///ConeTwistJointSW can be used to simulate ragdoll joints (upper arm, leg etc) -class ConeTwistJointSW : public JointSW { -#ifdef IN_PARALLELL_SOLVER -public: -#endif - - union { - struct { - BodySW *A; - BodySW *B; - }; - - BodySW *_arr[2]; - }; - - JacobianEntrySW m_jac[3]; //3 orthogonal linear constraints - - real_t m_appliedImpulse; - Transform m_rbAFrame; - Transform m_rbBFrame; - - real_t m_limitSoftness; - real_t m_biasFactor; - real_t m_relaxationFactor; - - real_t m_swingSpan1; - real_t m_swingSpan2; - real_t m_twistSpan; - - Vector3 m_swingAxis; - Vector3 m_twistAxis; - - real_t m_kSwing; - real_t m_kTwist; - - real_t m_twistLimitSign; - real_t m_swingCorrection; - real_t m_twistCorrection; - - real_t m_accSwingLimitImpulse; - real_t m_accTwistLimitImpulse; - - bool m_angularOnly; - bool m_solveTwistLimit; - bool m_solveSwingLimit; - -public: - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_CONE_TWIST; } - - virtual bool setup(real_t p_timestep); - virtual void solve(real_t p_timestep); - - ConeTwistJointSW(BodySW *rbA, BodySW *rbB, const Transform &rbAFrame, const Transform &rbBFrame); - - void setAngularOnly(bool angularOnly) { - m_angularOnly = angularOnly; - } - - void setLimit(real_t _swingSpan1, real_t _swingSpan2, real_t _twistSpan, real_t _softness = 0.8f, real_t _biasFactor = 0.3f, real_t _relaxationFactor = 1.0f) { - m_swingSpan1 = _swingSpan1; - m_swingSpan2 = _swingSpan2; - m_twistSpan = _twistSpan; - - m_limitSoftness = _softness; - m_biasFactor = _biasFactor; - m_relaxationFactor = _relaxationFactor; - } - - inline int getSolveTwistLimit() { - return m_solveTwistLimit; - } - - inline int getSolveSwingLimit() { - return m_solveTwistLimit; - } - - inline real_t getTwistLimitSign() { - return m_twistLimitSign; - } - - void set_param(PhysicsServer::ConeTwistJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::ConeTwistJointParam p_param) const; -}; - -#endif // CONE_TWIST_JOINT_SW_H diff --git a/servers/physics/joints/generic_6dof_joint_sw.cpp b/servers/physics/joints/generic_6dof_joint_sw.cpp deleted file mode 100644 index 8f0ccab7f7..0000000000 --- a/servers/physics/joints/generic_6dof_joint_sw.cpp +++ /dev/null @@ -1,686 +0,0 @@ -/*************************************************************************/ -/* generic_6dof_joint_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -2007-09-09 -Generic6DOFJointSW Refactored by Francisco Le?n -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ - -#include "generic_6dof_joint_sw.h" - -#define GENERIC_D6_DISABLE_WARMSTARTING 1 - -//////////////////////////// G6DOFRotationalLimitMotorSW //////////////////////////////////// - -int G6DOFRotationalLimitMotorSW::testLimitValue(real_t test_value) { - if (m_loLimit > m_hiLimit) { - m_currentLimit = 0; //Free from violation - return 0; - } - - if (test_value < m_loLimit) { - m_currentLimit = 1; //low limit violation - m_currentLimitError = test_value - m_loLimit; - return 1; - } else if (test_value > m_hiLimit) { - m_currentLimit = 2; //High limit violation - m_currentLimitError = test_value - m_hiLimit; - return 2; - }; - - m_currentLimit = 0; //Free from violation - return 0; -} - -real_t G6DOFRotationalLimitMotorSW::solveAngularLimits( - real_t timeStep, Vector3 &axis, real_t jacDiagABInv, - BodySW *body0, BodySW *body1) { - if (!needApplyTorques()) return 0.0f; - - real_t target_velocity = m_targetVelocity; - real_t maxMotorForce = m_maxMotorForce; - - //current error correction - if (m_currentLimit != 0) { - target_velocity = -m_ERP * m_currentLimitError / (timeStep); - maxMotorForce = m_maxLimitForce; - } - - maxMotorForce *= timeStep; - - // current velocity difference - Vector3 vel_diff = body0->get_angular_velocity(); - if (body1) { - vel_diff -= body1->get_angular_velocity(); - } - - real_t rel_vel = axis.dot(vel_diff); - - // correction velocity - real_t motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel); - - if (Math::is_zero_approx(motor_relvel)) { - return 0.0f; //no need for applying force - } - - // correction impulse - real_t unclippedMotorImpulse = (1 + m_bounce) * motor_relvel * jacDiagABInv; - - // clip correction impulse - real_t clippedMotorImpulse; - - ///@todo: should clip against accumulated impulse - if (unclippedMotorImpulse > 0.0f) { - clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce ? maxMotorForce : unclippedMotorImpulse; - } else { - clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce : unclippedMotorImpulse; - } - - // sort with accumulated impulses - real_t lo = real_t(-1e30); - real_t hi = real_t(1e30); - - real_t oldaccumImpulse = m_accumulatedImpulse; - real_t sum = oldaccumImpulse + clippedMotorImpulse; - m_accumulatedImpulse = sum > hi ? real_t(0.) : sum < lo ? real_t(0.) : sum; - - clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; - - Vector3 motorImp = clippedMotorImpulse * axis; - - body0->apply_torque_impulse(motorImp); - if (body1) body1->apply_torque_impulse(-motorImp); - - return clippedMotorImpulse; -} - -//////////////////////////// End G6DOFRotationalLimitMotorSW //////////////////////////////////// - -//////////////////////////// G6DOFTranslationalLimitMotorSW //////////////////////////////////// -real_t G6DOFTranslationalLimitMotorSW::solveLinearAxis( - real_t timeStep, - real_t jacDiagABInv, - BodySW *body1, const Vector3 &pointInA, - BodySW *body2, const Vector3 &pointInB, - int limit_index, - const Vector3 &axis_normal_on_a, - const Vector3 &anchorPos) { - - ///find relative velocity - // Vector3 rel_pos1 = pointInA - body1->get_transform().origin; - // Vector3 rel_pos2 = pointInB - body2->get_transform().origin; - Vector3 rel_pos1 = anchorPos - body1->get_transform().origin; - Vector3 rel_pos2 = anchorPos - body2->get_transform().origin; - - Vector3 vel1 = body1->get_velocity_in_local_point(rel_pos1); - Vector3 vel2 = body2->get_velocity_in_local_point(rel_pos2); - Vector3 vel = vel1 - vel2; - - real_t rel_vel = axis_normal_on_a.dot(vel); - - /// apply displacement correction - - //positional error (zeroth order error) - real_t depth = -(pointInA - pointInB).dot(axis_normal_on_a); - real_t lo = real_t(-1e30); - real_t hi = real_t(1e30); - - real_t minLimit = m_lowerLimit[limit_index]; - real_t maxLimit = m_upperLimit[limit_index]; - - //handle the limits - if (minLimit < maxLimit) { - { - if (depth > maxLimit) { - depth -= maxLimit; - lo = real_t(0.); - - } else { - if (depth < minLimit) { - depth -= minLimit; - hi = real_t(0.); - } else { - return 0.0f; - } - } - } - } - - real_t normalImpulse = m_limitSoftness[limit_index] * (m_restitution[limit_index] * depth / timeStep - m_damping[limit_index] * rel_vel) * jacDiagABInv; - - real_t oldNormalImpulse = m_accumulatedImpulse[limit_index]; - real_t sum = oldNormalImpulse + normalImpulse; - m_accumulatedImpulse[limit_index] = sum > hi ? real_t(0.) : sum < lo ? real_t(0.) : sum; - normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; - - Vector3 impulse_vector = axis_normal_on_a * normalImpulse; - body1->apply_impulse(rel_pos1, impulse_vector); - body2->apply_impulse(rel_pos2, -impulse_vector); - return normalImpulse; -} - -//////////////////////////// G6DOFTranslationalLimitMotorSW //////////////////////////////////// - -Generic6DOFJointSW::Generic6DOFJointSW(BodySW *rbA, BodySW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA) : - JointSW(_arr, 2), - m_frameInA(frameInA), - m_frameInB(frameInB), - m_useLinearReferenceFrameA(useLinearReferenceFrameA) { - A = rbA; - B = rbB; - A->add_constraint(this, 0); - B->add_constraint(this, 1); -} - -void Generic6DOFJointSW::calculateAngleInfo() { - Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis; - - m_calculatedAxisAngleDiff = relative_frame.get_euler_xyz(); - - // in euler angle mode we do not actually constrain the angular velocity - // along the axes axis[0] and axis[2] (although we do use axis[1]) : - // - // to get constrain w2-w1 along ...not - // ------ --------------------- ------ - // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] - // d(angle[1])/dt = 0 ax[1] - // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] - // - // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. - // to prove the result for angle[0], write the expression for angle[0] from - // GetInfo1 then take the derivative. to prove this for angle[2] it is - // easier to take the euler rate expression for d(angle[2])/dt with respect - // to the components of w and set that to 0. - - Vector3 axis0 = m_calculatedTransformB.basis.get_axis(0); - Vector3 axis2 = m_calculatedTransformA.basis.get_axis(2); - - m_calculatedAxis[1] = axis2.cross(axis0); - m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); - m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); - - /* - if(m_debugDrawer) - { - - char buff[300]; - sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", - m_calculatedAxisAngleDiff[0], - m_calculatedAxisAngleDiff[1], - m_calculatedAxisAngleDiff[2]); - m_debugDrawer->reportErrorWarning(buff); - } - */ -} - -void Generic6DOFJointSW::calculateTransforms() { - m_calculatedTransformA = A->get_transform() * m_frameInA; - m_calculatedTransformB = B->get_transform() * m_frameInB; - - calculateAngleInfo(); -} - -void Generic6DOFJointSW::buildLinearJacobian( - JacobianEntrySW &jacLinear, const Vector3 &normalWorld, - const Vector3 &pivotAInW, const Vector3 &pivotBInW) { - memnew_placement(&jacLinear, JacobianEntrySW( - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - pivotAInW - A->get_transform().origin - A->get_center_of_mass(), - pivotBInW - B->get_transform().origin - B->get_center_of_mass(), - normalWorld, - A->get_inv_inertia(), - A->get_inv_mass(), - B->get_inv_inertia(), - B->get_inv_mass())); -} - -void Generic6DOFJointSW::buildAngularJacobian( - JacobianEntrySW &jacAngular, const Vector3 &jointAxisW) { - memnew_placement(&jacAngular, JacobianEntrySW(jointAxisW, - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - A->get_inv_inertia(), - B->get_inv_inertia())); -} - -bool Generic6DOFJointSW::testAngularLimitMotor(int axis_index) { - real_t angle = m_calculatedAxisAngleDiff[axis_index]; - - //test limits - m_angularLimits[axis_index].testLimitValue(angle); - return m_angularLimits[axis_index].needApplyTorques(); -} - -bool Generic6DOFJointSW::setup(real_t p_timestep) { - - // Clear accumulated impulses for the next simulation step - m_linearLimits.m_accumulatedImpulse = Vector3(real_t(0.), real_t(0.), real_t(0.)); - int i; - for (i = 0; i < 3; i++) { - m_angularLimits[i].m_accumulatedImpulse = real_t(0.); - } - //calculates transform - calculateTransforms(); - - // const Vector3& pivotAInW = m_calculatedTransformA.origin; - // const Vector3& pivotBInW = m_calculatedTransformB.origin; - calcAnchorPos(); - Vector3 pivotAInW = m_AnchorPos; - Vector3 pivotBInW = m_AnchorPos; - - // not used here - // Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; - // Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; - - Vector3 normalWorld; - //linear part - for (i = 0; i < 3; i++) { - if (m_linearLimits.enable_limit[i] && m_linearLimits.isLimited(i)) { - if (m_useLinearReferenceFrameA) - normalWorld = m_calculatedTransformA.basis.get_axis(i); - else - normalWorld = m_calculatedTransformB.basis.get_axis(i); - - buildLinearJacobian( - m_jacLinear[i], normalWorld, - pivotAInW, pivotBInW); - } - } - - // angular part - for (i = 0; i < 3; i++) { - //calculates error angle - if (m_angularLimits[i].m_enableLimit && testAngularLimitMotor(i)) { - normalWorld = this->getAxis(i); - // Create angular atom - buildAngularJacobian(m_jacAng[i], normalWorld); - } - } - - return true; -} - -void Generic6DOFJointSW::solve(real_t p_timestep) { - m_timeStep = p_timestep; - - //calculateTransforms(); - - int i; - - // linear - - Vector3 pointInA = m_calculatedTransformA.origin; - Vector3 pointInB = m_calculatedTransformB.origin; - - real_t jacDiagABInv; - Vector3 linear_axis; - for (i = 0; i < 3; i++) { - if (m_linearLimits.enable_limit[i] && m_linearLimits.isLimited(i)) { - jacDiagABInv = real_t(1.) / m_jacLinear[i].getDiagonal(); - - if (m_useLinearReferenceFrameA) - linear_axis = m_calculatedTransformA.basis.get_axis(i); - else - linear_axis = m_calculatedTransformB.basis.get_axis(i); - - m_linearLimits.solveLinearAxis( - m_timeStep, - jacDiagABInv, - A, pointInA, - B, pointInB, - i, linear_axis, m_AnchorPos); - } - } - - // angular - Vector3 angular_axis; - real_t angularJacDiagABInv; - for (i = 0; i < 3; i++) { - if (m_angularLimits[i].m_enableLimit && m_angularLimits[i].needApplyTorques()) { - - // get axis - angular_axis = getAxis(i); - - angularJacDiagABInv = real_t(1.) / m_jacAng[i].getDiagonal(); - - m_angularLimits[i].solveAngularLimits(m_timeStep, angular_axis, angularJacDiagABInv, A, B); - } - } -} - -void Generic6DOFJointSW::updateRHS(real_t timeStep) { - (void)timeStep; -} - -Vector3 Generic6DOFJointSW::getAxis(int axis_index) const { - return m_calculatedAxis[axis_index]; -} - -real_t Generic6DOFJointSW::getAngle(int axis_index) const { - return m_calculatedAxisAngleDiff[axis_index]; -} - -void Generic6DOFJointSW::calcAnchorPos(void) { - real_t imA = A->get_inv_mass(); - real_t imB = B->get_inv_mass(); - real_t weight; - if (imB == real_t(0.0)) { - weight = real_t(1.0); - } else { - weight = imA / (imA + imB); - } - const Vector3 &pA = m_calculatedTransformA.origin; - const Vector3 &pB = m_calculatedTransformB.origin; - m_AnchorPos = pA * weight + pB * (real_t(1.0) - weight); -} // Generic6DOFJointSW::calcAnchorPos() - -void Generic6DOFJointSW::set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value) { - - ERR_FAIL_INDEX(p_axis, 3); - switch (p_param) { - case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { - - m_linearLimits.m_lowerLimit[p_axis] = p_value; - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT: { - - m_linearLimits.m_upperLimit[p_axis] = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: { - - m_linearLimits.m_limitSoftness[p_axis] = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION: { - - m_linearLimits.m_restitution[p_axis] = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING: { - - m_linearLimits.m_damping[p_axis] = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: { - - m_angularLimits[p_axis].m_loLimit = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: { - - m_angularLimits[p_axis].m_hiLimit = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: { - - m_angularLimits[p_axis].m_limitSoftness = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING: { - - m_angularLimits[p_axis].m_damping = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: { - - m_angularLimits[p_axis].m_bounce = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: { - - m_angularLimits[p_axis].m_maxLimitForce = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: { - - m_angularLimits[p_axis].m_ERP = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: { - - m_angularLimits[p_axis].m_targetVelocity = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: { - - m_angularLimits[p_axis].m_maxLimitForce = p_value; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning - } -} - -real_t Generic6DOFJointSW::get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const { - ERR_FAIL_INDEX_V(p_axis, 3, 0); - switch (p_param) { - case PhysicsServer::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { - - return m_linearLimits.m_lowerLimit[p_axis]; - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_UPPER_LIMIT: { - - return m_linearLimits.m_upperLimit[p_axis]; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: { - - return m_linearLimits.m_limitSoftness[p_axis]; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_RESTITUTION: { - - return m_linearLimits.m_restitution[p_axis]; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_DAMPING: { - - return m_linearLimits.m_damping[p_axis]; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: { - - return m_angularLimits[p_axis].m_loLimit; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: { - - return m_angularLimits[p_axis].m_hiLimit; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: { - - return m_angularLimits[p_axis].m_limitSoftness; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_DAMPING: { - - return m_angularLimits[p_axis].m_damping; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_RESTITUTION: { - - return m_angularLimits[p_axis].m_bounce; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: { - - return m_angularLimits[p_axis].m_maxLimitForce; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_ERP: { - - return m_angularLimits[p_axis].m_ERP; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: { - - return m_angularLimits[p_axis].m_targetVelocity; - - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: { - - return m_angularLimits[p_axis].m_maxMotorForce; - - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_DAMPING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning - } - return 0; -} - -void Generic6DOFJointSW::set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value) { - - ERR_FAIL_INDEX(p_axis, 3); - - switch (p_flag) { - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: { - - m_linearLimits.enable_limit[p_axis] = p_value; - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: { - - m_angularLimits[p_axis].m_enableLimit = p_value; - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR: { - - m_angularLimits[p_axis].m_enableMotor = p_value; - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning - } -} -bool Generic6DOFJointSW::get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const { - - ERR_FAIL_INDEX_V(p_axis, 3, 0); - switch (p_flag) { - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: { - - return m_linearLimits.enable_limit[p_axis]; - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: { - - return m_angularLimits[p_axis].m_enableLimit; - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_MOTOR: { - - return m_angularLimits[p_axis].m_enableMotor; - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: { - // Not implemented in GodotPhysics backend - } break; - case PhysicsServer::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning - } - - return 0; -} diff --git a/servers/physics/joints/generic_6dof_joint_sw.h b/servers/physics/joints/generic_6dof_joint_sw.h deleted file mode 100644 index 07626ffa97..0000000000 --- a/servers/physics/joints/generic_6dof_joint_sw.h +++ /dev/null @@ -1,401 +0,0 @@ -/*************************************************************************/ -/* generic_6dof_joint_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -#ifndef GENERIC_6DOF_JOINT_SW_H -#define GENERIC_6DOF_JOINT_SW_H - -#include "servers/physics/joints/jacobian_entry_sw.h" -#include "servers/physics/joints_sw.h" - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -2007-09-09 -Generic6DOFJointSW Refactored by Francisco Le?n -email: projectileman@yahoo.com -http://gimpact.sf.net -*/ - -//! Rotation Limit structure for generic joints -class G6DOFRotationalLimitMotorSW { -public: - //! limit_parameters - //!@{ - real_t m_loLimit; //!< joint limit - real_t m_hiLimit; //!< joint limit - real_t m_targetVelocity; //!< target motor velocity - real_t m_maxMotorForce; //!< max force on motor - real_t m_maxLimitForce; //!< max force on limit - real_t m_damping; //!< Damping. - real_t m_limitSoftness; //! Relaxation factor - real_t m_ERP; //!< Error tolerance factor when joint is at limit - real_t m_bounce; //!< restitution factor - bool m_enableMotor; - bool m_enableLimit; - - //!@} - - //! temp_variables - //!@{ - real_t m_currentLimitError; //! How much is violated this limit - int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit - real_t m_accumulatedImpulse; - //!@} - - G6DOFRotationalLimitMotorSW() { - m_accumulatedImpulse = 0.f; - m_targetVelocity = 0; - m_maxMotorForce = 0.1f; - m_maxLimitForce = 300.0f; - m_loLimit = -1e30; - m_hiLimit = 1e30; - m_ERP = 0.5f; - m_bounce = 0.0f; - m_damping = 1.0f; - m_limitSoftness = 0.5f; - m_currentLimit = 0; - m_currentLimitError = 0; - m_enableMotor = false; - m_enableLimit = false; - } - - G6DOFRotationalLimitMotorSW(const G6DOFRotationalLimitMotorSW &limot) { - m_targetVelocity = limot.m_targetVelocity; - m_maxMotorForce = limot.m_maxMotorForce; - m_limitSoftness = limot.m_limitSoftness; - m_loLimit = limot.m_loLimit; - m_hiLimit = limot.m_hiLimit; - m_ERP = limot.m_ERP; - m_bounce = limot.m_bounce; - m_currentLimit = limot.m_currentLimit; - m_currentLimitError = limot.m_currentLimitError; - m_enableMotor = limot.m_enableMotor; - } - - //! Is limited - bool isLimited() { - return (m_loLimit < m_hiLimit); - } - - //! Need apply correction - bool needApplyTorques() { - return (m_enableMotor || m_currentLimit != 0); - } - - //! calculates error - /*! - calculates m_currentLimit and m_currentLimitError. - */ - int testLimitValue(real_t test_value); - - //! apply the correction impulses for two bodies - real_t solveAngularLimits(real_t timeStep, Vector3 &axis, real_t jacDiagABInv, BodySW *body0, BodySW *body1); -}; - -class G6DOFTranslationalLimitMotorSW { -public: - Vector3 m_lowerLimit; //!< the constraint lower limits - Vector3 m_upperLimit; //!< the constraint upper limits - Vector3 m_accumulatedImpulse; - //! Linear_Limit_parameters - //!@{ - Vector3 m_limitSoftness; //!< Softness for linear limit - Vector3 m_damping; //!< Damping for linear limit - Vector3 m_restitution; //! Bounce parameter for linear limit - //!@} - bool enable_limit[3]; - - G6DOFTranslationalLimitMotorSW() { - m_lowerLimit = Vector3(0.f, 0.f, 0.f); - m_upperLimit = Vector3(0.f, 0.f, 0.f); - m_accumulatedImpulse = Vector3(0.f, 0.f, 0.f); - - m_limitSoftness = Vector3(1, 1, 1) * 0.7f; - m_damping = Vector3(1, 1, 1) * real_t(1.0f); - m_restitution = Vector3(1, 1, 1) * real_t(0.5f); - - enable_limit[0] = true; - enable_limit[1] = true; - enable_limit[2] = true; - } - - G6DOFTranslationalLimitMotorSW(const G6DOFTranslationalLimitMotorSW &other) { - m_lowerLimit = other.m_lowerLimit; - m_upperLimit = other.m_upperLimit; - m_accumulatedImpulse = other.m_accumulatedImpulse; - - m_limitSoftness = other.m_limitSoftness; - m_damping = other.m_damping; - m_restitution = other.m_restitution; - } - - //! Test limit - /*! - - free means upper < lower, - - locked means upper == lower - - limited means upper > lower - - limitIndex: first 3 are linear, next 3 are angular - */ - inline bool isLimited(int limitIndex) { - return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); - } - - real_t solveLinearAxis( - real_t timeStep, - real_t jacDiagABInv, - BodySW *body1, const Vector3 &pointInA, - BodySW *body2, const Vector3 &pointInB, - int limit_index, - const Vector3 &axis_normal_on_a, - const Vector3 &anchorPos); -}; - -class Generic6DOFJointSW : public JointSW { -protected: - union { - struct { - BodySW *A; - BodySW *B; - }; - - BodySW *_arr[2]; - }; - - //! relative_frames - //!@{ - Transform m_frameInA; //!< the constraint space w.r.t body A - Transform m_frameInB; //!< the constraint space w.r.t body B - //!@} - - //! Jacobians - //!@{ - JacobianEntrySW m_jacLinear[3]; //!< 3 orthogonal linear constraints - JacobianEntrySW m_jacAng[3]; //!< 3 orthogonal angular constraints - //!@} - - //! Linear_Limit_parameters - //!@{ - G6DOFTranslationalLimitMotorSW m_linearLimits; - //!@} - - //! hinge_parameters - //!@{ - G6DOFRotationalLimitMotorSW m_angularLimits[3]; - //!@} - -protected: - //! temporal variables - //!@{ - real_t m_timeStep; - Transform m_calculatedTransformA; - Transform m_calculatedTransformB; - Vector3 m_calculatedAxisAngleDiff; - Vector3 m_calculatedAxis[3]; - - Vector3 m_AnchorPos; // point between pivots of bodies A and B to solve linear axes - - bool m_useLinearReferenceFrameA; - - //!@} - - Generic6DOFJointSW &operator=(Generic6DOFJointSW &other) { - ERR_PRINT("pito"); - (void)other; - return *this; - } - - void buildLinearJacobian( - JacobianEntrySW &jacLinear, const Vector3 &normalWorld, - const Vector3 &pivotAInW, const Vector3 &pivotBInW); - - void buildAngularJacobian(JacobianEntrySW &jacAngular, const Vector3 &jointAxisW); - - //! calcs the euler angles between the two bodies. - void calculateAngleInfo(); - -public: - Generic6DOFJointSW(BodySW *rbA, BodySW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA); - - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_6DOF; } - - virtual bool setup(real_t p_timestep); - virtual void solve(real_t p_timestep); - - //! Calcs global transform of the offsets - /*! - Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. - \sa Generic6DOFJointSW.getCalculatedTransformA , Generic6DOFJointSW.getCalculatedTransformB, Generic6DOFJointSW.calculateAngleInfo - */ - void calculateTransforms(); - - //! Gets the global transform of the offset for body A - /*! - \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo. - */ - const Transform &getCalculatedTransformA() const { - return m_calculatedTransformA; - } - - //! Gets the global transform of the offset for body B - /*! - \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo. - */ - const Transform &getCalculatedTransformB() const { - return m_calculatedTransformB; - } - - const Transform &getFrameOffsetA() const { - return m_frameInA; - } - - const Transform &getFrameOffsetB() const { - return m_frameInB; - } - - Transform &getFrameOffsetA() { - return m_frameInA; - } - - Transform &getFrameOffsetB() { - return m_frameInB; - } - - //! performs Jacobian calculation, and also calculates angle differences and axis - - void updateRHS(real_t timeStep); - - //! Get the rotation axis in global coordinates - /*! - \pre Generic6DOFJointSW.buildJacobian must be called previously. - */ - Vector3 getAxis(int axis_index) const; - - //! Get the relative Euler angle - /*! - \pre Generic6DOFJointSW.buildJacobian must be called previously. - */ - real_t getAngle(int axis_index) const; - - //! Test angular limit. - /*! - Calculates angular correction and returns true if limit needs to be corrected. - \pre Generic6DOFJointSW.buildJacobian must be called previously. - */ - bool testAngularLimitMotor(int axis_index); - - void setLinearLowerLimit(const Vector3 &linearLower) { - m_linearLimits.m_lowerLimit = linearLower; - } - - void setLinearUpperLimit(const Vector3 &linearUpper) { - m_linearLimits.m_upperLimit = linearUpper; - } - - void setAngularLowerLimit(const Vector3 &angularLower) { - m_angularLimits[0].m_loLimit = angularLower.x; - m_angularLimits[1].m_loLimit = angularLower.y; - m_angularLimits[2].m_loLimit = angularLower.z; - } - - void setAngularUpperLimit(const Vector3 &angularUpper) { - m_angularLimits[0].m_hiLimit = angularUpper.x; - m_angularLimits[1].m_hiLimit = angularUpper.y; - m_angularLimits[2].m_hiLimit = angularUpper.z; - } - - //! Retrieves the angular limit informacion - G6DOFRotationalLimitMotorSW *getRotationalLimitMotor(int index) { - return &m_angularLimits[index]; - } - - //! Retrieves the limit informacion - G6DOFTranslationalLimitMotorSW *getTranslationalLimitMotor() { - return &m_linearLimits; - } - - //first 3 are linear, next 3 are angular - void setLimit(int axis, real_t lo, real_t hi) { - if (axis < 3) { - m_linearLimits.m_lowerLimit[axis] = lo; - m_linearLimits.m_upperLimit[axis] = hi; - } else { - m_angularLimits[axis - 3].m_loLimit = lo; - m_angularLimits[axis - 3].m_hiLimit = hi; - } - } - - //! Test limit - /*! - - free means upper < lower, - - locked means upper == lower - - limited means upper > lower - - limitIndex: first 3 are linear, next 3 are angular - */ - bool isLimited(int limitIndex) { - if (limitIndex < 3) { - return m_linearLimits.isLimited(limitIndex); - } - return m_angularLimits[limitIndex - 3].isLimited(); - } - - const BodySW *getRigidBodyA() const { - return A; - } - const BodySW *getRigidBodyB() const { - return B; - } - - virtual void calcAnchorPos(void); // overridable - - void set_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param, real_t p_value); - real_t get_param(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisParam p_param) const; - - void set_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag, bool p_value); - bool get_flag(Vector3::Axis p_axis, PhysicsServer::G6DOFJointAxisFlag p_flag) const; -}; - -#endif // GENERIC_6DOF_JOINT_SW_H diff --git a/servers/physics/joints/hinge_joint_sw.cpp b/servers/physics/joints/hinge_joint_sw.cpp deleted file mode 100644 index 1ad3e738ba..0000000000 --- a/servers/physics/joints/hinge_joint_sw.cpp +++ /dev/null @@ -1,450 +0,0 @@ -/*************************************************************************/ -/* hinge_joint_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "hinge_joint_sw.h" - -static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { - - if (Math::abs(n.z) > Math_SQRT12) { - // choose p in y-z plane - real_t a = n[1] * n[1] + n[2] * n[2]; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(0, -n[2] * k, n[1] * k); - // set q = n x p - q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); - } else { - // choose p in x-y plane - real_t a = n.x * n.x + n.y * n.y; - real_t k = 1.0 / Math::sqrt(a); - p = Vector3(-n.y * k, n.x * k, 0); - // set q = n x p - q = Vector3(-n.z * p.y, n.z * p.x, a * k); - } -} - -HingeJointSW::HingeJointSW(BodySW *rbA, BodySW *rbB, const Transform &frameA, const Transform &frameB) : - JointSW(_arr, 2) { - - A = rbA; - B = rbB; - - m_rbAFrame = frameA; - m_rbBFrame = frameB; - // flip axis - m_rbBFrame.basis[0][2] *= real_t(-1.); - m_rbBFrame.basis[1][2] *= real_t(-1.); - m_rbBFrame.basis[2][2] *= real_t(-1.); - - //start with free - m_lowerLimit = Math_PI; - m_upperLimit = -Math_PI; - - m_useLimit = false; - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; - - tau = 0.3; - - m_angularOnly = false; - m_enableAngularMotor = false; - - A->add_constraint(this, 0); - B->add_constraint(this, 1); -} - -HingeJointSW::HingeJointSW(BodySW *rbA, BodySW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, - const Vector3 &axisInA, const Vector3 &axisInB) : - JointSW(_arr, 2) { - - A = rbA; - B = rbB; - - m_rbAFrame.origin = pivotInA; - - // since no frame is given, assume this to be zero angle and just pick rb transform axis - Vector3 rbAxisA1 = rbA->get_transform().basis.get_axis(0); - - Vector3 rbAxisA2; - real_t projection = axisInA.dot(rbAxisA1); - if (projection >= 1.0f - CMP_EPSILON) { - rbAxisA1 = -rbA->get_transform().basis.get_axis(2); - rbAxisA2 = rbA->get_transform().basis.get_axis(1); - } else if (projection <= -1.0f + CMP_EPSILON) { - rbAxisA1 = rbA->get_transform().basis.get_axis(2); - rbAxisA2 = rbA->get_transform().basis.get_axis(1); - } else { - rbAxisA2 = axisInA.cross(rbAxisA1); - rbAxisA1 = rbAxisA2.cross(axisInA); - } - - m_rbAFrame.basis = Basis(rbAxisA1.x, rbAxisA2.x, axisInA.x, - rbAxisA1.y, rbAxisA2.y, axisInA.y, - rbAxisA1.z, rbAxisA2.z, axisInA.z); - - Quat rotationArc = Quat(axisInA, axisInB); - Vector3 rbAxisB1 = rotationArc.xform(rbAxisA1); - Vector3 rbAxisB2 = axisInB.cross(rbAxisB1); - - m_rbBFrame.origin = pivotInB; - m_rbBFrame.basis = Basis(rbAxisB1.x, rbAxisB2.x, -axisInB.x, - rbAxisB1.y, rbAxisB2.y, -axisInB.y, - rbAxisB1.z, rbAxisB2.z, -axisInB.z); - - //start with free - m_lowerLimit = Math_PI; - m_upperLimit = -Math_PI; - - m_useLimit = false; - m_biasFactor = 0.3f; - m_relaxationFactor = 1.0f; - m_limitSoftness = 0.9f; - m_solveLimit = false; - - tau = 0.3; - - m_angularOnly = false; - m_enableAngularMotor = false; - - A->add_constraint(this, 0); - B->add_constraint(this, 1); -} - -bool HingeJointSW::setup(real_t p_step) { - - m_appliedImpulse = real_t(0.); - - if (!m_angularOnly) { - Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); - Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); - Vector3 relPos = pivotBInW - pivotAInW; - - Vector3 normal[3]; - if (Math::is_zero_approx(relPos.length_squared())) { - normal[0] = Vector3(real_t(1.0), 0, 0); - } else { - normal[0] = relPos.normalized(); - } - - plane_space(normal[0], normal[1], normal[2]); - - for (int i = 0; i < 3; i++) { - memnew_placement(&m_jac[i], JacobianEntrySW( - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - pivotAInW - A->get_transform().origin - A->get_center_of_mass(), - pivotBInW - B->get_transform().origin - B->get_center_of_mass(), - normal[i], - A->get_inv_inertia(), - A->get_inv_mass(), - B->get_inv_inertia(), - B->get_inv_mass())); - } - } - - //calculate two perpendicular jointAxis, orthogonal to hingeAxis - //these two jointAxis require equal angular velocities for both bodies - - //this is unused for now, it's a todo - Vector3 jointAxis0local; - Vector3 jointAxis1local; - - plane_space(m_rbAFrame.basis.get_axis(2), jointAxis0local, jointAxis1local); - - Vector3 jointAxis0 = A->get_transform().basis.xform(jointAxis0local); - Vector3 jointAxis1 = A->get_transform().basis.xform(jointAxis1local); - Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); - - memnew_placement(&m_jacAng[0], JacobianEntrySW(jointAxis0, - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - A->get_inv_inertia(), - B->get_inv_inertia())); - - memnew_placement(&m_jacAng[1], JacobianEntrySW(jointAxis1, - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - A->get_inv_inertia(), - B->get_inv_inertia())); - - memnew_placement(&m_jacAng[2], JacobianEntrySW(hingeAxisWorld, - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - A->get_inv_inertia(), - B->get_inv_inertia())); - - // Compute limit information - real_t hingeAngle = get_hinge_angle(); - - //set bias, sign, clear accumulator - m_correction = real_t(0.); - m_limitSign = real_t(0.); - m_solveLimit = false; - m_accLimitImpulse = real_t(0.); - - //if (m_lowerLimit < m_upperLimit) - if (m_useLimit && m_lowerLimit <= m_upperLimit) { - //if (hingeAngle <= m_lowerLimit*m_limitSoftness) - if (hingeAngle <= m_lowerLimit) { - m_correction = (m_lowerLimit - hingeAngle); - m_limitSign = 1.0f; - m_solveLimit = true; - } - //else if (hingeAngle >= m_upperLimit*m_limitSoftness) - else if (hingeAngle >= m_upperLimit) { - m_correction = m_upperLimit - hingeAngle; - m_limitSign = -1.0f; - m_solveLimit = true; - } - } - - //Compute K = J*W*J' for hinge axis - Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); - m_kHinge = 1.0f / (A->compute_angular_impulse_denominator(axisA) + - B->compute_angular_impulse_denominator(axisA)); - - return true; -} - -void HingeJointSW::solve(real_t p_step) { - - Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); - Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); - - //real_t tau = real_t(0.3); - - //linear part - if (!m_angularOnly) { - Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; - Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; - - Vector3 vel1 = A->get_velocity_in_local_point(rel_pos1); - Vector3 vel2 = B->get_velocity_in_local_point(rel_pos2); - Vector3 vel = vel1 - vel2; - - for (int i = 0; i < 3; i++) { - const Vector3 &normal = m_jac[i].m_linearJointAxis; - real_t jacDiagABInv = real_t(1.) / m_jac[i].getDiagonal(); - - real_t rel_vel; - rel_vel = normal.dot(vel); - //positional error (zeroth order error) - real_t depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - real_t impulse = depth * tau / p_step * jacDiagABInv - rel_vel * jacDiagABInv; - m_appliedImpulse += impulse; - Vector3 impulse_vector = normal * impulse; - A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); - B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); - } - } - - { - ///solve angular part - - // get axes in world space - Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); - Vector3 axisB = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(2)); - - const Vector3 &angVelA = A->get_angular_velocity(); - const Vector3 &angVelB = B->get_angular_velocity(); - - Vector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); - Vector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); - - Vector3 angAorthog = angVelA - angVelAroundHingeAxisA; - Vector3 angBorthog = angVelB - angVelAroundHingeAxisB; - Vector3 velrelOrthog = angAorthog - angBorthog; - { - //solve orthogonal angular velocity correction - real_t relaxation = real_t(1.); - real_t len = velrelOrthog.length(); - if (len > real_t(0.00001)) { - Vector3 normal = velrelOrthog.normalized(); - real_t denom = A->compute_angular_impulse_denominator(normal) + - B->compute_angular_impulse_denominator(normal); - // scale for mass and relaxation - velrelOrthog *= (real_t(1.) / denom) * m_relaxationFactor; - } - - //solve angular positional correction - Vector3 angularError = -axisA.cross(axisB) * (real_t(1.) / p_step); - real_t len2 = angularError.length(); - if (len2 > real_t(0.00001)) { - Vector3 normal2 = angularError.normalized(); - real_t denom2 = A->compute_angular_impulse_denominator(normal2) + - B->compute_angular_impulse_denominator(normal2); - angularError *= (real_t(1.) / denom2) * relaxation; - } - - A->apply_torque_impulse(-velrelOrthog + angularError); - B->apply_torque_impulse(velrelOrthog - angularError); - - // solve limit - if (m_solveLimit) { - real_t amplitude = ((angVelB - angVelA).dot(axisA) * m_relaxationFactor + m_correction * (real_t(1.) / p_step) * m_biasFactor) * m_limitSign; - - real_t impulseMag = amplitude * m_kHinge; - - // Clamp the accumulated impulse - real_t temp = m_accLimitImpulse; - m_accLimitImpulse = MAX(m_accLimitImpulse + impulseMag, real_t(0)); - impulseMag = m_accLimitImpulse - temp; - - Vector3 impulse = axisA * impulseMag * m_limitSign; - A->apply_torque_impulse(impulse); - B->apply_torque_impulse(-impulse); - } - } - - //apply motor - if (m_enableAngularMotor) { - //todo: add limits too - Vector3 angularLimit(0, 0, 0); - - Vector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; - real_t projRelVel = velrel.dot(axisA); - - real_t desiredMotorVel = m_motorTargetVelocity; - real_t motor_relvel = desiredMotorVel - projRelVel; - - real_t unclippedMotorImpulse = m_kHinge * motor_relvel; - //todo: should clip against accumulated impulse - real_t clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; - clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; - Vector3 motorImp = clippedMotorImpulse * axisA; - - A->apply_torque_impulse(motorImp + angularLimit); - B->apply_torque_impulse(-motorImp - angularLimit); - } - } -} -/* -void HingeJointSW::updateRHS(real_t timeStep) -{ - (void)timeStep; - -} -*/ - -static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { - real_t coeff_1 = Math_PI / 4.0f; - real_t coeff_2 = 3.0f * coeff_1; - real_t abs_y = Math::abs(y); - real_t angle; - if (x >= 0.0f) { - real_t r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - real_t r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - -real_t HingeJointSW::get_hinge_angle() { - const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(0)); - const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(1)); - const Vector3 swingAxis = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(1)); - - return atan2fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); -} - -void HingeJointSW::set_param(PhysicsServer::HingeJointParam p_param, real_t p_value) { - - switch (p_param) { - - case PhysicsServer::HINGE_JOINT_BIAS: tau = p_value; break; - case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: m_upperLimit = p_value; break; - case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: m_lowerLimit = p_value; break; - case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: m_biasFactor = p_value; break; - case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: m_limitSoftness = p_value; break; - case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: m_relaxationFactor = p_value; break; - case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: m_motorTargetVelocity = p_value; break; - case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: m_maxMotorImpulse = p_value; break; - case PhysicsServer::HINGE_JOINT_MAX: break; // Can't happen, but silences warning - } -} - -real_t HingeJointSW::get_param(PhysicsServer::HingeJointParam p_param) const { - - switch (p_param) { - - case PhysicsServer::HINGE_JOINT_BIAS: return tau; - case PhysicsServer::HINGE_JOINT_LIMIT_UPPER: return m_upperLimit; - case PhysicsServer::HINGE_JOINT_LIMIT_LOWER: return m_lowerLimit; - case PhysicsServer::HINGE_JOINT_LIMIT_BIAS: return m_biasFactor; - case PhysicsServer::HINGE_JOINT_LIMIT_SOFTNESS: return m_limitSoftness; - case PhysicsServer::HINGE_JOINT_LIMIT_RELAXATION: return m_relaxationFactor; - case PhysicsServer::HINGE_JOINT_MOTOR_TARGET_VELOCITY: return m_motorTargetVelocity; - case PhysicsServer::HINGE_JOINT_MOTOR_MAX_IMPULSE: return m_maxMotorImpulse; - case PhysicsServer::HINGE_JOINT_MAX: break; // Can't happen, but silences warning - } - - return 0; -} - -void HingeJointSW::set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value) { - - switch (p_flag) { - case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: m_useLimit = p_value; break; - case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: m_enableAngularMotor = p_value; break; - case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning - } -} -bool HingeJointSW::get_flag(PhysicsServer::HingeJointFlag p_flag) const { - - switch (p_flag) { - case PhysicsServer::HINGE_JOINT_FLAG_USE_LIMIT: return m_useLimit; - case PhysicsServer::HINGE_JOINT_FLAG_ENABLE_MOTOR: return m_enableAngularMotor; - case PhysicsServer::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning - } - - return false; -} diff --git a/servers/physics/joints/hinge_joint_sw.h b/servers/physics/joints/hinge_joint_sw.h deleted file mode 100644 index 1c160cfc09..0000000000 --- a/servers/physics/joints/hinge_joint_sw.h +++ /dev/null @@ -1,117 +0,0 @@ -/*************************************************************************/ -/* hinge_joint_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -#ifndef HINGE_JOINT_SW_H -#define HINGE_JOINT_SW_H - -#include "servers/physics/joints/jacobian_entry_sw.h" -#include "servers/physics/joints_sw.h" - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -class HingeJointSW : public JointSW { - - union { - struct { - BodySW *A; - BodySW *B; - }; - - BodySW *_arr[2]; - }; - - JacobianEntrySW m_jac[3]; //3 orthogonal linear constraints - JacobianEntrySW m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor - - Transform m_rbAFrame; // constraint axii. Assumes z is hinge axis. - Transform m_rbBFrame; - - real_t m_motorTargetVelocity; - real_t m_maxMotorImpulse; - - real_t m_limitSoftness; - real_t m_biasFactor; - real_t m_relaxationFactor; - - real_t m_lowerLimit; - real_t m_upperLimit; - - real_t m_kHinge; - - real_t m_limitSign; - real_t m_correction; - - real_t m_accLimitImpulse; - - real_t tau; - - bool m_useLimit; - bool m_angularOnly; - bool m_enableAngularMotor; - bool m_solveLimit; - - real_t m_appliedImpulse; - -public: - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_HINGE; } - - virtual bool setup(real_t p_step); - virtual void solve(real_t p_step); - - real_t get_hinge_angle(); - - void set_param(PhysicsServer::HingeJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::HingeJointParam p_param) const; - - void set_flag(PhysicsServer::HingeJointFlag p_flag, bool p_value); - bool get_flag(PhysicsServer::HingeJointFlag p_flag) const; - - HingeJointSW(BodySW *rbA, BodySW *rbB, const Transform &frameA, const Transform &frameB); - HingeJointSW(BodySW *rbA, BodySW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB); -}; - -#endif // HINGE_JOINT_SW_H diff --git a/servers/physics/joints/jacobian_entry_sw.h b/servers/physics/joints/jacobian_entry_sw.h deleted file mode 100644 index a17175e6de..0000000000 --- a/servers/physics/joints/jacobian_entry_sw.h +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************************/ -/* jacobian_entry_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -#ifndef JACOBIAN_ENTRY_SW_H -#define JACOBIAN_ENTRY_SW_H - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "core/math/transform.h" - -class JacobianEntrySW { -public: - JacobianEntrySW(){}; - //constraint between two different rigidbodies - JacobianEntrySW( - const Basis &world2A, - const Basis &world2B, - const Vector3 &rel_pos1, const Vector3 &rel_pos2, - const Vector3 &jointAxis, - const Vector3 &inertiaInvA, - const real_t massInvA, - const Vector3 &inertiaInvB, - const real_t massInvB) : - m_linearJointAxis(jointAxis) { - m_aJ = world2A.xform(rel_pos1.cross(m_linearJointAxis)); - m_bJ = world2B.xform(rel_pos2.cross(-m_linearJointAxis)); - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); - - ERR_FAIL_COND(m_Adiag <= real_t(0.0)); - } - - //angular constraint between two different rigidbodies - JacobianEntrySW(const Vector3 &jointAxis, - const Basis &world2A, - const Basis &world2B, - const Vector3 &inertiaInvA, - const Vector3 &inertiaInvB) : - m_linearJointAxis(Vector3(real_t(0.), real_t(0.), real_t(0.))) { - m_aJ = world2A.xform(jointAxis); - m_bJ = world2B.xform(-jointAxis); - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); - - ERR_FAIL_COND(m_Adiag <= real_t(0.0)); - } - - //angular constraint between two different rigidbodies - JacobianEntrySW(const Vector3 &axisInA, - const Vector3 &axisInB, - const Vector3 &inertiaInvA, - const Vector3 &inertiaInvB) : - m_linearJointAxis(Vector3(real_t(0.), real_t(0.), real_t(0.))), - m_aJ(axisInA), - m_bJ(-axisInB) { - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = inertiaInvB * m_bJ; - m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); - - ERR_FAIL_COND(m_Adiag <= real_t(0.0)); - } - - //constraint on one rigidbody - JacobianEntrySW( - const Basis &world2A, - const Vector3 &rel_pos1, const Vector3 &rel_pos2, - const Vector3 &jointAxis, - const Vector3 &inertiaInvA, - const real_t massInvA) : - m_linearJointAxis(jointAxis) { - m_aJ = world2A.xform(rel_pos1.cross(jointAxis)); - m_bJ = world2A.xform(rel_pos2.cross(-jointAxis)); - m_0MinvJt = inertiaInvA * m_aJ; - m_1MinvJt = Vector3(real_t(0.), real_t(0.), real_t(0.)); - m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); - - ERR_FAIL_COND(m_Adiag <= real_t(0.0)); - } - - real_t getDiagonal() const { return m_Adiag; } - - // for two constraints on the same rigidbody (for example vehicle friction) - real_t getNonDiagonal(const JacobianEntrySW &jacB, const real_t massInvA) const { - const JacobianEntrySW &jacA = *this; - real_t lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); - real_t ang = jacA.m_0MinvJt.dot(jacB.m_aJ); - return lin + ang; - } - - // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) - real_t getNonDiagonal(const JacobianEntrySW &jacB, const real_t massInvA, const real_t massInvB) const { - const JacobianEntrySW &jacA = *this; - Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; - Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; - Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; - Vector3 lin0 = massInvA * lin; - Vector3 lin1 = massInvB * lin; - Vector3 sum = ang0 + ang1 + lin0 + lin1; - return sum[0] + sum[1] + sum[2]; - } - - real_t getRelativeVelocity(const Vector3 &linvelA, const Vector3 &angvelA, const Vector3 &linvelB, const Vector3 &angvelB) { - Vector3 linrel = linvelA - linvelB; - Vector3 angvela = angvelA * m_aJ; - Vector3 angvelb = angvelB * m_bJ; - linrel *= m_linearJointAxis; - angvela += angvelb; - angvela += linrel; - real_t rel_vel2 = angvela[0] + angvela[1] + angvela[2]; - return rel_vel2 + CMP_EPSILON; - } - //private: - - Vector3 m_linearJointAxis; - Vector3 m_aJ; - Vector3 m_bJ; - Vector3 m_0MinvJt; - Vector3 m_1MinvJt; - //Optimization: can be stored in the w/last component of one of the vectors - real_t m_Adiag; -}; - -#endif // JACOBIAN_ENTRY_SW_H diff --git a/servers/physics/joints/pin_joint_sw.cpp b/servers/physics/joints/pin_joint_sw.cpp deleted file mode 100644 index fe994aa172..0000000000 --- a/servers/physics/joints/pin_joint_sw.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/*************************************************************************/ -/* pin_joint_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -#include "pin_joint_sw.h" - -bool PinJointSW::setup(real_t p_step) { - - m_appliedImpulse = real_t(0.); - - Vector3 normal(0, 0, 0); - - for (int i = 0; i < 3; i++) { - normal[i] = 1; - memnew_placement(&m_jac[i], JacobianEntrySW( - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(), - B->get_transform().xform(m_pivotInB) - B->get_transform().origin - B->get_center_of_mass(), - normal, - A->get_inv_inertia(), - A->get_inv_mass(), - B->get_inv_inertia(), - B->get_inv_mass())); - normal[i] = 0; - } - - return true; -} - -void PinJointSW::solve(real_t p_step) { - - Vector3 pivotAInW = A->get_transform().xform(m_pivotInA); - Vector3 pivotBInW = B->get_transform().xform(m_pivotInB); - - Vector3 normal(0, 0, 0); - - //Vector3 angvelA = A->get_transform().origin.getBasis().transpose() * A->getAngularVelocity(); - //Vector3 angvelB = B->get_transform().origin.getBasis().transpose() * B->getAngularVelocity(); - - for (int i = 0; i < 3; i++) { - normal[i] = 1; - real_t jacDiagABInv = real_t(1.) / m_jac[i].getDiagonal(); - - Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; - Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; - //this jacobian entry could be re-used for all iterations - - Vector3 vel1 = A->get_velocity_in_local_point(rel_pos1); - Vector3 vel2 = B->get_velocity_in_local_point(rel_pos2); - Vector3 vel = vel1 - vel2; - - real_t rel_vel; - rel_vel = normal.dot(vel); - - /* - //velocity error (first order error) - real_t rel_vel = m_jac[i].getRelativeVelocity(A->getLinearVelocity(),angvelA, - B->getLinearVelocity(),angvelB); - */ - - //positional error (zeroth order error) - real_t depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal - - real_t impulse = depth * m_tau / p_step * jacDiagABInv - m_damping * rel_vel * jacDiagABInv; - - real_t impulseClamp = m_impulseClamp; - if (impulseClamp > 0) { - if (impulse < -impulseClamp) - impulse = -impulseClamp; - if (impulse > impulseClamp) - impulse = impulseClamp; - } - - m_appliedImpulse += impulse; - Vector3 impulse_vector = normal * impulse; - A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); - B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); - - normal[i] = 0; - } -} - -void PinJointSW::set_param(PhysicsServer::PinJointParam p_param, real_t p_value) { - - switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: m_tau = p_value; break; - case PhysicsServer::PIN_JOINT_DAMPING: m_damping = p_value; break; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: m_impulseClamp = p_value; break; - } -} - -real_t PinJointSW::get_param(PhysicsServer::PinJointParam p_param) const { - - switch (p_param) { - case PhysicsServer::PIN_JOINT_BIAS: return m_tau; - case PhysicsServer::PIN_JOINT_DAMPING: return m_damping; - case PhysicsServer::PIN_JOINT_IMPULSE_CLAMP: return m_impulseClamp; - } - - return 0; -} - -PinJointSW::PinJointSW(BodySW *p_body_a, const Vector3 &p_pos_a, BodySW *p_body_b, const Vector3 &p_pos_b) : - JointSW(_arr, 2) { - - A = p_body_a; - B = p_body_b; - m_pivotInA = p_pos_a; - m_pivotInB = p_pos_b; - - m_tau = 0.3; - m_damping = 1; - m_impulseClamp = 0; - m_appliedImpulse = 0; - - A->add_constraint(this, 0); - B->add_constraint(this, 1); -} - -PinJointSW::~PinJointSW() { -} diff --git a/servers/physics/joints/pin_joint_sw.h b/servers/physics/joints/pin_joint_sw.h deleted file mode 100644 index 42884e4940..0000000000 --- a/servers/physics/joints/pin_joint_sw.h +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************/ -/* pin_joint_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -#ifndef PIN_JOINT_SW_H -#define PIN_JOINT_SW_H - -#include "servers/physics/joints/jacobian_entry_sw.h" -#include "servers/physics/joints_sw.h" - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -class PinJointSW : public JointSW { - - union { - struct { - BodySW *A; - BodySW *B; - }; - - BodySW *_arr[2]; - }; - - real_t m_tau; //bias - real_t m_damping; - real_t m_impulseClamp; - real_t m_appliedImpulse; - - JacobianEntrySW m_jac[3]; //3 orthogonal linear constraints - - Vector3 m_pivotInA; - Vector3 m_pivotInB; - -public: - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_PIN; } - - virtual bool setup(real_t p_step); - virtual void solve(real_t p_step); - - void set_param(PhysicsServer::PinJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::PinJointParam p_param) const; - - void set_pos_a(const Vector3 &p_pos) { m_pivotInA = p_pos; } - void set_pos_b(const Vector3 &p_pos) { m_pivotInB = p_pos; } - - Vector3 get_position_a() { return m_pivotInA; } - Vector3 get_position_b() { return m_pivotInB; } - - PinJointSW(BodySW *p_body_a, const Vector3 &p_pos_a, BodySW *p_body_b, const Vector3 &p_pos_b); - ~PinJointSW(); -}; - -#endif // PIN_JOINT_SW_H diff --git a/servers/physics/joints/slider_joint_sw.cpp b/servers/physics/joints/slider_joint_sw.cpp deleted file mode 100644 index 9963c7ae89..0000000000 --- a/servers/physics/joints/slider_joint_sw.cpp +++ /dev/null @@ -1,443 +0,0 @@ -/*************************************************************************/ -/* slider_joint_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -Added by Roman Ponomarev (rponom@gmail.com) -April 04, 2008 - -*/ - -#include "slider_joint_sw.h" - -//----------------------------------------------------------------------------- - -static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { - real_t coeff_1 = Math_PI / 4.0f; - real_t coeff_2 = 3.0f * coeff_1; - real_t abs_y = Math::abs(y); - real_t angle; - if (x >= 0.0f) { - real_t r = (x - abs_y) / (x + abs_y); - angle = coeff_1 - coeff_1 * r; - } else { - real_t r = (x + abs_y) / (abs_y - x); - angle = coeff_2 - coeff_1 * r; - } - return (y < 0.0f) ? -angle : angle; -} - -void SliderJointSW::initParams() { - m_lowerLinLimit = real_t(1.0); - m_upperLinLimit = real_t(-1.0); - m_lowerAngLimit = real_t(0.); - m_upperAngLimit = real_t(0.); - m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingDirLin = real_t(0.); - m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingDirAng = real_t(0.); - m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; - m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; - m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; - m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; - m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; - m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; - - m_poweredLinMotor = false; - m_targetLinMotorVelocity = real_t(0.); - m_maxLinMotorForce = real_t(0.); - m_accumulatedLinMotorImpulse = real_t(0.0); - - m_poweredAngMotor = false; - m_targetAngMotorVelocity = real_t(0.); - m_maxAngMotorForce = real_t(0.); - m_accumulatedAngMotorImpulse = real_t(0.0); - -} // SliderJointSW::initParams() - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- - -SliderJointSW::SliderJointSW(BodySW *rbA, BodySW *rbB, const Transform &frameInA, const Transform &frameInB) : - JointSW(_arr, 2), - m_frameInA(frameInA), - m_frameInB(frameInB) { - - A = rbA; - B = rbB; - - A->add_constraint(this, 0); - B->add_constraint(this, 1); - - initParams(); -} // SliderJointSW::SliderJointSW() - -//----------------------------------------------------------------------------- - -bool SliderJointSW::setup(real_t p_step) { - - //calculate transforms - m_calculatedTransformA = A->get_transform() * m_frameInA; - m_calculatedTransformB = B->get_transform() * m_frameInB; - m_realPivotAInW = m_calculatedTransformA.origin; - m_realPivotBInW = m_calculatedTransformB.origin; - m_sliderAxis = m_calculatedTransformA.basis.get_axis(0); // along X - m_delta = m_realPivotBInW - m_realPivotAInW; - m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; - m_relPosA = m_projPivotInW - A->get_transform().origin; - m_relPosB = m_realPivotBInW - B->get_transform().origin; - Vector3 normalWorld; - int i; - //linear part - for (i = 0; i < 3; i++) { - normalWorld = m_calculatedTransformA.basis.get_axis(i); - memnew_placement(&m_jacLin[i], JacobianEntrySW( - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - m_relPosA - A->get_center_of_mass(), - m_relPosB - B->get_center_of_mass(), - normalWorld, - A->get_inv_inertia(), - A->get_inv_mass(), - B->get_inv_inertia(), - B->get_inv_mass())); - m_jacLinDiagABInv[i] = real_t(1.) / m_jacLin[i].getDiagonal(); - m_depth[i] = m_delta.dot(normalWorld); - } - testLinLimits(); - // angular part - for (i = 0; i < 3; i++) { - normalWorld = m_calculatedTransformA.basis.get_axis(i); - memnew_placement(&m_jacAng[i], JacobianEntrySW( - normalWorld, - A->get_principal_inertia_axes().transposed(), - B->get_principal_inertia_axes().transposed(), - A->get_inv_inertia(), - B->get_inv_inertia())); - } - testAngLimits(); - Vector3 axisA = m_calculatedTransformA.basis.get_axis(0); - m_kAngle = real_t(1.0) / (A->compute_angular_impulse_denominator(axisA) + B->compute_angular_impulse_denominator(axisA)); - // clear accumulator for motors - m_accumulatedLinMotorImpulse = real_t(0.0); - m_accumulatedAngMotorImpulse = real_t(0.0); - - return true; -} // SliderJointSW::buildJacobianInt() - -//----------------------------------------------------------------------------- - -void SliderJointSW::solve(real_t p_step) { - - int i; - // linear - Vector3 velA = A->get_velocity_in_local_point(m_relPosA); - Vector3 velB = B->get_velocity_in_local_point(m_relPosB); - Vector3 vel = velA - velB; - for (i = 0; i < 3; i++) { - const Vector3 &normal = m_jacLin[i].m_linearJointAxis; - real_t rel_vel = normal.dot(vel); - // calculate positional error - real_t depth = m_depth[i]; - // get parameters - real_t softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin); - real_t restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin); - real_t damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin); - // calcutate and apply impulse - real_t normalImpulse = softness * (restitution * depth / p_step - damping * rel_vel) * m_jacLinDiagABInv[i]; - Vector3 impulse_vector = normal * normalImpulse; - A->apply_impulse(m_relPosA, impulse_vector); - B->apply_impulse(m_relPosB, -impulse_vector); - if (m_poweredLinMotor && (!i)) { // apply linear motor - if (m_accumulatedLinMotorImpulse < m_maxLinMotorForce) { - real_t desiredMotorVel = m_targetLinMotorVelocity; - real_t motor_relvel = desiredMotorVel + rel_vel; - normalImpulse = -motor_relvel * m_jacLinDiagABInv[i]; - // clamp accumulated impulse - real_t new_acc = m_accumulatedLinMotorImpulse + Math::abs(normalImpulse); - if (new_acc > m_maxLinMotorForce) { - new_acc = m_maxLinMotorForce; - } - real_t del = new_acc - m_accumulatedLinMotorImpulse; - if (normalImpulse < real_t(0.0)) { - normalImpulse = -del; - } else { - normalImpulse = del; - } - m_accumulatedLinMotorImpulse = new_acc; - // apply clamped impulse - impulse_vector = normal * normalImpulse; - A->apply_impulse(m_relPosA, impulse_vector); - B->apply_impulse(m_relPosB, -impulse_vector); - } - } - } - // angular - // get axes in world space - Vector3 axisA = m_calculatedTransformA.basis.get_axis(0); - Vector3 axisB = m_calculatedTransformB.basis.get_axis(0); - - const Vector3 &angVelA = A->get_angular_velocity(); - const Vector3 &angVelB = B->get_angular_velocity(); - - Vector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); - Vector3 angVelAroundAxisB = axisB * axisB.dot(angVelB); - - Vector3 angAorthog = angVelA - angVelAroundAxisA; - Vector3 angBorthog = angVelB - angVelAroundAxisB; - Vector3 velrelOrthog = angAorthog - angBorthog; - //solve orthogonal angular velocity correction - real_t len = velrelOrthog.length(); - if (len > real_t(0.00001)) { - Vector3 normal = velrelOrthog.normalized(); - real_t denom = A->compute_angular_impulse_denominator(normal) + B->compute_angular_impulse_denominator(normal); - velrelOrthog *= (real_t(1.) / denom) * m_dampingOrthoAng * m_softnessOrthoAng; - } - //solve angular positional correction - Vector3 angularError = axisA.cross(axisB) * (real_t(1.) / p_step); - real_t len2 = angularError.length(); - if (len2 > real_t(0.00001)) { - Vector3 normal2 = angularError.normalized(); - real_t denom2 = A->compute_angular_impulse_denominator(normal2) + B->compute_angular_impulse_denominator(normal2); - angularError *= (real_t(1.) / denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; - } - // apply impulse - A->apply_torque_impulse(-velrelOrthog + angularError); - B->apply_torque_impulse(velrelOrthog - angularError); - real_t impulseMag; - //solve angular limits - if (m_solveAngLim) { - impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / p_step; - impulseMag *= m_kAngle * m_softnessLimAng; - } else { - impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / p_step; - impulseMag *= m_kAngle * m_softnessDirAng; - } - Vector3 impulse = axisA * impulseMag; - A->apply_torque_impulse(impulse); - B->apply_torque_impulse(-impulse); - //apply angular motor - if (m_poweredAngMotor) { - if (m_accumulatedAngMotorImpulse < m_maxAngMotorForce) { - Vector3 velrel = angVelAroundAxisA - angVelAroundAxisB; - real_t projRelVel = velrel.dot(axisA); - - real_t desiredMotorVel = m_targetAngMotorVelocity; - real_t motor_relvel = desiredMotorVel - projRelVel; - - real_t angImpulse = m_kAngle * motor_relvel; - // clamp accumulated impulse - real_t new_acc = m_accumulatedAngMotorImpulse + Math::abs(angImpulse); - if (new_acc > m_maxAngMotorForce) { - new_acc = m_maxAngMotorForce; - } - real_t del = new_acc - m_accumulatedAngMotorImpulse; - if (angImpulse < real_t(0.0)) { - angImpulse = -del; - } else { - angImpulse = del; - } - m_accumulatedAngMotorImpulse = new_acc; - // apply clamped impulse - Vector3 motorImp = angImpulse * axisA; - A->apply_torque_impulse(motorImp); - B->apply_torque_impulse(-motorImp); - } - } -} // SliderJointSW::solveConstraint() - -//----------------------------------------------------------------------------- - -//----------------------------------------------------------------------------- - -void SliderJointSW::calculateTransforms(void) { - m_calculatedTransformA = A->get_transform() * m_frameInA; - m_calculatedTransformB = B->get_transform() * m_frameInB; - m_realPivotAInW = m_calculatedTransformA.origin; - m_realPivotBInW = m_calculatedTransformB.origin; - m_sliderAxis = m_calculatedTransformA.basis.get_axis(0); // along X - m_delta = m_realPivotBInW - m_realPivotAInW; - m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; - Vector3 normalWorld; - int i; - //linear part - for (i = 0; i < 3; i++) { - normalWorld = m_calculatedTransformA.basis.get_axis(i); - m_depth[i] = m_delta.dot(normalWorld); - } -} // SliderJointSW::calculateTransforms() - -//----------------------------------------------------------------------------- - -void SliderJointSW::testLinLimits(void) { - m_solveLinLim = false; - m_linPos = m_depth[0]; - if (m_lowerLinLimit <= m_upperLinLimit) { - if (m_depth[0] > m_upperLinLimit) { - m_depth[0] -= m_upperLinLimit; - m_solveLinLim = true; - } else if (m_depth[0] < m_lowerLinLimit) { - m_depth[0] -= m_lowerLinLimit; - m_solveLinLim = true; - } else { - m_depth[0] = real_t(0.); - } - } else { - m_depth[0] = real_t(0.); - } -} // SliderJointSW::testLinLimits() - -//----------------------------------------------------------------------------- - -void SliderJointSW::testAngLimits(void) { - m_angDepth = real_t(0.); - m_solveAngLim = false; - if (m_lowerAngLimit <= m_upperAngLimit) { - const Vector3 axisA0 = m_calculatedTransformA.basis.get_axis(1); - const Vector3 axisA1 = m_calculatedTransformA.basis.get_axis(2); - const Vector3 axisB0 = m_calculatedTransformB.basis.get_axis(1); - real_t rot = atan2fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); - if (rot < m_lowerAngLimit) { - m_angDepth = rot - m_lowerAngLimit; - m_solveAngLim = true; - } else if (rot > m_upperAngLimit) { - m_angDepth = rot - m_upperAngLimit; - m_solveAngLim = true; - } - } -} // SliderJointSW::testAngLimits() - -//----------------------------------------------------------------------------- - -Vector3 SliderJointSW::getAncorInA(void) { - Vector3 ancorInA; - ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * real_t(0.5) * m_sliderAxis; - ancorInA = A->get_transform().inverse().xform(ancorInA); - return ancorInA; -} // SliderJointSW::getAncorInA() - -//----------------------------------------------------------------------------- - -Vector3 SliderJointSW::getAncorInB(void) { - Vector3 ancorInB; - ancorInB = m_frameInB.origin; - return ancorInB; -} // SliderJointSW::getAncorInB(); - -void SliderJointSW::set_param(PhysicsServer::SliderJointParam p_param, real_t p_value) { - - switch (p_param) { - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: m_upperLinLimit = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: m_lowerLinLimit = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: m_softnessLimLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: m_restitutionLimLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: m_dampingLimLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: m_softnessDirLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: m_restitutionDirLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: m_dampingDirLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: m_softnessOrthoLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: m_restitutionOrthoLin = p_value; break; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: m_dampingOrthoLin = p_value; break; - - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: m_upperAngLimit = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: m_lowerAngLimit = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: m_softnessLimAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: m_restitutionLimAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: m_dampingLimAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: m_softnessDirAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: m_restitutionDirAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: m_dampingDirAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: m_softnessOrthoAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: m_restitutionOrthoAng = p_value; break; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: m_dampingOrthoAng = p_value; break; - - case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning - } -} - -real_t SliderJointSW::get_param(PhysicsServer::SliderJointParam p_param) const { - - switch (p_param) { - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return m_upperLinLimit; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_LOWER: return m_lowerLinLimit; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: return m_softnessLimLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: return m_restitutionLimLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: return m_dampingLimLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: return m_softnessDirLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: return m_restitutionDirLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_MOTION_DAMPING: return m_dampingDirLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: return m_softnessOrthoLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: return m_restitutionOrthoLin; - case PhysicsServer::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: return m_dampingOrthoLin; - - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: return m_upperAngLimit; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: return m_lowerAngLimit; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: return m_softnessLimAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: return m_restitutionLimAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: return m_dampingLimAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: return m_softnessDirAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: return m_restitutionDirAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: return m_dampingDirAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return m_softnessOrthoAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return m_restitutionOrthoAng; - case PhysicsServer::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return m_dampingOrthoAng; - - case PhysicsServer::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning - } - - return 0; -} diff --git a/servers/physics/joints/slider_joint_sw.h b/servers/physics/joints/slider_joint_sw.h deleted file mode 100644 index 8b416eafc9..0000000000 --- a/servers/physics/joints/slider_joint_sw.h +++ /dev/null @@ -1,249 +0,0 @@ -/*************************************************************************/ -/* slider_joint_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -/* -Adapted to Godot from the Bullet library. -*/ - -#ifndef SLIDER_JOINT_SW_H -#define SLIDER_JOINT_SW_H - -#include "servers/physics/joints/jacobian_entry_sw.h" -#include "servers/physics/joints_sw.h" - -/* -Bullet Continuous Collision Detection and Physics Library -Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ - -This software is provided 'as-is', without any express or implied warranty. -In no event will the authors be held liable for any damages arising from the use of this software. -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it freely, -subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. -2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. -3. This notice may not be removed or altered from any source distribution. -*/ - -/* -Added by Roman Ponomarev (rponom@gmail.com) -April 04, 2008 - -*/ - -#define SLIDER_CONSTRAINT_DEF_SOFTNESS (real_t(1.0)) -#define SLIDER_CONSTRAINT_DEF_DAMPING (real_t(1.0)) -#define SLIDER_CONSTRAINT_DEF_RESTITUTION (real_t(0.7)) - -//----------------------------------------------------------------------------- - -class SliderJointSW : public JointSW { -protected: - union { - struct { - BodySW *A; - BodySW *B; - }; - - BodySW *_arr[2]; - }; - - Transform m_frameInA; - Transform m_frameInB; - - // linear limits - real_t m_lowerLinLimit; - real_t m_upperLinLimit; - // angular limits - real_t m_lowerAngLimit; - real_t m_upperAngLimit; - // softness, restitution and damping for different cases - // DirLin - moving inside linear limits - // LimLin - hitting linear limit - // DirAng - moving inside angular limits - // LimAng - hitting angular limit - // OrthoLin, OrthoAng - against constraint axis - real_t m_softnessDirLin; - real_t m_restitutionDirLin; - real_t m_dampingDirLin; - real_t m_softnessDirAng; - real_t m_restitutionDirAng; - real_t m_dampingDirAng; - real_t m_softnessLimLin; - real_t m_restitutionLimLin; - real_t m_dampingLimLin; - real_t m_softnessLimAng; - real_t m_restitutionLimAng; - real_t m_dampingLimAng; - real_t m_softnessOrthoLin; - real_t m_restitutionOrthoLin; - real_t m_dampingOrthoLin; - real_t m_softnessOrthoAng; - real_t m_restitutionOrthoAng; - real_t m_dampingOrthoAng; - - // for interlal use - bool m_solveLinLim; - bool m_solveAngLim; - - JacobianEntrySW m_jacLin[3]; - real_t m_jacLinDiagABInv[3]; - - JacobianEntrySW m_jacAng[3]; - - real_t m_timeStep; - Transform m_calculatedTransformA; - Transform m_calculatedTransformB; - - Vector3 m_sliderAxis; - Vector3 m_realPivotAInW; - Vector3 m_realPivotBInW; - Vector3 m_projPivotInW; - Vector3 m_delta; - Vector3 m_depth; - Vector3 m_relPosA; - Vector3 m_relPosB; - - real_t m_linPos; - - real_t m_angDepth; - real_t m_kAngle; - - bool m_poweredLinMotor; - real_t m_targetLinMotorVelocity; - real_t m_maxLinMotorForce; - real_t m_accumulatedLinMotorImpulse; - - bool m_poweredAngMotor; - real_t m_targetAngMotorVelocity; - real_t m_maxAngMotorForce; - real_t m_accumulatedAngMotorImpulse; - - //------------------------ - void initParams(); - -public: - // constructors - SliderJointSW(BodySW *rbA, BodySW *rbB, const Transform &frameInA, const Transform &frameInB); - //SliderJointSW(); - // overrides - - // access - const BodySW *getRigidBodyA() const { return A; } - const BodySW *getRigidBodyB() const { return B; } - const Transform &getCalculatedTransformA() const { return m_calculatedTransformA; } - const Transform &getCalculatedTransformB() const { return m_calculatedTransformB; } - const Transform &getFrameOffsetA() const { return m_frameInA; } - const Transform &getFrameOffsetB() const { return m_frameInB; } - Transform &getFrameOffsetA() { return m_frameInA; } - Transform &getFrameOffsetB() { return m_frameInB; } - real_t getLowerLinLimit() { return m_lowerLinLimit; } - void setLowerLinLimit(real_t lowerLimit) { m_lowerLinLimit = lowerLimit; } - real_t getUpperLinLimit() { return m_upperLinLimit; } - void setUpperLinLimit(real_t upperLimit) { m_upperLinLimit = upperLimit; } - real_t getLowerAngLimit() { return m_lowerAngLimit; } - void setLowerAngLimit(real_t lowerLimit) { m_lowerAngLimit = lowerLimit; } - real_t getUpperAngLimit() { return m_upperAngLimit; } - void setUpperAngLimit(real_t upperLimit) { m_upperAngLimit = upperLimit; } - - real_t getSoftnessDirLin() { return m_softnessDirLin; } - real_t getRestitutionDirLin() { return m_restitutionDirLin; } - real_t getDampingDirLin() { return m_dampingDirLin; } - real_t getSoftnessDirAng() { return m_softnessDirAng; } - real_t getRestitutionDirAng() { return m_restitutionDirAng; } - real_t getDampingDirAng() { return m_dampingDirAng; } - real_t getSoftnessLimLin() { return m_softnessLimLin; } - real_t getRestitutionLimLin() { return m_restitutionLimLin; } - real_t getDampingLimLin() { return m_dampingLimLin; } - real_t getSoftnessLimAng() { return m_softnessLimAng; } - real_t getRestitutionLimAng() { return m_restitutionLimAng; } - real_t getDampingLimAng() { return m_dampingLimAng; } - real_t getSoftnessOrthoLin() { return m_softnessOrthoLin; } - real_t getRestitutionOrthoLin() { return m_restitutionOrthoLin; } - real_t getDampingOrthoLin() { return m_dampingOrthoLin; } - real_t getSoftnessOrthoAng() { return m_softnessOrthoAng; } - real_t getRestitutionOrthoAng() { return m_restitutionOrthoAng; } - real_t getDampingOrthoAng() { return m_dampingOrthoAng; } - void setSoftnessDirLin(real_t softnessDirLin) { m_softnessDirLin = softnessDirLin; } - void setRestitutionDirLin(real_t restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } - void setDampingDirLin(real_t dampingDirLin) { m_dampingDirLin = dampingDirLin; } - void setSoftnessDirAng(real_t softnessDirAng) { m_softnessDirAng = softnessDirAng; } - void setRestitutionDirAng(real_t restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } - void setDampingDirAng(real_t dampingDirAng) { m_dampingDirAng = dampingDirAng; } - void setSoftnessLimLin(real_t softnessLimLin) { m_softnessLimLin = softnessLimLin; } - void setRestitutionLimLin(real_t restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } - void setDampingLimLin(real_t dampingLimLin) { m_dampingLimLin = dampingLimLin; } - void setSoftnessLimAng(real_t softnessLimAng) { m_softnessLimAng = softnessLimAng; } - void setRestitutionLimAng(real_t restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } - void setDampingLimAng(real_t dampingLimAng) { m_dampingLimAng = dampingLimAng; } - void setSoftnessOrthoLin(real_t softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } - void setRestitutionOrthoLin(real_t restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } - void setDampingOrthoLin(real_t dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } - void setSoftnessOrthoAng(real_t softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } - void setRestitutionOrthoAng(real_t restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } - void setDampingOrthoAng(real_t dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } - void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } - bool getPoweredLinMotor() { return m_poweredLinMotor; } - void setTargetLinMotorVelocity(real_t targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } - real_t getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } - void setMaxLinMotorForce(real_t maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } - real_t getMaxLinMotorForce() { return m_maxLinMotorForce; } - void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } - bool getPoweredAngMotor() { return m_poweredAngMotor; } - void setTargetAngMotorVelocity(real_t targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } - real_t getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } - void setMaxAngMotorForce(real_t maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } - real_t getMaxAngMotorForce() { return m_maxAngMotorForce; } - real_t getLinearPos() { return m_linPos; } - - // access for ODE solver - bool getSolveLinLimit() { return m_solveLinLim; } - real_t getLinDepth() { return m_depth[0]; } - bool getSolveAngLimit() { return m_solveAngLim; } - real_t getAngDepth() { return m_angDepth; } - // shared code used by ODE solver - void calculateTransforms(void); - void testLinLimits(void); - void testAngLimits(void); - // access for PE Solver - Vector3 getAncorInA(void); - Vector3 getAncorInB(void); - - void set_param(PhysicsServer::SliderJointParam p_param, real_t p_value); - real_t get_param(PhysicsServer::SliderJointParam p_param) const; - - bool setup(real_t p_step); - void solve(real_t p_step); - - virtual PhysicsServer::JointType get_type() const { return PhysicsServer::JOINT_SLIDER; } -}; - -#endif // SLIDER_JOINT_SW_H diff --git a/servers/physics/joints_sw.h b/servers/physics/joints_sw.h deleted file mode 100644 index c284d541e3..0000000000 --- a/servers/physics/joints_sw.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************/ -/* joints_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef JOINTS_SW_H -#define JOINTS_SW_H - -#include "body_sw.h" -#include "constraint_sw.h" - -class JointSW : public ConstraintSW { - -public: - virtual PhysicsServer::JointType get_type() const = 0; - _FORCE_INLINE_ JointSW(BodySW **p_body_ptr = NULL, int p_body_count = 0) : - ConstraintSW(p_body_ptr, p_body_count) { - } -}; - -#endif // JOINTS_SW_H diff --git a/servers/physics/physics_server_sw.cpp b/servers/physics/physics_server_sw.cpp deleted file mode 100644 index 25b21a5394..0000000000 --- a/servers/physics/physics_server_sw.cpp +++ /dev/null @@ -1,1589 +0,0 @@ -/*************************************************************************/ -/* physics_server_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_server_sw.h" - -#include "broad_phase_basic.h" -#include "broad_phase_octree.h" -#include "core/debugger/engine_debugger.h" -#include "core/os/os.h" -#include "joints/cone_twist_joint_sw.h" -#include "joints/generic_6dof_joint_sw.h" -#include "joints/hinge_joint_sw.h" -#include "joints/pin_joint_sw.h" -#include "joints/slider_joint_sw.h" - -#define FLUSH_QUERY_CHECK(m_object) \ - ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); - -RID PhysicsServerSW::shape_create(ShapeType p_shape) { - - ShapeSW *shape = NULL; - switch (p_shape) { - - case SHAPE_PLANE: { - - shape = memnew(PlaneShapeSW); - } break; - case SHAPE_RAY: { - - shape = memnew(RayShapeSW); - } break; - case SHAPE_SPHERE: { - - shape = memnew(SphereShapeSW); - } break; - case SHAPE_BOX: { - - shape = memnew(BoxShapeSW); - } break; - case SHAPE_CAPSULE: { - - shape = memnew(CapsuleShapeSW); - } break; - case SHAPE_CYLINDER: { - - ERR_FAIL_V_MSG(RID(), "CylinderShape is not supported in GodotPhysics. Please switch to Bullet in the Project Settings."); - } break; - case SHAPE_CONVEX_POLYGON: { - - shape = memnew(ConvexPolygonShapeSW); - } break; - case SHAPE_CONCAVE_POLYGON: { - - shape = memnew(ConcavePolygonShapeSW); - } break; - case SHAPE_HEIGHTMAP: { - - shape = memnew(HeightMapShapeSW); - } break; - case SHAPE_CUSTOM: { - - ERR_FAIL_V(RID()); - - } break; - } - - RID id = shape_owner.make_rid(shape); - shape->set_self(id); - - return id; -}; - -void PhysicsServerSW::shape_set_data(RID p_shape, const Variant &p_data) { - - ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - shape->set_data(p_data); -}; - -void PhysicsServerSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { - - ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - shape->set_custom_bias(p_bias); -} - -PhysicsServer::ShapeType PhysicsServerSW::shape_get_type(RID p_shape) const { - - const ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); - return shape->get_type(); -}; - -Variant PhysicsServerSW::shape_get_data(RID p_shape) const { - - const ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, Variant()); - ERR_FAIL_COND_V(!shape->is_configured(), Variant()); - return shape->get_data(); -}; - -void PhysicsServerSW::shape_set_margin(RID p_shape, real_t p_margin) { -} - -real_t PhysicsServerSW::shape_get_margin(RID p_shape) const { - return 0.0; -} - -real_t PhysicsServerSW::shape_get_custom_solver_bias(RID p_shape) const { - - const ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, 0); - return shape->get_custom_bias(); -} - -RID PhysicsServerSW::space_create() { - - SpaceSW *space = memnew(SpaceSW); - RID id = space_owner.make_rid(space); - space->set_self(id); - RID area_id = area_create(); - AreaSW *area = area_owner.getornull(area_id); - ERR_FAIL_COND_V(!area, RID()); - space->set_default_area(area); - area->set_space(space); - area->set_priority(-1); - RID sgb = body_create(); - body_set_space(sgb, id); - body_set_mode(sgb, BODY_MODE_STATIC); - space->set_static_global_body(sgb); - - return id; -}; - -void PhysicsServerSW::space_set_active(RID p_space, bool p_active) { - - SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - if (p_active) - active_spaces.insert(space); - else - active_spaces.erase(space); -} - -bool PhysicsServerSW::space_is_active(RID p_space) const { - - const SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, false); - - return active_spaces.has(space); -} - -void PhysicsServerSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { - - SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - - space->set_param(p_param, p_value); -} - -real_t PhysicsServerSW::space_get_param(RID p_space, SpaceParameter p_param) const { - - const SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_param(p_param); -} - -PhysicsDirectSpaceState *PhysicsServerSW::space_get_direct_state(RID p_space) { - - SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, NULL); - ERR_FAIL_COND_V_MSG(!doing_sync || space->is_locked(), NULL, "Space state is inaccessible right now, wait for iteration or physics process notification."); - - return space->get_direct_state(); -} - -void PhysicsServerSW::space_set_debug_contacts(RID p_space, int p_max_contacts) { - - SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - space->set_debug_contacts(p_max_contacts); -} - -Vector PhysicsServerSW::space_get_contacts(RID p_space) const { - - SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, Vector()); - return space->get_debug_contacts(); -} - -int PhysicsServerSW::space_get_contact_count(RID p_space) const { - - SpaceSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_debug_contact_count(); -} - -RID PhysicsServerSW::area_create() { - - AreaSW *area = memnew(AreaSW); - RID rid = area_owner.make_rid(area); - area->set_self(rid); - return rid; -}; - -void PhysicsServerSW::area_set_space(RID p_area, RID p_space) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - SpaceSW *space = NULL; - if (p_space.is_valid()) { - space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - } - - if (area->get_space() == space) - return; //pointless - - area->clear_constraints(); - area->set_space(space); -}; - -RID PhysicsServerSW::area_get_space(RID p_area) const { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, RID()); - - SpaceSW *space = area->get_space(); - if (!space) - return RID(); - return space->get_self(); -}; - -void PhysicsServerSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -PhysicsServer::AreaSpaceOverrideMode PhysicsServerSW::area_get_space_override_mode(RID p_area) const { - - const AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); -} - -void PhysicsServerSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - - area->add_shape(shape, p_transform, p_disabled); -} - -void PhysicsServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - area->set_shape(p_shape_idx, shape); -} - -void PhysicsServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_shape_transform(p_shape_idx, p_transform); -} - -int PhysicsServerSW::area_get_shape_count(RID p_area) const { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, -1); - - return area->get_shape_count(); -} -RID PhysicsServerSW::area_get_shape(RID p_area, int p_shape_idx) const { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, RID()); - - ShapeSW *shape = area->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} -Transform PhysicsServerSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, Transform()); - - return area->get_shape_transform(p_shape_idx); -} - -void PhysicsServerSW::area_remove_shape(RID p_area, int p_shape_idx) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->remove_shape(p_shape_idx); -} - -void PhysicsServerSW::area_clear_shapes(RID p_area) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - while (area->get_shape_count()) - area->remove_shape(0); -} - -void PhysicsServerSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count()); - FLUSH_QUERY_CHECK(area); - area->set_shape_as_disabled(p_shape_idx, p_disabled); -} - -void PhysicsServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { - - if (space_owner.owns(p_area)) { - SpaceSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_instance_id(p_id); -} -ObjectID PhysicsServerSW::area_get_object_instance_id(RID p_area) const { - - if (space_owner.owns(p_area)) { - SpaceSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, ObjectID()); - return area->get_instance_id(); -} - -void PhysicsServerSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { - - if (space_owner.owns(p_area)) { - SpaceSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_param(p_param, p_value); -}; - -void PhysicsServerSW::area_set_transform(RID p_area, const Transform &p_transform) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_transform(p_transform); -}; - -Variant PhysicsServerSW::area_get_param(RID p_area, AreaParameter p_param) const { - - if (space_owner.owns(p_area)) { - SpaceSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, Variant()); - - return area->get_param(p_param); -}; - -Transform PhysicsServerSW::area_get_transform(RID p_area) const { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, Transform()); - - return area->get_transform(); -}; - -void PhysicsServerSW::area_set_collision_layer(RID p_area, uint32_t p_layer) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_layer(p_layer); -} - -void PhysicsServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_mask(p_mask); -} - -void PhysicsServerSW::area_set_monitorable(RID p_area, bool p_monitorable) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - FLUSH_QUERY_CHECK(area); - - area->set_monitorable(p_monitorable); -} - -void PhysicsServerSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -void PhysicsServerSW::area_set_ray_pickable(RID p_area, bool p_enable) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_ray_pickable(p_enable); -} - -bool PhysicsServerSW::area_is_ray_pickable(RID p_area) const { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, false); - - return area->is_ray_pickable(); -} - -void PhysicsServerSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - - AreaSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -/* BODY API */ - -RID PhysicsServerSW::body_create(BodyMode p_mode, bool p_init_sleeping) { - - BodySW *body = memnew(BodySW); - if (p_mode != BODY_MODE_RIGID) - body->set_mode(p_mode); - if (p_init_sleeping) - body->set_state(BODY_STATE_SLEEPING, p_init_sleeping); - RID rid = body_owner.make_rid(body); - body->set_self(rid); - return rid; -}; - -void PhysicsServerSW::body_set_space(RID p_body, RID p_space) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - SpaceSW *space = NULL; - if (p_space.is_valid()) { - space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - } - - if (body->get_space() == space) - return; //pointless - - body->clear_constraint_map(); - body->set_space(space); -}; - -RID PhysicsServerSW::body_get_space(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, RID()); - - SpaceSW *space = body->get_space(); - if (!space) - return RID(); - return space->get_self(); -}; - -void PhysicsServerSW::body_set_mode(RID p_body, BodyMode p_mode) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_mode(p_mode); -}; - -PhysicsServer::BodyMode PhysicsServerSW::body_get_mode(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); - - return body->get_mode(); -}; - -void PhysicsServerSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - - body->add_shape(shape, p_transform, p_disabled); -} - -void PhysicsServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - ShapeSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - body->set_shape(p_shape_idx, shape); -} -void PhysicsServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_shape_transform(p_shape_idx, p_transform); -} - -int PhysicsServerSW::body_get_shape_count(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, -1); - - return body->get_shape_count(); -} -RID PhysicsServerSW::body_get_shape(RID p_body, int p_shape_idx) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, RID()); - - ShapeSW *shape = body->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} - -void PhysicsServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); - FLUSH_QUERY_CHECK(body); - - body->set_shape_as_disabled(p_shape_idx, p_disabled); -} - -Transform PhysicsServerSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Transform()); - - return body->get_shape_transform(p_shape_idx); -} - -void PhysicsServerSW::body_remove_shape(RID p_body, int p_shape_idx) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->remove_shape(p_shape_idx); -} - -void PhysicsServerSW::body_clear_shapes(RID p_body) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - while (body->get_shape_count()) - body->remove_shape(0); -} - -void PhysicsServerSW::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_continuous_collision_detection(p_enable); -} - -bool PhysicsServerSW::body_is_continuous_collision_detection_enabled(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - - return body->is_continuous_collision_detection_enabled(); -} - -void PhysicsServerSW::body_set_collision_layer(RID p_body, uint32_t p_layer) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_collision_layer(p_layer); - body->wakeup(); -} - -uint32_t PhysicsServerSW::body_get_collision_layer(RID p_body) const { - - const BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_layer(); -} - -void PhysicsServerSW::body_set_collision_mask(RID p_body, uint32_t p_mask) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_collision_mask(p_mask); - body->wakeup(); -} - -uint32_t PhysicsServerSW::body_get_collision_mask(RID p_body) const { - - const BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_mask(); -} - -void PhysicsServerSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_instance_id(p_id); -}; - -ObjectID PhysicsServerSW::body_get_object_instance_id(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, ObjectID()); - - return body->get_instance_id(); -}; - -void PhysicsServerSW::body_set_user_flags(RID p_body, uint32_t p_flags) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); -}; - -uint32_t PhysicsServerSW::body_get_user_flags(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return 0; -}; - -void PhysicsServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_param(p_param, p_value); -}; - -real_t PhysicsServerSW::body_get_param(RID p_body, BodyParameter p_param) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_param(p_param); -}; - -void PhysicsServerSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_kinematic_margin(p_margin); -} - -real_t PhysicsServerSW::body_get_kinematic_safe_margin(RID p_body) const { - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_kinematic_margin(); -} - -void PhysicsServerSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_state(p_state, p_variant); -}; - -Variant PhysicsServerSW::body_get_state(RID p_body, BodyState p_state) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Variant()); - - return body->get_state(p_state); -}; - -void PhysicsServerSW::body_set_applied_force(RID p_body, const Vector3 &p_force) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_force(p_force); - body->wakeup(); -}; - -Vector3 PhysicsServerSW::body_get_applied_force(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Vector3()); - return body->get_applied_force(); -}; - -void PhysicsServerSW::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_torque(p_torque); - body->wakeup(); -}; - -Vector3 PhysicsServerSW::body_get_applied_torque(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Vector3()); - - return body->get_applied_torque(); -}; - -void PhysicsServerSW::body_add_central_force(RID p_body, const Vector3 &p_force) { - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_central_force(p_force); - body->wakeup(); -} - -void PhysicsServerSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_force(p_force, p_pos); - body->wakeup(); -}; - -void PhysicsServerSW::body_add_torque(RID p_body, const Vector3 &p_torque) { - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_torque(p_torque); - body->wakeup(); -}; - -void PhysicsServerSW::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_central_impulse(p_impulse); - body->wakeup(); -} - -void PhysicsServerSW::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_impulse(p_pos, p_impulse); - body->wakeup(); -}; - -void PhysicsServerSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_torque_impulse(p_impulse); - body->wakeup(); -}; - -void PhysicsServerSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - Vector3 v = body->get_linear_velocity(); - Vector3 axis = p_axis_velocity.normalized(); - v -= axis * axis.dot(v); - v += p_axis_velocity; - body->set_linear_velocity(v); - body->wakeup(); -}; - -void PhysicsServerSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_axis_lock(p_axis, p_lock); - body->wakeup(); -} - -bool PhysicsServerSW::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { - - const BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - return body->is_axis_locked(p_axis); -} - -void PhysicsServerSW::body_add_collision_exception(RID p_body, RID p_body_b) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_exception(p_body_b); - body->wakeup(); -}; - -void PhysicsServerSW::body_remove_collision_exception(RID p_body, RID p_body_b) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->remove_exception(p_body_b); - body->wakeup(); -}; - -void PhysicsServerSW::body_get_collision_exceptions(RID p_body, List *p_exceptions) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - for (int i = 0; i < body->get_exceptions().size(); i++) { - p_exceptions->push_back(body->get_exceptions()[i]); - } -}; - -void PhysicsServerSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); -}; - -real_t PhysicsServerSW::body_get_contacts_reported_depth_threshold(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - return 0; -}; - -void PhysicsServerSW::body_set_omit_force_integration(RID p_body, bool p_omit) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_omit_force_integration(p_omit); -}; - -bool PhysicsServerSW::body_is_omitting_force_integration(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - return body->get_omit_force_integration(); -}; - -void PhysicsServerSW::body_set_max_contacts_reported(RID p_body, int p_contacts) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_max_contacts_reported(p_contacts); -} - -int PhysicsServerSW::body_get_max_contacts_reported(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, -1); - return body->get_max_contacts_reported(); -} - -void PhysicsServerSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); -} - -void PhysicsServerSW::body_set_ray_pickable(RID p_body, bool p_enable) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_ray_pickable(p_enable); -} - -bool PhysicsServerSW::body_is_ray_pickable(RID p_body) const { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - return body->is_ray_pickable(); -} - -bool PhysicsServerSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_COND_V(!body->get_space(), false); - ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - - _update_shapes(); - - return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result, p_exclude_raycast_shapes); -} - -int PhysicsServerSW::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_COND_V(!body->get_space(), false); - ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - - _update_shapes(); - - return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); -} - -PhysicsDirectBodyState *PhysicsServerSW::body_get_direct_state(RID p_body) { - - BodySW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, NULL); - ERR_FAIL_COND_V_MSG(!doing_sync || body->get_space()->is_locked(), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - direct_state->body = body; - return direct_state; -} - -/* JOINT API */ - -RID PhysicsServerSW::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { - - BodySW *body_A = body_owner.getornull(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND_V(!body_A->get_space(), RID()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - BodySW *body_B = body_owner.getornull(p_body_B); - ERR_FAIL_COND_V(!body_B, RID()); - - ERR_FAIL_COND_V(body_A == body_B, RID()); - - JointSW *joint = memnew(PinJointSW(body_A, p_local_A, body_B, p_local_B)); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -void PhysicsServerSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_PIN); - PinJointSW *pin_joint = static_cast(joint); - pin_joint->set_param(p_param, p_value); -} -real_t PhysicsServerSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0); - PinJointSW *pin_joint = static_cast(joint); - return pin_joint->get_param(p_param); -} - -void PhysicsServerSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_PIN); - PinJointSW *pin_joint = static_cast(joint); - pin_joint->set_pos_a(p_A); -} -Vector3 PhysicsServerSW::pin_joint_get_local_a(RID p_joint) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, Vector3()); - ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); - PinJointSW *pin_joint = static_cast(joint); - return pin_joint->get_position_a(); -} - -void PhysicsServerSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_PIN); - PinJointSW *pin_joint = static_cast(joint); - pin_joint->set_pos_b(p_B); -} -Vector3 PhysicsServerSW::pin_joint_get_local_b(RID p_joint) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, Vector3()); - ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); - PinJointSW *pin_joint = static_cast(joint); - return pin_joint->get_position_b(); -} - -RID PhysicsServerSW::joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) { - - BodySW *body_A = body_owner.getornull(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND_V(!body_A->get_space(), RID()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - BodySW *body_B = body_owner.getornull(p_body_B); - ERR_FAIL_COND_V(!body_B, RID()); - - ERR_FAIL_COND_V(body_A == body_B, RID()); - - JointSW *joint = memnew(HingeJointSW(body_A, body_B, p_frame_A, p_frame_B)); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -RID PhysicsServerSW::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { - - BodySW *body_A = body_owner.getornull(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND_V(!body_A->get_space(), RID()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - BodySW *body_B = body_owner.getornull(p_body_B); - ERR_FAIL_COND_V(!body_B, RID()); - - ERR_FAIL_COND_V(body_A == body_B, RID()); - - JointSW *joint = memnew(HingeJointSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B)); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -void PhysicsServerSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); - HingeJointSW *hinge_joint = static_cast(joint); - hinge_joint->set_param(p_param, p_value); -} -real_t PhysicsServerSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0); - HingeJointSW *hinge_joint = static_cast(joint); - return hinge_joint->get_param(p_param); -} - -void PhysicsServerSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); - HingeJointSW *hinge_joint = static_cast(joint); - hinge_joint->set_flag(p_flag, p_value); -} -bool PhysicsServerSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, false); - ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false); - HingeJointSW *hinge_joint = static_cast(joint); - return hinge_joint->get_flag(p_flag); -} - -void PhysicsServerSW::joint_set_solver_priority(RID p_joint, int p_priority) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - joint->set_priority(p_priority); -} - -int PhysicsServerSW::joint_get_solver_priority(RID p_joint) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, 0); - return joint->get_priority(); -} - -void PhysicsServerSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - - joint->disable_collisions_between_bodies(p_disable); - - if (2 == joint->get_body_count()) { - BodySW *body_a = *joint->get_body_ptr(); - BodySW *body_b = *(joint->get_body_ptr() + 1); - - if (p_disable) { - body_add_collision_exception(body_a->get_self(), body_b->get_self()); - body_add_collision_exception(body_b->get_self(), body_a->get_self()); - } else { - body_remove_collision_exception(body_a->get_self(), body_b->get_self()); - body_remove_collision_exception(body_b->get_self(), body_a->get_self()); - } - } -} - -bool PhysicsServerSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, true); - - return joint->is_disabled_collisions_between_bodies(); -} - -PhysicsServerSW::JointType PhysicsServerSW::joint_get_type(RID p_joint) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, JOINT_PIN); - return joint->get_type(); -} - -RID PhysicsServerSW::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { - - BodySW *body_A = body_owner.getornull(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND_V(!body_A->get_space(), RID()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - BodySW *body_B = body_owner.getornull(p_body_B); - ERR_FAIL_COND_V(!body_B, RID()); - - ERR_FAIL_COND_V(body_A == body_B, RID()); - - JointSW *joint = memnew(SliderJointSW(body_A, body_B, p_local_frame_A, p_local_frame_B)); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -void PhysicsServerSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER); - SliderJointSW *slider_joint = static_cast(joint); - slider_joint->set_param(p_param, p_value); -} -real_t PhysicsServerSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0); - SliderJointSW *slider_joint = static_cast(joint); - return slider_joint->get_param(p_param); -} - -RID PhysicsServerSW::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { - - BodySW *body_A = body_owner.getornull(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND_V(!body_A->get_space(), RID()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - BodySW *body_B = body_owner.getornull(p_body_B); - ERR_FAIL_COND_V(!body_B, RID()); - - ERR_FAIL_COND_V(body_A == body_B, RID()); - - JointSW *joint = memnew(ConeTwistJointSW(body_A, body_B, p_local_frame_A, p_local_frame_B)); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -void PhysicsServerSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST); - ConeTwistJointSW *cone_twist_joint = static_cast(joint); - cone_twist_joint->set_param(p_param, p_value); -} -real_t PhysicsServerSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0); - ConeTwistJointSW *cone_twist_joint = static_cast(joint); - return cone_twist_joint->get_param(p_param); -} - -RID PhysicsServerSW::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { - - BodySW *body_A = body_owner.getornull(p_body_A); - ERR_FAIL_COND_V(!body_A, RID()); - - if (!p_body_B.is_valid()) { - ERR_FAIL_COND_V(!body_A->get_space(), RID()); - p_body_B = body_A->get_space()->get_static_global_body(); - } - - BodySW *body_B = body_owner.getornull(p_body_B); - ERR_FAIL_COND_V(!body_B, RID()); - - ERR_FAIL_COND_V(body_A == body_B, RID()); - - JointSW *joint = memnew(Generic6DOFJointSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true)); - RID rid = joint_owner.make_rid(joint); - joint->set_self(rid); - return rid; -} - -void PhysicsServerSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); - Generic6DOFJointSW *generic_6dof_joint = static_cast(joint); - generic_6dof_joint->set_param(p_axis, p_param, p_value); -} -real_t PhysicsServerSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, 0); - ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0); - Generic6DOFJointSW *generic_6dof_joint = static_cast(joint); - return generic_6dof_joint->get_param(p_axis, p_param); -} - -void PhysicsServerSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); - Generic6DOFJointSW *generic_6dof_joint = static_cast(joint); - generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); -} -bool PhysicsServerSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) { - - JointSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, false); - ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false); - Generic6DOFJointSW *generic_6dof_joint = static_cast(joint); - return generic_6dof_joint->get_flag(p_axis, p_flag); -} - -void PhysicsServerSW::free(RID p_rid) { - - _update_shapes(); //just in case - - if (shape_owner.owns(p_rid)) { - - ShapeSW *shape = shape_owner.getornull(p_rid); - - while (shape->get_owners().size()) { - ShapeOwnerSW *so = shape->get_owners().front()->key(); - so->remove_shape(shape); - } - - shape_owner.free(p_rid); - memdelete(shape); - } else if (body_owner.owns(p_rid)) { - - BodySW *body = body_owner.getornull(p_rid); - - /* - if (body->get_state_query()) - _clear_query(body->get_state_query()); - - if (body->get_direct_state_query()) - _clear_query(body->get_direct_state_query()); - */ - - body->set_space(NULL); - - while (body->get_shape_count()) { - - body->remove_shape(0); - } - - body_owner.free(p_rid); - memdelete(body); - - } else if (area_owner.owns(p_rid)) { - - AreaSW *area = area_owner.getornull(p_rid); - - /* - if (area->get_monitor_query()) - _clear_query(area->get_monitor_query()); - */ - - area->set_space(NULL); - - while (area->get_shape_count()) { - - area->remove_shape(0); - } - - area_owner.free(p_rid); - memdelete(area); - } else if (space_owner.owns(p_rid)) { - - SpaceSW *space = space_owner.getornull(p_rid); - - while (space->get_objects().size()) { - CollisionObjectSW *co = (CollisionObjectSW *)space->get_objects().front()->get(); - co->set_space(NULL); - } - - active_spaces.erase(space); - free(space->get_default_area()->get_self()); - free(space->get_static_global_body()); - - space_owner.free(p_rid); - memdelete(space); - } else if (joint_owner.owns(p_rid)) { - - JointSW *joint = joint_owner.getornull(p_rid); - - for (int i = 0; i < joint->get_body_count(); i++) { - - joint->get_body_ptr()[i]->remove_constraint(joint); - } - joint_owner.free(p_rid); - memdelete(joint); - - } else { - - ERR_FAIL_MSG("Invalid ID."); - } -}; - -void PhysicsServerSW::set_active(bool p_active) { - - active = p_active; -}; - -void PhysicsServerSW::init() { - - doing_sync = true; - last_step = 0.001; - iterations = 8; // 8? - stepper = memnew(StepSW); - direct_state = memnew(PhysicsDirectBodyStateSW); -}; - -void PhysicsServerSW::step(real_t p_step) { - -#ifndef _3D_DISABLED - - if (!active) - return; - - _update_shapes(); - - doing_sync = false; - - last_step = p_step; - PhysicsDirectBodyStateSW::singleton->step = p_step; - - island_count = 0; - active_objects = 0; - collision_pairs = 0; - for (Set::Element *E = active_spaces.front(); E; E = E->next()) { - - stepper->step((SpaceSW *)E->get(), p_step, iterations); - island_count += E->get()->get_island_count(); - active_objects += E->get()->get_active_objects(); - collision_pairs += E->get()->get_collision_pairs(); - } -#endif -} - -void PhysicsServerSW::sync(){ - -}; - -void PhysicsServerSW::flush_queries() { - -#ifndef _3D_DISABLED - - if (!active) - return; - - doing_sync = true; - - flushing_queries = true; - - uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); - - for (Set::Element *E = active_spaces.front(); E; E = E->next()) { - - SpaceSW *space = (SpaceSW *)E->get(); - space->call_queries(); - } - - flushing_queries = false; - - if (EngineDebugger::is_profiling("servers")) { - - uint64_t total_time[SpaceSW::ELAPSED_TIME_MAX]; - static const char *time_name[SpaceSW::ELAPSED_TIME_MAX] = { - "integrate_forces", - "generate_islands", - "setup_constraints", - "solve_constraints", - "integrate_velocities" - }; - - for (int i = 0; i < SpaceSW::ELAPSED_TIME_MAX; i++) { - total_time[i] = 0; - } - - for (Set::Element *E = active_spaces.front(); E; E = E->next()) { - - for (int i = 0; i < SpaceSW::ELAPSED_TIME_MAX; i++) { - total_time[i] += E->get()->get_elapsed_time(SpaceSW::ElapsedTime(i)); - } - } - - Array values; - values.resize(SpaceSW::ELAPSED_TIME_MAX * 2); - for (int i = 0; i < SpaceSW::ELAPSED_TIME_MAX; i++) { - values[i * 2 + 0] = time_name[i]; - values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); - } - values.push_back("flush_queries"); - values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); - - values.push_front("physics"); - EngineDebugger::profiler_add_frame_data("server", values); - } -#endif -}; - -void PhysicsServerSW::finish() { - - memdelete(stepper); - memdelete(direct_state); -}; - -int PhysicsServerSW::get_process_info(ProcessInfo p_info) { - - switch (p_info) { - - case INFO_ACTIVE_OBJECTS: { - - return active_objects; - } break; - case INFO_COLLISION_PAIRS: { - return collision_pairs; - } break; - case INFO_ISLAND_COUNT: { - - return island_count; - } break; - } - - return 0; -} - -void PhysicsServerSW::_update_shapes() { - - while (pending_shape_update_list.first()) { - pending_shape_update_list.first()->self()->_shape_changed(); - pending_shape_update_list.remove(pending_shape_update_list.first()); - } -} - -void PhysicsServerSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { - - CollCbkData *cbk = (CollCbkData *)p_userdata; - - if (cbk->max == 0) - return; - - if (cbk->amount == cbk->max) { - //find least deep - real_t min_depth = 1e20; - int min_depth_idx = 0; - for (int i = 0; i < cbk->amount; i++) { - - real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); - if (d < min_depth) { - min_depth = d; - min_depth_idx = i; - } - } - - real_t d = p_point_A.distance_squared_to(p_point_B); - if (d < min_depth) - return; - cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; - cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; - - } else { - - cbk->ptr[cbk->amount * 2 + 0] = p_point_A; - cbk->ptr[cbk->amount * 2 + 1] = p_point_B; - cbk->amount++; - } -} - -PhysicsServerSW *PhysicsServerSW::singleton = NULL; -PhysicsServerSW::PhysicsServerSW() { - singleton = this; - BroadPhaseSW::create_func = BroadPhaseOctree::_create; - island_count = 0; - active_objects = 0; - collision_pairs = 0; - - active = true; - flushing_queries = false; -}; - -PhysicsServerSW::~PhysicsServerSW(){ - -}; diff --git a/servers/physics/physics_server_sw.h b/servers/physics/physics_server_sw.h deleted file mode 100644 index 459c7688f0..0000000000 --- a/servers/physics/physics_server_sw.h +++ /dev/null @@ -1,382 +0,0 @@ -/*************************************************************************/ -/* physics_server_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS_SERVER_SW -#define PHYSICS_SERVER_SW - -#include "core/rid_owner.h" -#include "joints_sw.h" -#include "servers/physics_server.h" -#include "shape_sw.h" -#include "space_sw.h" -#include "step_sw.h" - -class PhysicsServerSW : public PhysicsServer { - - GDCLASS(PhysicsServerSW, PhysicsServer); - - friend class PhysicsDirectSpaceStateSW; - bool active; - int iterations; - bool doing_sync; - real_t last_step; - - int island_count; - int active_objects; - int collision_pairs; - - bool flushing_queries; - - StepSW *stepper; - Set active_spaces; - - PhysicsDirectBodyStateSW *direct_state; - - mutable RID_PtrOwner shape_owner; - mutable RID_PtrOwner space_owner; - mutable RID_PtrOwner area_owner; - mutable RID_PtrOwner body_owner; - mutable RID_PtrOwner joint_owner; - - //void _clear_query(QuerySW *p_query); - friend class CollisionObjectSW; - SelfList::List pending_shape_update_list; - void _update_shapes(); - -public: - static PhysicsServerSW *singleton; - - struct CollCbkData { - - int max; - int amount; - Vector3 *ptr; - }; - - static void _shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); - - virtual RID shape_create(ShapeType p_shape); - virtual void shape_set_data(RID p_shape, const Variant &p_data); - virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias); - - virtual ShapeType shape_get_type(RID p_shape) const; - virtual Variant shape_get_data(RID p_shape) const; - - virtual void shape_set_margin(RID p_shape, real_t p_margin); - virtual real_t shape_get_margin(RID p_shape) const; - - virtual real_t shape_get_custom_solver_bias(RID p_shape) const; - - /* SPACE API */ - - virtual RID space_create(); - virtual void space_set_active(RID p_space, bool p_active); - virtual bool space_is_active(RID p_space) const; - - virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value); - virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; - - // this function only works on physics process, errors and returns null otherwise - virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space); - - virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); - virtual Vector space_get_contacts(RID p_space) const; - virtual int space_get_contact_count(RID p_space) const; - - /* AREA API */ - - virtual RID area_create(); - - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode); - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const; - - virtual void area_set_space(RID p_area, RID p_space); - virtual RID area_get_space(RID p_area) const; - - virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); - virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape); - virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform); - - virtual int area_get_shape_count(RID p_area) const; - virtual RID area_get_shape(RID p_area, int p_shape_idx) const; - virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const; - - virtual void area_remove_shape(RID p_area, int p_shape_idx); - virtual void area_clear_shapes(RID p_area); - - virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled); - - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id); - virtual ObjectID area_get_object_instance_id(RID p_area) const; - - virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value); - virtual void area_set_transform(RID p_area, const Transform &p_transform); - - virtual Variant area_get_param(RID p_area, AreaParameter p_param) const; - virtual Transform area_get_transform(RID p_area) const; - - virtual void area_set_ray_pickable(RID p_area, bool p_enable); - virtual bool area_is_ray_pickable(RID p_area) const; - - virtual void area_set_collision_mask(RID p_area, uint32_t p_mask); - virtual void area_set_collision_layer(RID p_area, uint32_t p_layer); - - virtual void area_set_monitorable(RID p_area, bool p_monitorable); - - virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); - virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); - - /* BODY API */ - - // create a body of a given type - virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false); - - virtual void body_set_space(RID p_body, RID p_space); - virtual RID body_get_space(RID p_body) const; - - virtual void body_set_mode(RID p_body, BodyMode p_mode); - virtual BodyMode body_get_mode(RID p_body) const; - - virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); - virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape); - virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform); - - virtual int body_get_shape_count(RID p_body) const; - virtual RID body_get_shape(RID p_body, int p_shape_idx) const; - virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const; - - virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); - - virtual void body_remove_shape(RID p_body, int p_shape_idx); - virtual void body_clear_shapes(RID p_body); - - virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); - virtual ObjectID body_get_object_instance_id(RID p_body) const; - - virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable); - virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const; - - virtual void body_set_collision_layer(RID p_body, uint32_t p_layer); - virtual uint32_t body_get_collision_layer(RID p_body) const; - - virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_collision_mask(RID p_body) const; - - virtual void body_set_user_flags(RID p_body, uint32_t p_flags); - virtual uint32_t body_get_user_flags(RID p_body) const; - - virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); - virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; - - virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin); - virtual real_t body_get_kinematic_safe_margin(RID p_body) const; - - virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant); - virtual Variant body_get_state(RID p_body, BodyState p_state) const; - - virtual void body_set_applied_force(RID p_body, const Vector3 &p_force); - virtual Vector3 body_get_applied_force(RID p_body) const; - - virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque); - virtual Vector3 body_get_applied_torque(RID p_body) const; - - virtual void body_add_central_force(RID p_body, const Vector3 &p_force); - virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos); - virtual void body_add_torque(RID p_body, const Vector3 &p_torque); - - virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse); - virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse); - virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse); - virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity); - - virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock); - virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const; - - virtual void body_add_collision_exception(RID p_body, RID p_body_b); - virtual void body_remove_collision_exception(RID p_body, RID p_body_b); - virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions); - - virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold); - virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const; - - virtual void body_set_omit_force_integration(RID p_body, bool p_omit); - virtual bool body_is_omitting_force_integration(RID p_body) const; - - virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); - virtual int body_get_max_contacts_reported(RID p_body) const; - - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()); - - virtual void body_set_ray_pickable(RID p_body, bool p_enable); - virtual bool body_is_ray_pickable(RID p_body) const; - - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); - virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); - - // this function only works on physics process, errors and returns null otherwise - virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body); - - /* SOFT BODY */ - - virtual RID soft_body_create(bool p_init_sleeping = false) { return RID(); } - - virtual void soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler) {} - - virtual void soft_body_set_space(RID p_body, RID p_space) {} - virtual RID soft_body_get_space(RID p_body) const { return RID(); } - - virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {} - virtual uint32_t soft_body_get_collision_layer(RID p_body) const { return 0; } - - virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {} - virtual uint32_t soft_body_get_collision_mask(RID p_body) const { return 0; } - - virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) {} - virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) {} - virtual void soft_body_get_collision_exceptions(RID p_body, List *p_exceptions) {} - - virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {} - virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const { return Variant(); } - - virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) {} - virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const { return Vector3(); } - - virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) {} - virtual bool soft_body_is_ray_pickable(RID p_body) const { return false; } - - virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {} - virtual int soft_body_get_simulation_precision(RID p_body) { return 0; } - - virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) {} - virtual real_t soft_body_get_total_mass(RID p_body) { return 0.; } - - virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {} - virtual real_t soft_body_get_linear_stiffness(RID p_body) { return 0.; } - - virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) {} - virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) { return 0.; } - - virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) {} - virtual real_t soft_body_get_volume_stiffness(RID p_body) { return 0.; } - - virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {} - virtual real_t soft_body_get_pressure_coefficient(RID p_body) { return 0.; } - - virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) {} - virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) { return 0.; } - - virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {} - virtual real_t soft_body_get_damping_coefficient(RID p_body) { return 0.; } - - virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {} - virtual real_t soft_body_get_drag_coefficient(RID p_body) { return 0.; } - - virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) {} - - virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {} - virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) { return Vector3(); } - - virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const { return Vector3(); } - - virtual void soft_body_remove_all_pinned_points(RID p_body) {} - virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {} - virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) { return 0; } - - /* JOINT API */ - - virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B); - - virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value); - virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const; - - virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A); - virtual Vector3 pin_joint_get_local_a(RID p_joint) const; - - virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B); - virtual Vector3 pin_joint_get_local_b(RID p_joint) const; - - virtual RID joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B); - virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B); - - virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value); - virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const; - - virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value); - virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const; - - virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B); //reference frame is A - - virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value); - virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const; - - virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B); //reference frame is A - - virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value); - virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const; - - virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B); //reference frame is A - - virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value); - virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param); - - virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable); - virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag); - - virtual void generic_6dof_joint_set_precision(RID p_joint, int precision) {} - virtual int generic_6dof_joint_get_precision(RID p_joint) { return 0; } - - virtual JointType joint_get_type(RID p_joint) const; - - virtual void joint_set_solver_priority(RID p_joint, int p_priority); - virtual int joint_get_solver_priority(RID p_joint) const; - - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable); - virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; - - /* MISC */ - - virtual void free(RID p_rid); - - virtual void set_active(bool p_active); - virtual void init(); - virtual void step(real_t p_step); - virtual void sync(); - virtual void flush_queries(); - virtual void finish(); - - virtual bool is_flushing_queries() const { return flushing_queries; } - - int get_process_info(ProcessInfo p_info); - - PhysicsServerSW(); - ~PhysicsServerSW(); -}; - -#endif diff --git a/servers/physics/shape_sw.cpp b/servers/physics/shape_sw.cpp deleted file mode 100644 index 4a6ed6be58..0000000000 --- a/servers/physics/shape_sw.cpp +++ /dev/null @@ -1,1655 +0,0 @@ -/*************************************************************************/ -/* shape_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shape_sw.h" - -#include "core/math/geometry.h" -#include "core/math/quick_hull.h" -#include "core/sort_array.h" - -#define _POINT_SNAP 0.001953125 -#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002 -#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.9998 - -void ShapeSW::configure(const AABB &p_aabb) { - aabb = p_aabb; - configured = true; - for (Map::Element *E = owners.front(); E; E = E->next()) { - ShapeOwnerSW *co = (ShapeOwnerSW *)E->key(); - co->_shape_changed(); - } -} - -Vector3 ShapeSW::get_support(const Vector3 &p_normal) const { - - Vector3 res; - int amnt; - get_supports(p_normal, 1, &res, amnt); - return res; -} - -void ShapeSW::add_owner(ShapeOwnerSW *p_owner) { - - Map::Element *E = owners.find(p_owner); - if (E) { - E->get()++; - } else { - owners[p_owner] = 1; - } -} - -void ShapeSW::remove_owner(ShapeOwnerSW *p_owner) { - - Map::Element *E = owners.find(p_owner); - ERR_FAIL_COND(!E); - E->get()--; - if (E->get() == 0) { - owners.erase(E); - } -} - -bool ShapeSW::is_owner(ShapeOwnerSW *p_owner) const { - - return owners.has(p_owner); -} - -const Map &ShapeSW::get_owners() const { - return owners; -} - -ShapeSW::ShapeSW() { - - custom_bias = 0; - configured = false; -} - -ShapeSW::~ShapeSW() { - - ERR_FAIL_COND(owners.size()); -} - -Plane PlaneShapeSW::get_plane() const { - - return plane; -} - -void PlaneShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - // gibberish, a plane is infinity - r_min = -1e7; - r_max = 1e7; -} - -Vector3 PlaneShapeSW::get_support(const Vector3 &p_normal) const { - - return p_normal * 1e15; -} - -bool PlaneShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - bool inters = plane.intersects_segment(p_begin, p_end, &r_result); - if (inters) - r_normal = plane.normal; - return inters; -} - -bool PlaneShapeSW::intersect_point(const Vector3 &p_point) const { - - return plane.distance_to(p_point) < 0; -} - -Vector3 PlaneShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - if (plane.is_point_over(p_point)) { - return plane.project(p_point); - } else { - return p_point; - } -} - -Vector3 PlaneShapeSW::get_moment_of_inertia(real_t p_mass) const { - - return Vector3(); //wtf -} - -void PlaneShapeSW::_setup(const Plane &p_plane) { - - plane = p_plane; - configure(AABB(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2))); -} - -void PlaneShapeSW::set_data(const Variant &p_data) { - - _setup(p_data); -} - -Variant PlaneShapeSW::get_data() const { - - return plane; -} - -PlaneShapeSW::PlaneShapeSW() { -} - -// - -real_t RayShapeSW::get_length() const { - - return length; -} - -bool RayShapeSW::get_slips_on_slope() const { - return slips_on_slope; -} - -void RayShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - // don't think this will be even used - r_min = 0; - r_max = 1; -} - -Vector3 RayShapeSW::get_support(const Vector3 &p_normal) const { - - if (p_normal.z > 0) - return Vector3(0, 0, length); - else - return Vector3(0, 0, 0); -} - -void RayShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { - - if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { - - r_amount = 2; - r_supports[0] = Vector3(0, 0, 0); - r_supports[1] = Vector3(0, 0, length); - } else if (p_normal.z > 0) { - r_amount = 1; - *r_supports = Vector3(0, 0, length); - } else { - r_amount = 1; - *r_supports = Vector3(0, 0, 0); - } -} - -bool RayShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - return false; //simply not possible -} - -bool RayShapeSW::intersect_point(const Vector3 &p_point) const { - - return false; //simply not possible -} - -Vector3 RayShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - Vector3 s[2] = { - Vector3(0, 0, 0), - Vector3(0, 0, length) - }; - - return Geometry::get_closest_point_to_segment(p_point, s); -} - -Vector3 RayShapeSW::get_moment_of_inertia(real_t p_mass) const { - - return Vector3(); -} - -void RayShapeSW::_setup(real_t p_length, bool p_slips_on_slope) { - - length = p_length; - slips_on_slope = p_slips_on_slope; - configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length))); -} - -void RayShapeSW::set_data(const Variant &p_data) { - - Dictionary d = p_data; - _setup(d["length"], d["slips_on_slope"]); -} - -Variant RayShapeSW::get_data() const { - - Dictionary d; - d["length"] = length; - d["slips_on_slope"] = slips_on_slope; - return d; -} - -RayShapeSW::RayShapeSW() { - - length = 1; - slips_on_slope = false; -} - -/********** SPHERE *************/ - -real_t SphereShapeSW::get_radius() const { - - return radius; -} - -void SphereShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - real_t d = p_normal.dot(p_transform.origin); - - // figure out scale at point - Vector3 local_normal = p_transform.basis.xform_inv(p_normal); - real_t scale = local_normal.length(); - - r_min = d - (radius)*scale; - r_max = d + (radius)*scale; -} - -Vector3 SphereShapeSW::get_support(const Vector3 &p_normal) const { - - return p_normal * radius; -} - -void SphereShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { - - *r_supports = p_normal * radius; - r_amount = 1; -} - -bool SphereShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - return Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal); -} - -bool SphereShapeSW::intersect_point(const Vector3 &p_point) const { - - return p_point.length() < radius; -} - -Vector3 SphereShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - Vector3 p = p_point; - float l = p.length(); - if (l < radius) - return p_point; - return (p / l) * radius; -} - -Vector3 SphereShapeSW::get_moment_of_inertia(real_t p_mass) const { - - real_t s = 0.4 * p_mass * radius * radius; - return Vector3(s, s, s); -} - -void SphereShapeSW::_setup(real_t p_radius) { - - radius = p_radius; - configure(AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2.0, radius * 2.0, radius * 2.0))); -} - -void SphereShapeSW::set_data(const Variant &p_data) { - - _setup(p_data); -} - -Variant SphereShapeSW::get_data() const { - - return radius; -} - -SphereShapeSW::SphereShapeSW() { - - radius = 0; -} - -/********** BOX *************/ - -void BoxShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - // no matter the angle, the box is mirrored anyway - Vector3 local_normal = p_transform.basis.xform_inv(p_normal); - - real_t length = local_normal.abs().dot(half_extents); - real_t distance = p_normal.dot(p_transform.origin); - - r_min = distance - length; - r_max = distance + length; -} - -Vector3 BoxShapeSW::get_support(const Vector3 &p_normal) const { - - Vector3 point( - (p_normal.x < 0) ? -half_extents.x : half_extents.x, - (p_normal.y < 0) ? -half_extents.y : half_extents.y, - (p_normal.z < 0) ? -half_extents.z : half_extents.z); - - return point; -} - -void BoxShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { - - static const int next[3] = { 1, 2, 0 }; - static const int next2[3] = { 2, 0, 1 }; - - for (int i = 0; i < 3; i++) { - - Vector3 axis; - axis[i] = 1.0; - real_t dot = p_normal.dot(axis); - if (Math::abs(dot) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { - - //Vector3 axis_b; - - bool neg = dot < 0; - r_amount = 4; - - Vector3 point; - point[i] = half_extents[i]; - - int i_n = next[i]; - int i_n2 = next2[i]; - - static const real_t sign[4][2] = { - - { -1.0, 1.0 }, - { 1.0, 1.0 }, - { 1.0, -1.0 }, - { -1.0, -1.0 }, - }; - - for (int j = 0; j < 4; j++) { - - point[i_n] = sign[j][0] * half_extents[i_n]; - point[i_n2] = sign[j][1] * half_extents[i_n2]; - r_supports[j] = neg ? -point : point; - } - - if (neg) { - SWAP(r_supports[1], r_supports[2]); - SWAP(r_supports[0], r_supports[3]); - } - - return; - } - - r_amount = 0; - } - - for (int i = 0; i < 3; i++) { - - Vector3 axis; - axis[i] = 1.0; - - if (Math::abs(p_normal.dot(axis)) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { - - r_amount = 2; - - int i_n = next[i]; - int i_n2 = next2[i]; - - Vector3 point = half_extents; - - if (p_normal[i_n] < 0) { - point[i_n] = -point[i_n]; - } - if (p_normal[i_n2] < 0) { - point[i_n2] = -point[i_n2]; - } - - r_supports[0] = point; - point[i] = -point[i]; - r_supports[1] = point; - return; - } - } - /* USE POINT */ - - Vector3 point( - (p_normal.x < 0) ? -half_extents.x : half_extents.x, - (p_normal.y < 0) ? -half_extents.y : half_extents.y, - (p_normal.z < 0) ? -half_extents.z : half_extents.z); - - r_amount = 1; - r_supports[0] = point; -} - -bool BoxShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - AABB aabb(-half_extents, half_extents * 2.0); - - return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal); -} - -bool BoxShapeSW::intersect_point(const Vector3 &p_point) const { - - return (Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y && Math::abs(p_point.z) < half_extents.z); -} - -Vector3 BoxShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - int outside = 0; - Vector3 min_point; - - for (int i = 0; i < 3; i++) { - - if (Math::abs(p_point[i]) > half_extents[i]) { - outside++; - if (outside == 1) { - //use plane if only one side matches - Vector3 n; - n[i] = SGN(p_point[i]); - - Plane p(n, half_extents[i]); - min_point = p.project(p_point); - } - } - } - - if (!outside) - return p_point; //it's inside, don't do anything else - - if (outside == 1) //if only above one plane, this plane clearly wins - return min_point; - - //check segments - float min_distance = 1e20; - Vector3 closest_vertex = half_extents * p_point.sign(); - Vector3 s[2] = { - closest_vertex, - closest_vertex - }; - - for (int i = 0; i < 3; i++) { - - s[1] = closest_vertex; - s[1][i] = -s[1][i]; //edge - - Vector3 closest_edge = Geometry::get_closest_point_to_segment(p_point, s); - - float d = p_point.distance_to(closest_edge); - if (d < min_distance) { - min_point = closest_edge; - min_distance = d; - } - } - - return min_point; -} - -Vector3 BoxShapeSW::get_moment_of_inertia(real_t p_mass) const { - - real_t lx = half_extents.x; - real_t ly = half_extents.y; - real_t lz = half_extents.z; - - return Vector3((p_mass / 3.0) * (ly * ly + lz * lz), (p_mass / 3.0) * (lx * lx + lz * lz), (p_mass / 3.0) * (lx * lx + ly * ly)); -} - -void BoxShapeSW::_setup(const Vector3 &p_half_extents) { - - half_extents = p_half_extents.abs(); - - configure(AABB(-half_extents, half_extents * 2)); -} - -void BoxShapeSW::set_data(const Variant &p_data) { - - _setup(p_data); -} - -Variant BoxShapeSW::get_data() const { - - return half_extents; -} - -BoxShapeSW::BoxShapeSW() { -} - -/********** CAPSULE *************/ - -void CapsuleShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - Vector3 n = p_transform.basis.xform_inv(p_normal).normalized(); - real_t h = (n.z > 0) ? height : -height; - - n *= radius; - n.z += h * 0.5; - - r_max = p_normal.dot(p_transform.xform(n)); - r_min = p_normal.dot(p_transform.xform(-n)); -} - -Vector3 CapsuleShapeSW::get_support(const Vector3 &p_normal) const { - - Vector3 n = p_normal; - - real_t h = (n.z > 0) ? height : -height; - - n *= radius; - n.z += h * 0.5; - return n; -} - -void CapsuleShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { - - Vector3 n = p_normal; - - real_t d = n.z; - - if (Math::abs(d) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { - - // make it flat - n.z = 0.0; - n.normalize(); - n *= radius; - - r_amount = 2; - r_supports[0] = n; - r_supports[0].z += height * 0.5; - r_supports[1] = n; - r_supports[1].z -= height * 0.5; - - } else { - - real_t h = (d > 0) ? height : -height; - - n *= radius; - n.z += h * 0.5; - r_amount = 1; - *r_supports = n; - } -} - -bool CapsuleShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - Vector3 norm = (p_end - p_begin).normalized(); - real_t min_d = 1e20; - - Vector3 res, n; - bool collision = false; - - Vector3 auxres, auxn; - bool collided; - - // test against cylinder and spheres :-| - - collided = Geometry::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn); - - if (collided) { - real_t d = norm.dot(auxres); - if (d < min_d) { - min_d = d; - res = auxres; - n = auxn; - collision = true; - } - } - - collided = Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * 0.5), radius, &auxres, &auxn); - - if (collided) { - real_t d = norm.dot(auxres); - if (d < min_d) { - min_d = d; - res = auxres; - n = auxn; - collision = true; - } - } - - collided = Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * -0.5), radius, &auxres, &auxn); - - if (collided) { - real_t d = norm.dot(auxres); - - if (d < min_d) { - min_d = d; - res = auxres; - n = auxn; - collision = true; - } - } - - if (collision) { - - r_result = res; - r_normal = n; - } - return collision; -} - -bool CapsuleShapeSW::intersect_point(const Vector3 &p_point) const { - - if (Math::abs(p_point.z) < height * 0.5) { - return Vector3(p_point.x, p_point.y, 0).length() < radius; - } else { - Vector3 p = p_point; - p.z = Math::abs(p.z) - height * 0.5; - return p.length() < radius; - } -} - -Vector3 CapsuleShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - Vector3 s[2] = { - Vector3(0, 0, -height * 0.5), - Vector3(0, 0, height * 0.5), - }; - - Vector3 p = Geometry::get_closest_point_to_segment(p_point, s); - - if (p.distance_to(p_point) < radius) - return p_point; - - return p + (p_point - p).normalized() * radius; -} - -Vector3 CapsuleShapeSW::get_moment_of_inertia(real_t p_mass) const { - - // use bad AABB approximation - Vector3 extents = get_aabb().size * 0.5; - - return Vector3( - (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), - (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); -} - -void CapsuleShapeSW::_setup(real_t p_height, real_t p_radius) { - - height = p_height; - radius = p_radius; - configure(AABB(Vector3(-radius, -radius, -height * 0.5 - radius), Vector3(radius * 2, radius * 2, height + radius * 2.0))); -} - -void CapsuleShapeSW::set_data(const Variant &p_data) { - - Dictionary d = p_data; - ERR_FAIL_COND(!d.has("radius")); - ERR_FAIL_COND(!d.has("height")); - _setup(d["height"], d["radius"]); -} - -Variant CapsuleShapeSW::get_data() const { - - Dictionary d; - d["radius"] = radius; - d["height"] = height; - return d; -} - -CapsuleShapeSW::CapsuleShapeSW() { - - height = radius = 0; -} - -/********** CONVEX POLYGON *************/ - -void ConvexPolygonShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - int vertex_count = mesh.vertices.size(); - if (vertex_count == 0) - return; - - const Vector3 *vrts = &mesh.vertices[0]; - - for (int i = 0; i < vertex_count; i++) { - - real_t d = p_normal.dot(p_transform.xform(vrts[i])); - - if (i == 0 || d > r_max) - r_max = d; - if (i == 0 || d < r_min) - r_min = d; - } -} - -Vector3 ConvexPolygonShapeSW::get_support(const Vector3 &p_normal) const { - - Vector3 n = p_normal; - - int vert_support_idx = -1; - real_t support_max = 0; - - int vertex_count = mesh.vertices.size(); - if (vertex_count == 0) - return Vector3(); - - const Vector3 *vrts = &mesh.vertices[0]; - - for (int i = 0; i < vertex_count; i++) { - - real_t d = n.dot(vrts[i]); - - if (i == 0 || d > support_max) { - support_max = d; - vert_support_idx = i; - } - } - - return vrts[vert_support_idx]; -} - -void ConvexPolygonShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int fc = mesh.faces.size(); - - const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); - int ec = mesh.edges.size(); - - const Vector3 *vertices = mesh.vertices.ptr(); - int vc = mesh.vertices.size(); - - //find vertex first - real_t max = 0; - int vtx = 0; - - for (int i = 0; i < vc; i++) { - - real_t d = p_normal.dot(vertices[i]); - - if (i == 0 || d > max) { - max = d; - vtx = i; - } - } - - for (int i = 0; i < fc; i++) { - - if (faces[i].plane.normal.dot(p_normal) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { - - int ic = faces[i].indices.size(); - const int *ind = faces[i].indices.ptr(); - - bool valid = false; - for (int j = 0; j < ic; j++) { - if (ind[j] == vtx) { - valid = true; - break; - } - } - - if (!valid) - continue; - - int m = MIN(p_max, ic); - for (int j = 0; j < m; j++) { - - r_supports[j] = vertices[ind[j]]; - } - r_amount = m; - return; - } - } - - for (int i = 0; i < ec; i++) { - - real_t dot = (vertices[edges[i].a] - vertices[edges[i].b]).normalized().dot(p_normal); - dot = ABS(dot); - if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD && (edges[i].a == vtx || edges[i].b == vtx)) { - - r_amount = 2; - r_supports[0] = vertices[edges[i].a]; - r_supports[1] = vertices[edges[i].b]; - return; - } - } - - r_supports[0] = vertices[vtx]; - r_amount = 1; -} - -bool ConvexPolygonShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int fc = mesh.faces.size(); - - const Vector3 *vertices = mesh.vertices.ptr(); - - Vector3 n = p_end - p_begin; - real_t min = 1e20; - bool col = false; - - for (int i = 0; i < fc; i++) { - - if (faces[i].plane.normal.dot(n) > 0) - continue; //opposing face - - int ic = faces[i].indices.size(); - const int *ind = faces[i].indices.ptr(); - - for (int j = 1; j < ic - 1; j++) { - - Face3 f(vertices[ind[0]], vertices[ind[j]], vertices[ind[j + 1]]); - Vector3 result; - if (f.intersects_segment(p_begin, p_end, &result)) { - real_t d = n.dot(result); - if (d < min) { - min = d; - r_result = result; - r_normal = faces[i].plane.normal; - col = true; - } - - break; - } - } - } - - return col; -} - -bool ConvexPolygonShapeSW::intersect_point(const Vector3 &p_point) const { - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int fc = mesh.faces.size(); - - for (int i = 0; i < fc; i++) { - - if (faces[i].plane.distance_to(p_point) >= 0) - return false; - } - - return true; -} - -Vector3 ConvexPolygonShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - const Geometry::MeshData::Face *faces = mesh.faces.ptr(); - int fc = mesh.faces.size(); - const Vector3 *vertices = mesh.vertices.ptr(); - - bool all_inside = true; - for (int i = 0; i < fc; i++) { - - if (!faces[i].plane.is_point_over(p_point)) - continue; - - all_inside = false; - bool is_inside = true; - int ic = faces[i].indices.size(); - const int *indices = faces[i].indices.ptr(); - - for (int j = 0; j < ic; j++) { - - Vector3 a = vertices[indices[j]]; - Vector3 b = vertices[indices[(j + 1) % ic]]; - Vector3 n = (a - b).cross(faces[i].plane.normal).normalized(); - if (Plane(a, n).is_point_over(p_point)) { - is_inside = false; - break; - } - } - - if (is_inside) { - return faces[i].plane.project(p_point); - } - } - - if (all_inside) { - return p_point; - } - - float min_distance = 1e20; - Vector3 min_point; - - //check edges - const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); - int ec = mesh.edges.size(); - for (int i = 0; i < ec; i++) { - - Vector3 s[2] = { - vertices[edges[i].a], - vertices[edges[i].b] - }; - - Vector3 closest = Geometry::get_closest_point_to_segment(p_point, s); - float d = closest.distance_to(p_point); - if (d < min_distance) { - min_distance = d; - min_point = closest; - } - } - - return min_point; -} - -Vector3 ConvexPolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { - - // use bad AABB approximation - Vector3 extents = get_aabb().size * 0.5; - - return Vector3( - (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), - (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); -} - -void ConvexPolygonShapeSW::_setup(const Vector &p_vertices) { - - Error err = QuickHull::build(p_vertices, mesh); - if (err != OK) - ERR_PRINT("Failed to build QuickHull"); - - AABB _aabb; - - for (int i = 0; i < mesh.vertices.size(); i++) { - - if (i == 0) - _aabb.position = mesh.vertices[i]; - else - _aabb.expand_to(mesh.vertices[i]); - } - - configure(_aabb); -} - -void ConvexPolygonShapeSW::set_data(const Variant &p_data) { - - _setup(p_data); -} - -Variant ConvexPolygonShapeSW::get_data() const { - - return mesh.vertices; -} - -ConvexPolygonShapeSW::ConvexPolygonShapeSW() { -} - -/********** FACE POLYGON *************/ - -void FaceShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - for (int i = 0; i < 3; i++) { - - Vector3 v = p_transform.xform(vertex[i]); - real_t d = p_normal.dot(v); - - if (i == 0 || d > r_max) - r_max = d; - - if (i == 0 || d < r_min) - r_min = d; - } -} - -Vector3 FaceShapeSW::get_support(const Vector3 &p_normal) const { - - int vert_support_idx = -1; - real_t support_max = 0; - - for (int i = 0; i < 3; i++) { - - real_t d = p_normal.dot(vertex[i]); - - if (i == 0 || d > support_max) { - support_max = d; - vert_support_idx = i; - } - } - - return vertex[vert_support_idx]; -} - -void FaceShapeSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { - - Vector3 n = p_normal; - - /** TEST FACE AS SUPPORT **/ - if (normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { - - r_amount = 3; - for (int i = 0; i < 3; i++) { - - r_supports[i] = vertex[i]; - } - return; - } - - /** FIND SUPPORT VERTEX **/ - - int vert_support_idx = -1; - real_t support_max = 0; - - for (int i = 0; i < 3; i++) { - - real_t d = n.dot(vertex[i]); - - if (i == 0 || d > support_max) { - support_max = d; - vert_support_idx = i; - } - } - - /** TEST EDGES AS SUPPORT **/ - - for (int i = 0; i < 3; i++) { - - int nx = (i + 1) % 3; - if (i != vert_support_idx && nx != vert_support_idx) - continue; - - // check if edge is valid as a support - real_t dot = (vertex[i] - vertex[nx]).normalized().dot(n); - dot = ABS(dot); - if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { - - r_amount = 2; - r_supports[0] = vertex[i]; - r_supports[1] = vertex[nx]; - return; - } - } - - r_amount = 1; - r_supports[0] = vertex[vert_support_idx]; -} - -bool FaceShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - bool c = Geometry::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result); - if (c) { - r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; - if (r_normal.dot(p_end - p_begin) > 0) { - r_normal = -r_normal; - } - } - - return c; -} - -bool FaceShapeSW::intersect_point(const Vector3 &p_point) const { - - return false; //face is flat -} - -Vector3 FaceShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - return Face3(vertex[0], vertex[1], vertex[2]).get_closest_point_to(p_point); -} - -Vector3 FaceShapeSW::get_moment_of_inertia(real_t p_mass) const { - - return Vector3(); // Sorry, but i don't think anyone cares, FaceShape! -} - -FaceShapeSW::FaceShapeSW() { - - configure(AABB()); -} - -Vector ConcavePolygonShapeSW::get_faces() const { - - Vector rfaces; - rfaces.resize(faces.size() * 3); - - for (int i = 0; i < faces.size(); i++) { - - Face f = faces.get(i); - - for (int j = 0; j < 3; j++) { - - rfaces.set(i * 3 + j, vertices.get(f.indices[j])); - } - } - - return rfaces; -} - -void ConcavePolygonShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - int count = vertices.size(); - if (count == 0) { - r_min = 0; - r_max = 0; - return; - } - const Vector3 *vptr = vertices.ptr(); - - for (int i = 0; i < count; i++) { - - real_t d = p_normal.dot(p_transform.xform(vptr[i])); - - if (i == 0 || d > r_max) - r_max = d; - if (i == 0 || d < r_min) - r_min = d; - } -} - -Vector3 ConcavePolygonShapeSW::get_support(const Vector3 &p_normal) const { - - int count = vertices.size(); - if (count == 0) - return Vector3(); - - const Vector3 *vptr = vertices.ptr(); - - Vector3 n = p_normal; - - int vert_support_idx = -1; - real_t support_max = 0; - - for (int i = 0; i < count; i++) { - - real_t d = n.dot(vptr[i]); - - if (i == 0 || d > support_max) { - support_max = d; - vert_support_idx = i; - } - } - - return vptr[vert_support_idx]; -} - -void ConcavePolygonShapeSW::_cull_segment(int p_idx, _SegmentCullParams *p_params) const { - - const BVH *bvh = &p_params->bvh[p_idx]; - - /* - if (p_params->dir.dot(bvh->aabb.get_support(-p_params->dir))>p_params->min_d) - return; //test against whole AABB, which isn't very costly - */ - - //printf("addr: %p\n",bvh); - if (!bvh->aabb.intersects_segment(p_params->from, p_params->to)) { - - return; - } - - if (bvh->face_index >= 0) { - - Vector3 res; - Vector3 vertices[3] = { - p_params->vertices[p_params->faces[bvh->face_index].indices[0]], - p_params->vertices[p_params->faces[bvh->face_index].indices[1]], - p_params->vertices[p_params->faces[bvh->face_index].indices[2]] - }; - - if (Geometry::segment_intersects_triangle( - p_params->from, - p_params->to, - vertices[0], - vertices[1], - vertices[2], - &res)) { - - real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from); - //TODO, seems segmen/triangle intersection is broken :( - if (d > 0 && d < p_params->min_d) { - - p_params->min_d = d; - p_params->result = res; - p_params->normal = Plane(vertices[0], vertices[1], vertices[2]).normal; - p_params->collisions++; - } - } - - } else { - - if (bvh->left >= 0) - _cull_segment(bvh->left, p_params); - if (bvh->right >= 0) - _cull_segment(bvh->right, p_params); - } -} - -bool ConcavePolygonShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { - - if (faces.size() == 0) - return false; - - // unlock data - const Face *fr = faces.ptr(); - const Vector3 *vr = vertices.ptr(); - const BVH *br = bvh.ptr(); - - _SegmentCullParams params; - params.from = p_begin; - params.to = p_end; - params.collisions = 0; - params.dir = (p_end - p_begin).normalized(); - - params.faces = fr; - params.vertices = vr; - params.bvh = br; - - params.min_d = 1e20; - // cull - _cull_segment(0, ¶ms); - - if (params.collisions > 0) { - - r_result = params.result; - r_normal = params.normal; - return true; - } else { - - return false; - } -} - -bool ConcavePolygonShapeSW::intersect_point(const Vector3 &p_point) const { - - return false; //face is flat -} - -Vector3 ConcavePolygonShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - return Vector3(); -} - -void ConcavePolygonShapeSW::_cull(int p_idx, _CullParams *p_params) const { - - const BVH *bvh = &p_params->bvh[p_idx]; - - if (!p_params->aabb.intersects(bvh->aabb)) - return; - - if (bvh->face_index >= 0) { - - const Face *f = &p_params->faces[bvh->face_index]; - FaceShapeSW *face = p_params->face; - face->normal = f->normal; - face->vertex[0] = p_params->vertices[f->indices[0]]; - face->vertex[1] = p_params->vertices[f->indices[1]]; - face->vertex[2] = p_params->vertices[f->indices[2]]; - p_params->callback(p_params->userdata, face); - - } else { - - if (bvh->left >= 0) { - - _cull(bvh->left, p_params); - } - - if (bvh->right >= 0) { - - _cull(bvh->right, p_params); - } - } -} - -void ConcavePolygonShapeSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const { - - // make matrix local to concave - if (faces.size() == 0) - return; - - AABB local_aabb = p_local_aabb; - - // unlock data - const Face *fr = faces.ptr(); - const Vector3 *vr = vertices.ptr(); - const BVH *br = bvh.ptr(); - - FaceShapeSW face; // use this to send in the callback - - _CullParams params; - params.aabb = local_aabb; - params.face = &face; - params.faces = fr; - params.vertices = vr; - params.bvh = br; - params.callback = p_callback; - params.userdata = p_userdata; - - // cull - _cull(0, ¶ms); -} - -Vector3 ConcavePolygonShapeSW::get_moment_of_inertia(real_t p_mass) const { - - // use bad AABB approximation - Vector3 extents = get_aabb().size * 0.5; - - return Vector3( - (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), - (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); -} - -struct _VolumeSW_BVH_Element { - - AABB aabb; - Vector3 center; - int face_index; -}; - -struct _VolumeSW_BVH_CompareX { - - _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { - - return a.center.x < b.center.x; - } -}; - -struct _VolumeSW_BVH_CompareY { - - _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { - - return a.center.y < b.center.y; - } -}; - -struct _VolumeSW_BVH_CompareZ { - - _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { - - return a.center.z < b.center.z; - } -}; - -struct _VolumeSW_BVH { - - AABB aabb; - _VolumeSW_BVH *left; - _VolumeSW_BVH *right; - - int face_index; -}; - -_VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_size, int &count) { - - _VolumeSW_BVH *bvh = memnew(_VolumeSW_BVH); - - if (p_size == 1) { - //leaf - bvh->aabb = p_elements[0].aabb; - bvh->left = NULL; - bvh->right = NULL; - bvh->face_index = p_elements->face_index; - count++; - return bvh; - } else { - - bvh->face_index = -1; - } - - AABB aabb; - for (int i = 0; i < p_size; i++) { - - if (i == 0) - aabb = p_elements[i].aabb; - else - aabb.merge_with(p_elements[i].aabb); - } - bvh->aabb = aabb; - switch (aabb.get_longest_axis_index()) { - - case 0: { - - SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareX> sort_x; - sort_x.sort(p_elements, p_size); - - } break; - case 1: { - - SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareY> sort_y; - sort_y.sort(p_elements, p_size); - } break; - case 2: { - - SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareZ> sort_z; - sort_z.sort(p_elements, p_size); - } break; - } - - int split = p_size / 2; - bvh->left = _volume_sw_build_bvh(p_elements, split, count); - bvh->right = _volume_sw_build_bvh(&p_elements[split], p_size - split, count); - - //printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index); - count++; - return bvh; -} - -void ConcavePolygonShapeSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx) { - - int idx = p_idx; - - p_bvh_array[idx].aabb = p_bvh_tree->aabb; - p_bvh_array[idx].face_index = p_bvh_tree->face_index; - //printf("%p - %i: %i(%p) -- %p:%p\n",%p_bvh_array[idx],p_idx,p_bvh_array[i]->face_index,&p_bvh_tree->face_index,p_bvh_tree->left,p_bvh_tree->right); - - if (p_bvh_tree->left) { - p_bvh_array[idx].left = ++p_idx; - _fill_bvh(p_bvh_tree->left, p_bvh_array, p_idx); - - } else { - - p_bvh_array[p_idx].left = -1; - } - - if (p_bvh_tree->right) { - p_bvh_array[idx].right = ++p_idx; - _fill_bvh(p_bvh_tree->right, p_bvh_array, p_idx); - - } else { - - p_bvh_array[p_idx].right = -1; - } - - memdelete(p_bvh_tree); -} - -void ConcavePolygonShapeSW::_setup(Vector p_faces) { - - int src_face_count = p_faces.size(); - if (src_face_count == 0) { - configure(AABB()); - return; - } - ERR_FAIL_COND(src_face_count % 3); - src_face_count /= 3; - - const Vector3 *facesr = p_faces.ptr(); - - Vector<_VolumeSW_BVH_Element> bvh_array; - bvh_array.resize(src_face_count); - - _VolumeSW_BVH_Element *bvh_arrayw = bvh_array.ptrw(); - - faces.resize(src_face_count); - Face *facesw = faces.ptrw(); - - vertices.resize(src_face_count * 3); - - Vector3 *verticesw = vertices.ptrw(); - - AABB _aabb; - - for (int i = 0; i < src_face_count; i++) { - - Face3 face(facesr[i * 3 + 0], facesr[i * 3 + 1], facesr[i * 3 + 2]); - - bvh_arrayw[i].aabb = face.get_aabb(); - bvh_arrayw[i].center = bvh_arrayw[i].aabb.position + bvh_arrayw[i].aabb.size * 0.5; - bvh_arrayw[i].face_index = i; - facesw[i].indices[0] = i * 3 + 0; - facesw[i].indices[1] = i * 3 + 1; - facesw[i].indices[2] = i * 3 + 2; - facesw[i].normal = face.get_plane().normal; - verticesw[i * 3 + 0] = face.vertex[0]; - verticesw[i * 3 + 1] = face.vertex[1]; - verticesw[i * 3 + 2] = face.vertex[2]; - if (i == 0) - _aabb = bvh_arrayw[i].aabb; - else - _aabb.merge_with(bvh_arrayw[i].aabb); - } - - int count = 0; - _VolumeSW_BVH *bvh_tree = _volume_sw_build_bvh(bvh_arrayw, src_face_count, count); - - bvh.resize(count + 1); - - BVH *bvh_arrayw2 = bvh.ptrw(); - - int idx = 0; - _fill_bvh(bvh_tree, bvh_arrayw2, idx); - - configure(_aabb); // this type of shape has no margin -} - -void ConcavePolygonShapeSW::set_data(const Variant &p_data) { - - _setup(p_data); -} - -Variant ConcavePolygonShapeSW::get_data() const { - - return get_faces(); -} - -ConcavePolygonShapeSW::ConcavePolygonShapeSW() { -} - -/* HEIGHT MAP SHAPE */ - -Vector HeightMapShapeSW::get_heights() const { - - return heights; -} -int HeightMapShapeSW::get_width() const { - - return width; -} -int HeightMapShapeSW::get_depth() const { - - return depth; -} -real_t HeightMapShapeSW::get_cell_size() const { - - return cell_size; -} - -void HeightMapShapeSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - //not very useful, but not very used either - p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal, 0), r_min, r_max); -} - -Vector3 HeightMapShapeSW::get_support(const Vector3 &p_normal) const { - - //not very useful, but not very used either - return get_aabb().get_support(p_normal); -} - -bool HeightMapShapeSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { - - return false; -} - -bool HeightMapShapeSW::intersect_point(const Vector3 &p_point) const { - return false; -} - -Vector3 HeightMapShapeSW::get_closest_point_to(const Vector3 &p_point) const { - - return Vector3(); -} - -void HeightMapShapeSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const { -} - -Vector3 HeightMapShapeSW::get_moment_of_inertia(real_t p_mass) const { - - // use bad AABB approximation - Vector3 extents = get_aabb().size * 0.5; - - return Vector3( - (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), - (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), - (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); -} - -void HeightMapShapeSW::_setup(Vector p_heights, int p_width, int p_depth, real_t p_cell_size) { - - heights = p_heights; - width = p_width; - depth = p_depth; - cell_size = p_cell_size; - - const real_t *r = heights.ptr(); - - AABB aabb; - - for (int i = 0; i < depth; i++) { - - for (int j = 0; j < width; j++) { - - real_t h = r[i * width + j]; - - Vector3 pos(j * cell_size, h, i * cell_size); - if (i == 0 || j == 0) - aabb.position = pos; - else - aabb.expand_to(pos); - } - } - - configure(aabb); -} - -void HeightMapShapeSW::set_data(const Variant &p_data) { - - ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY); - Dictionary d = p_data; - ERR_FAIL_COND(!d.has("width")); - ERR_FAIL_COND(!d.has("depth")); - ERR_FAIL_COND(!d.has("cell_size")); - ERR_FAIL_COND(!d.has("heights")); - - int width = d["width"]; - int depth = d["depth"]; - real_t cell_size = d["cell_size"]; - Vector heights = d["heights"]; - - ERR_FAIL_COND(width <= 0); - ERR_FAIL_COND(depth <= 0); - ERR_FAIL_COND(cell_size <= CMP_EPSILON); - ERR_FAIL_COND(heights.size() != (width * depth)); - _setup(heights, width, depth, cell_size); -} - -Variant HeightMapShapeSW::get_data() const { - - ERR_FAIL_V(Variant()); -} - -HeightMapShapeSW::HeightMapShapeSW() { - - width = 0; - depth = 0; - cell_size = 0; -} diff --git a/servers/physics/shape_sw.h b/servers/physics/shape_sw.h deleted file mode 100644 index eaae64be66..0000000000 --- a/servers/physics/shape_sw.h +++ /dev/null @@ -1,470 +0,0 @@ -/*************************************************************************/ -/* shape_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHAPE_SW_H -#define SHAPE_SW_H - -#include "core/math/geometry.h" -#include "servers/physics_server.h" -/* - -SHAPE_LINE, ///< plane:"plane" -SHAPE_SEGMENT, ///< real_t:"length" -SHAPE_CIRCLE, ///< real_t:"radius" -SHAPE_RECTANGLE, ///< vec3:"extents" -SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" -SHAPE_CONCAVE_POLYGON, ///< Vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) -SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error - -*/ - -class ShapeSW; - -class ShapeOwnerSW { -public: - virtual void _shape_changed() = 0; - virtual void remove_shape(ShapeSW *p_shape) = 0; - - virtual ~ShapeOwnerSW() {} -}; - -class ShapeSW { - - RID self; - AABB aabb; - bool configured; - real_t custom_bias; - - Map owners; - -protected: - void configure(const AABB &p_aabb); - -public: - enum { - MAX_SUPPORTS = 8 - }; - - virtual real_t get_area() const { return aabb.get_area(); } - - _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } - _FORCE_INLINE_ RID get_self() const { return self; } - - virtual PhysicsServer::ShapeType get_type() const = 0; - - _FORCE_INLINE_ AABB get_aabb() const { return aabb; } - _FORCE_INLINE_ bool is_configured() const { return configured; } - - virtual bool is_concave() const { return false; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const = 0; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const = 0; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0; - virtual bool intersect_point(const Vector3 &p_point) const = 0; - virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0; - - virtual void set_data(const Variant &p_data) = 0; - virtual Variant get_data() const = 0; - - _FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; } - _FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; } - - void add_owner(ShapeOwnerSW *p_owner); - void remove_owner(ShapeOwnerSW *p_owner); - bool is_owner(ShapeOwnerSW *p_owner) const; - const Map &get_owners() const; - - ShapeSW(); - virtual ~ShapeSW(); -}; - -class ConcaveShapeSW : public ShapeSW { - -public: - virtual bool is_concave() const { return true; } - typedef void (*Callback)(void *p_userdata, ShapeSW *p_convex); - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; } - - virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const = 0; - - ConcaveShapeSW() {} -}; - -class PlaneShapeSW : public ShapeSW { - - Plane plane; - - void _setup(const Plane &p_plane); - -public: - Plane get_plane() const; - - virtual real_t get_area() const { return Math_INF; } - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_PLANE; } - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; } - - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - PlaneShapeSW(); -}; - -class RayShapeSW : public ShapeSW { - - real_t length; - bool slips_on_slope; - - void _setup(real_t p_length, bool p_slips_on_slope); - -public: - real_t get_length() const; - bool get_slips_on_slope() const; - - virtual real_t get_area() const { return 0.0; } - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_RAY; } - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; - - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - RayShapeSW(); -}; - -class SphereShapeSW : public ShapeSW { - - real_t radius; - - void _setup(real_t p_radius); - -public: - real_t get_radius() const; - - virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius; } - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_SPHERE; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - SphereShapeSW(); -}; - -class BoxShapeSW : public ShapeSW { - - Vector3 half_extents; - void _setup(const Vector3 &p_half_extents); - -public: - _FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; } - virtual real_t get_area() const { return 8 * half_extents.x * half_extents.y * half_extents.z; } - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_BOX; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - BoxShapeSW(); -}; - -class CapsuleShapeSW : public ShapeSW { - - real_t height; - real_t radius; - - void _setup(real_t p_height, real_t p_radius); - -public: - _FORCE_INLINE_ real_t get_height() const { return height; } - _FORCE_INLINE_ real_t get_radius() const { return radius; } - - virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CAPSULE; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - CapsuleShapeSW(); -}; - -struct ConvexPolygonShapeSW : public ShapeSW { - - Geometry::MeshData mesh; - - void _setup(const Vector &p_vertices); - -public: - const Geometry::MeshData &get_mesh() const { return mesh; } - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONVEX_POLYGON; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - ConvexPolygonShapeSW(); -}; - -struct _VolumeSW_BVH; -struct FaceShapeSW; - -struct ConcavePolygonShapeSW : public ConcaveShapeSW { - // always a trimesh - - struct Face { - - Vector3 normal; - int indices[3]; - }; - - Vector faces; - Vector vertices; - - struct BVH { - - AABB aabb; - int left; - int right; - - int face_index; - }; - - Vector bvh; - - struct _CullParams { - - AABB aabb; - Callback callback; - void *userdata; - const Face *faces; - const Vector3 *vertices; - const BVH *bvh; - FaceShapeSW *face; - }; - - struct _SegmentCullParams { - - Vector3 from; - Vector3 to; - const Face *faces; - const Vector3 *vertices; - const BVH *bvh; - Vector3 dir; - - Vector3 result; - Vector3 normal; - real_t min_d; - int collisions; - }; - - void _cull_segment(int p_idx, _SegmentCullParams *p_params) const; - void _cull(int p_idx, _CullParams *p_params) const; - - void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx); - - void _setup(Vector p_faces); - -public: - Vector get_faces() const; - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONCAVE_POLYGON; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - ConcavePolygonShapeSW(); -}; - -struct HeightMapShapeSW : public ConcaveShapeSW { - - Vector heights; - int width; - int depth; - real_t cell_size; - - //void _cull_segment(int p_idx,_SegmentCullParams *p_params) const; - //void _cull(int p_idx,_CullParams *p_params) const; - - void _setup(Vector p_heights, int p_width, int p_depth, real_t p_cell_size); - -public: - Vector get_heights() const; - int get_width() const; - int get_depth() const; - real_t get_cell_size() const; - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_HEIGHTMAP; } - - virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - virtual Vector3 get_support(const Vector3 &p_normal) const; - virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const; - - virtual Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data); - virtual Variant get_data() const; - - HeightMapShapeSW(); -}; - -//used internally -struct FaceShapeSW : public ShapeSW { - - Vector3 normal; //cache - Vector3 vertex[3]; - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONCAVE_POLYGON; } - - const Vector3 &get_vertex(int p_idx) const { return vertex[p_idx]; } - - void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; - Vector3 get_support(const Vector3 &p_normal) const; - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; - bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; - virtual bool intersect_point(const Vector3 &p_point) const; - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; - - Vector3 get_moment_of_inertia(real_t p_mass) const; - - virtual void set_data(const Variant &p_data) {} - virtual Variant get_data() const { return Variant(); } - - FaceShapeSW(); -}; - -struct MotionShapeSW : public ShapeSW { - - ShapeSW *shape; - Vector3 motion; - - virtual PhysicsServer::ShapeType get_type() const { return PhysicsServer::SHAPE_CONVEX_POLYGON; } - - void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { - - Vector3 cast = p_transform.basis.xform(motion); - real_t mina, maxa; - real_t minb, maxb; - Transform ofsb = p_transform; - ofsb.origin += cast; - shape->project_range(p_normal, p_transform, mina, maxa); - shape->project_range(p_normal, ofsb, minb, maxb); - r_min = MIN(mina, minb); - r_max = MAX(maxa, maxb); - } - - Vector3 get_support(const Vector3 &p_normal) const { - - Vector3 support = shape->get_support(p_normal); - if (p_normal.dot(motion) > 0) { - support += motion; - } - return support; - } - virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; } - bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return false; } - virtual bool intersect_point(const Vector3 &p_point) const { return false; } - virtual Vector3 get_closest_point_to(const Vector3 &p_point) const { return p_point; } - - Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } - - virtual void set_data(const Variant &p_data) {} - virtual Variant get_data() const { return Variant(); } - - MotionShapeSW() { configure(AABB()); } -}; - -#endif // SHAPE_SW_H diff --git a/servers/physics/space_sw.cpp b/servers/physics/space_sw.cpp deleted file mode 100644 index 110520db5a..0000000000 --- a/servers/physics/space_sw.cpp +++ /dev/null @@ -1,1242 +0,0 @@ -/*************************************************************************/ -/* space_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "space_sw.h" - -#include "collision_solver_sw.h" -#include "core/project_settings.h" -#include "physics_server_sw.h" - -_FORCE_INLINE_ static bool _can_collide_with(CollisionObjectSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - if (!(p_object->get_collision_layer() & p_collision_mask)) { - return false; - } - - if (p_object->get_type() == CollisionObjectSW::TYPE_AREA && !p_collide_with_areas) - return false; - - if (p_object->get_type() == CollisionObjectSW::TYPE_BODY && !p_collide_with_bodies) - return false; - - return true; -} - -int PhysicsDirectSpaceStateSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - ERR_FAIL_COND_V(space->locked, false); - int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); - int cc = 0; - - //Transform ai = p_xform.affine_inverse(); - - for (int i = 0; i < amount; i++) { - - if (cc >= p_result_max) - break; - - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) - continue; - - //area can't be picked by ray (default) - - if (p_exclude.has(space->intersection_query_results[i]->get_self())) - continue; - - const CollisionObjectSW *col_obj = space->intersection_query_results[i]; - int shape_idx = space->intersection_query_subindex_results[i]; - - Transform inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); - inv_xform.affine_invert(); - - if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_point))) - continue; - - r_results[cc].collider_id = col_obj->get_instance_id(); - if (r_results[cc].collider_id.is_valid()) - r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); - else - r_results[cc].collider = NULL; - r_results[cc].rid = col_obj->get_self(); - r_results[cc].shape = shape_idx; - - cc++; - } - - return cc; -} - -bool PhysicsDirectSpaceStateSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { - - ERR_FAIL_COND_V(space->locked, false); - - Vector3 begin, end; - Vector3 normal; - begin = p_from; - end = p_to; - normal = (end - begin).normalized(); - - int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); - - //todo, create another array that references results, compute AABBs and check closest point to ray origin, sort, and stop evaluating results when beyond first collision - - bool collided = false; - Vector3 res_point, res_normal; - int res_shape; - const CollisionObjectSW *res_obj; - real_t min_d = 1e10; - - for (int i = 0; i < amount; i++) { - - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) - continue; - - if (p_pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) - continue; - - if (p_exclude.has(space->intersection_query_results[i]->get_self())) - continue; - - const CollisionObjectSW *col_obj = space->intersection_query_results[i]; - - int shape_idx = space->intersection_query_subindex_results[i]; - Transform inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform(); - - Vector3 local_from = inv_xform.xform(begin); - Vector3 local_to = inv_xform.xform(end); - - const ShapeSW *shape = col_obj->get_shape(shape_idx); - - Vector3 shape_point, shape_normal; - - if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { - - Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); - shape_point = xform.xform(shape_point); - - real_t ld = normal.dot(shape_point); - - if (ld < min_d) { - - min_d = ld; - res_point = shape_point; - res_normal = inv_xform.basis.xform_inv(shape_normal).normalized(); - res_shape = shape_idx; - res_obj = col_obj; - collided = true; - } - } - } - - if (!collided) - return false; - - r_result.collider_id = res_obj->get_instance_id(); - if (r_result.collider_id.is_valid()) - r_result.collider = ObjectDB::get_instance(r_result.collider_id); - else - r_result.collider = NULL; - r_result.normal = res_normal; - r_result.position = res_point; - r_result.rid = res_obj->get_self(); - r_result.shape = res_shape; - - return true; -} - -int PhysicsDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - if (p_result_max <= 0) - return 0; - - ShapeSW *shape = static_cast(PhysicsServer::get_singleton())->shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, 0); - - AABB aabb = p_xform.xform(shape->get_aabb()); - - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); - - int cc = 0; - - //Transform ai = p_xform.affine_inverse(); - - for (int i = 0; i < amount; i++) { - - if (cc >= p_result_max) - break; - - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) - continue; - - //area can't be picked by ray (default) - - if (p_exclude.has(space->intersection_query_results[i]->get_self())) - continue; - - const CollisionObjectSW *col_obj = space->intersection_query_results[i]; - int shape_idx = space->intersection_query_subindex_results[i]; - - if (!CollisionSolverSW::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), NULL, NULL, NULL, p_margin, 0)) - continue; - - if (r_results) { - r_results[cc].collider_id = col_obj->get_instance_id(); - if (r_results[cc].collider_id.is_valid()) - r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); - else - r_results[cc].collider = NULL; - r_results[cc].rid = col_obj->get_self(); - r_results[cc].shape = shape_idx; - } - - cc++; - } - - return cc; -} - -bool PhysicsDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { - - ShapeSW *shape = static_cast(PhysicsServer::get_singleton())->shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, false); - - AABB aabb = p_xform.xform(shape->get_aabb()); - aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion - aabb = aabb.grow(p_margin); - - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); - - real_t best_safe = 1; - real_t best_unsafe = 1; - - Transform xform_inv = p_xform.affine_inverse(); - MotionShapeSW mshape; - mshape.shape = shape; - mshape.motion = xform_inv.basis.xform(p_motion); - - bool best_first = true; - - Vector3 closest_A, closest_B; - - for (int i = 0; i < amount; i++) { - - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) - continue; - - if (p_exclude.has(space->intersection_query_results[i]->get_self())) - continue; //ignore excluded - - const CollisionObjectSW *col_obj = space->intersection_query_results[i]; - int shape_idx = space->intersection_query_subindex_results[i]; - - Vector3 point_A, point_B; - Vector3 sep_axis = p_motion.normalized(); - - Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); - //test initial overlap, does it collide if going all the way? - if (CollisionSolverSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { - continue; - } - - //test initial overlap - sep_axis = p_motion.normalized(); - - if (!CollisionSolverSW::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { - return false; - } - - //just do kinematic solving - real_t low = 0; - real_t hi = 1; - Vector3 mnormal = p_motion.normalized(); - - for (int j = 0; j < 8; j++) { //steps should be customizable.. - - real_t ofs = (low + hi) * 0.5; - - Vector3 sep = mnormal; //important optimization for this to work fast enough - - mshape.motion = xform_inv.basis.xform(p_motion * ofs); - - Vector3 lA, lB; - - bool collided = !CollisionSolverSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); - - if (collided) { - - hi = ofs; - } else { - - point_A = lA; - point_B = lB; - low = ofs; - } - } - - if (low < best_safe) { - best_first = true; //force reset - best_safe = low; - best_unsafe = hi; - } - - if (r_info && (best_first || (point_A.distance_squared_to(point_B) < closest_A.distance_squared_to(closest_B) && low <= best_safe))) { - closest_A = point_A; - closest_B = point_B; - r_info->collider_id = col_obj->get_instance_id(); - r_info->rid = col_obj->get_self(); - r_info->shape = shape_idx; - r_info->point = closest_B; - r_info->normal = (closest_A - closest_B).normalized(); - best_first = false; - if (col_obj->get_type() == CollisionObjectSW::TYPE_BODY) { - const BodySW *body = static_cast(col_obj); - r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - closest_B); - } - } - } - - p_closest_safe = best_safe; - p_closest_unsafe = best_unsafe; - - return true; -} - -bool PhysicsDirectSpaceStateSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - if (p_result_max <= 0) - return 0; - - ShapeSW *shape = static_cast(PhysicsServer::get_singleton())->shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, 0); - - AABB aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); - - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); - - bool collided = false; - r_result_count = 0; - - PhysicsServerSW::CollCbkData cbk; - cbk.max = p_result_max; - cbk.amount = 0; - cbk.ptr = r_results; - CollisionSolverSW::CallbackResult cbkres = PhysicsServerSW::_shape_col_cbk; - - PhysicsServerSW::CollCbkData *cbkptr = &cbk; - - for (int i = 0; i < amount; i++) { - - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) - continue; - - const CollisionObjectSW *col_obj = space->intersection_query_results[i]; - int shape_idx = space->intersection_query_subindex_results[i]; - - if (p_exclude.has(col_obj->get_self())) { - continue; - } - - if (CollisionSolverSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { - collided = true; - } - } - - r_result_count = cbk.amount; - - return collided; -} - -struct _RestCallbackData { - - const CollisionObjectSW *object; - const CollisionObjectSW *best_object; - int shape; - int best_shape; - Vector3 best_contact; - Vector3 best_normal; - real_t best_len; - real_t min_allowed_depth; -}; - -static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { - - _RestCallbackData *rd = (_RestCallbackData *)p_userdata; - - Vector3 contact_rel = p_point_B - p_point_A; - real_t len = contact_rel.length(); - if (len < rd->min_allowed_depth) - return; - if (len <= rd->best_len) - return; - - rd->best_len = len; - rd->best_contact = p_point_B; - rd->best_normal = contact_rel / len; - rd->best_object = rd->object; - rd->best_shape = rd->shape; -} -bool PhysicsDirectSpaceStateSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - ShapeSW *shape = static_cast(PhysicsServer::get_singleton())->shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, 0); - - AABB aabb = p_shape_xform.xform(shape->get_aabb()); - aabb = aabb.grow(p_margin); - - int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, SpaceSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); - - _RestCallbackData rcd; - rcd.best_len = 0; - rcd.best_object = NULL; - rcd.best_shape = 0; - rcd.min_allowed_depth = space->test_motion_min_contact_depth; - - for (int i = 0; i < amount; i++) { - - if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) - continue; - - const CollisionObjectSW *col_obj = space->intersection_query_results[i]; - int shape_idx = space->intersection_query_subindex_results[i]; - - if (p_exclude.has(col_obj->get_self())) - continue; - - rcd.object = col_obj; - rcd.shape = shape_idx; - bool sc = CollisionSolverSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, NULL, p_margin); - if (!sc) - continue; - } - - if (rcd.best_len == 0 || !rcd.best_object) - return false; - - r_info->collider_id = rcd.best_object->get_instance_id(); - r_info->shape = rcd.best_shape; - r_info->normal = rcd.best_normal; - r_info->point = rcd.best_contact; - r_info->rid = rcd.best_object->get_self(); - if (rcd.best_object->get_type() == CollisionObjectSW::TYPE_BODY) { - - const BodySW *body = static_cast(rcd.best_object); - r_info->linear_velocity = body->get_linear_velocity() + - (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); - - } else { - r_info->linear_velocity = Vector3(); - } - - return true; -} - -Vector3 PhysicsDirectSpaceStateSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { - - CollisionObjectSW *obj = PhysicsServerSW::singleton->area_owner.getornull(p_object); - if (!obj) { - obj = PhysicsServerSW::singleton->body_owner.getornull(p_object); - } - ERR_FAIL_COND_V(!obj, Vector3()); - - ERR_FAIL_COND_V(obj->get_space() != space, Vector3()); - - float min_distance = 1e20; - Vector3 min_point; - - bool shapes_found = false; - - for (int i = 0; i < obj->get_shape_count(); i++) { - - if (obj->is_shape_set_as_disabled(i)) - continue; - - Transform shape_xform = obj->get_transform() * obj->get_shape_transform(i); - ShapeSW *shape = obj->get_shape(i); - - Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point)); - point = shape_xform.xform(point); - - float dist = point.distance_to(p_point); - if (dist < min_distance) { - min_distance = dist; - min_point = point; - } - shapes_found = true; - } - - if (!shapes_found) { - return obj->get_transform().origin; //no shapes found, use distance to origin. - } else { - return min_point; - } -} - -PhysicsDirectSpaceStateSW::PhysicsDirectSpaceStateSW() { - - space = NULL; -} - -//////////////////////////////////////////////////////////////////////////////////////////////////////////// - -int SpaceSW::_cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb) { - - int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results); - - for (int i = 0; i < amount; i++) { - - bool keep = true; - - if (intersection_query_results[i] == p_body) - keep = false; - else if (intersection_query_results[i]->get_type() == CollisionObjectSW::TYPE_AREA) - keep = false; - else if ((static_cast(intersection_query_results[i])->test_collision_mask(p_body)) == 0) - keep = false; - else if (static_cast(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) - keep = false; - else if (static_cast(intersection_query_results[i])->is_shape_set_as_disabled(intersection_query_subindex_results[i])) - keep = false; - - if (!keep) { - - if (i < amount - 1) { - SWAP(intersection_query_results[i], intersection_query_results[amount - 1]); - SWAP(intersection_query_subindex_results[i], intersection_query_subindex_results[amount - 1]); - } - - amount--; - i--; - } - } - - return amount; -} - -int SpaceSW::test_body_ray_separation(BodySW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, real_t p_margin) { - - AABB body_aabb; - - bool shapes_found = false; - - for (int i = 0; i < p_body->get_shape_count(); i++) { - - if (p_body->is_shape_set_as_disabled(i)) - continue; - - if (!shapes_found) { - body_aabb = p_body->get_shape_aabb(i); - shapes_found = true; - } else { - body_aabb = body_aabb.merge(p_body->get_shape_aabb(i)); - } - } - - if (!shapes_found) { - return 0; - } - // Undo the currently transform the physics server is aware of and apply the provided one - body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb)); - body_aabb = body_aabb.grow(p_margin); - - Transform body_transform = p_transform; - - for (int i = 0; i < p_result_max; i++) { - //reset results - r_results[i].collision_depth = 0; - } - - int rays_found = 0; - - { - // raycast AND separate - - const int max_results = 32; - int recover_attempts = 4; - Vector3 sr[max_results * 2]; - PhysicsServerSW::CollCbkData cbk; - cbk.max = max_results; - PhysicsServerSW::CollCbkData *cbkptr = &cbk; - CollisionSolverSW::CallbackResult cbkres = PhysicsServerSW::_shape_col_cbk; - - do { - - Vector3 recover_motion; - - bool collided = false; - - int amount = _cull_aabb_for_body(p_body, body_aabb); - - for (int j = 0; j < p_body->get_shape_count(); j++) { - if (p_body->is_shape_set_as_disabled(j)) - continue; - - ShapeSW *body_shape = p_body->get_shape(j); - - if (body_shape->get_type() != PhysicsServer::SHAPE_RAY) - continue; - - Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); - - for (int i = 0; i < amount; i++) { - - const CollisionObjectSW *col_obj = intersection_query_results[i]; - int shape_idx = intersection_query_subindex_results[i]; - - cbk.amount = 0; - cbk.ptr = sr; - - if (CollisionObjectSW::TYPE_BODY == col_obj->get_type()) { - const BodySW *b = static_cast(col_obj); - if (p_infinite_inertia && PhysicsServer::BODY_MODE_STATIC != b->get_mode() && PhysicsServer::BODY_MODE_KINEMATIC != b->get_mode()) { - continue; - } - } - - ShapeSW *against_shape = col_obj->get_shape(shape_idx); - if (CollisionSolverSW::solve_static(body_shape, body_shape_xform, against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { - if (cbk.amount > 0) { - collided = true; - } - - int ray_index = -1; //reuse shape - for (int k = 0; k < rays_found; k++) { - if (r_results[k].collision_local_shape == j) { - ray_index = k; - } - } - - if (ray_index == -1 && rays_found < p_result_max) { - ray_index = rays_found; - rays_found++; - } - - if (ray_index != -1) { - PhysicsServer::SeparationResult &result = r_results[ray_index]; - - for (int k = 0; k < cbk.amount; k++) { - Vector3 a = sr[k * 2 + 0]; - Vector3 b = sr[k * 2 + 1]; - - recover_motion += (b - a) * 0.4; - - float depth = a.distance_to(b); - if (depth > result.collision_depth) { - - result.collision_depth = depth; - result.collision_point = b; - result.collision_normal = (b - a).normalized(); - result.collision_local_shape = j; - result.collider = col_obj->get_self(); - result.collider_id = col_obj->get_instance_id(); - result.collider_shape = shape_idx; - //result.collider_metadata = col_obj->get_shape_metadata(shape_idx); - if (col_obj->get_type() == CollisionObjectSW::TYPE_BODY) { - BodySW *body = (BodySW *)col_obj; - - Vector3 rel_vec = b - body->get_transform().get_origin(); - //result.collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); - result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rel_vec); // * mPos); - } - } - } - } - } - } - } - - if (!collided || recover_motion == Vector3()) { - break; - } - - body_transform.origin += recover_motion; - body_aabb.position += recover_motion; - - recover_attempts--; - } while (recover_attempts); - } - - //optimize results (remove non colliding) - for (int i = 0; i < rays_found; i++) { - if (r_results[i].collision_depth == 0) { - rays_found--; - SWAP(r_results[i], r_results[rays_found]); - } - } - - r_recover_motion = body_transform.origin - p_transform.origin; - return rays_found; -} - -bool SpaceSW::test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes) { - - //give me back regular physics engine logic - //this is madness - //and most people using this function will think - //what it does is simpler than using physics - //this took about a week to get right.. - //but is it right? who knows at this point.. - - if (r_result) { - r_result->collider_id = ObjectID(); - r_result->collider_shape = 0; - } - AABB body_aabb; - bool shapes_found = false; - - for (int i = 0; i < p_body->get_shape_count(); i++) { - - if (p_body->is_shape_set_as_disabled(i)) - continue; - - if (!shapes_found) { - body_aabb = p_body->get_shape_aabb(i); - shapes_found = true; - } else { - body_aabb = body_aabb.merge(p_body->get_shape_aabb(i)); - } - } - - if (!shapes_found) { - if (r_result) { - *r_result = PhysicsServer::MotionResult(); - r_result->motion = p_motion; - } - - return false; - } - - // Undo the currently transform the physics server is aware of and apply the provided one - body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb)); - body_aabb = body_aabb.grow(p_margin); - - Transform body_transform = p_from; - - { - //STEP 1, FREE BODY IF STUCK - - const int max_results = 32; - int recover_attempts = 4; - Vector3 sr[max_results * 2]; - - do { - - PhysicsServerSW::CollCbkData cbk; - cbk.max = max_results; - cbk.amount = 0; - cbk.ptr = sr; - - PhysicsServerSW::CollCbkData *cbkptr = &cbk; - CollisionSolverSW::CallbackResult cbkres = PhysicsServerSW::_shape_col_cbk; - - bool collided = false; - - int amount = _cull_aabb_for_body(p_body, body_aabb); - - for (int j = 0; j < p_body->get_shape_count(); j++) { - if (p_body->is_shape_set_as_disabled(j)) - continue; - - Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); - ShapeSW *body_shape = p_body->get_shape(j); - if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer::SHAPE_RAY) { - continue; - } - - for (int i = 0; i < amount; i++) { - - const CollisionObjectSW *col_obj = intersection_query_results[i]; - int shape_idx = intersection_query_subindex_results[i]; - - if (CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { - collided = cbk.amount > 0; - } - } - } - - if (!collided) { - break; - } - - Vector3 recover_motion; - - for (int i = 0; i < cbk.amount; i++) { - - Vector3 a = sr[i * 2 + 0]; - Vector3 b = sr[i * 2 + 1]; - recover_motion += (b - a) * 0.4; - } - - if (recover_motion == Vector3()) { - collided = false; - break; - } - - body_transform.origin += recover_motion; - body_aabb.position += recover_motion; - - recover_attempts--; - - } while (recover_attempts); - } - - real_t safe = 1.0; - real_t unsafe = 1.0; - int best_shape = -1; - - { - // STEP 2 ATTEMPT MOTION - - AABB motion_aabb = body_aabb; - motion_aabb.position += p_motion; - motion_aabb = motion_aabb.merge(body_aabb); - - int amount = _cull_aabb_for_body(p_body, motion_aabb); - - for (int j = 0; j < p_body->get_shape_count(); j++) { - - if (p_body->is_shape_set_as_disabled(j)) - continue; - - Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); - ShapeSW *body_shape = p_body->get_shape(j); - - if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer::SHAPE_RAY) { - continue; - } - - Transform body_shape_xform_inv = body_shape_xform.affine_inverse(); - MotionShapeSW mshape; - mshape.shape = body_shape; - mshape.motion = body_shape_xform_inv.basis.xform(p_motion); - - bool stuck = false; - - real_t best_safe = 1; - real_t best_unsafe = 1; - - for (int i = 0; i < amount; i++) { - - const CollisionObjectSW *col_obj = intersection_query_results[i]; - int shape_idx = intersection_query_subindex_results[i]; - - //test initial overlap, does it collide if going all the way? - Vector3 point_A, point_B; - Vector3 sep_axis = p_motion.normalized(); - - Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); - //test initial overlap, does it collide if going all the way? - if (CollisionSolverSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { - continue; - } - sep_axis = p_motion.normalized(); - - if (!CollisionSolverSW::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { - stuck = true; - break; - } - - //just do kinematic solving - real_t low = 0; - real_t hi = 1; - Vector3 mnormal = p_motion.normalized(); - - for (int k = 0; k < 8; k++) { //steps should be customizable.. - - real_t ofs = (low + hi) * 0.5; - - Vector3 sep = mnormal; //important optimization for this to work fast enough - - mshape.motion = body_shape_xform_inv.basis.xform(p_motion * ofs); - - Vector3 lA, lB; - - bool collided = !CollisionSolverSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep); - - if (collided) { - - hi = ofs; - } else { - - point_A = lA; - point_B = lB; - low = ofs; - } - } - - if (low < best_safe) { - best_safe = low; - best_unsafe = hi; - } - } - - if (stuck) { - - safe = 0; - unsafe = 0; - best_shape = j; //sadly it's the best - break; - } - if (best_safe == 1.0) { - continue; - } - if (best_safe < safe) { - - safe = best_safe; - unsafe = best_unsafe; - best_shape = j; - } - } - } - - bool collided = false; - if (safe >= 1) { - //not collided - collided = false; - if (r_result) { - - r_result->motion = p_motion; - r_result->remainder = Vector3(); - r_result->motion += (body_transform.get_origin() - p_from.get_origin()); - } - - } else { - - //it collided, let's get the rest info in unsafe advance - Transform ugt = body_transform; - ugt.origin += p_motion * unsafe; - - _RestCallbackData rcd; - rcd.best_len = 0; - rcd.best_object = NULL; - rcd.best_shape = 0; - rcd.min_allowed_depth = test_motion_min_contact_depth; - - Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape); - ShapeSW *body_shape = p_body->get_shape(best_shape); - - body_aabb.position += p_motion * unsafe; - - int amount = _cull_aabb_for_body(p_body, body_aabb); - - for (int i = 0; i < amount; i++) { - - const CollisionObjectSW *col_obj = intersection_query_results[i]; - int shape_idx = intersection_query_subindex_results[i]; - - rcd.object = col_obj; - rcd.shape = shape_idx; - bool sc = CollisionSolverSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, NULL, p_margin); - if (!sc) - continue; - } - - if (rcd.best_len != 0) { - - if (r_result) { - r_result->collider = rcd.best_object->get_self(); - r_result->collider_id = rcd.best_object->get_instance_id(); - r_result->collider_shape = rcd.best_shape; - r_result->collision_local_shape = best_shape; - r_result->collision_normal = rcd.best_normal; - r_result->collision_point = rcd.best_contact; - //r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape); - - const BodySW *body = static_cast(rcd.best_object); - //Vector3 rel_vec = r_result->collision_point - body->get_transform().get_origin(); - // r_result->collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); - r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); - - r_result->motion = safe * p_motion; - r_result->remainder = p_motion - safe * p_motion; - r_result->motion += (body_transform.get_origin() - p_from.get_origin()); - } - - collided = true; - } else { - if (r_result) { - - r_result->motion = p_motion; - r_result->remainder = Vector3(); - r_result->motion += (body_transform.get_origin() - p_from.get_origin()); - } - - collided = false; - } - } - - return collided; -} - -void *SpaceSW::_broadphase_pair(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_self) { - - CollisionObjectSW::Type type_A = A->get_type(); - CollisionObjectSW::Type type_B = B->get_type(); - if (type_A > type_B) { - - SWAP(A, B); - SWAP(p_subindex_A, p_subindex_B); - SWAP(type_A, type_B); - } - - SpaceSW *self = (SpaceSW *)p_self; - - self->collision_pairs++; - - if (type_A == CollisionObjectSW::TYPE_AREA) { - - AreaSW *area = static_cast(A); - if (type_B == CollisionObjectSW::TYPE_AREA) { - - AreaSW *area_b = static_cast(B); - Area2PairSW *area2_pair = memnew(Area2PairSW(area_b, p_subindex_B, area, p_subindex_A)); - return area2_pair; - } else { - - BodySW *body = static_cast(B); - AreaPairSW *area_pair = memnew(AreaPairSW(body, p_subindex_B, area, p_subindex_A)); - return area_pair; - } - } else { - - BodyPairSW *b = memnew(BodyPairSW((BodySW *)A, p_subindex_A, (BodySW *)B, p_subindex_B)); - return b; - } - - return NULL; -} - -void SpaceSW::_broadphase_unpair(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_data, void *p_self) { - - SpaceSW *self = (SpaceSW *)p_self; - self->collision_pairs--; - ConstraintSW *c = (ConstraintSW *)p_data; - memdelete(c); -} - -const SelfList::List &SpaceSW::get_active_body_list() const { - - return active_list; -} -void SpaceSW::body_add_to_active_list(SelfList *p_body) { - - active_list.add(p_body); -} -void SpaceSW::body_remove_from_active_list(SelfList *p_body) { - - active_list.remove(p_body); -} - -void SpaceSW::body_add_to_inertia_update_list(SelfList *p_body) { - - inertia_update_list.add(p_body); -} - -void SpaceSW::body_remove_from_inertia_update_list(SelfList *p_body) { - - inertia_update_list.remove(p_body); -} - -BroadPhaseSW *SpaceSW::get_broadphase() { - - return broadphase; -} - -void SpaceSW::add_object(CollisionObjectSW *p_object) { - - ERR_FAIL_COND(objects.has(p_object)); - objects.insert(p_object); -} - -void SpaceSW::remove_object(CollisionObjectSW *p_object) { - - ERR_FAIL_COND(!objects.has(p_object)); - objects.erase(p_object); -} - -const Set &SpaceSW::get_objects() const { - - return objects; -} - -void SpaceSW::body_add_to_state_query_list(SelfList *p_body) { - - state_query_list.add(p_body); -} -void SpaceSW::body_remove_from_state_query_list(SelfList *p_body) { - - state_query_list.remove(p_body); -} - -void SpaceSW::area_add_to_monitor_query_list(SelfList *p_area) { - - monitor_query_list.add(p_area); -} -void SpaceSW::area_remove_from_monitor_query_list(SelfList *p_area) { - - monitor_query_list.remove(p_area); -} - -void SpaceSW::area_add_to_moved_list(SelfList *p_area) { - - area_moved_list.add(p_area); -} - -void SpaceSW::area_remove_from_moved_list(SelfList *p_area) { - - area_moved_list.remove(p_area); -} - -const SelfList::List &SpaceSW::get_moved_area_list() const { - - return area_moved_list; -} - -void SpaceSW::call_queries() { - - while (state_query_list.first()) { - - BodySW *b = state_query_list.first()->self(); - state_query_list.remove(state_query_list.first()); - b->call_queries(); - } - - while (monitor_query_list.first()) { - - AreaSW *a = monitor_query_list.first()->self(); - monitor_query_list.remove(monitor_query_list.first()); - a->call_queries(); - } -} - -void SpaceSW::setup() { - - contact_debug_count = 0; - while (inertia_update_list.first()) { - inertia_update_list.first()->self()->update_inertias(); - inertia_update_list.remove(inertia_update_list.first()); - } -} - -void SpaceSW::update() { - - broadphase->update(); -} - -void SpaceSW::set_param(PhysicsServer::SpaceParameter p_param, real_t p_value) { - - switch (p_param) { - - case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: contact_recycle_radius = p_value; break; - case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: contact_max_separation = p_value; break; - case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: contact_max_allowed_penetration = p_value; break; - case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: body_linear_velocity_sleep_threshold = p_value; break; - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break; - case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break; - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio = p_value; break; - case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break; - case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break; - } -} - -real_t SpaceSW::get_param(PhysicsServer::SpaceParameter p_param) const { - - switch (p_param) { - - case PhysicsServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: return contact_recycle_radius; - case PhysicsServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: return contact_max_separation; - case PhysicsServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: return contact_max_allowed_penetration; - case PhysicsServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: return body_linear_velocity_sleep_threshold; - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold; - case PhysicsServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; - case PhysicsServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio; - case PhysicsServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; - case PhysicsServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth; - } - return 0; -} - -void SpaceSW::lock() { - - locked = true; -} - -void SpaceSW::unlock() { - - locked = false; -} - -bool SpaceSW::is_locked() const { - - return locked; -} - -PhysicsDirectSpaceStateSW *SpaceSW::get_direct_state() { - - return direct_access; -} - -SpaceSW::SpaceSW() { - - collision_pairs = 0; - active_objects = 0; - island_count = 0; - contact_debug_count = 0; - - locked = false; - contact_recycle_radius = 0.01; - contact_max_separation = 0.05; - contact_max_allowed_penetration = 0.01; - test_motion_min_contact_depth = 0.00001; - - constraint_bias = 0.01; - body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); - body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI)); - body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5); - ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); - body_angular_velocity_damp_ratio = 10; - - broadphase = BroadPhaseSW::create_func(); - broadphase->set_pair_callback(_broadphase_pair, this); - broadphase->set_unpair_callback(_broadphase_unpair, this); - area = NULL; - - direct_access = memnew(PhysicsDirectSpaceStateSW); - direct_access->space = this; - - for (int i = 0; i < ELAPSED_TIME_MAX; i++) - elapsed_time[i] = 0; -} - -SpaceSW::~SpaceSW() { - - memdelete(broadphase); - memdelete(direct_access); -} diff --git a/servers/physics/space_sw.h b/servers/physics/space_sw.h deleted file mode 100644 index 9e82720a75..0000000000 --- a/servers/physics/space_sw.h +++ /dev/null @@ -1,208 +0,0 @@ -/*************************************************************************/ -/* space_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SPACE_SW_H -#define SPACE_SW_H - -#include "area_pair_sw.h" -#include "area_sw.h" -#include "body_pair_sw.h" -#include "body_sw.h" -#include "broad_phase_sw.h" -#include "collision_object_sw.h" -#include "core/hash_map.h" -#include "core/project_settings.h" -#include "core/typedefs.h" - -class PhysicsDirectSpaceStateSW : public PhysicsDirectSpaceState { - - GDCLASS(PhysicsDirectSpaceStateSW, PhysicsDirectSpaceState); - -public: - SpaceSW *space; - - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false); - virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL); - virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const; - - PhysicsDirectSpaceStateSW(); -}; - -class SpaceSW { - -public: - enum ElapsedTime { - ELAPSED_TIME_INTEGRATE_FORCES, - ELAPSED_TIME_GENERATE_ISLANDS, - ELAPSED_TIME_SETUP_CONSTRAINTS, - ELAPSED_TIME_SOLVE_CONSTRAINTS, - ELAPSED_TIME_INTEGRATE_VELOCITIES, - ELAPSED_TIME_MAX - - }; - -private: - uint64_t elapsed_time[ELAPSED_TIME_MAX]; - - PhysicsDirectSpaceStateSW *direct_access; - RID self; - - BroadPhaseSW *broadphase; - SelfList::List active_list; - SelfList::List inertia_update_list; - SelfList::List state_query_list; - SelfList::List monitor_query_list; - SelfList::List area_moved_list; - - static void *_broadphase_pair(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_self); - static void _broadphase_unpair(CollisionObjectSW *A, int p_subindex_A, CollisionObjectSW *B, int p_subindex_B, void *p_data, void *p_self); - - Set objects; - - AreaSW *area; - - real_t contact_recycle_radius; - real_t contact_max_separation; - real_t contact_max_allowed_penetration; - real_t constraint_bias; - real_t test_motion_min_contact_depth; - - enum { - - INTERSECTION_QUERY_MAX = 2048 - }; - - CollisionObjectSW *intersection_query_results[INTERSECTION_QUERY_MAX]; - int intersection_query_subindex_results[INTERSECTION_QUERY_MAX]; - - real_t body_linear_velocity_sleep_threshold; - real_t body_angular_velocity_sleep_threshold; - real_t body_time_to_sleep; - real_t body_angular_velocity_damp_ratio; - - bool locked; - - int island_count; - int active_objects; - int collision_pairs; - - RID static_global_body; - - Vector contact_debug; - int contact_debug_count; - - friend class PhysicsDirectSpaceStateSW; - - int _cull_aabb_for_body(BodySW *p_body, const AABB &p_aabb); - -public: - _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } - _FORCE_INLINE_ RID get_self() const { return self; } - - void set_default_area(AreaSW *p_area) { area = p_area; } - AreaSW *get_default_area() const { return area; } - - const SelfList::List &get_active_body_list() const; - void body_add_to_active_list(SelfList *p_body); - void body_remove_from_active_list(SelfList *p_body); - void body_add_to_inertia_update_list(SelfList *p_body); - void body_remove_from_inertia_update_list(SelfList *p_body); - - void body_add_to_state_query_list(SelfList *p_body); - void body_remove_from_state_query_list(SelfList *p_body); - - void area_add_to_monitor_query_list(SelfList *p_area); - void area_remove_from_monitor_query_list(SelfList *p_area); - void area_add_to_moved_list(SelfList *p_area); - void area_remove_from_moved_list(SelfList *p_area); - const SelfList::List &get_moved_area_list() const; - - BroadPhaseSW *get_broadphase(); - - void add_object(CollisionObjectSW *p_object); - void remove_object(CollisionObjectSW *p_object); - const Set &get_objects() const; - - _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } - _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; } - _FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; } - _FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; } - _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_threshold() const { return body_linear_velocity_sleep_threshold; } - _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_threshold() const { return body_angular_velocity_sleep_threshold; } - _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; } - _FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; } - - void update(); - void setup(); - void call_queries(); - - bool is_locked() const; - void lock(); - void unlock(); - - void set_param(PhysicsServer::SpaceParameter p_param, real_t p_value); - real_t get_param(PhysicsServer::SpaceParameter p_param) const; - - void set_island_count(int p_island_count) { island_count = p_island_count; } - int get_island_count() const { return island_count; } - - void set_active_objects(int p_active_objects) { active_objects = p_active_objects; } - int get_active_objects() const { return active_objects; } - - int get_collision_pairs() const { return collision_pairs; } - - PhysicsDirectSpaceStateSW *get_direct_state(); - - void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } - _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); } - _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) { - if (contact_debug_count < contact_debug.size()) contact_debug.write[contact_debug_count++] = p_contact; - } - _FORCE_INLINE_ Vector get_debug_contacts() { return contact_debug; } - _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; } - - void set_static_global_body(RID p_body) { static_global_body = p_body; } - RID get_static_global_body() { return static_global_body; } - - void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; } - uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; } - - int test_body_ray_separation(BodySW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer::SeparationResult *r_results, int p_result_max, real_t p_margin); - bool test_body_motion(BodySW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer::MotionResult *r_result, bool p_exclude_raycast_shapes); - - SpaceSW(); - ~SpaceSW(); -}; - -#endif // SPACE__SW_H diff --git a/servers/physics/step_sw.cpp b/servers/physics/step_sw.cpp deleted file mode 100644 index f4055ecff7..0000000000 --- a/servers/physics/step_sw.cpp +++ /dev/null @@ -1,299 +0,0 @@ -/*************************************************************************/ -/* step_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "step_sw.h" -#include "joints_sw.h" - -#include "core/os/os.h" - -void StepSW::_populate_island(BodySW *p_body, BodySW **p_island, ConstraintSW **p_constraint_island) { - - p_body->set_island_step(_step); - p_body->set_island_next(*p_island); - *p_island = p_body; - - for (Map::Element *E = p_body->get_constraint_map().front(); E; E = E->next()) { - - ConstraintSW *c = (ConstraintSW *)E->key(); - if (c->get_island_step() == _step) - continue; //already processed - c->set_island_step(_step); - c->set_island_next(*p_constraint_island); - *p_constraint_island = c; - - for (int i = 0; i < c->get_body_count(); i++) { - if (i == E->get()) - continue; - BodySW *b = c->get_body_ptr()[i]; - if (b->get_island_step() == _step || b->get_mode() == PhysicsServer::BODY_MODE_STATIC || b->get_mode() == PhysicsServer::BODY_MODE_KINEMATIC) - continue; //no go - _populate_island(c->get_body_ptr()[i], p_island, p_constraint_island); - } - } -} - -void StepSW::_setup_island(ConstraintSW *p_island, real_t p_delta) { - - ConstraintSW *ci = p_island; - while (ci) { - ci->setup(p_delta); - //todo remove from island if process fails - ci = ci->get_island_next(); - } -} - -void StepSW::_solve_island(ConstraintSW *p_island, int p_iterations, real_t p_delta) { - - int at_priority = 1; - - while (p_island) { - - for (int i = 0; i < p_iterations; i++) { - - ConstraintSW *ci = p_island; - while (ci) { - ci->solve(p_delta); - ci = ci->get_island_next(); - } - } - - at_priority++; - - { - ConstraintSW *ci = p_island; - ConstraintSW *prev = NULL; - while (ci) { - if (ci->get_priority() < at_priority) { - if (prev) { - prev->set_island_next(ci->get_island_next()); //remove - } else { - p_island = ci->get_island_next(); - } - } else { - - prev = ci; - } - - ci = ci->get_island_next(); - } - } - } -} - -void StepSW::_check_suspend(BodySW *p_island, real_t p_delta) { - - bool can_sleep = true; - - BodySW *b = p_island; - while (b) { - - if (b->get_mode() == PhysicsServer::BODY_MODE_STATIC || b->get_mode() == PhysicsServer::BODY_MODE_KINEMATIC) { - b = b->get_island_next(); - continue; //ignore for static - } - - if (!b->sleep_test(p_delta)) - can_sleep = false; - - b = b->get_island_next(); - } - - //put all to sleep or wake up everyoen - - b = p_island; - while (b) { - - if (b->get_mode() == PhysicsServer::BODY_MODE_STATIC || b->get_mode() == PhysicsServer::BODY_MODE_KINEMATIC) { - b = b->get_island_next(); - continue; //ignore for static - } - - bool active = b->is_active(); - - if (active == can_sleep) - b->set_active(!can_sleep); - - b = b->get_island_next(); - } -} - -void StepSW::step(SpaceSW *p_space, real_t p_delta, int p_iterations) { - - p_space->lock(); // can't access space during this - - p_space->setup(); //update inertias, etc - - const SelfList::List *body_list = &p_space->get_active_body_list(); - - /* INTEGRATE FORCES */ - - uint64_t profile_begtime = OS::get_singleton()->get_ticks_usec(); - uint64_t profile_endtime = 0; - - int active_count = 0; - - const SelfList *b = body_list->first(); - while (b) { - - b->self()->integrate_forces(p_delta); - b = b->next(); - active_count++; - } - - p_space->set_active_objects(active_count); - - { //profile - profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(SpaceSW::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); - profile_begtime = profile_endtime; - } - - /* GENERATE CONSTRAINT ISLANDS */ - - BodySW *island_list = NULL; - ConstraintSW *constraint_island_list = NULL; - b = body_list->first(); - - int island_count = 0; - - while (b) { - BodySW *body = b->self(); - - if (body->get_island_step() != _step) { - - BodySW *island = NULL; - ConstraintSW *constraint_island = NULL; - _populate_island(body, &island, &constraint_island); - - island->set_island_list_next(island_list); - island_list = island; - - if (constraint_island) { - constraint_island->set_island_list_next(constraint_island_list); - constraint_island_list = constraint_island; - island_count++; - } - } - b = b->next(); - } - - p_space->set_island_count(island_count); - - const SelfList::List &aml = p_space->get_moved_area_list(); - - while (aml.first()) { - for (const Set::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { - - ConstraintSW *c = E->get(); - if (c->get_island_step() == _step) - continue; - c->set_island_step(_step); - c->set_island_next(NULL); - c->set_island_list_next(constraint_island_list); - constraint_island_list = c; - } - p_space->area_remove_from_moved_list((SelfList *)aml.first()); //faster to remove here - } - - { //profile - profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(SpaceSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); - profile_begtime = profile_endtime; - } - - /* SETUP CONSTRAINT ISLANDS */ - - { - ConstraintSW *ci = constraint_island_list; - while (ci) { - - _setup_island(ci, p_delta); - ci = ci->get_island_list_next(); - } - } - - { //profile - profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(SpaceSW::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime); - profile_begtime = profile_endtime; - } - - /* SOLVE CONSTRAINT ISLANDS */ - - { - ConstraintSW *ci = constraint_island_list; - while (ci) { - //iterating each island separatedly improves cache efficiency - _solve_island(ci, p_iterations, p_delta); - ci = ci->get_island_list_next(); - } - } - - { //profile - profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(SpaceSW::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime); - profile_begtime = profile_endtime; - } - - /* INTEGRATE VELOCITIES */ - - b = body_list->first(); - while (b) { - const SelfList *n = b->next(); - b->self()->integrate_velocities(p_delta); - b = n; - } - - /* SLEEP / WAKE UP ISLANDS */ - - { - BodySW *bi = island_list; - while (bi) { - - _check_suspend(bi, p_delta); - bi = bi->get_island_list_next(); - } - } - - { //profile - profile_endtime = OS::get_singleton()->get_ticks_usec(); - p_space->set_elapsed_time(SpaceSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); - profile_begtime = profile_endtime; - } - - p_space->update(); - p_space->unlock(); - _step++; -} - -StepSW::StepSW() { - - _step = 1; -} diff --git a/servers/physics/step_sw.h b/servers/physics/step_sw.h deleted file mode 100644 index 40022ef8b9..0000000000 --- a/servers/physics/step_sw.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************/ -/* step_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef STEP_SW_H -#define STEP_SW_H - -#include "space_sw.h" - -class StepSW { - - uint64_t _step; - - void _populate_island(BodySW *p_body, BodySW **p_island, ConstraintSW **p_constraint_island); - void _setup_island(ConstraintSW *p_island, real_t p_delta); - void _solve_island(ConstraintSW *p_island, int p_iterations, real_t p_delta); - void _check_suspend(BodySW *p_island, real_t p_delta); - -public: - void step(SpaceSW *p_space, real_t p_delta, int p_iterations); - StepSW(); -}; - -#endif // STEP__SW_H diff --git a/servers/physics_2d/area_2d_sw.cpp b/servers/physics_2d/area_2d_sw.cpp index 45666d9d09..85ec2aae47 100644 --- a/servers/physics_2d/area_2d_sw.cpp +++ b/servers/physics_2d/area_2d_sw.cpp @@ -117,40 +117,40 @@ void Area2DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_meth get_space()->area_add_to_moved_list(&moved_list); } -void Area2DSW::set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode) { - bool do_override = p_mode != Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED; - if (do_override == (space_override_mode != Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED)) +void Area2DSW::set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode) { + bool do_override = p_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; + if (do_override == (space_override_mode != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED)) return; _unregister_shapes(); space_override_mode = p_mode; _shape_changed(); } -void Area2DSW::set_param(Physics2DServer::AreaParameter p_param, const Variant &p_value) { +void Area2DSW::set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value) { switch (p_param) { - case Physics2DServer::AREA_PARAM_GRAVITY: gravity = p_value; break; - case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: gravity_vector = p_value; break; - case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; - case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale = p_value; break; - case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; - case Physics2DServer::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; - case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; - case Physics2DServer::AREA_PARAM_PRIORITY: priority = p_value; break; + case PhysicsServer2D::AREA_PARAM_GRAVITY: gravity = p_value; break; + case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR: gravity_vector = p_value; break; + case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; + case PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale = p_value; break; + case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; + case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; + case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; + case PhysicsServer2D::AREA_PARAM_PRIORITY: priority = p_value; break; } } -Variant Area2DSW::get_param(Physics2DServer::AreaParameter p_param) const { +Variant Area2DSW::get_param(PhysicsServer2D::AreaParameter p_param) const { switch (p_param) { - case Physics2DServer::AREA_PARAM_GRAVITY: return gravity; - case Physics2DServer::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; - case Physics2DServer::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; - case Physics2DServer::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; - case Physics2DServer::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; - case Physics2DServer::AREA_PARAM_LINEAR_DAMP: return linear_damp; - case Physics2DServer::AREA_PARAM_ANGULAR_DAMP: return angular_damp; - case Physics2DServer::AREA_PARAM_PRIORITY: return priority; + case PhysicsServer2D::AREA_PARAM_GRAVITY: return gravity; + case PhysicsServer2D::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; + case PhysicsServer2D::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case PhysicsServer2D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; + case PhysicsServer2D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; + case PhysicsServer2D::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer2D::AREA_PARAM_ANGULAR_DAMP: return angular_damp; + case PhysicsServer2D::AREA_PARAM_PRIORITY: return priority; } return Variant(); @@ -194,7 +194,7 @@ void Area2DSW::call_queries() { if (E->get().state == 0) continue; //nothing happened - res[0] = E->get().state > 0 ? Physics2DServer::AREA_BODY_ADDED : Physics2DServer::AREA_BODY_REMOVED; + res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; res[1] = E->key().rid; res[2] = E->key().instance_id; res[3] = E->key().body_shape; @@ -226,7 +226,7 @@ void Area2DSW::call_queries() { if (E->get().state == 0) continue; //nothing happened - res[0] = E->get().state > 0 ? Physics2DServer::AREA_BODY_ADDED : Physics2DServer::AREA_BODY_REMOVED; + res[0] = E->get().state > 0 ? PhysicsServer2D::AREA_BODY_ADDED : PhysicsServer2D::AREA_BODY_REMOVED; res[1] = E->key().rid; res[2] = E->key().instance_id; res[3] = E->key().body_shape; @@ -248,7 +248,7 @@ Area2DSW::Area2DSW() : moved_list(this) { _set_static(true); //areas are not active by default - space_override_mode = Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED; + space_override_mode = PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED; gravity = 9.80665; gravity_vector = Vector2(0, -1); gravity_is_point = false; diff --git a/servers/physics_2d/area_2d_sw.h b/servers/physics_2d/area_2d_sw.h index 54ffd9763d..ae2a8ff995 100644 --- a/servers/physics_2d/area_2d_sw.h +++ b/servers/physics_2d/area_2d_sw.h @@ -33,8 +33,8 @@ #include "collision_object_2d_sw.h" #include "core/self_list.h" -#include "servers/physics_2d_server.h" -//#include "servers/physics/query_sw.h" +#include "servers/physics_server_2d.h" +//#include "servers/physics_3d/query_sw.h" class Space2DSW; class Body2DSW; @@ -42,7 +42,7 @@ class Constraint2DSW; class Area2DSW : public CollisionObject2DSW { - Physics2DServer::AreaSpaceOverrideMode space_override_mode; + PhysicsServer2D::AreaSpaceOverrideMode space_override_mode; real_t gravity; Vector2 gravity_vector; bool gravity_is_point; @@ -121,11 +121,11 @@ public: _FORCE_INLINE_ void add_area_to_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); _FORCE_INLINE_ void remove_area_from_query(Area2DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); - void set_param(Physics2DServer::AreaParameter p_param, const Variant &p_value); - Variant get_param(Physics2DServer::AreaParameter p_param) const; + void set_param(PhysicsServer2D::AreaParameter p_param, const Variant &p_value); + Variant get_param(PhysicsServer2D::AreaParameter p_param) const; - void set_space_override_mode(Physics2DServer::AreaSpaceOverrideMode p_mode); - Physics2DServer::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } + void set_space_override_mode(PhysicsServer2D::AreaSpaceOverrideMode p_mode); + PhysicsServer2D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } _FORCE_INLINE_ real_t get_gravity() const { return gravity; } diff --git a/servers/physics_2d/area_pair_2d_sw.cpp b/servers/physics_2d/area_pair_2d_sw.cpp index 05d71cfabe..669f27bcc8 100644 --- a/servers/physics_2d/area_pair_2d_sw.cpp +++ b/servers/physics_2d/area_pair_2d_sw.cpp @@ -45,14 +45,14 @@ bool AreaPair2DSW::setup(real_t p_step) { if (result) { - if (area->get_space_override_mode() != Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED) + if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) body->add_area(area); if (area->has_monitor_callback()) area->add_body_to_query(body, body_shape, area_shape); } else { - if (area->get_space_override_mode() != Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED) + if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) body->remove_area(area); if (area->has_monitor_callback()) area->remove_body_from_query(body, body_shape, area_shape); @@ -76,7 +76,7 @@ AreaPair2DSW::AreaPair2DSW(Body2DSW *p_body, int p_body_shape, Area2DSW *p_area, colliding = false; body->add_constraint(this, 0); area->add_constraint(this); - if (p_body->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC) //need to be active to process pair + if (p_body->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) //need to be active to process pair p_body->set_active(true); } @@ -84,7 +84,7 @@ AreaPair2DSW::~AreaPair2DSW() { if (colliding) { - if (area->get_space_override_mode() != Physics2DServer::AREA_SPACE_OVERRIDE_DISABLED) + if (area->get_space_override_mode() != PhysicsServer2D::AREA_SPACE_OVERRIDE_DISABLED) body->remove_area(area); if (area->has_monitor_callback()) area->remove_body_from_query(body, body_shape, area_shape); diff --git a/servers/physics_2d/body_2d_sw.cpp b/servers/physics_2d/body_2d_sw.cpp index 863b422996..79388ffe93 100644 --- a/servers/physics_2d/body_2d_sw.cpp +++ b/servers/physics_2d/body_2d_sw.cpp @@ -30,7 +30,7 @@ #include "body_2d_sw.h" #include "area_2d_sw.h" -#include "physics_2d_server_sw.h" +#include "physics_server_2d_sw.h" #include "space_2d_sw.h" void Body2DSW::_update_inertia() { @@ -45,7 +45,7 @@ void Body2DSW::update_inertias() { switch (mode) { - case Physics2DServer::BODY_MODE_RIGID: { + case PhysicsServer2D::BODY_MODE_RIGID: { if (user_inertia) { _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0; @@ -86,13 +86,13 @@ void Body2DSW::update_inertias() { _inv_mass = 0; } break; - case Physics2DServer::BODY_MODE_KINEMATIC: - case Physics2DServer::BODY_MODE_STATIC: { + case PhysicsServer2D::BODY_MODE_KINEMATIC: + case PhysicsServer2D::BODY_MODE_STATIC: { _inv_inertia = 0; _inv_mass = 0; } break; - case Physics2DServer::BODY_MODE_CHARACTER: { + case PhysicsServer2D::BODY_MODE_CHARACTER: { _inv_inertia = 0; _inv_mass = 1.0 / mass; @@ -114,7 +114,7 @@ void Body2DSW::set_active(bool p_active) { if (get_space()) get_space()->body_remove_from_active_list(&active_list); } else { - if (mode == Physics2DServer::BODY_MODE_STATIC) + if (mode == PhysicsServer2D::BODY_MODE_STATIC) return; //static bodies can't become active if (get_space()) get_space()->body_add_to_active_list(&active_list); @@ -134,24 +134,24 @@ void Body2DSW::set_active(bool p_active) { */ } -void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) { +void Body2DSW::set_param(PhysicsServer2D::BodyParameter p_param, real_t p_value) { switch (p_param) { - case Physics2DServer::BODY_PARAM_BOUNCE: { + case PhysicsServer2D::BODY_PARAM_BOUNCE: { bounce = p_value; } break; - case Physics2DServer::BODY_PARAM_FRICTION: { + case PhysicsServer2D::BODY_PARAM_FRICTION: { friction = p_value; } break; - case Physics2DServer::BODY_PARAM_MASS: { + case PhysicsServer2D::BODY_PARAM_MASS: { ERR_FAIL_COND(p_value <= 0); mass = p_value; _update_inertia(); } break; - case Physics2DServer::BODY_PARAM_INERTIA: { + case PhysicsServer2D::BODY_PARAM_INERTIA: { if (p_value <= 0) { user_inertia = false; _update_inertia(); @@ -161,14 +161,14 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) _inv_inertia = 1.0 / p_value; } } break; - case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { + case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: { gravity_scale = p_value; } break; - case Physics2DServer::BODY_PARAM_LINEAR_DAMP: { + case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP: { linear_damp = p_value; } break; - case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: { + case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP: { angular_damp = p_value; } break; @@ -177,31 +177,31 @@ void Body2DSW::set_param(Physics2DServer::BodyParameter p_param, real_t p_value) } } -real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { +real_t Body2DSW::get_param(PhysicsServer2D::BodyParameter p_param) const { switch (p_param) { - case Physics2DServer::BODY_PARAM_BOUNCE: { + case PhysicsServer2D::BODY_PARAM_BOUNCE: { return bounce; } - case Physics2DServer::BODY_PARAM_FRICTION: { + case PhysicsServer2D::BODY_PARAM_FRICTION: { return friction; } - case Physics2DServer::BODY_PARAM_MASS: { + case PhysicsServer2D::BODY_PARAM_MASS: { return mass; } - case Physics2DServer::BODY_PARAM_INERTIA: { + case PhysicsServer2D::BODY_PARAM_INERTIA: { return inertia; } - case Physics2DServer::BODY_PARAM_GRAVITY_SCALE: { + case PhysicsServer2D::BODY_PARAM_GRAVITY_SCALE: { return gravity_scale; } - case Physics2DServer::BODY_PARAM_LINEAR_DAMP: { + case PhysicsServer2D::BODY_PARAM_LINEAR_DAMP: { return linear_damp; } - case Physics2DServer::BODY_PARAM_ANGULAR_DAMP: { + case PhysicsServer2D::BODY_PARAM_ANGULAR_DAMP: { return angular_damp; } @@ -212,28 +212,28 @@ real_t Body2DSW::get_param(Physics2DServer::BodyParameter p_param) const { return 0; } -void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { +void Body2DSW::set_mode(PhysicsServer2D::BodyMode p_mode) { - Physics2DServer::BodyMode prev = mode; + PhysicsServer2D::BodyMode prev = mode; mode = p_mode; switch (p_mode) { //CLEAR UP EVERYTHING IN CASE IT NOT WORKS! - case Physics2DServer::BODY_MODE_STATIC: - case Physics2DServer::BODY_MODE_KINEMATIC: { + case PhysicsServer2D::BODY_MODE_STATIC: + case PhysicsServer2D::BODY_MODE_KINEMATIC: { _set_inv_transform(get_transform().affine_inverse()); _inv_mass = 0; _inv_inertia = 0; - _set_static(p_mode == Physics2DServer::BODY_MODE_STATIC); - set_active(p_mode == Physics2DServer::BODY_MODE_KINEMATIC && contacts.size()); + _set_static(p_mode == PhysicsServer2D::BODY_MODE_STATIC); + set_active(p_mode == PhysicsServer2D::BODY_MODE_KINEMATIC && contacts.size()); linear_velocity = Vector2(); angular_velocity = 0; - if (mode == Physics2DServer::BODY_MODE_KINEMATIC && prev != mode) { + if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC && prev != mode) { first_time_kinematic = true; } } break; - case Physics2DServer::BODY_MODE_RIGID: { + case PhysicsServer2D::BODY_MODE_RIGID: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = inertia > 0 ? (1.0 / inertia) : 0; @@ -241,7 +241,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { set_active(true); } break; - case Physics2DServer::BODY_MODE_CHARACTER: { + case PhysicsServer2D::BODY_MODE_CHARACTER: { _inv_mass = mass > 0 ? (1.0 / mass) : 0; _inv_inertia = 0; @@ -250,7 +250,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { angular_velocity = 0; } break; } - if (p_mode == Physics2DServer::BODY_MODE_RIGID && _inv_inertia == 0) { + if (p_mode == PhysicsServer2D::BODY_MODE_RIGID && _inv_inertia == 0) { _update_inertia(); } /* @@ -258,7 +258,7 @@ void Body2DSW::set_mode(Physics2DServer::BodyMode p_mode) { _update_queries(); */ } -Physics2DServer::BodyMode Body2DSW::get_mode() const { +PhysicsServer2D::BodyMode Body2DSW::get_mode() const { return mode; } @@ -269,12 +269,12 @@ void Body2DSW::_shapes_changed() { wakeup_neighbours(); } -void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant &p_variant) { +void Body2DSW::set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant) { switch (p_state) { - case Physics2DServer::BODY_STATE_TRANSFORM: { + case PhysicsServer2D::BODY_STATE_TRANSFORM: { - if (mode == Physics2DServer::BODY_MODE_KINEMATIC) { + if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { new_transform = p_variant; //wakeup_neighbours(); @@ -284,7 +284,7 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant &p_va _set_inv_transform(get_transform().affine_inverse()); first_time_kinematic = false; } - } else if (mode == Physics2DServer::BODY_MODE_STATIC) { + } else if (mode == PhysicsServer2D::BODY_MODE_STATIC) { _set_transform(p_variant); _set_inv_transform(get_transform().affine_inverse()); wakeup_neighbours(); @@ -300,28 +300,28 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant &p_va wakeup(); } break; - case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: { + case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: { /* - if (mode==Physics2DServer::BODY_MODE_STATIC) + if (mode==PhysicsServer2D::BODY_MODE_STATIC) break; */ linear_velocity = p_variant; wakeup(); } break; - case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: { + case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: { /* - if (mode!=Physics2DServer::BODY_MODE_RIGID) + if (mode!=PhysicsServer2D::BODY_MODE_RIGID) break; */ angular_velocity = p_variant; wakeup(); } break; - case Physics2DServer::BODY_STATE_SLEEPING: { + case PhysicsServer2D::BODY_STATE_SLEEPING: { //? - if (mode == Physics2DServer::BODY_MODE_STATIC || mode == Physics2DServer::BODY_MODE_KINEMATIC) + if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) break; bool do_sleep = p_variant; if (do_sleep) { @@ -331,34 +331,34 @@ void Body2DSW::set_state(Physics2DServer::BodyState p_state, const Variant &p_va //biased_angular_velocity=Vector3(); set_active(false); } else { - if (mode != Physics2DServer::BODY_MODE_STATIC) + if (mode != PhysicsServer2D::BODY_MODE_STATIC) set_active(true); } } break; - case Physics2DServer::BODY_STATE_CAN_SLEEP: { + case PhysicsServer2D::BODY_STATE_CAN_SLEEP: { can_sleep = p_variant; - if (mode == Physics2DServer::BODY_MODE_RIGID && !active && !can_sleep) + if (mode == PhysicsServer2D::BODY_MODE_RIGID && !active && !can_sleep) set_active(true); } break; } } -Variant Body2DSW::get_state(Physics2DServer::BodyState p_state) const { +Variant Body2DSW::get_state(PhysicsServer2D::BodyState p_state) const { switch (p_state) { - case Physics2DServer::BODY_STATE_TRANSFORM: { + case PhysicsServer2D::BODY_STATE_TRANSFORM: { return get_transform(); } - case Physics2DServer::BODY_STATE_LINEAR_VELOCITY: { + case PhysicsServer2D::BODY_STATE_LINEAR_VELOCITY: { return linear_velocity; } - case Physics2DServer::BODY_STATE_ANGULAR_VELOCITY: { + case PhysicsServer2D::BODY_STATE_ANGULAR_VELOCITY: { return angular_velocity; } - case Physics2DServer::BODY_STATE_SLEEPING: { + case PhysicsServer2D::BODY_STATE_SLEEPING: { return !is_active(); } - case Physics2DServer::BODY_STATE_CAN_SLEEP: { + case PhysicsServer2D::BODY_STATE_CAN_SLEEP: { return can_sleep; } } @@ -418,7 +418,7 @@ void Body2DSW::_compute_area_gravity_and_dampenings(const Area2DSW *p_area) { void Body2DSW::integrate_forces(real_t p_step) { - if (mode == Physics2DServer::BODY_MODE_STATIC) + if (mode == PhysicsServer2D::BODY_MODE_STATIC) return; Area2DSW *def_area = get_space()->get_default_area(); @@ -435,20 +435,20 @@ void Body2DSW::integrate_forces(real_t p_step) { const AreaCMP *aa = &areas[0]; // damp_area = aa[ac-1].area; for (int i = ac - 1; i >= 0 && !stopped; i--) { - Physics2DServer::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); + PhysicsServer2D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); switch (mode) { - case Physics2DServer::AREA_SPACE_OVERRIDE_COMBINE: - case Physics2DServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { _compute_area_gravity_and_dampenings(aa[i].area); - stopped = mode == Physics2DServer::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; } break; - case Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE: - case Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { gravity = Vector2(0, 0); area_angular_damp = 0; area_linear_damp = 0; _compute_area_gravity_and_dampenings(aa[i].area); - stopped = mode == Physics2DServer::AREA_SPACE_OVERRIDE_REPLACE; + stopped = mode == PhysicsServer2D::AREA_SPACE_OVERRIDE_REPLACE; } break; default: { } @@ -478,7 +478,7 @@ void Body2DSW::integrate_forces(real_t p_step) { Vector2 motion; bool do_motion = false; - if (mode == Physics2DServer::BODY_MODE_KINEMATIC) { + if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { //compute motion, angular and etc. velocities from prev transform motion = new_transform.get_origin() - get_transform().get_origin(); @@ -521,7 +521,7 @@ void Body2DSW::integrate_forces(real_t p_step) { angular_velocity += _inv_inertia * torque * p_step; } - if (continuous_cd_mode != Physics2DServer::CCD_MODE_DISABLED) { + if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) { motion = linear_velocity * p_step; do_motion = true; @@ -545,13 +545,13 @@ void Body2DSW::integrate_forces(real_t p_step) { void Body2DSW::integrate_velocities(real_t p_step) { - if (mode == Physics2DServer::BODY_MODE_STATIC) + if (mode == PhysicsServer2D::BODY_MODE_STATIC) return; if (fi_callback) get_space()->body_add_to_state_query_list(&direct_state_query_list); - if (mode == Physics2DServer::BODY_MODE_KINEMATIC) { + if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { _set_transform(new_transform, false); _set_inv_transform(new_transform.affine_inverse()); @@ -566,10 +566,10 @@ void Body2DSW::integrate_velocities(real_t p_step) { real_t angle = get_transform().get_rotation() + total_angular_velocity * p_step; Vector2 pos = get_transform().get_origin() + total_linear_velocity * p_step; - _set_transform(Transform2D(angle, pos), continuous_cd_mode == Physics2DServer::CCD_MODE_DISABLED); + _set_transform(Transform2D(angle, pos), continuous_cd_mode == PhysicsServer2D::CCD_MODE_DISABLED); _set_inv_transform(get_transform().inverse()); - if (continuous_cd_mode != Physics2DServer::CCD_MODE_DISABLED) + if (continuous_cd_mode != PhysicsServer2D::CCD_MODE_DISABLED) new_transform = get_transform(); //_update_inertia_tensor(); @@ -588,7 +588,7 @@ void Body2DSW::wakeup_neighbours() { if (i == E->get()) continue; Body2DSW *b = n[i]; - if (b->mode != Physics2DServer::BODY_MODE_RIGID) + if (b->mode != PhysicsServer2D::BODY_MODE_RIGID) continue; if (!b->is_active()) @@ -626,9 +626,9 @@ void Body2DSW::call_queries() { bool Body2DSW::sleep_test(real_t p_step) { - if (mode == Physics2DServer::BODY_MODE_STATIC || mode == Physics2DServer::BODY_MODE_KINEMATIC) + if (mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) return true; // - else if (mode == Physics2DServer::BODY_MODE_CHARACTER) + else if (mode == PhysicsServer2D::BODY_MODE_CHARACTER) return !active; // characters and kinematic bodies don't sleep unless asked to sleep else if (!can_sleep) return false; @@ -668,7 +668,7 @@ Body2DSW::Body2DSW() : inertia_update_list(this), direct_state_query_list(this) { - mode = Physics2DServer::BODY_MODE_RIGID; + mode = PhysicsServer2D::BODY_MODE_RIGID; active = true; angular_velocity = 0; biased_angular_velocity = 0; @@ -695,7 +695,7 @@ Body2DSW::Body2DSW() : first_integration = false; still_time = 0; - continuous_cd_mode = Physics2DServer::CCD_MODE_DISABLED; + continuous_cd_mode = PhysicsServer2D::CCD_MODE_DISABLED; can_sleep = true; fi_callback = NULL; } @@ -708,7 +708,7 @@ Body2DSW::~Body2DSW() { Physics2DDirectBodyStateSW *Physics2DDirectBodyStateSW::singleton = NULL; -Physics2DDirectSpaceState *Physics2DDirectBodyStateSW::get_space_state() { +PhysicsDirectSpaceState2D *Physics2DDirectBodyStateSW::get_space_state() { return body->get_space()->get_direct_state(); } @@ -717,11 +717,11 @@ Variant Physics2DDirectBodyStateSW::get_contact_collider_shape_metadata(int p_co ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Variant()); - if (!Physics2DServerSW::singletonsw->body_owner.owns(body->contacts[p_contact_idx].collider)) { + if (!PhysicsServer2DSW::singletonsw->body_owner.owns(body->contacts[p_contact_idx].collider)) { return Variant(); } - Body2DSW *other = Physics2DServerSW::singletonsw->body_owner.getornull(body->contacts[p_contact_idx].collider); + Body2DSW *other = PhysicsServer2DSW::singletonsw->body_owner.getornull(body->contacts[p_contact_idx].collider); int sidx = body->contacts[p_contact_idx].collider_shape; if (sidx < 0 || sidx >= other->get_shape_count()) { diff --git a/servers/physics_2d/body_2d_sw.h b/servers/physics_2d/body_2d_sw.h index ea07b8260c..4a83cf9500 100644 --- a/servers/physics_2d/body_2d_sw.h +++ b/servers/physics_2d/body_2d_sw.h @@ -39,7 +39,7 @@ class Constraint2DSW; class Body2DSW : public CollisionObject2DSW { - Physics2DServer::BodyMode mode; + PhysicsServer2D::BodyMode mode; Vector2 biased_linear_velocity; real_t biased_angular_velocity; @@ -74,7 +74,7 @@ class Body2DSW : public CollisionObject2DSW { SelfList direct_state_query_list; VSet exceptions; - Physics2DServer::CCDMode continuous_cd_mode; + PhysicsServer2D::CCDMode continuous_cd_mode; bool omit_force_integration; bool active; bool can_sleep; @@ -158,7 +158,7 @@ public: _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { contacts.resize(p_size); contact_count = 0; - if (mode == Physics2DServer::BODY_MODE_KINEMATIC && p_size) set_active(true); + if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC && p_size) set_active(true); } _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } @@ -224,19 +224,19 @@ public: _FORCE_INLINE_ bool is_active() const { return active; } _FORCE_INLINE_ void wakeup() { - if ((!get_space()) || mode == Physics2DServer::BODY_MODE_STATIC || mode == Physics2DServer::BODY_MODE_KINEMATIC) + if ((!get_space()) || mode == PhysicsServer2D::BODY_MODE_STATIC || mode == PhysicsServer2D::BODY_MODE_KINEMATIC) return; set_active(true); } - void set_param(Physics2DServer::BodyParameter p_param, real_t); - real_t get_param(Physics2DServer::BodyParameter p_param) const; + void set_param(PhysicsServer2D::BodyParameter p_param, real_t); + real_t get_param(PhysicsServer2D::BodyParameter p_param) const; - void set_mode(Physics2DServer::BodyMode p_mode); - Physics2DServer::BodyMode get_mode() const; + void set_mode(PhysicsServer2D::BodyMode p_mode); + PhysicsServer2D::BodyMode get_mode() const; - void set_state(Physics2DServer::BodyState p_state, const Variant &p_variant); - Variant get_state(Physics2DServer::BodyState p_state) const; + void set_state(PhysicsServer2D::BodyState p_state, const Variant &p_variant); + Variant get_state(PhysicsServer2D::BodyState p_state) const; void set_applied_force(const Vector2 &p_force) { applied_force = p_force; } Vector2 get_applied_force() const { return applied_force; } @@ -258,8 +258,8 @@ public: applied_torque += p_torque; } - _FORCE_INLINE_ void set_continuous_collision_detection_mode(Physics2DServer::CCDMode p_mode) { continuous_cd_mode = p_mode; } - _FORCE_INLINE_ Physics2DServer::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } + _FORCE_INLINE_ void set_continuous_collision_detection_mode(PhysicsServer2D::CCDMode p_mode) { continuous_cd_mode = p_mode; } + _FORCE_INLINE_ PhysicsServer2D::CCDMode get_continuous_collision_detection_mode() const { return continuous_cd_mode; } void set_space(Space2DSW *p_space); @@ -278,9 +278,9 @@ public: _FORCE_INLINE_ Vector2 get_motion() const { - if (mode > Physics2DServer::BODY_MODE_KINEMATIC) { + if (mode > PhysicsServer2D::BODY_MODE_KINEMATIC) { return new_transform.get_origin() - get_transform().get_origin(); - } else if (mode == Physics2DServer::BODY_MODE_KINEMATIC) { + } else if (mode == PhysicsServer2D::BODY_MODE_KINEMATIC) { return get_transform().get_origin() - new_transform.get_origin(); //kinematic simulates forward } return Vector2(); @@ -341,9 +341,9 @@ void Body2DSW::add_contact(const Vector2 &p_local_pos, const Vector2 &p_local_no c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos; } -class Physics2DDirectBodyStateSW : public Physics2DDirectBodyState { +class Physics2DDirectBodyStateSW : public PhysicsDirectBodyState2D { - GDCLASS(Physics2DDirectBodyStateSW, Physics2DDirectBodyState); + GDCLASS(Physics2DDirectBodyStateSW, PhysicsDirectBodyState2D); public: static Physics2DDirectBodyStateSW *singleton; @@ -363,7 +363,7 @@ public: virtual void set_angular_velocity(real_t p_velocity) { body->set_angular_velocity(p_velocity); } virtual real_t get_angular_velocity() const { return body->get_angular_velocity(); } - virtual void set_transform(const Transform2D &p_transform) { body->set_state(Physics2DServer::BODY_STATE_TRANSFORM, p_transform); } + virtual void set_transform(const Transform2D &p_transform) { body->set_state(PhysicsServer2D::BODY_STATE_TRANSFORM, p_transform); } virtual Transform2D get_transform() const { return body->get_transform(); } virtual void add_central_force(const Vector2 &p_force) { body->add_central_force(p_force); } @@ -414,7 +414,7 @@ public: return body->contacts[p_contact_idx].collider_velocity_at_pos; } - virtual Physics2DDirectSpaceState *get_space_state(); + virtual PhysicsDirectSpaceState2D *get_space_state(); virtual real_t get_step() const { return step; } Physics2DDirectBodyStateSW() { diff --git a/servers/physics_2d/body_pair_2d_sw.cpp b/servers/physics_2d/body_pair_2d_sw.cpp index 38f33134a5..f38a76cff6 100644 --- a/servers/physics_2d/body_pair_2d_sw.cpp +++ b/servers/physics_2d/body_pair_2d_sw.cpp @@ -230,7 +230,7 @@ real_t combine_friction(Body2DSW *A, Body2DSW *B) { bool BodyPair2DSW::setup(real_t p_step) { //cannot collide - if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) { + if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) { collided = false; return false; } @@ -258,10 +258,10 @@ bool BodyPair2DSW::setup(real_t p_step) { Vector2 motion_A, motion_B; - if (A->get_continuous_collision_detection_mode() == Physics2DServer::CCD_MODE_CAST_SHAPE) { + if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_SHAPE) { motion_A = A->get_motion(); } - if (B->get_continuous_collision_detection_mode() == Physics2DServer::CCD_MODE_CAST_SHAPE) { + if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_SHAPE) { motion_B = B->get_motion(); } //faster to set than to check.. @@ -273,12 +273,12 @@ bool BodyPair2DSW::setup(real_t p_step) { //test ccd (currently just a raycast) - if (A->get_continuous_collision_detection_mode() == Physics2DServer::CCD_MODE_CAST_RAY && A->get_mode() > Physics2DServer::BODY_MODE_KINEMATIC) { + if (A->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && A->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) { if (_test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B)) collided = true; } - if (B->get_continuous_collision_detection_mode() == Physics2DServer::CCD_MODE_CAST_RAY && B->get_mode() > Physics2DServer::BODY_MODE_KINEMATIC) { + if (B->get_continuous_collision_detection_mode() == PhysicsServer2D::CCD_MODE_CAST_RAY && B->get_mode() > PhysicsServer2D::BODY_MODE_KINEMATIC) { if (_test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A, true)) collided = true; } @@ -405,7 +405,7 @@ bool BodyPair2DSW::setup(real_t p_step) { } } - if ((A->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC && B->get_mode() <= Physics2DServer::BODY_MODE_KINEMATIC)) { + if ((A->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer2D::BODY_MODE_KINEMATIC)) { c.active = false; collided = false; continue; diff --git a/servers/physics_2d/collision_object_2d_sw.cpp b/servers/physics_2d/collision_object_2d_sw.cpp index 8fb3296be6..a6891372c2 100644 --- a/servers/physics_2d/collision_object_2d_sw.cpp +++ b/servers/physics_2d/collision_object_2d_sw.cpp @@ -29,7 +29,7 @@ /*************************************************************************/ #include "collision_object_2d_sw.h" -#include "servers/physics_2d/physics_2d_server_sw.h" +#include "servers/physics_2d/physics_server_2d_sw.h" #include "space_2d_sw.h" void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_transform, bool p_disabled) { @@ -46,7 +46,7 @@ void CollisionObject2DSW::add_shape(Shape2DSW *p_shape, const Transform2D &p_tra p_shape->add_owner(this); if (!pending_shape_update_list.in_list()) { - Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); } // _update_shapes(); // _shapes_changed(); @@ -61,7 +61,7 @@ void CollisionObject2DSW::set_shape(int p_index, Shape2DSW *p_shape) { p_shape->add_owner(this); if (!pending_shape_update_list.in_list()) { - Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); } // _update_shapes(); // _shapes_changed(); @@ -81,7 +81,7 @@ void CollisionObject2DSW::set_shape_transform(int p_index, const Transform2D &p_ shapes.write[p_index].xform_inv = p_transform.affine_inverse(); if (!pending_shape_update_list.in_list()) { - Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); } // _update_shapes(); // _shapes_changed(); @@ -103,12 +103,12 @@ void CollisionObject2DSW::set_shape_as_disabled(int p_idx, bool p_disabled) { space->get_broadphase()->remove(shape.bpid); shape.bpid = 0; if (!pending_shape_update_list.in_list()) { - Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); } //_update_shapes(); } else if (!p_disabled && shape.bpid == 0) { if (!pending_shape_update_list.in_list()) { - Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); } //_update_shapes(); // automatically adds shape with bpid == 0 } @@ -142,7 +142,7 @@ void CollisionObject2DSW::remove_shape(int p_index) { shapes.remove(p_index); if (!pending_shape_update_list.in_list()) { - Physics2DServerSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); + PhysicsServer2DSW::singletonsw->pending_shape_update_list.add(&pending_shape_update_list); } // _update_shapes(); // _shapes_changed(); diff --git a/servers/physics_2d/collision_object_2d_sw.h b/servers/physics_2d/collision_object_2d_sw.h index 3f9d19bbab..98105a7c0e 100644 --- a/servers/physics_2d/collision_object_2d_sw.h +++ b/servers/physics_2d/collision_object_2d_sw.h @@ -33,7 +33,7 @@ #include "broad_phase_2d_sw.h" #include "core/self_list.h" -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" #include "shape_2d_sw.h" class Space2DSW; diff --git a/servers/physics_2d/collision_solver_2d_sat.cpp b/servers/physics_2d/collision_solver_2d_sat.cpp index da67fcc770..217c93c6da 100644 --- a/servers/physics_2d/collision_solver_2d_sat.cpp +++ b/servers/physics_2d/collision_solver_2d_sat.cpp @@ -1042,16 +1042,16 @@ static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) { - Physics2DServer::ShapeType type_A = p_shape_A->get_type(); + PhysicsServer2D::ShapeType type_A = p_shape_A->get_type(); - ERR_FAIL_COND_V(type_A == Physics2DServer::SHAPE_LINE, false); - //ERR_FAIL_COND_V(type_A==Physics2DServer::SHAPE_RAY,false); + ERR_FAIL_COND_V(type_A == PhysicsServer2D::SHAPE_LINE, false); + //ERR_FAIL_COND_V(type_A==PhysicsServer2D::SHAPE_RAY,false); ERR_FAIL_COND_V(p_shape_A->is_concave(), false); - Physics2DServer::ShapeType type_B = p_shape_B->get_type(); + PhysicsServer2D::ShapeType type_B = p_shape_B->get_type(); - ERR_FAIL_COND_V(type_B == Physics2DServer::SHAPE_LINE, false); - //ERR_FAIL_COND_V(type_B==Physics2DServer::SHAPE_RAY,false); + ERR_FAIL_COND_V(type_B == PhysicsServer2D::SHAPE_LINE, false); + //ERR_FAIL_COND_V(type_B==PhysicsServer2D::SHAPE_RAY,false); ERR_FAIL_COND_V(p_shape_B->is_concave(), false); static const CollisionFunc collision_table[5][5] = { diff --git a/servers/physics_2d/collision_solver_2d_sw.cpp b/servers/physics_2d/collision_solver_2d_sw.cpp index 60cca6f825..f117dcbfe5 100644 --- a/servers/physics_2d/collision_solver_2d_sw.cpp +++ b/servers/physics_2d/collision_solver_2d_sw.cpp @@ -37,7 +37,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { const LineShape2DSW *line = static_cast(p_shape_A); - if (p_shape_B->get_type() == Physics2DServer::SHAPE_LINE) + if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_LINE) return false; Vector2 n = p_transform_A.basis_xform(line->get_normal()).normalized(); @@ -75,7 +75,7 @@ bool CollisionSolver2DSW::solve_static_line(const Shape2DSW *p_shape_A, const Tr bool CollisionSolver2DSW::solve_raycast(const Shape2DSW *p_shape_A, const Vector2 &p_motion_A, const Transform2D &p_transform_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, Vector2 *sep_axis) { const RayShape2DSW *ray = static_cast(p_shape_A); - if (p_shape_B->get_type() == Physics2DServer::SHAPE_RAY) + if (p_shape_B->get_type() == PhysicsServer2D::SHAPE_RAY) return false; Vector2 from = p_transform_A.get_origin(); @@ -195,8 +195,8 @@ bool CollisionSolver2DSW::solve_concave(const Shape2DSW *p_shape_A, const Transf bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CallbackResult p_result_callback, void *p_userdata, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) { - Physics2DServer::ShapeType type_A = p_shape_A->get_type(); - Physics2DServer::ShapeType type_B = p_shape_B->get_type(); + PhysicsServer2D::ShapeType type_A = p_shape_A->get_type(); + PhysicsServer2D::ShapeType type_B = p_shape_B->get_type(); bool concave_A = p_shape_A->is_concave(); bool concave_B = p_shape_B->is_concave(); real_t margin_A = p_margin_A, margin_B = p_margin_B; @@ -210,9 +210,9 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p swap = true; } - if (type_A == Physics2DServer::SHAPE_LINE) { + if (type_A == PhysicsServer2D::SHAPE_LINE) { - if (type_B == Physics2DServer::SHAPE_LINE || type_B == Physics2DServer::SHAPE_RAY) { + if (type_B == PhysicsServer2D::SHAPE_LINE || type_B == PhysicsServer2D::SHAPE_RAY) { return false; } @@ -222,9 +222,9 @@ bool CollisionSolver2DSW::solve(const Shape2DSW *p_shape_A, const Transform2D &p return solve_static_line(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); } - } else if (type_A == Physics2DServer::SHAPE_RAY) { + } else if (type_A == PhysicsServer2D::SHAPE_RAY) { - if (type_B == Physics2DServer::SHAPE_RAY) { + if (type_B == PhysicsServer2D::SHAPE_RAY) { return false; //no ray-ray } diff --git a/servers/physics_2d/joints_2d_sw.cpp b/servers/physics_2d/joints_2d_sw.cpp index 02b3502242..4524629d50 100644 --- a/servers/physics_2d/joints_2d_sw.cpp +++ b/servers/physics_2d/joints_2d_sw.cpp @@ -171,15 +171,15 @@ void PinJoint2DSW::solve(real_t p_step) { P += impulse; } -void PinJoint2DSW::set_param(Physics2DServer::PinJointParam p_param, real_t p_value) { +void PinJoint2DSW::set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value) { - if (p_param == Physics2DServer::PIN_JOINT_SOFTNESS) + if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) softness = p_value; } -real_t PinJoint2DSW::get_param(Physics2DServer::PinJointParam p_param) const { +real_t PinJoint2DSW::get_param(PhysicsServer2D::PinJointParam p_param) const { - if (p_param == Physics2DServer::PIN_JOINT_SOFTNESS) + if (p_param == PhysicsServer2D::PIN_JOINT_SOFTNESS) return softness; ERR_FAIL_V(0); } @@ -396,38 +396,38 @@ void DampedSpringJoint2DSW::solve(real_t p_step) { B->apply_impulse(rB, j); } -void DampedSpringJoint2DSW::set_param(Physics2DServer::DampedStringParam p_param, real_t p_value) { +void DampedSpringJoint2DSW::set_param(PhysicsServer2D::DampedStringParam p_param, real_t p_value) { switch (p_param) { - case Physics2DServer::DAMPED_STRING_REST_LENGTH: { + case PhysicsServer2D::DAMPED_STRING_REST_LENGTH: { rest_length = p_value; } break; - case Physics2DServer::DAMPED_STRING_DAMPING: { + case PhysicsServer2D::DAMPED_STRING_DAMPING: { damping = p_value; } break; - case Physics2DServer::DAMPED_STRING_STIFFNESS: { + case PhysicsServer2D::DAMPED_STRING_STIFFNESS: { stiffness = p_value; } break; } } -real_t DampedSpringJoint2DSW::get_param(Physics2DServer::DampedStringParam p_param) const { +real_t DampedSpringJoint2DSW::get_param(PhysicsServer2D::DampedStringParam p_param) const { switch (p_param) { - case Physics2DServer::DAMPED_STRING_REST_LENGTH: { + case PhysicsServer2D::DAMPED_STRING_REST_LENGTH: { return rest_length; } break; - case Physics2DServer::DAMPED_STRING_DAMPING: { + case PhysicsServer2D::DAMPED_STRING_DAMPING: { return damping; } break; - case Physics2DServer::DAMPED_STRING_STIFFNESS: { + case PhysicsServer2D::DAMPED_STRING_STIFFNESS: { return stiffness; } break; diff --git a/servers/physics_2d/joints_2d_sw.h b/servers/physics_2d/joints_2d_sw.h index 3e8fc1a29f..f4aeb6e3c8 100644 --- a/servers/physics_2d/joints_2d_sw.h +++ b/servers/physics_2d/joints_2d_sw.h @@ -50,7 +50,7 @@ public: _FORCE_INLINE_ void set_max_bias(real_t p_bias) { max_bias = p_bias; } _FORCE_INLINE_ real_t get_max_bias() const { return max_bias; } - virtual Physics2DServer::JointType get_type() const = 0; + virtual PhysicsServer2D::JointType get_type() const = 0; Joint2DSW(Body2DSW **p_body_ptr = NULL, int p_body_count = 0) : Constraint2DSW(p_body_ptr, p_body_count) { bias = 0; @@ -78,13 +78,13 @@ class PinJoint2DSW : public Joint2DSW { real_t softness; public: - virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_PIN; } + virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_PIN; } virtual bool setup(real_t p_step); virtual void solve(real_t p_step); - void set_param(Physics2DServer::PinJointParam p_param, real_t p_value); - real_t get_param(Physics2DServer::PinJointParam p_param) const; + void set_param(PhysicsServer2D::PinJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer2D::PinJointParam p_param) const; PinJoint2DSW(const Vector2 &p_pos, Body2DSW *p_body_a, Body2DSW *p_body_b = NULL); ~PinJoint2DSW(); @@ -116,7 +116,7 @@ class GrooveJoint2DSW : public Joint2DSW { bool correct; public: - virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_GROOVE; } + virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_GROOVE; } virtual bool setup(real_t p_step); virtual void solve(real_t p_step); @@ -150,13 +150,13 @@ class DampedSpringJoint2DSW : public Joint2DSW { real_t v_coef; public: - virtual Physics2DServer::JointType get_type() const { return Physics2DServer::JOINT_DAMPED_SPRING; } + virtual PhysicsServer2D::JointType get_type() const { return PhysicsServer2D::JOINT_DAMPED_SPRING; } virtual bool setup(real_t p_step); virtual void solve(real_t p_step); - void set_param(Physics2DServer::DampedStringParam p_param, real_t p_value); - real_t get_param(Physics2DServer::DampedStringParam p_param) const; + void set_param(PhysicsServer2D::DampedStringParam p_param, real_t p_value); + real_t get_param(PhysicsServer2D::DampedStringParam p_param) const; DampedSpringJoint2DSW(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, Body2DSW *p_body_a, Body2DSW *p_body_b); ~DampedSpringJoint2DSW(); diff --git a/servers/physics_2d/physics_2d_server_sw.cpp b/servers/physics_2d/physics_2d_server_sw.cpp deleted file mode 100644 index baeb3f76b0..0000000000 --- a/servers/physics_2d/physics_2d_server_sw.cpp +++ /dev/null @@ -1,1464 +0,0 @@ -/*************************************************************************/ -/* physics_2d_server_sw.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_2d_server_sw.h" -#include "broad_phase_2d_basic.h" -#include "broad_phase_2d_hash_grid.h" -#include "collision_solver_2d_sw.h" -#include "core/debugger/engine_debugger.h" -#include "core/os/os.h" -#include "core/project_settings.h" - -#define FLUSH_QUERY_CHECK(m_object) \ - ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); - -RID Physics2DServerSW::_shape_create(ShapeType p_shape) { - - Shape2DSW *shape = NULL; - switch (p_shape) { - - case SHAPE_LINE: { - - shape = memnew(LineShape2DSW); - } break; - case SHAPE_RAY: { - - shape = memnew(RayShape2DSW); - } break; - case SHAPE_SEGMENT: { - - shape = memnew(SegmentShape2DSW); - } break; - case SHAPE_CIRCLE: { - - shape = memnew(CircleShape2DSW); - } break; - case SHAPE_RECTANGLE: { - - shape = memnew(RectangleShape2DSW); - } break; - case SHAPE_CAPSULE: { - - shape = memnew(CapsuleShape2DSW); - } break; - case SHAPE_CONVEX_POLYGON: { - - shape = memnew(ConvexPolygonShape2DSW); - } break; - case SHAPE_CONCAVE_POLYGON: { - - shape = memnew(ConcavePolygonShape2DSW); - } break; - case SHAPE_CUSTOM: { - - ERR_FAIL_V(RID()); - - } break; - } - - RID id = shape_owner.make_rid(shape); - shape->set_self(id); - - return id; -} - -RID Physics2DServerSW::line_shape_create() { - - return _shape_create(SHAPE_LINE); -} - -RID Physics2DServerSW::ray_shape_create() { - - return _shape_create(SHAPE_RAY); -} -RID Physics2DServerSW::segment_shape_create() { - - return _shape_create(SHAPE_SEGMENT); -} -RID Physics2DServerSW::circle_shape_create() { - - return _shape_create(SHAPE_CIRCLE); -} -RID Physics2DServerSW::rectangle_shape_create() { - - return _shape_create(SHAPE_RECTANGLE); -} -RID Physics2DServerSW::capsule_shape_create() { - - return _shape_create(SHAPE_CAPSULE); -} - -RID Physics2DServerSW::convex_polygon_shape_create() { - - return _shape_create(SHAPE_CONVEX_POLYGON); -} -RID Physics2DServerSW::concave_polygon_shape_create() { - - return _shape_create(SHAPE_CONCAVE_POLYGON); -} - -void Physics2DServerSW::shape_set_data(RID p_shape, const Variant &p_data) { - - Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - shape->set_data(p_data); -}; - -void Physics2DServerSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { - - Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - shape->set_custom_bias(p_bias); -} - -Physics2DServer::ShapeType Physics2DServerSW::shape_get_type(RID p_shape) const { - - const Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); - return shape->get_type(); -}; - -Variant Physics2DServerSW::shape_get_data(RID p_shape) const { - - const Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, Variant()); - ERR_FAIL_COND_V(!shape->is_configured(), Variant()); - return shape->get_data(); -}; - -real_t Physics2DServerSW::shape_get_custom_solver_bias(RID p_shape) const { - - const Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND_V(!shape, 0); - return shape->get_custom_bias(); -} - -void Physics2DServerSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { - - CollCbkData *cbk = (CollCbkData *)p_userdata; - - if (cbk->max == 0) - return; - - if (cbk->valid_dir != Vector2()) { - if (p_point_A.distance_squared_to(p_point_B) > cbk->valid_depth * cbk->valid_depth) { - cbk->invalid_by_dir++; - return; - } - Vector2 rel_dir = (p_point_A - p_point_B).normalized(); - - if (cbk->valid_dir.dot(rel_dir) < Math_SQRT12) { //sqrt(2)/2.0 - 45 degrees - cbk->invalid_by_dir++; - - /* - print_line("A: "+p_point_A); - print_line("B: "+p_point_B); - print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B)))); - print_line("resnorm: "+(p_point_A-p_point_B).normalized()); - print_line("distance: "+rtos(p_point_A.distance_to(p_point_B))); - */ - return; - } - } - - if (cbk->amount == cbk->max) { - //find least deep - real_t min_depth = 1e20; - int min_depth_idx = 0; - for (int i = 0; i < cbk->amount; i++) { - - real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); - if (d < min_depth) { - min_depth = d; - min_depth_idx = i; - } - } - - real_t d = p_point_A.distance_squared_to(p_point_B); - if (d < min_depth) - return; - cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; - cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; - cbk->passed++; - - } else { - - cbk->ptr[cbk->amount * 2 + 0] = p_point_A; - cbk->ptr[cbk->amount * 2 + 1] = p_point_B; - cbk->amount++; - cbk->passed++; - } -} - -bool Physics2DServerSW::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) { - - Shape2DSW *shape_A = shape_owner.getornull(p_shape_A); - ERR_FAIL_COND_V(!shape_A, false); - Shape2DSW *shape_B = shape_owner.getornull(p_shape_B); - ERR_FAIL_COND_V(!shape_B, false); - - if (p_result_max == 0) { - - return CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, NULL, NULL); - } - - CollCbkData cbk; - cbk.max = p_result_max; - cbk.amount = 0; - cbk.passed = 0; - cbk.ptr = r_results; - - bool res = CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk); - r_result_count = cbk.amount; - return res; -} - -RID Physics2DServerSW::space_create() { - - Space2DSW *space = memnew(Space2DSW); - RID id = space_owner.make_rid(space); - space->set_self(id); - RID area_id = area_create(); - Area2DSW *area = area_owner.getornull(area_id); - ERR_FAIL_COND_V(!area, RID()); - space->set_default_area(area); - area->set_space(space); - area->set_priority(-1); - - return id; -}; - -void Physics2DServerSW::space_set_active(RID p_space, bool p_active) { - - Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - if (p_active) - active_spaces.insert(space); - else - active_spaces.erase(space); -} - -bool Physics2DServerSW::space_is_active(RID p_space) const { - - const Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, false); - - return active_spaces.has(space); -} - -void Physics2DServerSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { - - Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - - space->set_param(p_param, p_value); -} - -real_t Physics2DServerSW::space_get_param(RID p_space, SpaceParameter p_param) const { - - const Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_param(p_param); -} - -void Physics2DServerSW::space_set_debug_contacts(RID p_space, int p_max_contacts) { - - Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - space->set_debug_contacts(p_max_contacts); -} - -Vector Physics2DServerSW::space_get_contacts(RID p_space) const { - - Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, Vector()); - return space->get_debug_contacts(); -} - -int Physics2DServerSW::space_get_contact_count(RID p_space) const { - - Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, 0); - return space->get_debug_contact_count(); -} - -Physics2DDirectSpaceState *Physics2DServerSW::space_get_direct_state(RID p_space) { - - Space2DSW *space = space_owner.getornull(p_space); - ERR_FAIL_COND_V(!space, NULL); - ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), NULL, "Space state is inaccessible right now, wait for iteration or physics process notification."); - - return space->get_direct_state(); -} - -RID Physics2DServerSW::area_create() { - - Area2DSW *area = memnew(Area2DSW); - RID rid = area_owner.make_rid(area); - area->set_self(rid); - return rid; -}; - -void Physics2DServerSW::area_set_space(RID p_area, RID p_space) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - Space2DSW *space = NULL; - if (p_space.is_valid()) { - space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - } - - if (area->get_space() == space) - return; //pointless - - area->clear_constraints(); - area->set_space(space); -}; - -RID Physics2DServerSW::area_get_space(RID p_area) const { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, RID()); - - Space2DSW *space = area->get_space(); - if (!space) - return RID(); - return space->get_self(); -}; - -void Physics2DServerSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_space_override_mode(p_mode); -} - -Physics2DServer::AreaSpaceOverrideMode Physics2DServerSW::area_get_space_override_mode(RID p_area) const { - - const Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); - - return area->get_space_override_mode(); -} - -void Physics2DServerSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - - area->add_shape(shape, p_transform, p_disabled); -} - -void Physics2DServerSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - area->set_shape(p_shape_idx, shape); -} -void Physics2DServerSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_shape_transform(p_shape_idx, p_transform); -} - -void Physics2DServerSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - ERR_FAIL_INDEX(p_shape, area->get_shape_count()); - FLUSH_QUERY_CHECK(area); - - area->set_shape_as_disabled(p_shape, p_disabled); -} - -int Physics2DServerSW::area_get_shape_count(RID p_area) const { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, -1); - - return area->get_shape_count(); -} -RID Physics2DServerSW::area_get_shape(RID p_area, int p_shape_idx) const { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, RID()); - - Shape2DSW *shape = area->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} -Transform2D Physics2DServerSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, Transform2D()); - - return area->get_shape_transform(p_shape_idx); -} - -void Physics2DServerSW::area_remove_shape(RID p_area, int p_shape_idx) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->remove_shape(p_shape_idx); -} - -void Physics2DServerSW::area_clear_shapes(RID p_area) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - while (area->get_shape_count()) - area->remove_shape(0); -} - -void Physics2DServerSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { - - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_instance_id(p_id); -} -ObjectID Physics2DServerSW::area_get_object_instance_id(RID p_area) const { - - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, ObjectID()); - return area->get_instance_id(); -} - -void Physics2DServerSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) { - - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_canvas_instance_id(p_id); -} -ObjectID Physics2DServerSW::area_get_canvas_instance_id(RID p_area) const { - - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, ObjectID()); - return area->get_canvas_instance_id(); -} - -void Physics2DServerSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { - - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_param(p_param, p_value); -}; - -void Physics2DServerSW::area_set_transform(RID p_area, const Transform2D &p_transform) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_transform(p_transform); -}; - -Variant Physics2DServerSW::area_get_param(RID p_area, AreaParameter p_param) const { - - if (space_owner.owns(p_area)) { - Space2DSW *space = space_owner.getornull(p_area); - p_area = space->get_default_area()->get_self(); - } - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, Variant()); - - return area->get_param(p_param); -}; - -Transform2D Physics2DServerSW::area_get_transform(RID p_area) const { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND_V(!area, Transform2D()); - - return area->get_transform(); -}; - -void Physics2DServerSW::area_set_pickable(RID p_area, bool p_pickable) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - area->set_pickable(p_pickable); -} - -void Physics2DServerSW::area_set_monitorable(RID p_area, bool p_monitorable) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - FLUSH_QUERY_CHECK(area); - - area->set_monitorable(p_monitorable); -} - -void Physics2DServerSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_mask(p_mask); -} - -void Physics2DServerSW::area_set_collision_layer(RID p_area, uint32_t p_layer) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_collision_layer(p_layer); -} - -void Physics2DServerSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -void Physics2DServerSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { - - Area2DSW *area = area_owner.getornull(p_area); - ERR_FAIL_COND(!area); - - area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); -} - -/* BODY API */ - -RID Physics2DServerSW::body_create() { - - Body2DSW *body = memnew(Body2DSW); - RID rid = body_owner.make_rid(body); - body->set_self(rid); - return rid; -} - -void Physics2DServerSW::body_set_space(RID p_body, RID p_space) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - Space2DSW *space = NULL; - if (p_space.is_valid()) { - space = space_owner.getornull(p_space); - ERR_FAIL_COND(!space); - } - - if (body->get_space() == space) - return; //pointless - - body->clear_constraint_map(); - body->set_space(space); -}; - -RID Physics2DServerSW::body_get_space(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, RID()); - - Space2DSW *space = body->get_space(); - if (!space) - return RID(); - return space->get_self(); -}; - -void Physics2DServerSW::body_set_mode(RID p_body, BodyMode p_mode) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - FLUSH_QUERY_CHECK(body); - - body->set_mode(p_mode); -}; - -Physics2DServer::BodyMode Physics2DServerSW::body_get_mode(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); - - return body->get_mode(); -}; - -void Physics2DServerSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - - body->add_shape(shape, p_transform, p_disabled); -} - -void Physics2DServerSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - Shape2DSW *shape = shape_owner.getornull(p_shape); - ERR_FAIL_COND(!shape); - ERR_FAIL_COND(!shape->is_configured()); - - body->set_shape(p_shape_idx, shape); -} -void Physics2DServerSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_shape_transform(p_shape_idx, p_transform); -} - -void Physics2DServerSW::body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_shape_metadata(p_shape_idx, p_metadata); -} - -Variant Physics2DServerSW::body_get_shape_metadata(RID p_body, int p_shape_idx) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Variant()); - return body->get_shape_metadata(p_shape_idx); -} - -int Physics2DServerSW::body_get_shape_count(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, -1); - - return body->get_shape_count(); -} -RID Physics2DServerSW::body_get_shape(RID p_body, int p_shape_idx) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, RID()); - - Shape2DSW *shape = body->get_shape(p_shape_idx); - ERR_FAIL_COND_V(!shape, RID()); - - return shape->get_self(); -} -Transform2D Physics2DServerSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Transform2D()); - - return body->get_shape_transform(p_shape_idx); -} - -void Physics2DServerSW::body_remove_shape(RID p_body, int p_shape_idx) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->remove_shape(p_shape_idx); -} - -void Physics2DServerSW::body_clear_shapes(RID p_body) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - while (body->get_shape_count()) - body->remove_shape(0); -} - -void Physics2DServerSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); - FLUSH_QUERY_CHECK(body); - - body->set_shape_as_disabled(p_shape_idx, p_disabled); -} -void Physics2DServerSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); - FLUSH_QUERY_CHECK(body); - - body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin); -} - -void Physics2DServerSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_continuous_collision_detection_mode(p_mode); -} - -Physics2DServerSW::CCDMode Physics2DServerSW::body_get_continuous_collision_detection_mode(RID p_body) const { - - const Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED); - - return body->get_continuous_collision_detection_mode(); -} - -void Physics2DServerSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_instance_id(p_id); -}; - -ObjectID Physics2DServerSW::body_get_object_instance_id(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, ObjectID()); - - return body->get_instance_id(); -}; - -void Physics2DServerSW::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_canvas_instance_id(p_id); -}; - -ObjectID Physics2DServerSW::body_get_canvas_instance_id(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, ObjectID()); - - return body->get_canvas_instance_id(); -}; - -void Physics2DServerSW::body_set_collision_layer(RID p_body, uint32_t p_layer) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_collision_layer(p_layer); -}; - -uint32_t Physics2DServerSW::body_get_collision_layer(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_layer(); -}; - -void Physics2DServerSW::body_set_collision_mask(RID p_body, uint32_t p_mask) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_collision_mask(p_mask); -}; - -uint32_t Physics2DServerSW::body_get_collision_mask(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_collision_mask(); -}; - -void Physics2DServerSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_param(p_param, p_value); -}; - -real_t Physics2DServerSW::body_get_param(RID p_body, BodyParameter p_param) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_param(p_param); -}; - -void Physics2DServerSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_state(p_state, p_variant); -}; - -Variant Physics2DServerSW::body_get_state(RID p_body, BodyState p_state) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Variant()); - - return body->get_state(p_state); -}; - -void Physics2DServerSW::body_set_applied_force(RID p_body, const Vector2 &p_force) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_force(p_force); - body->wakeup(); -}; - -Vector2 Physics2DServerSW::body_get_applied_force(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, Vector2()); - return body->get_applied_force(); -}; - -void Physics2DServerSW::body_set_applied_torque(RID p_body, real_t p_torque) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_applied_torque(p_torque); - body->wakeup(); -}; - -real_t Physics2DServerSW::body_get_applied_torque(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - - return body->get_applied_torque(); -}; - -void Physics2DServerSW::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) { - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->apply_central_impulse(p_impulse); - body->wakeup(); -} - -void Physics2DServerSW::body_apply_torque_impulse(RID p_body, real_t p_torque) { - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_torque_impulse(p_torque); -} - -void Physics2DServerSW::body_apply_impulse(RID p_body, const Vector2 &p_pos, const Vector2 &p_impulse) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - body->apply_impulse(p_pos, p_impulse); - body->wakeup(); -}; - -void Physics2DServerSW::body_add_central_force(RID p_body, const Vector2 &p_force) { - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_central_force(p_force); - body->wakeup(); -}; - -void Physics2DServerSW::body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_force(p_offset, p_force); - body->wakeup(); -}; - -void Physics2DServerSW::body_add_torque(RID p_body, real_t p_torque) { - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_torque(p_torque); - body->wakeup(); -}; - -void Physics2DServerSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - _update_shapes(); - - Vector2 v = body->get_linear_velocity(); - Vector2 axis = p_axis_velocity.normalized(); - v -= axis * axis.dot(v); - v += p_axis_velocity; - body->set_linear_velocity(v); - body->wakeup(); -}; - -void Physics2DServerSW::body_add_collision_exception(RID p_body, RID p_body_b) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->add_exception(p_body_b); - body->wakeup(); -}; - -void Physics2DServerSW::body_remove_collision_exception(RID p_body, RID p_body_b) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->remove_exception(p_body_b); - body->wakeup(); -}; - -void Physics2DServerSW::body_get_collision_exceptions(RID p_body, List *p_exceptions) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - for (int i = 0; i < body->get_exceptions().size(); i++) { - p_exceptions->push_back(body->get_exceptions()[i]); - } -}; - -void Physics2DServerSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); -}; - -real_t Physics2DServerSW::body_get_contacts_reported_depth_threshold(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, 0); - return 0; -}; - -void Physics2DServerSW::body_set_omit_force_integration(RID p_body, bool p_omit) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - - body->set_omit_force_integration(p_omit); -}; - -bool Physics2DServerSW::body_is_omitting_force_integration(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - return body->get_omit_force_integration(); -}; - -void Physics2DServerSW::body_set_max_contacts_reported(RID p_body, int p_contacts) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_max_contacts_reported(p_contacts); -} - -int Physics2DServerSW::body_get_max_contacts_reported(RID p_body) const { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, -1); - return body->get_max_contacts_reported(); -} - -void Physics2DServerSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); -} - -bool Physics2DServerSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false); - - return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); -} - -void Physics2DServerSW::body_set_pickable(RID p_body, bool p_pickable) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND(!body); - body->set_pickable(p_pickable); -} - -bool Physics2DServerSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_COND_V(!body->get_space(), false); - ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - - _update_shapes(); - - return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes); -} - -int Physics2DServerSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, false); - ERR_FAIL_COND_V(!body->get_space(), false); - ERR_FAIL_COND_V(body->get_space()->is_locked(), false); - - return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); -} - -Physics2DDirectBodyState *Physics2DServerSW::body_get_direct_state(RID p_body) { - - ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - if (!body_owner.owns(p_body)) - return NULL; - - Body2DSW *body = body_owner.getornull(p_body); - ERR_FAIL_COND_V(!body, NULL); - ERR_FAIL_COND_V(!body->get_space(), NULL); - ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification."); - - direct_state->body = body; - return direct_state; -} - -/* JOINT API */ - -void Physics2DServerSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) { - - Joint2DSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - - switch (p_param) { - case JOINT_PARAM_BIAS: joint->set_bias(p_value); break; - case JOINT_PARAM_MAX_BIAS: joint->set_max_bias(p_value); break; - case JOINT_PARAM_MAX_FORCE: joint->set_max_force(p_value); break; - } -} - -real_t Physics2DServerSW::joint_get_param(RID p_joint, JointParam p_param) const { - - const Joint2DSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, -1); - - switch (p_param) { - case JOINT_PARAM_BIAS: return joint->get_bias(); break; - case JOINT_PARAM_MAX_BIAS: return joint->get_max_bias(); break; - case JOINT_PARAM_MAX_FORCE: return joint->get_max_force(); break; - } - - return 0; -} - -void Physics2DServerSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { - Joint2DSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!joint); - - joint->disable_collisions_between_bodies(p_disable); - - if (2 == joint->get_body_count()) { - Body2DSW *body_a = *joint->get_body_ptr(); - Body2DSW *body_b = *(joint->get_body_ptr() + 1); - - if (p_disable) { - body_add_collision_exception(body_a->get_self(), body_b->get_self()); - body_add_collision_exception(body_b->get_self(), body_a->get_self()); - } else { - body_remove_collision_exception(body_a->get_self(), body_b->get_self()); - body_remove_collision_exception(body_b->get_self(), body_a->get_self()); - } - } -} - -bool Physics2DServerSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { - const Joint2DSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, true); - - return joint->is_disabled_collisions_between_bodies(); -} - -RID Physics2DServerSW::pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b) { - - Body2DSW *A = body_owner.getornull(p_body_a); - ERR_FAIL_COND_V(!A, RID()); - Body2DSW *B = NULL; - if (body_owner.owns(p_body_b)) { - B = body_owner.getornull(p_body_b); - ERR_FAIL_COND_V(!B, RID()); - } - - Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B)); - RID self = joint_owner.make_rid(joint); - joint->set_self(self); - - return self; -} - -RID Physics2DServerSW::groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) { - - Body2DSW *A = body_owner.getornull(p_body_a); - ERR_FAIL_COND_V(!A, RID()); - - Body2DSW *B = body_owner.getornull(p_body_b); - ERR_FAIL_COND_V(!B, RID()); - - Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B)); - RID self = joint_owner.make_rid(joint); - joint->set_self(self); - return self; -} - -RID Physics2DServerSW::damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) { - - Body2DSW *A = body_owner.getornull(p_body_a); - ERR_FAIL_COND_V(!A, RID()); - - Body2DSW *B = body_owner.getornull(p_body_b); - ERR_FAIL_COND_V(!B, RID()); - - Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B)); - RID self = joint_owner.make_rid(joint); - joint->set_self(self); - return self; -} - -void Physics2DServerSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { - - Joint2DSW *j = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!j); - ERR_FAIL_COND(j->get_type() != JOINT_PIN); - - PinJoint2DSW *pin_joint = static_cast(j); - pin_joint->set_param(p_param, p_value); -} - -real_t Physics2DServerSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { - Joint2DSW *j = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!j, 0); - ERR_FAIL_COND_V(j->get_type() != JOINT_PIN, 0); - - PinJoint2DSW *pin_joint = static_cast(j); - return pin_joint->get_param(p_param); -} - -void Physics2DServerSW::damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value) { - - Joint2DSW *j = joint_owner.getornull(p_joint); - ERR_FAIL_COND(!j); - ERR_FAIL_COND(j->get_type() != JOINT_DAMPED_SPRING); - - DampedSpringJoint2DSW *dsj = static_cast(j); - dsj->set_param(p_param, p_value); -} - -real_t Physics2DServerSW::damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const { - - Joint2DSW *j = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!j, 0); - ERR_FAIL_COND_V(j->get_type() != JOINT_DAMPED_SPRING, 0); - - DampedSpringJoint2DSW *dsj = static_cast(j); - return dsj->get_param(p_param); -} - -Physics2DServer::JointType Physics2DServerSW::joint_get_type(RID p_joint) const { - - Joint2DSW *joint = joint_owner.getornull(p_joint); - ERR_FAIL_COND_V(!joint, JOINT_PIN); - - return joint->get_type(); -} - -void Physics2DServerSW::free(RID p_rid) { - - _update_shapes(); // just in case - - if (shape_owner.owns(p_rid)) { - - Shape2DSW *shape = shape_owner.getornull(p_rid); - - while (shape->get_owners().size()) { - ShapeOwner2DSW *so = shape->get_owners().front()->key(); - so->remove_shape(shape); - } - - shape_owner.free(p_rid); - memdelete(shape); - } else if (body_owner.owns(p_rid)) { - - Body2DSW *body = body_owner.getornull(p_rid); - - /* - if (body->get_state_query()) - _clear_query(body->get_state_query()); - - if (body->get_direct_state_query()) - _clear_query(body->get_direct_state_query()); - */ - - body_set_space(p_rid, RID()); - - while (body->get_shape_count()) { - - body->remove_shape(0); - } - - body_owner.free(p_rid); - memdelete(body); - - } else if (area_owner.owns(p_rid)) { - - Area2DSW *area = area_owner.getornull(p_rid); - - /* - if (area->get_monitor_query()) - _clear_query(area->get_monitor_query()); - */ - - area->set_space(NULL); - - while (area->get_shape_count()) { - - area->remove_shape(0); - } - - area_owner.free(p_rid); - memdelete(area); - } else if (space_owner.owns(p_rid)) { - - Space2DSW *space = space_owner.getornull(p_rid); - - while (space->get_objects().size()) { - CollisionObject2DSW *co = (CollisionObject2DSW *)space->get_objects().front()->get(); - co->set_space(NULL); - } - - active_spaces.erase(space); - free(space->get_default_area()->get_self()); - space_owner.free(p_rid); - memdelete(space); - } else if (joint_owner.owns(p_rid)) { - - Joint2DSW *joint = joint_owner.getornull(p_rid); - - joint_owner.free(p_rid); - memdelete(joint); - - } else { - - ERR_FAIL_MSG("Invalid ID."); - } -}; - -void Physics2DServerSW::set_active(bool p_active) { - - active = p_active; -}; - -void Physics2DServerSW::init() { - - doing_sync = false; - last_step = 0.001; - iterations = 8; // 8? - stepper = memnew(Step2DSW); - direct_state = memnew(Physics2DDirectBodyStateSW); -}; - -void Physics2DServerSW::step(real_t p_step) { - - if (!active) - return; - - _update_shapes(); - - doing_sync = false; - - last_step = p_step; - Physics2DDirectBodyStateSW::singleton->step = p_step; - island_count = 0; - active_objects = 0; - collision_pairs = 0; - for (Set::Element *E = active_spaces.front(); E; E = E->next()) { - - stepper->step((Space2DSW *)E->get(), p_step, iterations); - island_count += E->get()->get_island_count(); - active_objects += E->get()->get_active_objects(); - collision_pairs += E->get()->get_collision_pairs(); - } -}; - -void Physics2DServerSW::sync() { - - doing_sync = true; -}; - -void Physics2DServerSW::flush_queries() { - - if (!active) - return; - - flushing_queries = true; - - uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); - - for (Set::Element *E = active_spaces.front(); E; E = E->next()) { - - Space2DSW *space = (Space2DSW *)E->get(); - space->call_queries(); - } - - flushing_queries = false; - - if (EngineDebugger::is_profiling("servers")) { - - uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX]; - static const char *time_name[Space2DSW::ELAPSED_TIME_MAX] = { - "integrate_forces", - "generate_islands", - "setup_constraints", - "solve_constraints", - "integrate_velocities" - }; - - for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { - total_time[i] = 0; - } - - for (Set::Element *E = active_spaces.front(); E; E = E->next()) { - - for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { - total_time[i] += E->get()->get_elapsed_time(Space2DSW::ElapsedTime(i)); - } - } - - Array values; - values.resize(Space2DSW::ELAPSED_TIME_MAX * 2); - for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { - values[i * 2 + 0] = time_name[i]; - values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); - } - values.push_back("flush_queries"); - values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); - - values.push_front("physics_2d"); - EngineDebugger::profiler_add_frame_data("servers", values); - } -} - -void Physics2DServerSW::end_sync() { - doing_sync = false; -} - -void Physics2DServerSW::finish() { - - memdelete(stepper); - memdelete(direct_state); -}; - -void Physics2DServerSW::_update_shapes() { - - while (pending_shape_update_list.first()) { - pending_shape_update_list.first()->self()->_shape_changed(); - pending_shape_update_list.remove(pending_shape_update_list.first()); - } -} - -int Physics2DServerSW::get_process_info(ProcessInfo p_info) { - - switch (p_info) { - - case INFO_ACTIVE_OBJECTS: { - - return active_objects; - } break; - case INFO_COLLISION_PAIRS: { - return collision_pairs; - } break; - case INFO_ISLAND_COUNT: { - - return island_count; - } break; - } - - return 0; -} - -Physics2DServerSW *Physics2DServerSW::singletonsw = NULL; - -Physics2DServerSW::Physics2DServerSW() { - - singletonsw = this; - BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create; - //BroadPhase2DSW::create_func=BroadPhase2DBasic::_create; - - active = true; - island_count = 0; - active_objects = 0; - collision_pairs = 0; - using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2; - flushing_queries = false; -}; - -Physics2DServerSW::~Physics2DServerSW(){ - -}; diff --git a/servers/physics_2d/physics_2d_server_sw.h b/servers/physics_2d/physics_2d_server_sw.h deleted file mode 100644 index a95a2ea0dd..0000000000 --- a/servers/physics_2d/physics_2d_server_sw.h +++ /dev/null @@ -1,296 +0,0 @@ -/*************************************************************************/ -/* physics_2d_server_sw.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS_2D_SERVER_SW -#define PHYSICS_2D_SERVER_SW - -#include "core/rid_owner.h" -#include "joints_2d_sw.h" -#include "servers/physics_2d_server.h" -#include "shape_2d_sw.h" -#include "space_2d_sw.h" -#include "step_2d_sw.h" - -class Physics2DServerSW : public Physics2DServer { - - GDCLASS(Physics2DServerSW, Physics2DServer); - - friend class Physics2DDirectSpaceStateSW; - friend class Physics2DDirectBodyStateSW; - bool active; - int iterations; - bool doing_sync; - real_t last_step; - - int island_count; - int active_objects; - int collision_pairs; - - bool using_threads; - - bool flushing_queries; - - Step2DSW *stepper; - Set active_spaces; - - Physics2DDirectBodyStateSW *direct_state; - - mutable RID_PtrOwner shape_owner; - mutable RID_PtrOwner space_owner; - mutable RID_PtrOwner area_owner; - mutable RID_PtrOwner body_owner; - mutable RID_PtrOwner joint_owner; - - static Physics2DServerSW *singletonsw; - - //void _clear_query(Query2DSW *p_query); - friend class CollisionObject2DSW; - SelfList::List pending_shape_update_list; - void _update_shapes(); - - RID _shape_create(ShapeType p_shape); - -public: - struct CollCbkData { - - Vector2 valid_dir; - real_t valid_depth; - int max; - int amount; - int passed; - int invalid_by_dir; - Vector2 *ptr; - }; - - virtual RID line_shape_create(); - virtual RID ray_shape_create(); - virtual RID segment_shape_create(); - virtual RID circle_shape_create(); - virtual RID rectangle_shape_create(); - virtual RID capsule_shape_create(); - virtual RID convex_polygon_shape_create(); - virtual RID concave_polygon_shape_create(); - - static void _shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata); - - virtual void shape_set_data(RID p_shape, const Variant &p_data); - virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias); - - virtual ShapeType shape_get_type(RID p_shape) const; - virtual Variant shape_get_data(RID p_shape) const; - virtual real_t shape_get_custom_solver_bias(RID p_shape) const; - - virtual bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count); - - /* SPACE API */ - - virtual RID space_create(); - virtual void space_set_active(RID p_space, bool p_active); - virtual bool space_is_active(RID p_space) const; - - virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value); - virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; - - virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); - virtual Vector space_get_contacts(RID p_space) const; - virtual int space_get_contact_count(RID p_space) const; - - // this function only works on physics process, errors and returns null otherwise - virtual Physics2DDirectSpaceState *space_get_direct_state(RID p_space); - - /* AREA API */ - - virtual RID area_create(); - - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode); - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const; - - virtual void area_set_space(RID p_area, RID p_space); - virtual RID area_get_space(RID p_area) const; - - virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); - virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape); - virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform); - - virtual int area_get_shape_count(RID p_area) const; - virtual RID area_get_shape(RID p_area, int p_shape_idx) const; - virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const; - - virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled); - - virtual void area_remove_shape(RID p_area, int p_shape_idx); - virtual void area_clear_shapes(RID p_area); - - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id); - virtual ObjectID area_get_object_instance_id(RID p_area) const; - - virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id); - virtual ObjectID area_get_canvas_instance_id(RID p_area) const; - - virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value); - virtual void area_set_transform(RID p_area, const Transform2D &p_transform); - - virtual Variant area_get_param(RID p_area, AreaParameter p_param) const; - virtual Transform2D area_get_transform(RID p_area) const; - virtual void area_set_monitorable(RID p_area, bool p_monitorable); - virtual void area_set_collision_mask(RID p_area, uint32_t p_mask); - virtual void area_set_collision_layer(RID p_area, uint32_t p_layer); - - virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); - virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); - - virtual void area_set_pickable(RID p_area, bool p_pickable); - - /* BODY API */ - - // create a body of a given type - virtual RID body_create(); - - virtual void body_set_space(RID p_body, RID p_space); - virtual RID body_get_space(RID p_body) const; - - virtual void body_set_mode(RID p_body, BodyMode p_mode); - virtual BodyMode body_get_mode(RID p_body) const; - - virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); - virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape); - virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform); - virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata); - - virtual int body_get_shape_count(RID p_body) const; - virtual RID body_get_shape(RID p_body, int p_shape_idx) const; - virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const; - virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const; - - virtual void body_remove_shape(RID p_body, int p_shape_idx); - virtual void body_clear_shapes(RID p_body); - - virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); - virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin); - - virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); - virtual ObjectID body_get_object_instance_id(RID p_body) const; - - virtual void body_attach_canvas_instance_id(RID p_body, ObjectID p_id); - virtual ObjectID body_get_canvas_instance_id(RID p_body) const; - - virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode); - virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; - - virtual void body_set_collision_layer(RID p_body, uint32_t p_layer); - virtual uint32_t body_get_collision_layer(RID p_body) const; - - virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); - virtual uint32_t body_get_collision_mask(RID p_body) const; - - virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); - virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; - - virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant); - virtual Variant body_get_state(RID p_body, BodyState p_state) const; - - virtual void body_set_applied_force(RID p_body, const Vector2 &p_force); - virtual Vector2 body_get_applied_force(RID p_body) const; - - virtual void body_set_applied_torque(RID p_body, real_t p_torque); - virtual real_t body_get_applied_torque(RID p_body) const; - - virtual void body_add_central_force(RID p_body, const Vector2 &p_force); - virtual void body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force); - virtual void body_add_torque(RID p_body, real_t p_torque); - - virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse); - virtual void body_apply_torque_impulse(RID p_body, real_t p_torque); - virtual void body_apply_impulse(RID p_body, const Vector2 &p_pos, const Vector2 &p_impulse); - virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity); - - virtual void body_add_collision_exception(RID p_body, RID p_body_b); - virtual void body_remove_collision_exception(RID p_body, RID p_body_b); - virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions); - - virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold); - virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const; - - virtual void body_set_omit_force_integration(RID p_body, bool p_omit); - virtual bool body_is_omitting_force_integration(RID p_body) const; - - virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); - virtual int body_get_max_contacts_reported(RID p_body) const; - - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()); - virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count); - - virtual void body_set_pickable(RID p_body, bool p_pickable); - - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); - virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); - - // this function only works on physics process, errors and returns null otherwise - virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body); - - /* JOINT API */ - - virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); - virtual real_t joint_get_param(RID p_joint, JointParam p_param) const; - - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disabled); - virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; - - virtual RID pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b = RID()); - virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b); - virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()); - virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value); - virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const; - virtual void damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value); - virtual real_t damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const; - - virtual JointType joint_get_type(RID p_joint) const; - - /* MISC */ - - virtual void free(RID p_rid); - - virtual void set_active(bool p_active); - virtual void init(); - virtual void step(real_t p_step); - virtual void sync(); - virtual void flush_queries(); - virtual void end_sync(); - virtual void finish(); - - virtual bool is_flushing_queries() const { return flushing_queries; } - - int get_process_info(ProcessInfo p_info); - - Physics2DServerSW(); - ~Physics2DServerSW(); -}; - -#endif diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.cpp b/servers/physics_2d/physics_2d_server_wrap_mt.cpp deleted file mode 100644 index 76036930c6..0000000000 --- a/servers/physics_2d/physics_2d_server_wrap_mt.cpp +++ /dev/null @@ -1,173 +0,0 @@ -/*************************************************************************/ -/* physics_2d_server_wrap_mt.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_2d_server_wrap_mt.h" - -#include "core/os/os.h" - -void Physics2DServerWrapMT::thread_exit() { - - exit = true; -} - -void Physics2DServerWrapMT::thread_step(real_t p_delta) { - - physics_2d_server->step(p_delta); - step_sem.post(); -} - -void Physics2DServerWrapMT::_thread_callback(void *_instance) { - - Physics2DServerWrapMT *vsmt = reinterpret_cast(_instance); - - vsmt->thread_loop(); -} - -void Physics2DServerWrapMT::thread_loop() { - - server_thread = Thread::get_caller_id(); - - physics_2d_server->init(); - - exit = false; - step_thread_up = true; - while (!exit) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush_one(); - } - - command_queue.flush_all(); // flush all - - physics_2d_server->finish(); -} - -/* EVENT QUEUING */ - -void Physics2DServerWrapMT::step(real_t p_step) { - - if (create_thread) { - - command_queue.push(this, &Physics2DServerWrapMT::thread_step, p_step); - } else { - - command_queue.flush_all(); //flush all pending from other threads - physics_2d_server->step(p_step); - } -} - -void Physics2DServerWrapMT::sync() { - - if (thread) { - if (first_frame) - first_frame = false; - else - step_sem.wait(); //must not wait if a step was not issued - } - physics_2d_server->sync(); -} - -void Physics2DServerWrapMT::flush_queries() { - - physics_2d_server->flush_queries(); -} - -void Physics2DServerWrapMT::end_sync() { - - physics_2d_server->end_sync(); -} - -void Physics2DServerWrapMT::init() { - - if (create_thread) { - - //OS::get_singleton()->release_rendering_thread(); - thread = Thread::create(_thread_callback, this); - while (!step_thread_up) { - OS::get_singleton()->delay_usec(1000); - } - } else { - - physics_2d_server->init(); - } -} - -void Physics2DServerWrapMT::finish() { - - if (thread) { - - command_queue.push(this, &Physics2DServerWrapMT::thread_exit); - Thread::wait_to_finish(thread); - memdelete(thread); - - thread = NULL; - } else { - physics_2d_server->finish(); - } - - line_shape_free_cached_ids(); - ray_shape_free_cached_ids(); - segment_shape_free_cached_ids(); - circle_shape_free_cached_ids(); - rectangle_shape_free_cached_ids(); - capsule_shape_free_cached_ids(); - convex_polygon_shape_free_cached_ids(); - concave_polygon_shape_free_cached_ids(); - - space_free_cached_ids(); - area_free_cached_ids(); - body_free_cached_ids(); -} - -Physics2DServerWrapMT::Physics2DServerWrapMT(Physics2DServer *p_contained, bool p_create_thread) : - command_queue(p_create_thread) { - - physics_2d_server = p_contained; - create_thread = p_create_thread; - thread = NULL; - step_pending = 0; - step_thread_up = false; - - pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); - - if (!p_create_thread) { - server_thread = Thread::get_caller_id(); - } else { - server_thread = 0; - } - - main_thread = Thread::get_caller_id(); - first_frame = true; -} - -Physics2DServerWrapMT::~Physics2DServerWrapMT() { - - memdelete(physics_2d_server); - //finish(); -} diff --git a/servers/physics_2d/physics_2d_server_wrap_mt.h b/servers/physics_2d/physics_2d_server_wrap_mt.h deleted file mode 100644 index 4d5e317c8c..0000000000 --- a/servers/physics_2d/physics_2d_server_wrap_mt.h +++ /dev/null @@ -1,348 +0,0 @@ -/*************************************************************************/ -/* physics_2d_server_wrap_mt.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS2DSERVERWRAPMT_H -#define PHYSICS2DSERVERWRAPMT_H - -#include "core/command_queue_mt.h" -#include "core/os/thread.h" -#include "core/project_settings.h" -#include "servers/physics_2d_server.h" - -#ifdef DEBUG_SYNC -#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__)); -#else -#define SYNC_DEBUG -#endif - -class Physics2DServerWrapMT : public Physics2DServer { - - mutable Physics2DServer *physics_2d_server; - - mutable CommandQueueMT command_queue; - - static void _thread_callback(void *_instance); - void thread_loop(); - - Thread::ID server_thread; - Thread::ID main_thread; - volatile bool exit; - Thread *thread; - volatile bool step_thread_up; - bool create_thread; - - Semaphore step_sem; - int step_pending; - void thread_step(real_t p_delta); - void thread_flush(); - - void thread_exit(); - - bool first_frame; - - Mutex alloc_mutex; - int pool_max_size; - -public: -#define ServerName Physics2DServer -#define ServerNameWrapMT Physics2DServerWrapMT -#define server_name physics_2d_server -#include "servers/server_wrap_mt_common.h" - - //FUNC1RID(shape,ShapeType); todo fix - FUNCRID(line_shape) - FUNCRID(ray_shape) - FUNCRID(segment_shape) - FUNCRID(circle_shape) - FUNCRID(rectangle_shape) - FUNCRID(capsule_shape) - FUNCRID(convex_polygon_shape) - FUNCRID(concave_polygon_shape) - - FUNC2(shape_set_data, RID, const Variant &); - FUNC2(shape_set_custom_solver_bias, RID, real_t); - - FUNC1RC(ShapeType, shape_get_type, RID); - FUNC1RC(Variant, shape_get_data, RID); - FUNC1RC(real_t, shape_get_custom_solver_bias, RID); - - //these work well, but should be used from the main thread only - bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); - } - - /* SPACE API */ - - FUNCRID(space); - FUNC2(space_set_active, RID, bool); - FUNC1RC(bool, space_is_active, RID); - - FUNC3(space_set_param, RID, SpaceParameter, real_t); - FUNC2RC(real_t, space_get_param, RID, SpaceParameter); - - // this function only works on physics process, errors and returns null otherwise - Physics2DDirectSpaceState *space_get_direct_state(RID p_space) { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL); - return physics_2d_server->space_get_direct_state(p_space); - } - - FUNC2(space_set_debug_contacts, RID, int); - virtual Vector space_get_contacts(RID p_space) const { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector()); - return physics_2d_server->space_get_contacts(p_space); - } - - virtual int space_get_contact_count(RID p_space) const { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); - return physics_2d_server->space_get_contact_count(p_space); - } - - /* AREA API */ - - //FUNC0RID(area); - FUNCRID(area); - - FUNC2(area_set_space, RID, RID); - FUNC1RC(RID, area_get_space, RID); - - FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); - FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); - - FUNC4(area_add_shape, RID, RID, const Transform2D &, bool); - FUNC3(area_set_shape, RID, int, RID); - FUNC3(area_set_shape_transform, RID, int, const Transform2D &); - FUNC3(area_set_shape_disabled, RID, int, bool); - - FUNC1RC(int, area_get_shape_count, RID); - FUNC2RC(RID, area_get_shape, RID, int); - FUNC2RC(Transform2D, area_get_shape_transform, RID, int); - FUNC2(area_remove_shape, RID, int); - FUNC1(area_clear_shapes, RID); - - FUNC2(area_attach_object_instance_id, RID, ObjectID); - FUNC1RC(ObjectID, area_get_object_instance_id, RID); - - FUNC2(area_attach_canvas_instance_id, RID, ObjectID); - FUNC1RC(ObjectID, area_get_canvas_instance_id, RID); - - FUNC3(area_set_param, RID, AreaParameter, const Variant &); - FUNC2(area_set_transform, RID, const Transform2D &); - - FUNC2RC(Variant, area_get_param, RID, AreaParameter); - FUNC1RC(Transform2D, area_get_transform, RID); - - FUNC2(area_set_collision_mask, RID, uint32_t); - FUNC2(area_set_collision_layer, RID, uint32_t); - - FUNC2(area_set_monitorable, RID, bool); - FUNC2(area_set_pickable, RID, bool); - - FUNC3(area_set_monitor_callback, RID, Object *, const StringName &); - FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &); - - /* BODY API */ - - //FUNC2RID(body,BodyMode,bool); - FUNCRID(body) - - FUNC2(body_set_space, RID, RID); - FUNC1RC(RID, body_get_space, RID); - - FUNC2(body_set_mode, RID, BodyMode); - FUNC1RC(BodyMode, body_get_mode, RID); - - FUNC4(body_add_shape, RID, RID, const Transform2D &, bool); - FUNC3(body_set_shape, RID, int, RID); - FUNC3(body_set_shape_transform, RID, int, const Transform2D &); - FUNC3(body_set_shape_metadata, RID, int, const Variant &); - - FUNC1RC(int, body_get_shape_count, RID); - FUNC2RC(Transform2D, body_get_shape_transform, RID, int); - FUNC2RC(Variant, body_get_shape_metadata, RID, int); - FUNC2RC(RID, body_get_shape, RID, int); - - FUNC3(body_set_shape_disabled, RID, int, bool); - FUNC4(body_set_shape_as_one_way_collision, RID, int, bool, float); - - FUNC2(body_remove_shape, RID, int); - FUNC1(body_clear_shapes, RID); - - FUNC2(body_attach_object_instance_id, RID, ObjectID); - FUNC1RC(ObjectID, body_get_object_instance_id, RID); - - FUNC2(body_attach_canvas_instance_id, RID, ObjectID); - FUNC1RC(ObjectID, body_get_canvas_instance_id, RID); - - FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode); - FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID); - - FUNC2(body_set_collision_layer, RID, uint32_t); - FUNC1RC(uint32_t, body_get_collision_layer, RID); - - FUNC2(body_set_collision_mask, RID, uint32_t); - FUNC1RC(uint32_t, body_get_collision_mask, RID); - - FUNC3(body_set_param, RID, BodyParameter, real_t); - FUNC2RC(real_t, body_get_param, RID, BodyParameter); - - FUNC3(body_set_state, RID, BodyState, const Variant &); - FUNC2RC(Variant, body_get_state, RID, BodyState); - - FUNC2(body_set_applied_force, RID, const Vector2 &); - FUNC1RC(Vector2, body_get_applied_force, RID); - - FUNC2(body_set_applied_torque, RID, real_t); - FUNC1RC(real_t, body_get_applied_torque, RID); - - FUNC2(body_add_central_force, RID, const Vector2 &); - FUNC3(body_add_force, RID, const Vector2 &, const Vector2 &); - FUNC2(body_add_torque, RID, real_t); - FUNC2(body_apply_central_impulse, RID, const Vector2 &); - FUNC2(body_apply_torque_impulse, RID, real_t); - FUNC3(body_apply_impulse, RID, const Vector2 &, const Vector2 &); - FUNC2(body_set_axis_velocity, RID, const Vector2 &); - - FUNC2(body_add_collision_exception, RID, RID); - FUNC2(body_remove_collision_exception, RID, RID); - FUNC2S(body_get_collision_exceptions, RID, List *); - - FUNC2(body_set_max_contacts_reported, RID, int); - FUNC1RC(int, body_get_max_contacts_reported, RID); - - FUNC2(body_set_contacts_reported_depth_threshold, RID, real_t); - FUNC1RC(real_t, body_get_contacts_reported_depth_threshold, RID); - - FUNC2(body_set_omit_force_integration, RID, bool); - FUNC1RC(bool, body_is_omitting_force_integration, RID); - - FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &); - - bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { - return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); - } - - FUNC2(body_set_pickable, RID, bool); - - bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes); - } - - int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); - return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); - } - - // this function only works on physics process, errors and returns null otherwise - Physics2DDirectBodyState *body_get_direct_state(RID p_body) { - - ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL); - return physics_2d_server->body_get_direct_state(p_body); - } - - /* JOINT API */ - - FUNC3(joint_set_param, RID, JointParam, real_t); - FUNC2RC(real_t, joint_get_param, RID, JointParam); - - FUNC2(joint_disable_collisions_between_bodies, RID, const bool); - FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID); - - ///FUNC3RID(pin_joint,const Vector2&,RID,RID); - ///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID); - ///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID); - - //TODO need to convert this to FUNCRID, but it's a hassle.. - - FUNC3R(RID, pin_joint_create, const Vector2 &, RID, RID); - FUNC5R(RID, groove_joint_create, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID); - FUNC4R(RID, damped_spring_joint_create, const Vector2 &, const Vector2 &, RID, RID); - - FUNC3(pin_joint_set_param, RID, PinJointParam, real_t); - FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam); - - FUNC3(damped_string_joint_set_param, RID, DampedStringParam, real_t); - FUNC2RC(real_t, damped_string_joint_get_param, RID, DampedStringParam); - - FUNC1RC(JointType, joint_get_type, RID); - - /* MISC */ - - FUNC1(free, RID); - FUNC1(set_active, bool); - - virtual void init(); - virtual void step(real_t p_step); - virtual void sync(); - virtual void end_sync(); - virtual void flush_queries(); - virtual void finish(); - - virtual bool is_flushing_queries() const { - return physics_2d_server->is_flushing_queries(); - } - - int get_process_info(ProcessInfo p_info) { - return physics_2d_server->get_process_info(p_info); - } - - Physics2DServerWrapMT(Physics2DServer *p_contained, bool p_create_thread); - ~Physics2DServerWrapMT(); - - template - static Physics2DServer *init_server() { - - int tm = GLOBAL_DEF("physics/2d/thread_model", 1); - if (tm == 0) // single unsafe - return memnew(T); - else if (tm == 1) // single safe - return memnew(Physics2DServerWrapMT(memnew(T), false)); - else // multi threaded - return memnew(Physics2DServerWrapMT(memnew(T), true)); - } - -#undef ServerNameWrapMT -#undef ServerName -#undef server_name -}; - -#ifdef DEBUG_SYNC -#undef DEBUG_SYNC -#endif -#undef SYNC_DEBUG - -#endif // PHYSICS2DSERVERWRAPMT_H diff --git a/servers/physics_2d/physics_server_2d_sw.cpp b/servers/physics_2d/physics_server_2d_sw.cpp new file mode 100644 index 0000000000..cd1f14b69d --- /dev/null +++ b/servers/physics_2d/physics_server_2d_sw.cpp @@ -0,0 +1,1464 @@ +/*************************************************************************/ +/* physics_2d_server_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_2d_sw.h" +#include "broad_phase_2d_basic.h" +#include "broad_phase_2d_hash_grid.h" +#include "collision_solver_2d_sw.h" +#include "core/debugger/engine_debugger.h" +#include "core/os/os.h" +#include "core/project_settings.h" + +#define FLUSH_QUERY_CHECK(m_object) \ + ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); + +RID PhysicsServer2DSW::_shape_create(ShapeType p_shape) { + + Shape2DSW *shape = NULL; + switch (p_shape) { + + case SHAPE_LINE: { + + shape = memnew(LineShape2DSW); + } break; + case SHAPE_RAY: { + + shape = memnew(RayShape2DSW); + } break; + case SHAPE_SEGMENT: { + + shape = memnew(SegmentShape2DSW); + } break; + case SHAPE_CIRCLE: { + + shape = memnew(CircleShape2DSW); + } break; + case SHAPE_RECTANGLE: { + + shape = memnew(RectangleShape2DSW); + } break; + case SHAPE_CAPSULE: { + + shape = memnew(CapsuleShape2DSW); + } break; + case SHAPE_CONVEX_POLYGON: { + + shape = memnew(ConvexPolygonShape2DSW); + } break; + case SHAPE_CONCAVE_POLYGON: { + + shape = memnew(ConcavePolygonShape2DSW); + } break; + case SHAPE_CUSTOM: { + + ERR_FAIL_V(RID()); + + } break; + } + + RID id = shape_owner.make_rid(shape); + shape->set_self(id); + + return id; +} + +RID PhysicsServer2DSW::line_shape_create() { + + return _shape_create(SHAPE_LINE); +} + +RID PhysicsServer2DSW::ray_shape_create() { + + return _shape_create(SHAPE_RAY); +} +RID PhysicsServer2DSW::segment_shape_create() { + + return _shape_create(SHAPE_SEGMENT); +} +RID PhysicsServer2DSW::circle_shape_create() { + + return _shape_create(SHAPE_CIRCLE); +} +RID PhysicsServer2DSW::rectangle_shape_create() { + + return _shape_create(SHAPE_RECTANGLE); +} +RID PhysicsServer2DSW::capsule_shape_create() { + + return _shape_create(SHAPE_CAPSULE); +} + +RID PhysicsServer2DSW::convex_polygon_shape_create() { + + return _shape_create(SHAPE_CONVEX_POLYGON); +} +RID PhysicsServer2DSW::concave_polygon_shape_create() { + + return _shape_create(SHAPE_CONCAVE_POLYGON); +} + +void PhysicsServer2DSW::shape_set_data(RID p_shape, const Variant &p_data) { + + Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + shape->set_data(p_data); +}; + +void PhysicsServer2DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { + + Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + shape->set_custom_bias(p_bias); +} + +PhysicsServer2D::ShapeType PhysicsServer2DSW::shape_get_type(RID p_shape) const { + + const Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); + return shape->get_type(); +}; + +Variant PhysicsServer2DSW::shape_get_data(RID p_shape) const { + + const Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, Variant()); + ERR_FAIL_COND_V(!shape->is_configured(), Variant()); + return shape->get_data(); +}; + +real_t PhysicsServer2DSW::shape_get_custom_solver_bias(RID p_shape) const { + + const Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); + return shape->get_custom_bias(); +} + +void PhysicsServer2DSW::_shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata) { + + CollCbkData *cbk = (CollCbkData *)p_userdata; + + if (cbk->max == 0) + return; + + if (cbk->valid_dir != Vector2()) { + if (p_point_A.distance_squared_to(p_point_B) > cbk->valid_depth * cbk->valid_depth) { + cbk->invalid_by_dir++; + return; + } + Vector2 rel_dir = (p_point_A - p_point_B).normalized(); + + if (cbk->valid_dir.dot(rel_dir) < Math_SQRT12) { //sqrt(2)/2.0 - 45 degrees + cbk->invalid_by_dir++; + + /* + print_line("A: "+p_point_A); + print_line("B: "+p_point_B); + print_line("discard too angled "+rtos(cbk->valid_dir.dot((p_point_A-p_point_B)))); + print_line("resnorm: "+(p_point_A-p_point_B).normalized()); + print_line("distance: "+rtos(p_point_A.distance_to(p_point_B))); + */ + return; + } + } + + if (cbk->amount == cbk->max) { + //find least deep + real_t min_depth = 1e20; + int min_depth_idx = 0; + for (int i = 0; i < cbk->amount; i++) { + + real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); + if (d < min_depth) { + min_depth = d; + min_depth_idx = i; + } + } + + real_t d = p_point_A.distance_squared_to(p_point_B); + if (d < min_depth) + return; + cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; + cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; + cbk->passed++; + + } else { + + cbk->ptr[cbk->amount * 2 + 0] = p_point_A; + cbk->ptr[cbk->amount * 2 + 1] = p_point_B; + cbk->amount++; + cbk->passed++; + } +} + +bool PhysicsServer2DSW::shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) { + + Shape2DSW *shape_A = shape_owner.getornull(p_shape_A); + ERR_FAIL_COND_V(!shape_A, false); + Shape2DSW *shape_B = shape_owner.getornull(p_shape_B); + ERR_FAIL_COND_V(!shape_B, false); + + if (p_result_max == 0) { + + return CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, NULL, NULL); + } + + CollCbkData cbk; + cbk.max = p_result_max; + cbk.amount = 0; + cbk.passed = 0; + cbk.ptr = r_results; + + bool res = CollisionSolver2DSW::solve(shape_A, p_xform_A, p_motion_A, shape_B, p_xform_B, p_motion_B, _shape_col_cbk, &cbk); + r_result_count = cbk.amount; + return res; +} + +RID PhysicsServer2DSW::space_create() { + + Space2DSW *space = memnew(Space2DSW); + RID id = space_owner.make_rid(space); + space->set_self(id); + RID area_id = area_create(); + Area2DSW *area = area_owner.getornull(area_id); + ERR_FAIL_COND_V(!area, RID()); + space->set_default_area(area); + area->set_space(space); + area->set_priority(-1); + + return id; +}; + +void PhysicsServer2DSW::space_set_active(RID p_space, bool p_active) { + + Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + if (p_active) + active_spaces.insert(space); + else + active_spaces.erase(space); +} + +bool PhysicsServer2DSW::space_is_active(RID p_space) const { + + const Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, false); + + return active_spaces.has(space); +} + +void PhysicsServer2DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { + + Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + + space->set_param(p_param, p_value); +} + +real_t PhysicsServer2DSW::space_get_param(RID p_space, SpaceParameter p_param) const { + + const Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_param(p_param); +} + +void PhysicsServer2DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) { + + Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + space->set_debug_contacts(p_max_contacts); +} + +Vector PhysicsServer2DSW::space_get_contacts(RID p_space) const { + + Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, Vector()); + return space->get_debug_contacts(); +} + +int PhysicsServer2DSW::space_get_contact_count(RID p_space) const { + + Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_debug_contact_count(); +} + +PhysicsDirectSpaceState2D *PhysicsServer2DSW::space_get_direct_state(RID p_space) { + + Space2DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, NULL); + ERR_FAIL_COND_V_MSG((using_threads && !doing_sync) || space->is_locked(), NULL, "Space state is inaccessible right now, wait for iteration or physics process notification."); + + return space->get_direct_state(); +} + +RID PhysicsServer2DSW::area_create() { + + Area2DSW *area = memnew(Area2DSW); + RID rid = area_owner.make_rid(area); + area->set_self(rid); + return rid; +}; + +void PhysicsServer2DSW::area_set_space(RID p_area, RID p_space) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + Space2DSW *space = NULL; + if (p_space.is_valid()) { + space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + } + + if (area->get_space() == space) + return; //pointless + + area->clear_constraints(); + area->set_space(space); +}; + +RID PhysicsServer2DSW::area_get_space(RID p_area) const { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, RID()); + + Space2DSW *space = area->get_space(); + if (!space) + return RID(); + return space->get_self(); +}; + +void PhysicsServer2DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_space_override_mode(p_mode); +} + +PhysicsServer2D::AreaSpaceOverrideMode PhysicsServer2DSW::area_get_space_override_mode(RID p_area) const { + + const Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); + + return area->get_space_override_mode(); +} + +void PhysicsServer2DSW::area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform, bool p_disabled) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + + area->add_shape(shape, p_transform, p_disabled); +} + +void PhysicsServer2DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + area->set_shape(p_shape_idx, shape); +} +void PhysicsServer2DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_shape_transform(p_shape_idx, p_transform); +} + +void PhysicsServer2DSW::area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + ERR_FAIL_INDEX(p_shape, area->get_shape_count()); + FLUSH_QUERY_CHECK(area); + + area->set_shape_as_disabled(p_shape, p_disabled); +} + +int PhysicsServer2DSW::area_get_shape_count(RID p_area) const { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, -1); + + return area->get_shape_count(); +} +RID PhysicsServer2DSW::area_get_shape(RID p_area, int p_shape_idx) const { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, RID()); + + Shape2DSW *shape = area->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} +Transform2D PhysicsServer2DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, Transform2D()); + + return area->get_shape_transform(p_shape_idx); +} + +void PhysicsServer2DSW::area_remove_shape(RID p_area, int p_shape_idx) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->remove_shape(p_shape_idx); +} + +void PhysicsServer2DSW::area_clear_shapes(RID p_area) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + while (area->get_shape_count()) + area->remove_shape(0); +} + +void PhysicsServer2DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { + + if (space_owner.owns(p_area)) { + Space2DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_instance_id(p_id); +} +ObjectID PhysicsServer2DSW::area_get_object_instance_id(RID p_area) const { + + if (space_owner.owns(p_area)) { + Space2DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, ObjectID()); + return area->get_instance_id(); +} + +void PhysicsServer2DSW::area_attach_canvas_instance_id(RID p_area, ObjectID p_id) { + + if (space_owner.owns(p_area)) { + Space2DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_canvas_instance_id(p_id); +} +ObjectID PhysicsServer2DSW::area_get_canvas_instance_id(RID p_area) const { + + if (space_owner.owns(p_area)) { + Space2DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, ObjectID()); + return area->get_canvas_instance_id(); +} + +void PhysicsServer2DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { + + if (space_owner.owns(p_area)) { + Space2DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_param(p_param, p_value); +}; + +void PhysicsServer2DSW::area_set_transform(RID p_area, const Transform2D &p_transform) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_transform(p_transform); +}; + +Variant PhysicsServer2DSW::area_get_param(RID p_area, AreaParameter p_param) const { + + if (space_owner.owns(p_area)) { + Space2DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, Variant()); + + return area->get_param(p_param); +}; + +Transform2D PhysicsServer2DSW::area_get_transform(RID p_area) const { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, Transform2D()); + + return area->get_transform(); +}; + +void PhysicsServer2DSW::area_set_pickable(RID p_area, bool p_pickable) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_pickable(p_pickable); +} + +void PhysicsServer2DSW::area_set_monitorable(RID p_area, bool p_monitorable) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + FLUSH_QUERY_CHECK(area); + + area->set_monitorable(p_monitorable); +} + +void PhysicsServer2DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_mask(p_mask); +} + +void PhysicsServer2DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_layer(p_layer); +} + +void PhysicsServer2DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +void PhysicsServer2DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + + Area2DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +/* BODY API */ + +RID PhysicsServer2DSW::body_create() { + + Body2DSW *body = memnew(Body2DSW); + RID rid = body_owner.make_rid(body); + body->set_self(rid); + return rid; +} + +void PhysicsServer2DSW::body_set_space(RID p_body, RID p_space) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + Space2DSW *space = NULL; + if (p_space.is_valid()) { + space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + } + + if (body->get_space() == space) + return; //pointless + + body->clear_constraint_map(); + body->set_space(space); +}; + +RID PhysicsServer2DSW::body_get_space(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, RID()); + + Space2DSW *space = body->get_space(); + if (!space) + return RID(); + return space->get_self(); +}; + +void PhysicsServer2DSW::body_set_mode(RID p_body, BodyMode p_mode) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + FLUSH_QUERY_CHECK(body); + + body->set_mode(p_mode); +}; + +PhysicsServer2D::BodyMode PhysicsServer2DSW::body_get_mode(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); + + return body->get_mode(); +}; + +void PhysicsServer2DSW::body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform, bool p_disabled) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + + body->add_shape(shape, p_transform, p_disabled); +} + +void PhysicsServer2DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + Shape2DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + body->set_shape(p_shape_idx, shape); +} +void PhysicsServer2DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_shape_transform(p_shape_idx, p_transform); +} + +void PhysicsServer2DSW::body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_shape_metadata(p_shape_idx, p_metadata); +} + +Variant PhysicsServer2DSW::body_get_shape_metadata(RID p_body, int p_shape_idx) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Variant()); + return body->get_shape_metadata(p_shape_idx); +} + +int PhysicsServer2DSW::body_get_shape_count(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, -1); + + return body->get_shape_count(); +} +RID PhysicsServer2DSW::body_get_shape(RID p_body, int p_shape_idx) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, RID()); + + Shape2DSW *shape = body->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} +Transform2D PhysicsServer2DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Transform2D()); + + return body->get_shape_transform(p_shape_idx); +} + +void PhysicsServer2DSW::body_remove_shape(RID p_body, int p_shape_idx) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->remove_shape(p_shape_idx); +} + +void PhysicsServer2DSW::body_clear_shapes(RID p_body) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + while (body->get_shape_count()) + body->remove_shape(0); +} + +void PhysicsServer2DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); + FLUSH_QUERY_CHECK(body); + + body->set_shape_as_disabled(p_shape_idx, p_disabled); +} +void PhysicsServer2DSW::body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); + FLUSH_QUERY_CHECK(body); + + body->set_shape_as_one_way_collision(p_shape_idx, p_enable, p_margin); +} + +void PhysicsServer2DSW::body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_continuous_collision_detection_mode(p_mode); +} + +PhysicsServer2DSW::CCDMode PhysicsServer2DSW::body_get_continuous_collision_detection_mode(RID p_body) const { + + const Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, CCD_MODE_DISABLED); + + return body->get_continuous_collision_detection_mode(); +} + +void PhysicsServer2DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_instance_id(p_id); +}; + +ObjectID PhysicsServer2DSW::body_get_object_instance_id(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, ObjectID()); + + return body->get_instance_id(); +}; + +void PhysicsServer2DSW::body_attach_canvas_instance_id(RID p_body, ObjectID p_id) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_canvas_instance_id(p_id); +}; + +ObjectID PhysicsServer2DSW::body_get_canvas_instance_id(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, ObjectID()); + + return body->get_canvas_instance_id(); +}; + +void PhysicsServer2DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_collision_layer(p_layer); +}; + +uint32_t PhysicsServer2DSW::body_get_collision_layer(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_layer(); +}; + +void PhysicsServer2DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_collision_mask(p_mask); +}; + +uint32_t PhysicsServer2DSW::body_get_collision_mask(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_mask(); +}; + +void PhysicsServer2DSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_param(p_param, p_value); +}; + +real_t PhysicsServer2DSW::body_get_param(RID p_body, BodyParameter p_param) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_param(p_param); +}; + +void PhysicsServer2DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_state(p_state, p_variant); +}; + +Variant PhysicsServer2DSW::body_get_state(RID p_body, BodyState p_state) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Variant()); + + return body->get_state(p_state); +}; + +void PhysicsServer2DSW::body_set_applied_force(RID p_body, const Vector2 &p_force) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_force(p_force); + body->wakeup(); +}; + +Vector2 PhysicsServer2DSW::body_get_applied_force(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Vector2()); + return body->get_applied_force(); +}; + +void PhysicsServer2DSW::body_set_applied_torque(RID p_body, real_t p_torque) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_torque(p_torque); + body->wakeup(); +}; + +real_t PhysicsServer2DSW::body_get_applied_torque(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_applied_torque(); +}; + +void PhysicsServer2DSW::body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) { + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->apply_central_impulse(p_impulse); + body->wakeup(); +} + +void PhysicsServer2DSW::body_apply_torque_impulse(RID p_body, real_t p_torque) { + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_torque_impulse(p_torque); +} + +void PhysicsServer2DSW::body_apply_impulse(RID p_body, const Vector2 &p_pos, const Vector2 &p_impulse) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_impulse(p_pos, p_impulse); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_add_central_force(RID p_body, const Vector2 &p_force) { + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_central_force(p_force); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_force(p_offset, p_force); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_add_torque(RID p_body, real_t p_torque) { + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_torque(p_torque); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + Vector2 v = body->get_linear_velocity(); + Vector2 axis = p_axis_velocity.normalized(); + v -= axis * axis.dot(v); + v += p_axis_velocity; + body->set_linear_velocity(v); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_add_collision_exception(RID p_body, RID p_body_b) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_exception(p_body_b); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_remove_collision_exception(RID p_body, RID p_body_b) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->remove_exception(p_body_b); + body->wakeup(); +}; + +void PhysicsServer2DSW::body_get_collision_exceptions(RID p_body, List *p_exceptions) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + for (int i = 0; i < body->get_exceptions().size(); i++) { + p_exceptions->push_back(body->get_exceptions()[i]); + } +}; + +void PhysicsServer2DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); +}; + +real_t PhysicsServer2DSW::body_get_contacts_reported_depth_threshold(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + return 0; +}; + +void PhysicsServer2DSW::body_set_omit_force_integration(RID p_body, bool p_omit) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_omit_force_integration(p_omit); +}; + +bool PhysicsServer2DSW::body_is_omitting_force_integration(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + return body->get_omit_force_integration(); +}; + +void PhysicsServer2DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_max_contacts_reported(p_contacts); +} + +int PhysicsServer2DSW::body_get_max_contacts_reported(RID p_body) const { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, -1); + return body->get_max_contacts_reported(); +} + +void PhysicsServer2DSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); +} + +bool PhysicsServer2DSW::body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_INDEX_V(p_body_shape, body->get_shape_count(), false); + + return shape_collide(body->get_shape(p_body_shape)->get_self(), body->get_transform() * body->get_shape_transform(p_body_shape), Vector2(), p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); +} + +void PhysicsServer2DSW::body_set_pickable(RID p_body, bool p_pickable) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_pickable(p_pickable); +} + +bool PhysicsServer2DSW::body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, MotionResult *r_result, bool p_exclude_raycast_shapes) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + _update_shapes(); + + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes); +} + +int PhysicsServer2DSW::body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); +} + +PhysicsDirectBodyState2D *PhysicsServer2DSW::body_get_direct_state(RID p_body) { + + ERR_FAIL_COND_V_MSG((using_threads && !doing_sync), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + if (!body_owner.owns(p_body)) + return NULL; + + Body2DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, NULL); + ERR_FAIL_COND_V(!body->get_space(), NULL); + ERR_FAIL_COND_V_MSG(body->get_space()->is_locked(), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + direct_state->body = body; + return direct_state; +} + +/* JOINT API */ + +void PhysicsServer2DSW::joint_set_param(RID p_joint, JointParam p_param, real_t p_value) { + + Joint2DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + + switch (p_param) { + case JOINT_PARAM_BIAS: joint->set_bias(p_value); break; + case JOINT_PARAM_MAX_BIAS: joint->set_max_bias(p_value); break; + case JOINT_PARAM_MAX_FORCE: joint->set_max_force(p_value); break; + } +} + +real_t PhysicsServer2DSW::joint_get_param(RID p_joint, JointParam p_param) const { + + const Joint2DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, -1); + + switch (p_param) { + case JOINT_PARAM_BIAS: return joint->get_bias(); break; + case JOINT_PARAM_MAX_BIAS: return joint->get_max_bias(); break; + case JOINT_PARAM_MAX_FORCE: return joint->get_max_force(); break; + } + + return 0; +} + +void PhysicsServer2DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + Joint2DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); + + if (2 == joint->get_body_count()) { + Body2DSW *body_a = *joint->get_body_ptr(); + Body2DSW *body_b = *(joint->get_body_ptr() + 1); + + if (p_disable) { + body_add_collision_exception(body_a->get_self(), body_b->get_self()); + body_add_collision_exception(body_b->get_self(), body_a->get_self()); + } else { + body_remove_collision_exception(body_a->get_self(), body_b->get_self()); + body_remove_collision_exception(body_b->get_self(), body_a->get_self()); + } + } +} + +bool PhysicsServer2DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + const Joint2DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, true); + + return joint->is_disabled_collisions_between_bodies(); +} + +RID PhysicsServer2DSW::pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b) { + + Body2DSW *A = body_owner.getornull(p_body_a); + ERR_FAIL_COND_V(!A, RID()); + Body2DSW *B = NULL; + if (body_owner.owns(p_body_b)) { + B = body_owner.getornull(p_body_b); + ERR_FAIL_COND_V(!B, RID()); + } + + Joint2DSW *joint = memnew(PinJoint2DSW(p_pos, A, B)); + RID self = joint_owner.make_rid(joint); + joint->set_self(self); + + return self; +} + +RID PhysicsServer2DSW::groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) { + + Body2DSW *A = body_owner.getornull(p_body_a); + ERR_FAIL_COND_V(!A, RID()); + + Body2DSW *B = body_owner.getornull(p_body_b); + ERR_FAIL_COND_V(!B, RID()); + + Joint2DSW *joint = memnew(GrooveJoint2DSW(p_a_groove1, p_a_groove2, p_b_anchor, A, B)); + RID self = joint_owner.make_rid(joint); + joint->set_self(self); + return self; +} + +RID PhysicsServer2DSW::damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b) { + + Body2DSW *A = body_owner.getornull(p_body_a); + ERR_FAIL_COND_V(!A, RID()); + + Body2DSW *B = body_owner.getornull(p_body_b); + ERR_FAIL_COND_V(!B, RID()); + + Joint2DSW *joint = memnew(DampedSpringJoint2DSW(p_anchor_a, p_anchor_b, A, B)); + RID self = joint_owner.make_rid(joint); + joint->set_self(self); + return self; +} + +void PhysicsServer2DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { + + Joint2DSW *j = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!j); + ERR_FAIL_COND(j->get_type() != JOINT_PIN); + + PinJoint2DSW *pin_joint = static_cast(j); + pin_joint->set_param(p_param, p_value); +} + +real_t PhysicsServer2DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { + Joint2DSW *j = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!j, 0); + ERR_FAIL_COND_V(j->get_type() != JOINT_PIN, 0); + + PinJoint2DSW *pin_joint = static_cast(j); + return pin_joint->get_param(p_param); +} + +void PhysicsServer2DSW::damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value) { + + Joint2DSW *j = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!j); + ERR_FAIL_COND(j->get_type() != JOINT_DAMPED_SPRING); + + DampedSpringJoint2DSW *dsj = static_cast(j); + dsj->set_param(p_param, p_value); +} + +real_t PhysicsServer2DSW::damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const { + + Joint2DSW *j = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!j, 0); + ERR_FAIL_COND_V(j->get_type() != JOINT_DAMPED_SPRING, 0); + + DampedSpringJoint2DSW *dsj = static_cast(j); + return dsj->get_param(p_param); +} + +PhysicsServer2D::JointType PhysicsServer2DSW::joint_get_type(RID p_joint) const { + + Joint2DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, JOINT_PIN); + + return joint->get_type(); +} + +void PhysicsServer2DSW::free(RID p_rid) { + + _update_shapes(); // just in case + + if (shape_owner.owns(p_rid)) { + + Shape2DSW *shape = shape_owner.getornull(p_rid); + + while (shape->get_owners().size()) { + ShapeOwner2DSW *so = shape->get_owners().front()->key(); + so->remove_shape(shape); + } + + shape_owner.free(p_rid); + memdelete(shape); + } else if (body_owner.owns(p_rid)) { + + Body2DSW *body = body_owner.getornull(p_rid); + + /* + if (body->get_state_query()) + _clear_query(body->get_state_query()); + + if (body->get_direct_state_query()) + _clear_query(body->get_direct_state_query()); + */ + + body_set_space(p_rid, RID()); + + while (body->get_shape_count()) { + + body->remove_shape(0); + } + + body_owner.free(p_rid); + memdelete(body); + + } else if (area_owner.owns(p_rid)) { + + Area2DSW *area = area_owner.getornull(p_rid); + + /* + if (area->get_monitor_query()) + _clear_query(area->get_monitor_query()); + */ + + area->set_space(NULL); + + while (area->get_shape_count()) { + + area->remove_shape(0); + } + + area_owner.free(p_rid); + memdelete(area); + } else if (space_owner.owns(p_rid)) { + + Space2DSW *space = space_owner.getornull(p_rid); + + while (space->get_objects().size()) { + CollisionObject2DSW *co = (CollisionObject2DSW *)space->get_objects().front()->get(); + co->set_space(NULL); + } + + active_spaces.erase(space); + free(space->get_default_area()->get_self()); + space_owner.free(p_rid); + memdelete(space); + } else if (joint_owner.owns(p_rid)) { + + Joint2DSW *joint = joint_owner.getornull(p_rid); + + joint_owner.free(p_rid); + memdelete(joint); + + } else { + + ERR_FAIL_MSG("Invalid ID."); + } +}; + +void PhysicsServer2DSW::set_active(bool p_active) { + + active = p_active; +}; + +void PhysicsServer2DSW::init() { + + doing_sync = false; + last_step = 0.001; + iterations = 8; // 8? + stepper = memnew(Step2DSW); + direct_state = memnew(Physics2DDirectBodyStateSW); +}; + +void PhysicsServer2DSW::step(real_t p_step) { + + if (!active) + return; + + _update_shapes(); + + doing_sync = false; + + last_step = p_step; + Physics2DDirectBodyStateSW::singleton->step = p_step; + island_count = 0; + active_objects = 0; + collision_pairs = 0; + for (Set::Element *E = active_spaces.front(); E; E = E->next()) { + + stepper->step((Space2DSW *)E->get(), p_step, iterations); + island_count += E->get()->get_island_count(); + active_objects += E->get()->get_active_objects(); + collision_pairs += E->get()->get_collision_pairs(); + } +}; + +void PhysicsServer2DSW::sync() { + + doing_sync = true; +}; + +void PhysicsServer2DSW::flush_queries() { + + if (!active) + return; + + flushing_queries = true; + + uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); + + for (Set::Element *E = active_spaces.front(); E; E = E->next()) { + + Space2DSW *space = (Space2DSW *)E->get(); + space->call_queries(); + } + + flushing_queries = false; + + if (EngineDebugger::is_profiling("servers")) { + + uint64_t total_time[Space2DSW::ELAPSED_TIME_MAX]; + static const char *time_name[Space2DSW::ELAPSED_TIME_MAX] = { + "integrate_forces", + "generate_islands", + "setup_constraints", + "solve_constraints", + "integrate_velocities" + }; + + for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { + total_time[i] = 0; + } + + for (Set::Element *E = active_spaces.front(); E; E = E->next()) { + + for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { + total_time[i] += E->get()->get_elapsed_time(Space2DSW::ElapsedTime(i)); + } + } + + Array values; + values.resize(Space2DSW::ELAPSED_TIME_MAX * 2); + for (int i = 0; i < Space2DSW::ELAPSED_TIME_MAX; i++) { + values[i * 2 + 0] = time_name[i]; + values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); + } + values.push_back("flush_queries"); + values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); + + values.push_front("physics_2d"); + EngineDebugger::profiler_add_frame_data("servers", values); + } +} + +void PhysicsServer2DSW::end_sync() { + doing_sync = false; +} + +void PhysicsServer2DSW::finish() { + + memdelete(stepper); + memdelete(direct_state); +}; + +void PhysicsServer2DSW::_update_shapes() { + + while (pending_shape_update_list.first()) { + pending_shape_update_list.first()->self()->_shape_changed(); + pending_shape_update_list.remove(pending_shape_update_list.first()); + } +} + +int PhysicsServer2DSW::get_process_info(ProcessInfo p_info) { + + switch (p_info) { + + case INFO_ACTIVE_OBJECTS: { + + return active_objects; + } break; + case INFO_COLLISION_PAIRS: { + return collision_pairs; + } break; + case INFO_ISLAND_COUNT: { + + return island_count; + } break; + } + + return 0; +} + +PhysicsServer2DSW *PhysicsServer2DSW::singletonsw = NULL; + +PhysicsServer2DSW::PhysicsServer2DSW() { + + singletonsw = this; + BroadPhase2DSW::create_func = BroadPhase2DHashGrid::_create; + //BroadPhase2DSW::create_func=BroadPhase2DBasic::_create; + + active = true; + island_count = 0; + active_objects = 0; + collision_pairs = 0; + using_threads = int(ProjectSettings::get_singleton()->get("physics/2d/thread_model")) == 2; + flushing_queries = false; +}; + +PhysicsServer2DSW::~PhysicsServer2DSW(){ + +}; diff --git a/servers/physics_2d/physics_server_2d_sw.h b/servers/physics_2d/physics_server_2d_sw.h new file mode 100644 index 0000000000..196b9a50b9 --- /dev/null +++ b/servers/physics_2d/physics_server_2d_sw.h @@ -0,0 +1,296 @@ +/*************************************************************************/ +/* physics_2d_server_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_2D_SERVER_SW +#define PHYSICS_2D_SERVER_SW + +#include "core/rid_owner.h" +#include "joints_2d_sw.h" +#include "servers/physics_server_2d.h" +#include "shape_2d_sw.h" +#include "space_2d_sw.h" +#include "step_2d_sw.h" + +class PhysicsServer2DSW : public PhysicsServer2D { + + GDCLASS(PhysicsServer2DSW, PhysicsServer2D); + + friend class Physics2DDirectSpaceStateSW; + friend class Physics2DDirectBodyStateSW; + bool active; + int iterations; + bool doing_sync; + real_t last_step; + + int island_count; + int active_objects; + int collision_pairs; + + bool using_threads; + + bool flushing_queries; + + Step2DSW *stepper; + Set active_spaces; + + Physics2DDirectBodyStateSW *direct_state; + + mutable RID_PtrOwner shape_owner; + mutable RID_PtrOwner space_owner; + mutable RID_PtrOwner area_owner; + mutable RID_PtrOwner body_owner; + mutable RID_PtrOwner joint_owner; + + static PhysicsServer2DSW *singletonsw; + + //void _clear_query(Query2DSW *p_query); + friend class CollisionObject2DSW; + SelfList::List pending_shape_update_list; + void _update_shapes(); + + RID _shape_create(ShapeType p_shape); + +public: + struct CollCbkData { + + Vector2 valid_dir; + real_t valid_depth; + int max; + int amount; + int passed; + int invalid_by_dir; + Vector2 *ptr; + }; + + virtual RID line_shape_create(); + virtual RID ray_shape_create(); + virtual RID segment_shape_create(); + virtual RID circle_shape_create(); + virtual RID rectangle_shape_create(); + virtual RID capsule_shape_create(); + virtual RID convex_polygon_shape_create(); + virtual RID concave_polygon_shape_create(); + + static void _shape_col_cbk(const Vector2 &p_point_A, const Vector2 &p_point_B, void *p_userdata); + + virtual void shape_set_data(RID p_shape, const Variant &p_data); + virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias); + + virtual ShapeType shape_get_type(RID p_shape) const; + virtual Variant shape_get_data(RID p_shape) const; + virtual real_t shape_get_custom_solver_bias(RID p_shape) const; + + virtual bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count); + + /* SPACE API */ + + virtual RID space_create(); + virtual void space_set_active(RID p_space, bool p_active); + virtual bool space_is_active(RID p_space) const; + + virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value); + virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; + + virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); + virtual Vector space_get_contacts(RID p_space) const; + virtual int space_get_contact_count(RID p_space) const; + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space); + + /* AREA API */ + + virtual RID area_create(); + + virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode); + virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const; + + virtual void area_set_space(RID p_area, RID p_space); + virtual RID area_get_space(RID p_area) const; + + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); + virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape); + virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform); + + virtual int area_get_shape_count(RID p_area) const; + virtual RID area_get_shape(RID p_area, int p_shape_idx) const; + virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const; + + virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled); + + virtual void area_remove_shape(RID p_area, int p_shape_idx); + virtual void area_clear_shapes(RID p_area); + + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id); + virtual ObjectID area_get_object_instance_id(RID p_area) const; + + virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id); + virtual ObjectID area_get_canvas_instance_id(RID p_area) const; + + virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value); + virtual void area_set_transform(RID p_area, const Transform2D &p_transform); + + virtual Variant area_get_param(RID p_area, AreaParameter p_param) const; + virtual Transform2D area_get_transform(RID p_area) const; + virtual void area_set_monitorable(RID p_area, bool p_monitorable); + virtual void area_set_collision_mask(RID p_area, uint32_t p_mask); + virtual void area_set_collision_layer(RID p_area, uint32_t p_layer); + + virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); + virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); + + virtual void area_set_pickable(RID p_area, bool p_pickable); + + /* BODY API */ + + // create a body of a given type + virtual RID body_create(); + + virtual void body_set_space(RID p_body, RID p_space); + virtual RID body_get_space(RID p_body) const; + + virtual void body_set_mode(RID p_body, BodyMode p_mode); + virtual BodyMode body_get_mode(RID p_body) const; + + virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false); + virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape); + virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform); + virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata); + + virtual int body_get_shape_count(RID p_body) const; + virtual RID body_get_shape(RID p_body, int p_shape_idx) const; + virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const; + virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const; + + virtual void body_remove_shape(RID p_body, int p_shape_idx); + virtual void body_clear_shapes(RID p_body); + + virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); + virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape_idx, bool p_enable, float p_margin); + + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_object_instance_id(RID p_body) const; + + virtual void body_attach_canvas_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_canvas_instance_id(RID p_body) const; + + virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode); + virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const; + + virtual void body_set_collision_layer(RID p_body, uint32_t p_layer); + virtual uint32_t body_get_collision_layer(RID p_body) const; + + virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); + virtual uint32_t body_get_collision_mask(RID p_body) const; + + virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); + virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; + + virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant); + virtual Variant body_get_state(RID p_body, BodyState p_state) const; + + virtual void body_set_applied_force(RID p_body, const Vector2 &p_force); + virtual Vector2 body_get_applied_force(RID p_body) const; + + virtual void body_set_applied_torque(RID p_body, real_t p_torque); + virtual real_t body_get_applied_torque(RID p_body) const; + + virtual void body_add_central_force(RID p_body, const Vector2 &p_force); + virtual void body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force); + virtual void body_add_torque(RID p_body, real_t p_torque); + + virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse); + virtual void body_apply_torque_impulse(RID p_body, real_t p_torque); + virtual void body_apply_impulse(RID p_body, const Vector2 &p_pos, const Vector2 &p_impulse); + virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity); + + virtual void body_add_collision_exception(RID p_body, RID p_body_b); + virtual void body_remove_collision_exception(RID p_body, RID p_body_b); + virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions); + + virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold); + virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const; + + virtual void body_set_omit_force_integration(RID p_body, bool p_omit); + virtual bool body_is_omitting_force_integration(RID p_body) const; + + virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); + virtual int body_get_max_contacts_reported(RID p_body) const; + + virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()); + virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count); + + virtual void body_set_pickable(RID p_body, bool p_pickable); + + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); + virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body); + + /* JOINT API */ + + virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value); + virtual real_t joint_get_param(RID p_joint, JointParam p_param) const; + + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disabled); + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; + + virtual RID pin_joint_create(const Vector2 &p_pos, RID p_body_a, RID p_body_b = RID()); + virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b); + virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()); + virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value); + virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const; + virtual void damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value); + virtual real_t damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const; + + virtual JointType joint_get_type(RID p_joint) const; + + /* MISC */ + + virtual void free(RID p_rid); + + virtual void set_active(bool p_active); + virtual void init(); + virtual void step(real_t p_step); + virtual void sync(); + virtual void flush_queries(); + virtual void end_sync(); + virtual void finish(); + + virtual bool is_flushing_queries() const { return flushing_queries; } + + int get_process_info(ProcessInfo p_info); + + PhysicsServer2DSW(); + ~PhysicsServer2DSW(); +}; + +#endif diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.cpp b/servers/physics_2d/physics_server_2d_wrap_mt.cpp new file mode 100644 index 0000000000..c0f49aa4d1 --- /dev/null +++ b/servers/physics_2d/physics_server_2d_wrap_mt.cpp @@ -0,0 +1,173 @@ +/*************************************************************************/ +/* physics_2d_server_wrap_mt.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_2d_wrap_mt.h" + +#include "core/os/os.h" + +void PhysicsServer2DWrapMT::thread_exit() { + + exit = true; +} + +void PhysicsServer2DWrapMT::thread_step(real_t p_delta) { + + physics_2d_server->step(p_delta); + step_sem.post(); +} + +void PhysicsServer2DWrapMT::_thread_callback(void *_instance) { + + PhysicsServer2DWrapMT *vsmt = reinterpret_cast(_instance); + + vsmt->thread_loop(); +} + +void PhysicsServer2DWrapMT::thread_loop() { + + server_thread = Thread::get_caller_id(); + + physics_2d_server->init(); + + exit = false; + step_thread_up = true; + while (!exit) { + // flush commands one by one, until exit is requested + command_queue.wait_and_flush_one(); + } + + command_queue.flush_all(); // flush all + + physics_2d_server->finish(); +} + +/* EVENT QUEUING */ + +void PhysicsServer2DWrapMT::step(real_t p_step) { + + if (create_thread) { + + command_queue.push(this, &PhysicsServer2DWrapMT::thread_step, p_step); + } else { + + command_queue.flush_all(); //flush all pending from other threads + physics_2d_server->step(p_step); + } +} + +void PhysicsServer2DWrapMT::sync() { + + if (thread) { + if (first_frame) + first_frame = false; + else + step_sem.wait(); //must not wait if a step was not issued + } + physics_2d_server->sync(); +} + +void PhysicsServer2DWrapMT::flush_queries() { + + physics_2d_server->flush_queries(); +} + +void PhysicsServer2DWrapMT::end_sync() { + + physics_2d_server->end_sync(); +} + +void PhysicsServer2DWrapMT::init() { + + if (create_thread) { + + //OS::get_singleton()->release_rendering_thread(); + thread = Thread::create(_thread_callback, this); + while (!step_thread_up) { + OS::get_singleton()->delay_usec(1000); + } + } else { + + physics_2d_server->init(); + } +} + +void PhysicsServer2DWrapMT::finish() { + + if (thread) { + + command_queue.push(this, &PhysicsServer2DWrapMT::thread_exit); + Thread::wait_to_finish(thread); + memdelete(thread); + + thread = NULL; + } else { + physics_2d_server->finish(); + } + + line_shape_free_cached_ids(); + ray_shape_free_cached_ids(); + segment_shape_free_cached_ids(); + circle_shape_free_cached_ids(); + rectangle_shape_free_cached_ids(); + capsule_shape_free_cached_ids(); + convex_polygon_shape_free_cached_ids(); + concave_polygon_shape_free_cached_ids(); + + space_free_cached_ids(); + area_free_cached_ids(); + body_free_cached_ids(); +} + +PhysicsServer2DWrapMT::PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread) : + command_queue(p_create_thread) { + + physics_2d_server = p_contained; + create_thread = p_create_thread; + thread = NULL; + step_pending = 0; + step_thread_up = false; + + pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); + + if (!p_create_thread) { + server_thread = Thread::get_caller_id(); + } else { + server_thread = 0; + } + + main_thread = Thread::get_caller_id(); + first_frame = true; +} + +PhysicsServer2DWrapMT::~PhysicsServer2DWrapMT() { + + memdelete(physics_2d_server); + //finish(); +} diff --git a/servers/physics_2d/physics_server_2d_wrap_mt.h b/servers/physics_2d/physics_server_2d_wrap_mt.h new file mode 100644 index 0000000000..8196ede069 --- /dev/null +++ b/servers/physics_2d/physics_server_2d_wrap_mt.h @@ -0,0 +1,348 @@ +/*************************************************************************/ +/* physics_2d_server_wrap_mt.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS2DSERVERWRAPMT_H +#define PHYSICS2DSERVERWRAPMT_H + +#include "core/command_queue_mt.h" +#include "core/os/thread.h" +#include "core/project_settings.h" +#include "servers/physics_server_2d.h" + +#ifdef DEBUG_SYNC +#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__)); +#else +#define SYNC_DEBUG +#endif + +class PhysicsServer2DWrapMT : public PhysicsServer2D { + + mutable PhysicsServer2D *physics_2d_server; + + mutable CommandQueueMT command_queue; + + static void _thread_callback(void *_instance); + void thread_loop(); + + Thread::ID server_thread; + Thread::ID main_thread; + volatile bool exit; + Thread *thread; + volatile bool step_thread_up; + bool create_thread; + + Semaphore step_sem; + int step_pending; + void thread_step(real_t p_delta); + void thread_flush(); + + void thread_exit(); + + bool first_frame; + + Mutex alloc_mutex; + int pool_max_size; + +public: +#define ServerName PhysicsServer2D +#define ServerNameWrapMT PhysicsServer2DWrapMT +#define server_name physics_2d_server +#include "servers/server_wrap_mt_common.h" + + //FUNC1RID(shape,ShapeType); todo fix + FUNCRID(line_shape) + FUNCRID(ray_shape) + FUNCRID(segment_shape) + FUNCRID(circle_shape) + FUNCRID(rectangle_shape) + FUNCRID(capsule_shape) + FUNCRID(convex_polygon_shape) + FUNCRID(concave_polygon_shape) + + FUNC2(shape_set_data, RID, const Variant &); + FUNC2(shape_set_custom_solver_bias, RID, real_t); + + FUNC1RC(ShapeType, shape_get_type, RID); + FUNC1RC(Variant, shape_get_data, RID); + FUNC1RC(real_t, shape_get_custom_solver_bias, RID); + + //these work well, but should be used from the main thread only + bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + return physics_2d_server->shape_collide(p_shape_A, p_xform_A, p_motion_A, p_shape_B, p_xform_B, p_motion_B, r_results, p_result_max, r_result_count); + } + + /* SPACE API */ + + FUNCRID(space); + FUNC2(space_set_active, RID, bool); + FUNC1RC(bool, space_is_active, RID); + + FUNC3(space_set_param, RID, SpaceParameter, real_t); + FUNC2RC(real_t, space_get_param, RID, SpaceParameter); + + // this function only works on physics process, errors and returns null otherwise + PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL); + return physics_2d_server->space_get_direct_state(p_space); + } + + FUNC2(space_set_debug_contacts, RID, int); + virtual Vector space_get_contacts(RID p_space) const { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), Vector()); + return physics_2d_server->space_get_contacts(p_space); + } + + virtual int space_get_contact_count(RID p_space) const { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), 0); + return physics_2d_server->space_get_contact_count(p_space); + } + + /* AREA API */ + + //FUNC0RID(area); + FUNCRID(area); + + FUNC2(area_set_space, RID, RID); + FUNC1RC(RID, area_get_space, RID); + + FUNC2(area_set_space_override_mode, RID, AreaSpaceOverrideMode); + FUNC1RC(AreaSpaceOverrideMode, area_get_space_override_mode, RID); + + FUNC4(area_add_shape, RID, RID, const Transform2D &, bool); + FUNC3(area_set_shape, RID, int, RID); + FUNC3(area_set_shape_transform, RID, int, const Transform2D &); + FUNC3(area_set_shape_disabled, RID, int, bool); + + FUNC1RC(int, area_get_shape_count, RID); + FUNC2RC(RID, area_get_shape, RID, int); + FUNC2RC(Transform2D, area_get_shape_transform, RID, int); + FUNC2(area_remove_shape, RID, int); + FUNC1(area_clear_shapes, RID); + + FUNC2(area_attach_object_instance_id, RID, ObjectID); + FUNC1RC(ObjectID, area_get_object_instance_id, RID); + + FUNC2(area_attach_canvas_instance_id, RID, ObjectID); + FUNC1RC(ObjectID, area_get_canvas_instance_id, RID); + + FUNC3(area_set_param, RID, AreaParameter, const Variant &); + FUNC2(area_set_transform, RID, const Transform2D &); + + FUNC2RC(Variant, area_get_param, RID, AreaParameter); + FUNC1RC(Transform2D, area_get_transform, RID); + + FUNC2(area_set_collision_mask, RID, uint32_t); + FUNC2(area_set_collision_layer, RID, uint32_t); + + FUNC2(area_set_monitorable, RID, bool); + FUNC2(area_set_pickable, RID, bool); + + FUNC3(area_set_monitor_callback, RID, Object *, const StringName &); + FUNC3(area_set_area_monitor_callback, RID, Object *, const StringName &); + + /* BODY API */ + + //FUNC2RID(body,BodyMode,bool); + FUNCRID(body) + + FUNC2(body_set_space, RID, RID); + FUNC1RC(RID, body_get_space, RID); + + FUNC2(body_set_mode, RID, BodyMode); + FUNC1RC(BodyMode, body_get_mode, RID); + + FUNC4(body_add_shape, RID, RID, const Transform2D &, bool); + FUNC3(body_set_shape, RID, int, RID); + FUNC3(body_set_shape_transform, RID, int, const Transform2D &); + FUNC3(body_set_shape_metadata, RID, int, const Variant &); + + FUNC1RC(int, body_get_shape_count, RID); + FUNC2RC(Transform2D, body_get_shape_transform, RID, int); + FUNC2RC(Variant, body_get_shape_metadata, RID, int); + FUNC2RC(RID, body_get_shape, RID, int); + + FUNC3(body_set_shape_disabled, RID, int, bool); + FUNC4(body_set_shape_as_one_way_collision, RID, int, bool, float); + + FUNC2(body_remove_shape, RID, int); + FUNC1(body_clear_shapes, RID); + + FUNC2(body_attach_object_instance_id, RID, ObjectID); + FUNC1RC(ObjectID, body_get_object_instance_id, RID); + + FUNC2(body_attach_canvas_instance_id, RID, ObjectID); + FUNC1RC(ObjectID, body_get_canvas_instance_id, RID); + + FUNC2(body_set_continuous_collision_detection_mode, RID, CCDMode); + FUNC1RC(CCDMode, body_get_continuous_collision_detection_mode, RID); + + FUNC2(body_set_collision_layer, RID, uint32_t); + FUNC1RC(uint32_t, body_get_collision_layer, RID); + + FUNC2(body_set_collision_mask, RID, uint32_t); + FUNC1RC(uint32_t, body_get_collision_mask, RID); + + FUNC3(body_set_param, RID, BodyParameter, real_t); + FUNC2RC(real_t, body_get_param, RID, BodyParameter); + + FUNC3(body_set_state, RID, BodyState, const Variant &); + FUNC2RC(Variant, body_get_state, RID, BodyState); + + FUNC2(body_set_applied_force, RID, const Vector2 &); + FUNC1RC(Vector2, body_get_applied_force, RID); + + FUNC2(body_set_applied_torque, RID, real_t); + FUNC1RC(real_t, body_get_applied_torque, RID); + + FUNC2(body_add_central_force, RID, const Vector2 &); + FUNC3(body_add_force, RID, const Vector2 &, const Vector2 &); + FUNC2(body_add_torque, RID, real_t); + FUNC2(body_apply_central_impulse, RID, const Vector2 &); + FUNC2(body_apply_torque_impulse, RID, real_t); + FUNC3(body_apply_impulse, RID, const Vector2 &, const Vector2 &); + FUNC2(body_set_axis_velocity, RID, const Vector2 &); + + FUNC2(body_add_collision_exception, RID, RID); + FUNC2(body_remove_collision_exception, RID, RID); + FUNC2S(body_get_collision_exceptions, RID, List *); + + FUNC2(body_set_max_contacts_reported, RID, int); + FUNC1RC(int, body_get_max_contacts_reported, RID); + + FUNC2(body_set_contacts_reported_depth_threshold, RID, real_t); + FUNC1RC(real_t, body_get_contacts_reported_depth_threshold, RID); + + FUNC2(body_set_omit_force_integration, RID, bool); + FUNC1RC(bool, body_is_omitting_force_integration, RID); + + FUNC4(body_set_force_integration_callback, RID, Object *, const StringName &, const Variant &); + + bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) { + return physics_2d_server->body_collide_shape(p_body, p_body_shape, p_shape, p_shape_xform, p_motion, r_results, p_result_max, r_result_count); + } + + FUNC2(body_set_pickable, RID, bool); + + bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + return physics_2d_server->body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r_result, p_exclude_raycast_shapes); + } + + int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), false); + return physics_2d_server->body_test_ray_separation(p_body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); + } + + // this function only works on physics process, errors and returns null otherwise + PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) { + + ERR_FAIL_COND_V(main_thread != Thread::get_caller_id(), NULL); + return physics_2d_server->body_get_direct_state(p_body); + } + + /* JOINT API */ + + FUNC3(joint_set_param, RID, JointParam, real_t); + FUNC2RC(real_t, joint_get_param, RID, JointParam); + + FUNC2(joint_disable_collisions_between_bodies, RID, const bool); + FUNC1RC(bool, joint_is_disabled_collisions_between_bodies, RID); + + ///FUNC3RID(pin_joint,const Vector2&,RID,RID); + ///FUNC5RID(groove_joint,const Vector2&,const Vector2&,const Vector2&,RID,RID); + ///FUNC4RID(damped_spring_joint,const Vector2&,const Vector2&,RID,RID); + + //TODO need to convert this to FUNCRID, but it's a hassle.. + + FUNC3R(RID, pin_joint_create, const Vector2 &, RID, RID); + FUNC5R(RID, groove_joint_create, const Vector2 &, const Vector2 &, const Vector2 &, RID, RID); + FUNC4R(RID, damped_spring_joint_create, const Vector2 &, const Vector2 &, RID, RID); + + FUNC3(pin_joint_set_param, RID, PinJointParam, real_t); + FUNC2RC(real_t, pin_joint_get_param, RID, PinJointParam); + + FUNC3(damped_string_joint_set_param, RID, DampedStringParam, real_t); + FUNC2RC(real_t, damped_string_joint_get_param, RID, DampedStringParam); + + FUNC1RC(JointType, joint_get_type, RID); + + /* MISC */ + + FUNC1(free, RID); + FUNC1(set_active, bool); + + virtual void init(); + virtual void step(real_t p_step); + virtual void sync(); + virtual void end_sync(); + virtual void flush_queries(); + virtual void finish(); + + virtual bool is_flushing_queries() const { + return physics_2d_server->is_flushing_queries(); + } + + int get_process_info(ProcessInfo p_info) { + return physics_2d_server->get_process_info(p_info); + } + + PhysicsServer2DWrapMT(PhysicsServer2D *p_contained, bool p_create_thread); + ~PhysicsServer2DWrapMT(); + + template + static PhysicsServer2D *init_server() { + + int tm = GLOBAL_DEF("physics/2d/thread_model", 1); + if (tm == 0) // single unsafe + return memnew(T); + else if (tm == 1) // single safe + return memnew(PhysicsServer2DWrapMT(memnew(T), false)); + else // multi threaded + return memnew(PhysicsServer2DWrapMT(memnew(T), true)); + } + +#undef ServerNameWrapMT +#undef ServerName +#undef server_name +}; + +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG + +#endif // PHYSICS2DSERVERWRAPMT_H diff --git a/servers/physics_2d/shape_2d_sw.h b/servers/physics_2d/shape_2d_sw.h index fa56f2a250..48f3bea1e1 100644 --- a/servers/physics_2d/shape_2d_sw.h +++ b/servers/physics_2d/shape_2d_sw.h @@ -31,7 +31,7 @@ #ifndef SHAPE_2D_2DSW_H #define SHAPE_2D_2DSW_H -#include "servers/physics_2d_server.h" +#include "servers/physics_server_2d.h" #define _SEGMENT_IS_VALID_SUPPORT_THRESHOLD 0.99998 /* @@ -72,7 +72,7 @@ public: _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } _FORCE_INLINE_ RID get_self() const { return self; } - virtual Physics2DServer::ShapeType get_type() const = 0; + virtual PhysicsServer2D::ShapeType get_type() const = 0; _FORCE_INLINE_ Rect2 get_aabb() const { return aabb; } _FORCE_INLINE_ bool is_configured() const { return configured; } @@ -165,7 +165,7 @@ public: _FORCE_INLINE_ Vector2 get_normal() const { return normal; } _FORCE_INLINE_ real_t get_d() const { return d; } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_LINE; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_LINE; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; @@ -203,7 +203,7 @@ public: _FORCE_INLINE_ real_t get_length() const { return length; } _FORCE_INLINE_ bool get_slips_on_slope() const { return slips_on_slope; } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RAY; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RAY; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; @@ -242,7 +242,7 @@ public: _FORCE_INLINE_ const Vector2 &get_b() const { return b; } _FORCE_INLINE_ const Vector2 &get_normal() const { return n; } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_SEGMENT; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_SEGMENT; } _FORCE_INLINE_ Vector2 get_xformed_normal(const Transform2D &p_xform) const { @@ -285,7 +285,7 @@ class CircleShape2DSW : public Shape2DSW { public: _FORCE_INLINE_ const real_t &get_radius() const { return radius; } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CIRCLE; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_CIRCLE; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; @@ -319,7 +319,7 @@ class RectangleShape2DSW : public Shape2DSW { public: _FORCE_INLINE_ const Vector2 &get_half_extents() const { return half_extents; } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_RECTANGLE; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_RECTANGLE; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; @@ -395,7 +395,7 @@ public: _FORCE_INLINE_ const real_t &get_radius() const { return radius; } _FORCE_INLINE_ const real_t &get_height() const { return height; } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CAPSULE; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_CAPSULE; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; @@ -452,7 +452,7 @@ public: return (p_xform.xform(b) - p_xform.xform(a)).normalized().tangent(); } - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONVEX_POLYGON; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_CONVEX_POLYGON; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { project_range(p_normal, p_transform, r_min, r_max); } virtual void get_supports(const Vector2 &p_normal, Vector2 *r_supports, int &r_amount) const; @@ -531,7 +531,7 @@ class ConcavePolygonShape2DSW : public ConcaveShape2DSW { int _generate_bvh(BVH *p_bvh, int p_len, int p_depth); public: - virtual Physics2DServer::ShapeType get_type() const { return Physics2DServer::SHAPE_CONCAVE_POLYGON; } + virtual PhysicsServer2D::ShapeType get_type() const { return PhysicsServer2D::SHAPE_CONCAVE_POLYGON; } virtual void project_rangev(const Vector2 &p_normal, const Transform2D &p_transform, real_t &r_min, real_t &r_max) const { /*project_range(p_normal,p_transform,r_min,r_max);*/ } diff --git a/servers/physics_2d/space_2d_sw.cpp b/servers/physics_2d/space_2d_sw.cpp index 2009cb823d..72f3e8d1b4 100644 --- a/servers/physics_2d/space_2d_sw.cpp +++ b/servers/physics_2d/space_2d_sw.cpp @@ -33,7 +33,7 @@ #include "collision_solver_2d_sw.h" #include "core/os/os.h" #include "core/pair.h" -#include "physics_2d_server_sw.h" +#include "physics_server_2d_sw.h" _FORCE_INLINE_ static bool _can_collide_with(CollisionObject2DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { if (!(p_object->get_collision_layer() & p_collision_mask)) { @@ -198,7 +198,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans if (p_result_max <= 0) return 0; - Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.getornull(p_shape); + Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, 0); Rect2 aabb = p_xform.xform(shape->get_aabb()); @@ -240,7 +240,7 @@ int Physics2DDirectSpaceStateSW::intersect_shape(const RID &p_shape, const Trans bool Physics2DDirectSpaceStateSW::cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.getornull(p_shape); + Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, false); Rect2 aabb = p_xform.xform(shape->get_aabb()); @@ -313,7 +313,7 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D & if (p_result_max <= 0) return 0; - Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.getornull(p_shape); + Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, 0); Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); @@ -325,14 +325,14 @@ bool Physics2DDirectSpaceStateSW::collide_shape(RID p_shape, const Transform2D & bool collided = false; r_result_count = 0; - Physics2DServerSW::CollCbkData cbk; + PhysicsServer2DSW::CollCbkData cbk; cbk.max = p_result_max; cbk.amount = 0; cbk.passed = 0; cbk.ptr = r_results; - CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk; + CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk; - Physics2DServerSW::CollCbkData *cbkptr = &cbk; + PhysicsServer2DSW::CollCbkData *cbkptr = &cbk; for (int i = 0; i < amount; i++) { @@ -404,7 +404,7 @@ static void _rest_cbk_result(const Vector2 &p_point_A, const Vector2 &p_point_B, bool Physics2DDirectSpaceStateSW::rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, real_t p_margin, ShapeRestInfo *r_info, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - Shape2DSW *shape = Physics2DServerSW::singletonsw->shape_owner.getornull(p_shape); + Shape2DSW *shape = PhysicsServer2DSW::singletonsw->shape_owner.getornull(p_shape); ERR_FAIL_COND_V(!shape, 0); Rect2 aabb = p_shape_xform.xform(shape->get_aabb()); @@ -503,7 +503,7 @@ int Space2DSW::_cull_aabb_for_body(Body2DSW *p_body, const Rect2 &p_aabb) { return amount; } -int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, Physics2DServer::SeparationResult *r_results, int p_result_max, real_t p_margin) { +int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, PhysicsServer2D::SeparationResult *r_results, int p_result_max, real_t p_margin) { Rect2 body_aabb; @@ -514,7 +514,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t if (p_body->is_shape_set_as_disabled(i)) continue; - if (p_body->get_shape(i)->get_type() != Physics2DServer::SHAPE_RAY) + if (p_body->get_shape(i)->get_type() != PhysicsServer2D::SHAPE_RAY) continue; if (!shapes_found) { @@ -548,10 +548,10 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t const int max_results = 32; int recover_attempts = 4; Vector2 sr[max_results * 2]; - Physics2DServerSW::CollCbkData cbk; + PhysicsServer2DSW::CollCbkData cbk; cbk.max = max_results; - Physics2DServerSW::CollCbkData *cbkptr = &cbk; - CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk; + PhysicsServer2DSW::CollCbkData *cbkptr = &cbk; + CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk; do { @@ -567,7 +567,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t Shape2DSW *body_shape = p_body->get_shape(j); - if (body_shape->get_type() != Physics2DServer::SHAPE_RAY) + if (body_shape->get_type() != PhysicsServer2D::SHAPE_RAY) continue; Transform2D body_shape_xform = body_transform * p_body->get_shape_transform(j); @@ -584,7 +584,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { const Body2DSW *b = static_cast(col_obj); - if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) { continue; } } @@ -632,7 +632,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t if (ray_index != -1) { - Physics2DServer::SeparationResult &result = r_results[ray_index]; + PhysicsServer2D::SeparationResult &result = r_results[ray_index]; for (int k = 0; k < cbk.amount; k++) { Vector2 a = sr[k * 2 + 0]; @@ -687,7 +687,7 @@ int Space2DSW::test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_t return rays_found; } -bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result, bool p_exclude_raycast_shapes) { +bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes) { //give me back regular physics engine logic //this is madness @@ -709,7 +709,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (p_body->is_shape_set_as_disabled(i)) continue; - if (p_exclude_raycast_shapes && p_body->get_shape(i)->get_type() == Physics2DServer::SHAPE_RAY) + if (p_exclude_raycast_shapes && p_body->get_shape(i)->get_type() == PhysicsServer2D::SHAPE_RAY) continue; if (!shapes_found) { @@ -722,7 +722,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (!shapes_found) { if (r_result) { - *r_result = Physics2DServer::MotionResult(); + *r_result = PhysicsServer2D::MotionResult(); r_result->motion = p_motion; } return false; @@ -749,7 +749,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co do { - Physics2DServerSW::CollCbkData cbk; + PhysicsServer2DSW::CollCbkData cbk; cbk.max = max_results; cbk.amount = 0; cbk.passed = 0; @@ -757,8 +757,8 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.invalid_by_dir = 0; excluded_shape_pair_count = 0; //last step is the one valid - Physics2DServerSW::CollCbkData *cbkptr = &cbk; - CollisionSolver2DSW::CallbackResult cbkres = Physics2DServerSW::_shape_col_cbk; + PhysicsServer2DSW::CollCbkData *cbkptr = &cbk; + CollisionSolver2DSW::CallbackResult cbkres = PhysicsServer2DSW::_shape_col_cbk; bool collided = false; @@ -769,7 +769,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co continue; Shape2DSW *body_shape = p_body->get_shape(j); - if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) { + if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer2D::SHAPE_RAY) { continue; } @@ -781,7 +781,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { const Body2DSW *b = static_cast(col_obj); - if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) { continue; } } @@ -798,7 +798,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (col_obj->get_type() == CollisionObject2DSW::TYPE_BODY) { const Body2DSW *b = static_cast(col_obj); - if (b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC || b->get_mode() == Physics2DServer::BODY_MODE_RIGID) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_RIGID) { //fix for moving platforms (kinematic and dynamic), margin is increased by how much it moved in the given direction Vector2 lv = b->get_linear_velocity(); //compute displacement from linear velocity @@ -884,7 +884,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co continue; Shape2DSW *body_shape = p_body->get_shape(body_shape_idx); - if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) { + if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer2D::SHAPE_RAY) { continue; } @@ -903,7 +903,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { const Body2DSW *b = static_cast(col_obj); - if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) { continue; } } @@ -964,7 +964,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (col_obj->is_shape_set_as_one_way_collision(col_shape_idx)) { Vector2 cd[2]; - Physics2DServerSW::CollCbkData cbk; + PhysicsServer2DSW::CollCbkData cbk; cbk.max = 1; cbk.amount = 0; cbk.passed = 0; @@ -974,7 +974,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co cbk.valid_depth = 10e20; Vector2 sep = mnormal; //important optimization for this to work fast enough - bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), Physics2DServerSW::_shape_col_cbk, &cbk, &sep, 0); + bool collided = CollisionSolver2DSW::solve(body_shape, body_shape_xform, p_motion * (hi + contact_max_allowed_penetration), col_obj->get_shape(col_shape_idx), col_obj_shape_xform, Vector2(), PhysicsServer2DSW::_shape_col_cbk, &cbk, &sep, 0); if (!collided || cbk.amount == 0) { continue; } @@ -1034,7 +1034,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co Transform2D body_shape_xform = ugt * p_body->get_shape_transform(j); Shape2DSW *body_shape = p_body->get_shape(j); - if (p_exclude_raycast_shapes && body_shape->get_type() == Physics2DServer::SHAPE_RAY) { + if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer2D::SHAPE_RAY) { continue; } @@ -1049,7 +1049,7 @@ bool Space2DSW::test_body_motion(Body2DSW *p_body, const Transform2D &p_from, co if (CollisionObject2DSW::TYPE_BODY == col_obj->get_type()) { const Body2DSW *b = static_cast(col_obj); - if (p_infinite_inertia && Physics2DServer::BODY_MODE_STATIC != b->get_mode() && Physics2DServer::BODY_MODE_KINEMATIC != b->get_mode()) { + if (p_infinite_inertia && PhysicsServer2D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer2D::BODY_MODE_KINEMATIC != b->get_mode()) { continue; } } @@ -1277,33 +1277,33 @@ void Space2DSW::update() { broadphase->update(); } -void Space2DSW::set_param(Physics2DServer::SpaceParameter p_param, real_t p_value) { +void Space2DSW::set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value) { switch (p_param) { - case Physics2DServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: contact_recycle_radius = p_value; break; - case Physics2DServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: contact_max_separation = p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: contact_max_allowed_penetration = p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: body_linear_velocity_sleep_threshold = p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break; - case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break; - case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break; - case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break; + case PhysicsServer2D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: contact_recycle_radius = p_value; break; + case PhysicsServer2D::SPACE_PARAM_CONTACT_MAX_SEPARATION: contact_max_separation = p_value; break; + case PhysicsServer2D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: contact_max_allowed_penetration = p_value; break; + case PhysicsServer2D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: body_linear_velocity_sleep_threshold = p_value; break; + case PhysicsServer2D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break; + case PhysicsServer2D::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break; + case PhysicsServer2D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break; + case PhysicsServer2D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break; } } -real_t Space2DSW::get_param(Physics2DServer::SpaceParameter p_param) const { +real_t Space2DSW::get_param(PhysicsServer2D::SpaceParameter p_param) const { switch (p_param) { - case Physics2DServer::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: return contact_recycle_radius; - case Physics2DServer::SPACE_PARAM_CONTACT_MAX_SEPARATION: return contact_max_separation; - case Physics2DServer::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: return contact_max_allowed_penetration; - case Physics2DServer::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: return body_linear_velocity_sleep_threshold; - case Physics2DServer::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold; - case Physics2DServer::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; - case Physics2DServer::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; - case Physics2DServer::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth; + case PhysicsServer2D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: return contact_recycle_radius; + case PhysicsServer2D::SPACE_PARAM_CONTACT_MAX_SEPARATION: return contact_max_separation; + case PhysicsServer2D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: return contact_max_allowed_penetration; + case PhysicsServer2D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: return body_linear_velocity_sleep_threshold; + case PhysicsServer2D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold; + case PhysicsServer2D::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; + case PhysicsServer2D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; + case PhysicsServer2D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth; } return 0; } diff --git a/servers/physics_2d/space_2d_sw.h b/servers/physics_2d/space_2d_sw.h index 919c65d849..f4971635b9 100644 --- a/servers/physics_2d/space_2d_sw.h +++ b/servers/physics_2d/space_2d_sw.h @@ -41,9 +41,9 @@ #include "core/project_settings.h" #include "core/typedefs.h" -class Physics2DDirectSpaceStateSW : public Physics2DDirectSpaceState { +class Physics2DDirectSpaceStateSW : public PhysicsDirectSpaceState2D { - GDCLASS(Physics2DDirectSpaceStateSW, Physics2DDirectSpaceState); + GDCLASS(Physics2DDirectSpaceStateSW, PhysicsDirectSpaceState2D); int _intersect_point_impl(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_point, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); @@ -175,8 +175,8 @@ public: void lock(); void unlock(); - void set_param(Physics2DServer::SpaceParameter p_param, real_t p_value); - real_t get_param(Physics2DServer::SpaceParameter p_param) const; + void set_param(PhysicsServer2D::SpaceParameter p_param, real_t p_value); + real_t get_param(PhysicsServer2D::SpaceParameter p_param) const; void set_island_count(int p_island_count) { island_count = p_island_count; } int get_island_count() const { return island_count; } @@ -186,8 +186,8 @@ public: int get_collision_pairs() const { return collision_pairs; } - bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, Physics2DServer::MotionResult *r_result, bool p_exclude_raycast_shapes = true); - int test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, Physics2DServer::SeparationResult *r_results, int p_result_max, real_t p_margin); + bool test_body_motion(Body2DSW *p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer2D::MotionResult *r_result, bool p_exclude_raycast_shapes = true); + int test_body_ray_separation(Body2DSW *p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, PhysicsServer2D::SeparationResult *r_results, int p_result_max, real_t p_margin); void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); } diff --git a/servers/physics_2d/step_2d_sw.cpp b/servers/physics_2d/step_2d_sw.cpp index 21f18229e7..198fccdb80 100644 --- a/servers/physics_2d/step_2d_sw.cpp +++ b/servers/physics_2d/step_2d_sw.cpp @@ -50,7 +50,7 @@ void Step2DSW::_populate_island(Body2DSW *p_body, Body2DSW **p_island, Constrain if (i == E->get()) continue; Body2DSW *b = c->get_body_ptr()[i]; - if (b->get_island_step() == _step || b->get_mode() == Physics2DServer::BODY_MODE_STATIC || b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC) + if (b->get_island_step() == _step || b->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) continue; //no go _populate_island(c->get_body_ptr()[i], p_island, p_constraint_island); } @@ -101,7 +101,7 @@ void Step2DSW::_check_suspend(Body2DSW *p_island, real_t p_delta) { Body2DSW *b = p_island; while (b) { - if (b->get_mode() == Physics2DServer::BODY_MODE_STATIC || b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { b = b->get_island_next(); continue; //ignore for static } @@ -117,7 +117,7 @@ void Step2DSW::_check_suspend(Body2DSW *p_island, real_t p_delta) { b = p_island; while (b) { - if (b->get_mode() == Physics2DServer::BODY_MODE_STATIC || b->get_mode() == Physics2DServer::BODY_MODE_KINEMATIC) { + if (b->get_mode() == PhysicsServer2D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer2D::BODY_MODE_KINEMATIC) { b = b->get_island_next(); continue; //ignore for static } diff --git a/servers/physics_2d_server.cpp b/servers/physics_2d_server.cpp deleted file mode 100644 index 1f92d6e419..0000000000 --- a/servers/physics_2d_server.cpp +++ /dev/null @@ -1,840 +0,0 @@ -/*************************************************************************/ -/* physics_2d_server.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_2d_server.h" - -#include "core/method_bind_ext.gen.inc" -#include "core/print_string.h" -#include "core/project_settings.h" - -Physics2DServer *Physics2DServer::singleton = NULL; - -void Physics2DDirectBodyState::integrate_forces() { - - real_t step = get_step(); - Vector2 lv = get_linear_velocity(); - lv += get_total_gravity() * step; - - real_t av = get_angular_velocity(); - - float damp = 1.0 - step * get_total_linear_damp(); - - if (damp < 0) // reached zero in the given time - damp = 0; - - lv *= damp; - - damp = 1.0 - step * get_total_angular_damp(); - - if (damp < 0) // reached zero in the given time - damp = 0; - - av *= damp; - - set_linear_velocity(lv); - set_angular_velocity(av); -} - -Object *Physics2DDirectBodyState::get_contact_collider_object(int p_contact_idx) const { - - ObjectID objid = get_contact_collider_id(p_contact_idx); - Object *obj = ObjectDB::get_instance(objid); - return obj; -} - -Physics2DServer *Physics2DServer::get_singleton() { - - return singleton; -} - -void Physics2DDirectBodyState::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_total_gravity"), &Physics2DDirectBodyState::get_total_gravity); - ClassDB::bind_method(D_METHOD("get_total_linear_damp"), &Physics2DDirectBodyState::get_total_linear_damp); - ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &Physics2DDirectBodyState::get_total_angular_damp); - - ClassDB::bind_method(D_METHOD("get_inverse_mass"), &Physics2DDirectBodyState::get_inverse_mass); - ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &Physics2DDirectBodyState::get_inverse_inertia); - - ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &Physics2DDirectBodyState::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &Physics2DDirectBodyState::get_linear_velocity); - - ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &Physics2DDirectBodyState::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &Physics2DDirectBodyState::get_angular_velocity); - - ClassDB::bind_method(D_METHOD("set_transform", "transform"), &Physics2DDirectBodyState::set_transform); - ClassDB::bind_method(D_METHOD("get_transform"), &Physics2DDirectBodyState::get_transform); - - ClassDB::bind_method(D_METHOD("add_central_force", "force"), &Physics2DDirectBodyState::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &Physics2DDirectBodyState::add_force); - ClassDB::bind_method(D_METHOD("add_torque", "torque"), &Physics2DDirectBodyState::add_torque); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &Physics2DDirectBodyState::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &Physics2DDirectBodyState::apply_torque_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "offset", "impulse"), &Physics2DDirectBodyState::apply_impulse); - - ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &Physics2DDirectBodyState::set_sleep_state); - ClassDB::bind_method(D_METHOD("is_sleeping"), &Physics2DDirectBodyState::is_sleeping); - - ClassDB::bind_method(D_METHOD("get_contact_count"), &Physics2DDirectBodyState::get_contact_count); - - ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_position); - ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_normal); - ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &Physics2DDirectBodyState::get_contact_local_shape); - ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider); - ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_position); - ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_id); - ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_object); - ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_shape); - ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_shape_metadata); - ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &Physics2DDirectBodyState::get_contact_collider_velocity_at_position); - ClassDB::bind_method(D_METHOD("get_step"), &Physics2DDirectBodyState::get_step); - ClassDB::bind_method(D_METHOD("integrate_forces"), &Physics2DDirectBodyState::integrate_forces); - ClassDB::bind_method(D_METHOD("get_space_state"), &Physics2DDirectBodyState::get_space_state); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step"), "", "get_step"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inverse_mass"), "", "get_inverse_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inverse_inertia"), "", "get_inverse_inertia"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_angular_damp"), "", "get_total_angular_damp"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "total_gravity"), "", "get_total_gravity"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); -} - -Physics2DDirectBodyState::Physics2DDirectBodyState() {} - -/////////////////////////////////////////////////////// - -void Physics2DShapeQueryParameters::set_shape(const RES &p_shape) { - - ERR_FAIL_COND(p_shape.is_null()); - shape = p_shape->get_rid(); -} - -void Physics2DShapeQueryParameters::set_shape_rid(const RID &p_shape) { - - shape = p_shape; -} - -RID Physics2DShapeQueryParameters::get_shape_rid() const { - - return shape; -} - -void Physics2DShapeQueryParameters::set_transform(const Transform2D &p_transform) { - - transform = p_transform; -} -Transform2D Physics2DShapeQueryParameters::get_transform() const { - - return transform; -} - -void Physics2DShapeQueryParameters::set_motion(const Vector2 &p_motion) { - - motion = p_motion; -} -Vector2 Physics2DShapeQueryParameters::get_motion() const { - - return motion; -} - -void Physics2DShapeQueryParameters::set_margin(float p_margin) { - - margin = p_margin; -} -float Physics2DShapeQueryParameters::get_margin() const { - - return margin; -} - -void Physics2DShapeQueryParameters::set_collision_mask(int p_collision_mask) { - - collision_mask = p_collision_mask; -} -int Physics2DShapeQueryParameters::get_collision_mask() const { - - return collision_mask; -} - -void Physics2DShapeQueryParameters::set_exclude(const Vector &p_exclude) { - - exclude.clear(); - for (int i = 0; i < p_exclude.size(); i++) - exclude.insert(p_exclude[i]); -} - -Vector Physics2DShapeQueryParameters::get_exclude() const { - - Vector ret; - ret.resize(exclude.size()); - int idx = 0; - for (Set::Element *E = exclude.front(); E; E = E->next()) { - ret.write[idx] = E->get(); - } - return ret; -} - -void Physics2DShapeQueryParameters::set_collide_with_bodies(bool p_enable) { - collide_with_bodies = p_enable; -} - -bool Physics2DShapeQueryParameters::is_collide_with_bodies_enabled() const { - return collide_with_bodies; -} - -void Physics2DShapeQueryParameters::set_collide_with_areas(bool p_enable) { - collide_with_areas = p_enable; -} - -bool Physics2DShapeQueryParameters::is_collide_with_areas_enabled() const { - return collide_with_areas; -} - -void Physics2DShapeQueryParameters::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_shape", "shape"), &Physics2DShapeQueryParameters::set_shape); - ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &Physics2DShapeQueryParameters::set_shape_rid); - ClassDB::bind_method(D_METHOD("get_shape_rid"), &Physics2DShapeQueryParameters::get_shape_rid); - - ClassDB::bind_method(D_METHOD("set_transform", "transform"), &Physics2DShapeQueryParameters::set_transform); - ClassDB::bind_method(D_METHOD("get_transform"), &Physics2DShapeQueryParameters::get_transform); - - ClassDB::bind_method(D_METHOD("set_motion", "motion"), &Physics2DShapeQueryParameters::set_motion); - ClassDB::bind_method(D_METHOD("get_motion"), &Physics2DShapeQueryParameters::get_motion); - - ClassDB::bind_method(D_METHOD("set_margin", "margin"), &Physics2DShapeQueryParameters::set_margin); - ClassDB::bind_method(D_METHOD("get_margin"), &Physics2DShapeQueryParameters::get_margin); - - ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &Physics2DShapeQueryParameters::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_layer"), &Physics2DShapeQueryParameters::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &Physics2DShapeQueryParameters::set_exclude); - ClassDB::bind_method(D_METHOD("get_exclude"), &Physics2DShapeQueryParameters::get_exclude); - - ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &Physics2DShapeQueryParameters::set_collide_with_bodies); - ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &Physics2DShapeQueryParameters::is_collide_with_bodies_enabled); - - ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &Physics2DShapeQueryParameters::set_collide_with_areas); - ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &Physics2DShapeQueryParameters::is_collide_with_areas_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); - //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter - ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); -} - -Physics2DShapeQueryParameters::Physics2DShapeQueryParameters() { - - margin = 0; - collision_mask = 0x7FFFFFFF; - collide_with_bodies = true; - collide_with_areas = false; -} - -Dictionary Physics2DDirectSpaceState::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - - RayResult inters; - Set exclude; - for (int i = 0; i < p_exclude.size(); i++) - exclude.insert(p_exclude[i]); - - bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - - if (!res) - return Dictionary(); - - Dictionary d; - d["position"] = inters.position; - d["normal"] = inters.normal; - d["collider_id"] = inters.collider_id; - d["collider"] = inters.collider; - d["shape"] = inters.shape; - d["rid"] = inters.rid; - d["metadata"] = inters.metadata; - - return d; -} - -Array Physics2DDirectSpaceState::_intersect_shape(const Ref &p_shape_query, int p_max_results) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - - Vector sr; - sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - Array ret; - ret.resize(rc); - for (int i = 0; i < rc; i++) { - - Dictionary d; - d["rid"] = sr[i].rid; - d["collider_id"] = sr[i].collider_id; - d["collider"] = sr[i].collider; - d["shape"] = sr[i].shape; - d["metadata"] = sr[i].metadata; - ret[i] = d; - } - - return ret; -} - -Array Physics2DDirectSpaceState::_cast_motion(const Ref &p_shape_query) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - - float closest_safe, closest_unsafe; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - if (!res) - return Array(); - Array ret; - ret.resize(2); - ret[0] = closest_safe; - ret[1] = closest_unsafe; - return ret; -} - -Array Physics2DDirectSpaceState::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { - - Set exclude; - for (int i = 0; i < p_exclude.size(); i++) - exclude.insert(p_exclude[i]); - - Vector ret; - ret.resize(p_max_results); - - int rc; - if (p_filter_by_canvas) - rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - else - rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); - - if (rc == 0) - return Array(); - - Array r; - r.resize(rc); - for (int i = 0; i < rc; i++) { - - Dictionary d; - d["rid"] = ret[i].rid; - d["collider_id"] = ret[i].collider_id; - d["collider"] = ret[i].collider; - d["shape"] = ret[i].shape; - d["metadata"] = ret[i].metadata; - r[i] = d; - } - return r; -} - -Array Physics2DDirectSpaceState::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - - return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); -} - -Array Physics2DDirectSpaceState::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { - - return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id); -} - -Array Physics2DDirectSpaceState::_collide_shape(const Ref &p_shape_query, int p_max_results) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - - Vector ret; - ret.resize(p_max_results * 2); - int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - if (!res) - return Array(); - Array r; - r.resize(rc * 2); - for (int i = 0; i < rc * 2; i++) - r[i] = ret[i]; - return r; -} -Dictionary Physics2DDirectSpaceState::_get_rest_info(const Ref &p_shape_query) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Dictionary()); - - ShapeRestInfo sri; - - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - Dictionary r; - if (!res) - return r; - - r["point"] = sri.point; - r["normal"] = sri.normal; - r["rid"] = sri.rid; - r["collider_id"] = sri.collider_id; - r["shape"] = sri.shape; - r["linear_velocity"] = sri.linear_velocity; - r["metadata"] = sri.metadata; - - return r; -} - -Physics2DDirectSpaceState::Physics2DDirectSpaceState() { -} - -void Physics2DDirectSpaceState::_bind_methods() { - - ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &Physics2DDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_intersect_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &Physics2DDirectSpaceState::_cast_motion); - ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &Physics2DDirectSpaceState::_collide_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &Physics2DDirectSpaceState::_get_rest_info); -} - -int Physics2DShapeQueryResult::get_result_count() const { - - return result.size(); -} -RID Physics2DShapeQueryResult::get_result_rid(int p_idx) const { - - return result[p_idx].rid; -} -ObjectID Physics2DShapeQueryResult::get_result_object_id(int p_idx) const { - - return result[p_idx].collider_id; -} -Object *Physics2DShapeQueryResult::get_result_object(int p_idx) const { - - return result[p_idx].collider; -} -int Physics2DShapeQueryResult::get_result_object_shape(int p_idx) const { - - return result[p_idx].shape; -} - -Physics2DShapeQueryResult::Physics2DShapeQueryResult() { -} - -void Physics2DShapeQueryResult::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_result_count"), &Physics2DShapeQueryResult::get_result_count); - ClassDB::bind_method(D_METHOD("get_result_rid", "idx"), &Physics2DShapeQueryResult::get_result_rid); - ClassDB::bind_method(D_METHOD("get_result_object_id", "idx"), &Physics2DShapeQueryResult::get_result_object_id); - ClassDB::bind_method(D_METHOD("get_result_object", "idx"), &Physics2DShapeQueryResult::get_result_object); - ClassDB::bind_method(D_METHOD("get_result_object_shape", "idx"), &Physics2DShapeQueryResult::get_result_object_shape); -} - -/////////////////////////////// - -Vector2 Physics2DTestMotionResult::get_motion() const { - - return result.motion; -} -Vector2 Physics2DTestMotionResult::get_motion_remainder() const { - - return result.remainder; -} - -Vector2 Physics2DTestMotionResult::get_collision_point() const { - - return result.collision_point; -} -Vector2 Physics2DTestMotionResult::get_collision_normal() const { - - return result.collision_normal; -} -Vector2 Physics2DTestMotionResult::get_collider_velocity() const { - - return result.collider_velocity; -} -ObjectID Physics2DTestMotionResult::get_collider_id() const { - - return result.collider_id; -} -RID Physics2DTestMotionResult::get_collider_rid() const { - - return result.collider; -} - -Object *Physics2DTestMotionResult::get_collider() const { - return ObjectDB::get_instance(result.collider_id); -} - -int Physics2DTestMotionResult::get_collider_shape() const { - - return result.collider_shape; -} - -void Physics2DTestMotionResult::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_motion"), &Physics2DTestMotionResult::get_motion); - ClassDB::bind_method(D_METHOD("get_motion_remainder"), &Physics2DTestMotionResult::get_motion_remainder); - ClassDB::bind_method(D_METHOD("get_collision_point"), &Physics2DTestMotionResult::get_collision_point); - ClassDB::bind_method(D_METHOD("get_collision_normal"), &Physics2DTestMotionResult::get_collision_normal); - ClassDB::bind_method(D_METHOD("get_collider_velocity"), &Physics2DTestMotionResult::get_collider_velocity); - ClassDB::bind_method(D_METHOD("get_collider_id"), &Physics2DTestMotionResult::get_collider_id); - ClassDB::bind_method(D_METHOD("get_collider_rid"), &Physics2DTestMotionResult::get_collider_rid); - ClassDB::bind_method(D_METHOD("get_collider"), &Physics2DTestMotionResult::get_collider); - ClassDB::bind_method(D_METHOD("get_collider_shape"), &Physics2DTestMotionResult::get_collider_shape); - - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "", "get_motion"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_remainder"), "", "get_motion_remainder"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_point"), "", "get_collision_point"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_normal"), "", "get_collision_normal"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id"); - ADD_PROPERTY(PropertyInfo(Variant::_RID, "collider_rid"), "", "get_collider_rid"); - ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider"); - ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape"); -} - -Physics2DTestMotionResult::Physics2DTestMotionResult() { - - colliding = false; - - result.collider_shape = 0; -} - -/////////////////////////////////////// - -bool Physics2DServer::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref &p_result) { - - MotionResult *r = NULL; - if (p_result.is_valid()) - r = p_result->get_result_ptr(); - return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r); -} - -void Physics2DServer::_bind_methods() { - - ClassDB::bind_method(D_METHOD("line_shape_create"), &Physics2DServer::line_shape_create); - ClassDB::bind_method(D_METHOD("ray_shape_create"), &Physics2DServer::ray_shape_create); - ClassDB::bind_method(D_METHOD("segment_shape_create"), &Physics2DServer::segment_shape_create); - ClassDB::bind_method(D_METHOD("circle_shape_create"), &Physics2DServer::circle_shape_create); - ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &Physics2DServer::rectangle_shape_create); - ClassDB::bind_method(D_METHOD("capsule_shape_create"), &Physics2DServer::capsule_shape_create); - ClassDB::bind_method(D_METHOD("convex_polygon_shape_create"), &Physics2DServer::convex_polygon_shape_create); - ClassDB::bind_method(D_METHOD("concave_polygon_shape_create"), &Physics2DServer::concave_polygon_shape_create); - - ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &Physics2DServer::shape_set_data); - - ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &Physics2DServer::shape_get_type); - ClassDB::bind_method(D_METHOD("shape_get_data", "shape"), &Physics2DServer::shape_get_data); - - ClassDB::bind_method(D_METHOD("space_create"), &Physics2DServer::space_create); - ClassDB::bind_method(D_METHOD("space_set_active", "space", "active"), &Physics2DServer::space_set_active); - ClassDB::bind_method(D_METHOD("space_is_active", "space"), &Physics2DServer::space_is_active); - ClassDB::bind_method(D_METHOD("space_set_param", "space", "param", "value"), &Physics2DServer::space_set_param); - ClassDB::bind_method(D_METHOD("space_get_param", "space", "param"), &Physics2DServer::space_get_param); - ClassDB::bind_method(D_METHOD("space_get_direct_state", "space"), &Physics2DServer::space_get_direct_state); - - ClassDB::bind_method(D_METHOD("area_create"), &Physics2DServer::area_create); - ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &Physics2DServer::area_set_space); - ClassDB::bind_method(D_METHOD("area_get_space", "area"), &Physics2DServer::area_get_space); - - ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &Physics2DServer::area_set_space_override_mode); - ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &Physics2DServer::area_get_space_override_mode); - - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &Physics2DServer::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &Physics2DServer::area_set_shape); - ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &Physics2DServer::area_set_shape_transform); - ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &Physics2DServer::area_set_shape_disabled); - - ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &Physics2DServer::area_get_shape_count); - ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &Physics2DServer::area_get_shape); - ClassDB::bind_method(D_METHOD("area_get_shape_transform", "area", "shape_idx"), &Physics2DServer::area_get_shape_transform); - - ClassDB::bind_method(D_METHOD("area_remove_shape", "area", "shape_idx"), &Physics2DServer::area_remove_shape); - ClassDB::bind_method(D_METHOD("area_clear_shapes", "area"), &Physics2DServer::area_clear_shapes); - - ClassDB::bind_method(D_METHOD("area_set_collision_layer", "area", "layer"), &Physics2DServer::area_set_collision_layer); - ClassDB::bind_method(D_METHOD("area_set_collision_mask", "area", "mask"), &Physics2DServer::area_set_collision_mask); - - ClassDB::bind_method(D_METHOD("area_set_param", "area", "param", "value"), &Physics2DServer::area_set_param); - ClassDB::bind_method(D_METHOD("area_set_transform", "area", "transform"), &Physics2DServer::area_set_transform); - - ClassDB::bind_method(D_METHOD("area_get_param", "area", "param"), &Physics2DServer::area_get_param); - ClassDB::bind_method(D_METHOD("area_get_transform", "area"), &Physics2DServer::area_get_transform); - - ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &Physics2DServer::area_attach_object_instance_id); - ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &Physics2DServer::area_get_object_instance_id); - - ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &Physics2DServer::area_attach_canvas_instance_id); - ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &Physics2DServer::area_get_canvas_instance_id); - - ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_monitor_callback); - ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &Physics2DServer::area_set_area_monitor_callback); - ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &Physics2DServer::area_set_monitorable); - - ClassDB::bind_method(D_METHOD("body_create"), &Physics2DServer::body_create); - - ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &Physics2DServer::body_set_space); - ClassDB::bind_method(D_METHOD("body_get_space", "body"), &Physics2DServer::body_get_space); - - ClassDB::bind_method(D_METHOD("body_set_mode", "body", "mode"), &Physics2DServer::body_set_mode); - ClassDB::bind_method(D_METHOD("body_get_mode", "body"), &Physics2DServer::body_get_mode); - - ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &Physics2DServer::body_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &Physics2DServer::body_set_shape); - ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &Physics2DServer::body_set_shape_transform); - ClassDB::bind_method(D_METHOD("body_set_shape_metadata", "body", "shape_idx", "metadata"), &Physics2DServer::body_set_shape_metadata); - - ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &Physics2DServer::body_get_shape_count); - ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &Physics2DServer::body_get_shape); - ClassDB::bind_method(D_METHOD("body_get_shape_transform", "body", "shape_idx"), &Physics2DServer::body_get_shape_transform); - ClassDB::bind_method(D_METHOD("body_get_shape_metadata", "body", "shape_idx"), &Physics2DServer::body_get_shape_metadata); - - ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &Physics2DServer::body_remove_shape); - ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &Physics2DServer::body_clear_shapes); - - ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &Physics2DServer::body_set_shape_disabled); - ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable", "margin"), &Physics2DServer::body_set_shape_as_one_way_collision); - - ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &Physics2DServer::body_attach_object_instance_id); - ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &Physics2DServer::body_get_object_instance_id); - - ClassDB::bind_method(D_METHOD("body_attach_canvas_instance_id", "body", "id"), &Physics2DServer::body_attach_canvas_instance_id); - ClassDB::bind_method(D_METHOD("body_get_canvas_instance_id", "body"), &Physics2DServer::body_get_canvas_instance_id); - - ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode", "body", "mode"), &Physics2DServer::body_set_continuous_collision_detection_mode); - ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode", "body"), &Physics2DServer::body_get_continuous_collision_detection_mode); - - ClassDB::bind_method(D_METHOD("body_set_collision_layer", "body", "layer"), &Physics2DServer::body_set_collision_layer); - ClassDB::bind_method(D_METHOD("body_get_collision_layer", "body"), &Physics2DServer::body_get_collision_layer); - - ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &Physics2DServer::body_set_collision_mask); - ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &Physics2DServer::body_get_collision_mask); - - ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &Physics2DServer::body_set_param); - ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &Physics2DServer::body_get_param); - - ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &Physics2DServer::body_set_state); - ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &Physics2DServer::body_get_state); - - ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &Physics2DServer::body_apply_central_impulse); - ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &Physics2DServer::body_apply_torque_impulse); - ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &Physics2DServer::body_apply_impulse); - ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &Physics2DServer::body_add_central_force); - ClassDB::bind_method(D_METHOD("body_add_force", "body", "offset", "force"), &Physics2DServer::body_add_force); - ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &Physics2DServer::body_add_torque); - ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &Physics2DServer::body_set_axis_velocity); - - ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &Physics2DServer::body_add_collision_exception); - ClassDB::bind_method(D_METHOD("body_remove_collision_exception", "body", "excepted_body"), &Physics2DServer::body_remove_collision_exception); - - ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported", "body", "amount"), &Physics2DServer::body_set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported", "body"), &Physics2DServer::body_get_max_contacts_reported); - - ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &Physics2DServer::body_set_omit_force_integration); - ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &Physics2DServer::body_is_omitting_force_integration); - - ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &Physics2DServer::body_set_force_integration_callback, DEFVAL(Variant())); - - ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &Physics2DServer::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant())); - - ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &Physics2DServer::body_get_direct_state); - - /* JOINT API */ - - ClassDB::bind_method(D_METHOD("joint_set_param", "joint", "param", "value"), &Physics2DServer::joint_set_param); - ClassDB::bind_method(D_METHOD("joint_get_param", "joint", "param"), &Physics2DServer::joint_get_param); - - ClassDB::bind_method(D_METHOD("pin_joint_create", "anchor", "body_a", "body_b"), &Physics2DServer::pin_joint_create, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("groove_joint_create", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &Physics2DServer::groove_joint_create, DEFVAL(RID()), DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("damped_spring_joint_create", "anchor_a", "anchor_b", "body_a", "body_b"), &Physics2DServer::damped_spring_joint_create, DEFVAL(RID())); - - ClassDB::bind_method(D_METHOD("damped_string_joint_set_param", "joint", "param", "value"), &Physics2DServer::damped_string_joint_set_param); - ClassDB::bind_method(D_METHOD("damped_string_joint_get_param", "joint", "param"), &Physics2DServer::damped_string_joint_get_param); - - ClassDB::bind_method(D_METHOD("joint_get_type", "joint"), &Physics2DServer::joint_get_type); - - ClassDB::bind_method(D_METHOD("free_rid", "rid"), &Physics2DServer::free); - - ClassDB::bind_method(D_METHOD("set_active", "active"), &Physics2DServer::set_active); - - ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &Physics2DServer::get_process_info); - - BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); - BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); - BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); - BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); - - BIND_ENUM_CONSTANT(SHAPE_LINE); - BIND_ENUM_CONSTANT(SHAPE_RAY); - BIND_ENUM_CONSTANT(SHAPE_SEGMENT); - BIND_ENUM_CONSTANT(SHAPE_CIRCLE); - BIND_ENUM_CONSTANT(SHAPE_RECTANGLE); - BIND_ENUM_CONSTANT(SHAPE_CAPSULE); - BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON); - BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); - BIND_ENUM_CONSTANT(SHAPE_CUSTOM); - - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); - BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); - BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); - BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); - - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE_REPLACE); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE_COMBINE); - - BIND_ENUM_CONSTANT(BODY_MODE_STATIC); - BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); - BIND_ENUM_CONSTANT(BODY_MODE_RIGID); - BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER); - - BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); - BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); - BIND_ENUM_CONSTANT(BODY_PARAM_MASS); - BIND_ENUM_CONSTANT(BODY_PARAM_INERTIA); - BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE); - BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP); - BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP); - BIND_ENUM_CONSTANT(BODY_PARAM_MAX); - - BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM); - BIND_ENUM_CONSTANT(BODY_STATE_LINEAR_VELOCITY); - BIND_ENUM_CONSTANT(BODY_STATE_ANGULAR_VELOCITY); - BIND_ENUM_CONSTANT(BODY_STATE_SLEEPING); - BIND_ENUM_CONSTANT(BODY_STATE_CAN_SLEEP); - - BIND_ENUM_CONSTANT(JOINT_PIN); - BIND_ENUM_CONSTANT(JOINT_GROOVE); - BIND_ENUM_CONSTANT(JOINT_DAMPED_SPRING); - - BIND_ENUM_CONSTANT(JOINT_PARAM_BIAS); - BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS); - BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_FORCE); - - BIND_ENUM_CONSTANT(DAMPED_STRING_REST_LENGTH); - BIND_ENUM_CONSTANT(DAMPED_STRING_STIFFNESS); - BIND_ENUM_CONSTANT(DAMPED_STRING_DAMPING); - - BIND_ENUM_CONSTANT(CCD_MODE_DISABLED); - BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY); - BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE); - - BIND_ENUM_CONSTANT(AREA_BODY_ADDED); - BIND_ENUM_CONSTANT(AREA_BODY_REMOVED); - - BIND_ENUM_CONSTANT(INFO_ACTIVE_OBJECTS); - BIND_ENUM_CONSTANT(INFO_COLLISION_PAIRS); - BIND_ENUM_CONSTANT(INFO_ISLAND_COUNT); -} - -Physics2DServer::Physics2DServer() { - - singleton = this; -} - -Physics2DServer::~Physics2DServer() { - - singleton = NULL; -} - -Vector Physics2DServerManager::physics_2d_servers; -int Physics2DServerManager::default_server_id = -1; -int Physics2DServerManager::default_server_priority = -1; -const String Physics2DServerManager::setting_property_name("physics/2d/physics_engine"); - -void Physics2DServerManager::on_servers_changed() { - - String physics_servers("DEFAULT"); - for (int i = get_servers_count() - 1; 0 <= i; --i) { - physics_servers += "," + get_server_name(i); - } - ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers)); -} - -void Physics2DServerManager::register_server(const String &p_name, CreatePhysics2DServerCallback p_creat_callback) { - - ERR_FAIL_COND(!p_creat_callback); - ERR_FAIL_COND(find_server_id(p_name) != -1); - physics_2d_servers.push_back(ClassInfo(p_name, p_creat_callback)); - on_servers_changed(); -} - -void Physics2DServerManager::set_default_server(const String &p_name, int p_priority) { - - const int id = find_server_id(p_name); - ERR_FAIL_COND(id == -1); // Not found - if (default_server_priority < p_priority) { - default_server_id = id; - default_server_priority = p_priority; - } -} - -int Physics2DServerManager::find_server_id(const String &p_name) { - - for (int i = physics_2d_servers.size() - 1; 0 <= i; --i) { - if (p_name == physics_2d_servers[i].name) { - return i; - } - } - return -1; -} - -int Physics2DServerManager::get_servers_count() { - return physics_2d_servers.size(); -} - -String Physics2DServerManager::get_server_name(int p_id) { - ERR_FAIL_INDEX_V(p_id, get_servers_count(), ""); - return physics_2d_servers[p_id].name; -} - -Physics2DServer *Physics2DServerManager::new_default_server() { - ERR_FAIL_COND_V(default_server_id == -1, NULL); - return physics_2d_servers[default_server_id].create_callback(); -} - -Physics2DServer *Physics2DServerManager::new_server(const String &p_name) { - int id = find_server_id(p_name); - if (id == -1) { - return NULL; - } else { - return physics_2d_servers[id].create_callback(); - } -} diff --git a/servers/physics_2d_server.h b/servers/physics_2d_server.h deleted file mode 100644 index c923ef16b7..0000000000 --- a/servers/physics_2d_server.h +++ /dev/null @@ -1,699 +0,0 @@ -/*************************************************************************/ -/* physics_2d_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS_2D_SERVER_H -#define PHYSICS_2D_SERVER_H - -#include "core/object.h" -#include "core/reference.h" -#include "core/resource.h" - -class Physics2DDirectSpaceState; - -class Physics2DDirectBodyState : public Object { - - GDCLASS(Physics2DDirectBodyState, Object); - -protected: - static void _bind_methods(); - -public: - virtual Vector2 get_total_gravity() const = 0; // get gravity vector working on this body space/area - virtual float get_total_linear_damp() const = 0; // get density of this body space/area - virtual float get_total_angular_damp() const = 0; // get density of this body space/area - - virtual float get_inverse_mass() const = 0; // get the mass - virtual real_t get_inverse_inertia() const = 0; // get density of this body space - - virtual void set_linear_velocity(const Vector2 &p_velocity) = 0; - virtual Vector2 get_linear_velocity() const = 0; - - virtual void set_angular_velocity(real_t p_velocity) = 0; - virtual real_t get_angular_velocity() const = 0; - - virtual void set_transform(const Transform2D &p_transform) = 0; - virtual Transform2D get_transform() const = 0; - - virtual void add_central_force(const Vector2 &p_force) = 0; - virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) = 0; - virtual void add_torque(real_t p_torque) = 0; - virtual void apply_central_impulse(const Vector2 &p_impulse) = 0; - virtual void apply_torque_impulse(real_t p_torque) = 0; - virtual void apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) = 0; - - virtual void set_sleep_state(bool p_enable) = 0; - virtual bool is_sleeping() const = 0; - - virtual int get_contact_count() const = 0; - - virtual Vector2 get_contact_local_position(int p_contact_idx) const = 0; - virtual Vector2 get_contact_local_normal(int p_contact_idx) const = 0; - virtual int get_contact_local_shape(int p_contact_idx) const = 0; - - virtual RID get_contact_collider(int p_contact_idx) const = 0; - virtual Vector2 get_contact_collider_position(int p_contact_idx) const = 0; - virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0; - virtual Object *get_contact_collider_object(int p_contact_idx) const; - virtual int get_contact_collider_shape(int p_contact_idx) const = 0; - virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const = 0; - virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0; - - virtual real_t get_step() const = 0; - virtual void integrate_forces(); - - virtual Physics2DDirectSpaceState *get_space_state() = 0; - - Physics2DDirectBodyState(); -}; - -class Physics2DShapeQueryResult; - -//used for script -class Physics2DShapeQueryParameters : public Reference { - - GDCLASS(Physics2DShapeQueryParameters, Reference); - friend class Physics2DDirectSpaceState; - RID shape; - Transform2D transform; - Vector2 motion; - float margin; - Set exclude; - uint32_t collision_mask; - - bool collide_with_bodies; - bool collide_with_areas; - -protected: - static void _bind_methods(); - -public: - void set_shape(const RES &p_shape); - void set_shape_rid(const RID &p_shape); - RID get_shape_rid() const; - - void set_transform(const Transform2D &p_transform); - Transform2D get_transform() const; - - void set_motion(const Vector2 &p_motion); - Vector2 get_motion() const; - - void set_margin(float p_margin); - float get_margin() const; - - void set_collision_mask(int p_collision_mask); - int get_collision_mask() const; - - void set_collide_with_bodies(bool p_enable); - bool is_collide_with_bodies_enabled() const; - - void set_collide_with_areas(bool p_enable); - bool is_collide_with_areas_enabled() const; - - void set_exclude(const Vector &p_exclude); - Vector get_exclude() const; - - Physics2DShapeQueryParameters(); -}; - -class Physics2DDirectSpaceState : public Object { - - GDCLASS(Physics2DDirectSpaceState, Object); - - Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector &p_exclude = Vector(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector &p_exclude = Vector(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector &p_exclude = Vector(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); - Array _intersect_shape(const Ref &p_shape_query, int p_max_results = 32); - Array _cast_motion(const Ref &p_shape_query); - Array _collide_shape(const Ref &p_shape_query, int p_max_results = 32); - Dictionary _get_rest_info(const Ref &p_shape_query); - -protected: - static void _bind_methods(); - -public: - struct RayResult { - - Vector2 position; - Vector2 normal; - RID rid; - ObjectID collider_id; - Object *collider; - int shape; - Variant metadata; - }; - - virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - struct ShapeResult { - - RID rid; - ObjectID collider_id; - Object *collider; - int shape; - Variant metadata; - }; - - virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; - virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; - - virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - struct ShapeRestInfo { - - Vector2 point; - Vector2 normal; - RID rid; - ObjectID collider_id; - int shape; - Vector2 linear_velocity; //velocity at contact point - Variant metadata; - }; - - virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, ShapeRestInfo *r_info, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - Physics2DDirectSpaceState(); -}; - -class Physics2DShapeQueryResult : public Reference { - - GDCLASS(Physics2DShapeQueryResult, Reference); - - Vector result; - - friend class Physics2DDirectSpaceState; - -protected: - static void _bind_methods(); - -public: - int get_result_count() const; - RID get_result_rid(int p_idx) const; - ObjectID get_result_object_id(int p_idx) const; - Object *get_result_object(int p_idx) const; - int get_result_object_shape(int p_idx) const; - - Physics2DShapeQueryResult(); -}; - -class Physics2DTestMotionResult; - -class Physics2DServer : public Object { - - GDCLASS(Physics2DServer, Object); - - static Physics2DServer *singleton; - - virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.08, const Ref &p_result = Ref()); - -protected: - static void _bind_methods(); - -public: - static Physics2DServer *get_singleton(); - - enum ShapeType { - SHAPE_LINE, ///< plane:"plane" - SHAPE_RAY, ///< float:"length" - SHAPE_SEGMENT, ///< float:"length" - SHAPE_CIRCLE, ///< float:"radius" - SHAPE_RECTANGLE, ///< vec3:"extents" - SHAPE_CAPSULE, - SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" - SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array) - SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error - }; - - virtual RID line_shape_create() = 0; - virtual RID ray_shape_create() = 0; - virtual RID segment_shape_create() = 0; - virtual RID circle_shape_create() = 0; - virtual RID rectangle_shape_create() = 0; - virtual RID capsule_shape_create() = 0; - virtual RID convex_polygon_shape_create() = 0; - virtual RID concave_polygon_shape_create() = 0; - - virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0; - virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0; - - virtual ShapeType shape_get_type(RID p_shape) const = 0; - virtual Variant shape_get_data(RID p_shape) const = 0; - virtual real_t shape_get_custom_solver_bias(RID p_shape) const = 0; - - //these work well, but should be used from the main thread only - virtual bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; - - /* SPACE API */ - - virtual RID space_create() = 0; - virtual void space_set_active(RID p_space, bool p_active) = 0; - virtual bool space_is_active(RID p_space) const = 0; - - enum SpaceParameter { - - SPACE_PARAM_CONTACT_RECYCLE_RADIUS, - SPACE_PARAM_CONTACT_MAX_SEPARATION, - SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION, - SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD, - SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD, - SPACE_PARAM_BODY_TIME_TO_SLEEP, - SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, - SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH, - }; - - virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; - virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0; - - // this function only works on physics process, errors and returns null otherwise - virtual Physics2DDirectSpaceState *space_get_direct_state(RID p_space) = 0; - - virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0; - virtual Vector space_get_contacts(RID p_space) const = 0; - virtual int space_get_contact_count(RID p_space) const = 0; - - //missing space parameters - - /* AREA API */ - - //missing attenuation? missing better override? - - enum AreaParameter { - AREA_PARAM_GRAVITY, - AREA_PARAM_GRAVITY_VECTOR, - AREA_PARAM_GRAVITY_IS_POINT, - AREA_PARAM_GRAVITY_DISTANCE_SCALE, - AREA_PARAM_GRAVITY_POINT_ATTENUATION, - AREA_PARAM_LINEAR_DAMP, - AREA_PARAM_ANGULAR_DAMP, - AREA_PARAM_PRIORITY - }; - - virtual RID area_create() = 0; - - virtual void area_set_space(RID p_area, RID p_space) = 0; - virtual RID area_get_space(RID p_area) const = 0; - - enum AreaSpaceOverrideMode { - AREA_SPACE_OVERRIDE_DISABLED, - AREA_SPACE_OVERRIDE_COMBINE, - AREA_SPACE_OVERRIDE_COMBINE_REPLACE, // Combines, then discards all subsequent calculations - AREA_SPACE_OVERRIDE_REPLACE, - AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining - }; - - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - - virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; - virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; - virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0; - - virtual int area_get_shape_count(RID p_area) const = 0; - virtual RID area_get_shape(RID p_area, int p_shape_idx) const = 0; - virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const = 0; - - virtual void area_remove_shape(RID p_area, int p_shape_idx) = 0; - virtual void area_clear_shapes(RID p_area) = 0; - - virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) = 0; - - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0; - virtual ObjectID area_get_object_instance_id(RID p_area) const = 0; - - virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id) = 0; - virtual ObjectID area_get_canvas_instance_id(RID p_area) const = 0; - - virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0; - virtual void area_set_transform(RID p_area, const Transform2D &p_transform) = 0; - - virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0; - virtual Transform2D area_get_transform(RID p_area) const = 0; - - virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0; - virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0; - - virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0; - virtual void area_set_pickable(RID p_area, bool p_pickable) = 0; - - virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; - virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; - - /* BODY API */ - - //missing ccd? - - enum BodyMode { - BODY_MODE_STATIC, - BODY_MODE_KINEMATIC, - BODY_MODE_RIGID, - BODY_MODE_CHARACTER - }; - - virtual RID body_create() = 0; - - virtual void body_set_space(RID p_body, RID p_space) = 0; - virtual RID body_get_space(RID p_body) const = 0; - - virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0; - virtual BodyMode body_get_mode(RID p_body) const = 0; - - virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; - virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; - virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) = 0; - virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) = 0; - - virtual int body_get_shape_count(RID p_body) const = 0; - virtual RID body_get_shape(RID p_body, int p_shape_idx) const = 0; - virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const = 0; - virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const = 0; - - virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled) = 0; - virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled, float p_margin = 0) = 0; - - virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0; - virtual void body_clear_shapes(RID p_body) = 0; - - virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) = 0; - virtual ObjectID body_get_object_instance_id(RID p_body) const = 0; - - virtual void body_attach_canvas_instance_id(RID p_body, ObjectID p_id) = 0; - virtual ObjectID body_get_canvas_instance_id(RID p_body) const = 0; - - enum CCDMode { - CCD_MODE_DISABLED, - CCD_MODE_CAST_RAY, - CCD_MODE_CAST_SHAPE, - }; - - virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) = 0; - virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const = 0; - - virtual void body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; - virtual uint32_t body_get_collision_layer(RID p_body) const = 0; - - virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; - virtual uint32_t body_get_collision_mask(RID p_body) const = 0; - - // common body variables - enum BodyParameter { - BODY_PARAM_BOUNCE, - BODY_PARAM_FRICTION, - BODY_PARAM_MASS, ///< unused for static, always infinite - BODY_PARAM_INERTIA, // read-only: computed from mass & shapes - BODY_PARAM_GRAVITY_SCALE, - BODY_PARAM_LINEAR_DAMP, - BODY_PARAM_ANGULAR_DAMP, - BODY_PARAM_MAX, - }; - - virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; - virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0; - - //state - enum BodyState { - BODY_STATE_TRANSFORM, - BODY_STATE_LINEAR_VELOCITY, - BODY_STATE_ANGULAR_VELOCITY, - BODY_STATE_SLEEPING, - BODY_STATE_CAN_SLEEP, - }; - - virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; - virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0; - - //do something about it - virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) = 0; - virtual Vector2 body_get_applied_force(RID p_body) const = 0; - - virtual void body_set_applied_torque(RID p_body, float p_torque) = 0; - virtual float body_get_applied_torque(RID p_body) const = 0; - - virtual void body_add_central_force(RID p_body, const Vector2 &p_force) = 0; - virtual void body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force) = 0; - virtual void body_add_torque(RID p_body, float p_torque) = 0; - - virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) = 0; - virtual void body_apply_torque_impulse(RID p_body, float p_torque) = 0; - virtual void body_apply_impulse(RID p_body, const Vector2 &p_offset, const Vector2 &p_impulse) = 0; - virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) = 0; - - //fix - virtual void body_add_collision_exception(RID p_body, RID p_body_b) = 0; - virtual void body_remove_collision_exception(RID p_body, RID p_body_b) = 0; - virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; - - virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) = 0; - virtual int body_get_max_contacts_reported(RID p_body) const = 0; - - //missing remove - virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) = 0; - virtual float body_get_contacts_reported_depth_threshold(RID p_body) const = 0; - - virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0; - virtual bool body_is_omitting_force_integration(RID p_body) const = 0; - - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; - - virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; - - virtual void body_set_pickable(RID p_body, bool p_pickable) = 0; - - // this function only works on physics process, errors and returns null otherwise - virtual Physics2DDirectBodyState *body_get_direct_state(RID p_body) = 0; - - struct MotionResult { - - Vector2 motion; - Vector2 remainder; - - Vector2 collision_point; - Vector2 collision_normal; - Vector2 collider_velocity; - int collision_local_shape; - ObjectID collider_id; - RID collider; - int collider_shape; - Variant collider_metadata; - - MotionResult() { - collision_local_shape = 0; - collider_shape = 0; - collider_id = ObjectID(); - } - }; - - virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; - - struct SeparationResult { - - float collision_depth; - Vector2 collision_point; - Vector2 collision_normal; - Vector2 collider_velocity; - int collision_local_shape; - ObjectID collider_id; - RID collider; - int collider_shape; - Variant collider_metadata; - }; - - virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0; - - /* JOINT API */ - - enum JointType { - - JOINT_PIN, - JOINT_GROOVE, - JOINT_DAMPED_SPRING - }; - - enum JointParam { - JOINT_PARAM_BIAS, - JOINT_PARAM_MAX_BIAS, - JOINT_PARAM_MAX_FORCE, - }; - - virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value) = 0; - virtual real_t joint_get_param(RID p_joint, JointParam p_param) const = 0; - - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; - virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; - - virtual RID pin_joint_create(const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0; - virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0; - virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0; - - enum PinJointParam { - PIN_JOINT_SOFTNESS - }; - - virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) = 0; - virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0; - - enum DampedStringParam { - DAMPED_STRING_REST_LENGTH, - DAMPED_STRING_STIFFNESS, - DAMPED_STRING_DAMPING - }; - virtual void damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value) = 0; - virtual real_t damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const = 0; - - virtual JointType joint_get_type(RID p_joint) const = 0; - - /* QUERY API */ - - enum AreaBodyStatus { - AREA_BODY_ADDED, - AREA_BODY_REMOVED - }; - - /* MISC */ - - virtual void free(RID p_rid) = 0; - - virtual void set_active(bool p_active) = 0; - virtual void init() = 0; - virtual void step(float p_step) = 0; - virtual void sync() = 0; - virtual void flush_queries() = 0; - virtual void end_sync() = 0; - virtual void finish() = 0; - - virtual bool is_flushing_queries() const = 0; - - enum ProcessInfo { - - INFO_ACTIVE_OBJECTS, - INFO_COLLISION_PAIRS, - INFO_ISLAND_COUNT - }; - - virtual int get_process_info(ProcessInfo p_info) = 0; - - Physics2DServer(); - ~Physics2DServer(); -}; - -class Physics2DTestMotionResult : public Reference { - - GDCLASS(Physics2DTestMotionResult, Reference); - - Physics2DServer::MotionResult result; - bool colliding; - friend class Physics2DServer; - -protected: - static void _bind_methods(); - -public: - Physics2DServer::MotionResult *get_result_ptr() const { return const_cast(&result); } - - //bool is_colliding() const; - Vector2 get_motion() const; - Vector2 get_motion_remainder() const; - - Vector2 get_collision_point() const; - Vector2 get_collision_normal() const; - Vector2 get_collider_velocity() const; - ObjectID get_collider_id() const; - RID get_collider_rid() const; - Object *get_collider() const; - int get_collider_shape() const; - - Physics2DTestMotionResult(); -}; - -typedef Physics2DServer *(*CreatePhysics2DServerCallback)(); - -class Physics2DServerManager { - struct ClassInfo { - String name; - CreatePhysics2DServerCallback create_callback; - - ClassInfo() : - name(""), - create_callback(NULL) {} - - ClassInfo(String p_name, CreatePhysics2DServerCallback p_create_callback) : - name(p_name), - create_callback(p_create_callback) {} - - ClassInfo(const ClassInfo &p_ci) : - name(p_ci.name), - create_callback(p_ci.create_callback) {} - - ClassInfo operator=(const ClassInfo &p_ci) { - name = p_ci.name; - create_callback = p_ci.create_callback; - return *this; - } - }; - - static Vector physics_2d_servers; - static int default_server_id; - static int default_server_priority; - -public: - static const String setting_property_name; - -private: - static void on_servers_changed(); - -public: - static void register_server(const String &p_name, CreatePhysics2DServerCallback p_creat_callback); - static void set_default_server(const String &p_name, int p_priority = 0); - static int find_server_id(const String &p_name); - static int get_servers_count(); - static String get_server_name(int p_id); - static Physics2DServer *new_default_server(); - static Physics2DServer *new_server(const String &p_name); -}; - -VARIANT_ENUM_CAST(Physics2DServer::ShapeType); -VARIANT_ENUM_CAST(Physics2DServer::SpaceParameter); -VARIANT_ENUM_CAST(Physics2DServer::AreaParameter); -VARIANT_ENUM_CAST(Physics2DServer::AreaSpaceOverrideMode); -VARIANT_ENUM_CAST(Physics2DServer::BodyMode); -VARIANT_ENUM_CAST(Physics2DServer::BodyParameter); -VARIANT_ENUM_CAST(Physics2DServer::BodyState); -VARIANT_ENUM_CAST(Physics2DServer::CCDMode); -VARIANT_ENUM_CAST(Physics2DServer::JointParam); -VARIANT_ENUM_CAST(Physics2DServer::JointType); -VARIANT_ENUM_CAST(Physics2DServer::DampedStringParam); -//VARIANT_ENUM_CAST( Physics2DServer::ObjectType ); -VARIANT_ENUM_CAST(Physics2DServer::AreaBodyStatus); -VARIANT_ENUM_CAST(Physics2DServer::ProcessInfo); - -#endif diff --git a/servers/physics_3d/SCsub b/servers/physics_3d/SCsub new file mode 100644 index 0000000000..c5cc889112 --- /dev/null +++ b/servers/physics_3d/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.servers_sources, "*.cpp") + +SConscript("joints/SCsub") diff --git a/servers/physics_3d/area_3d_sw.cpp b/servers/physics_3d/area_3d_sw.cpp new file mode 100644 index 0000000000..99d4d2ec1b --- /dev/null +++ b/servers/physics_3d/area_3d_sw.cpp @@ -0,0 +1,264 @@ +/*************************************************************************/ +/* area_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "area_3d_sw.h" +#include "body_3d_sw.h" +#include "space_3d_sw.h" + +Area3DSW::BodyKey::BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { + rid = p_body->get_self(); + instance_id = p_body->get_instance_id(); + body_shape = p_body_shape; + area_shape = p_area_shape; +} +Area3DSW::BodyKey::BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { + rid = p_body->get_self(); + instance_id = p_body->get_instance_id(); + body_shape = p_body_shape; + area_shape = p_area_shape; +} + +void Area3DSW::_shapes_changed() { + + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); +} + +void Area3DSW::set_transform(const Transform &p_transform) { + + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); + + _set_transform(p_transform); + _set_inv_transform(p_transform.affine_inverse()); +} + +void Area3DSW::set_space(Space3DSW *p_space) { + + if (get_space()) { + if (monitor_query_list.in_list()) + get_space()->area_remove_from_monitor_query_list(&monitor_query_list); + if (moved_list.in_list()) + get_space()->area_remove_from_moved_list(&moved_list); + } + + monitored_bodies.clear(); + monitored_areas.clear(); + + _set_space(p_space); +} + +void Area3DSW::set_monitor_callback(ObjectID p_id, const StringName &p_method) { + + if (p_id == monitor_callback_id) { + monitor_callback_method = p_method; + return; + } + + _unregister_shapes(); + + monitor_callback_id = p_id; + monitor_callback_method = p_method; + + monitored_bodies.clear(); + monitored_areas.clear(); + + _shape_changed(); + + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); +} + +void Area3DSW::set_area_monitor_callback(ObjectID p_id, const StringName &p_method) { + + if (p_id == area_monitor_callback_id) { + area_monitor_callback_method = p_method; + return; + } + + _unregister_shapes(); + + area_monitor_callback_id = p_id; + area_monitor_callback_method = p_method; + + monitored_bodies.clear(); + monitored_areas.clear(); + + _shape_changed(); + + if (!moved_list.in_list() && get_space()) + get_space()->area_add_to_moved_list(&moved_list); +} + +void Area3DSW::set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode) { + bool do_override = p_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + if (do_override == (space_override_mode != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED)) + return; + _unregister_shapes(); + space_override_mode = p_mode; + _shape_changed(); +} + +void Area3DSW::set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value) { + + switch (p_param) { + case PhysicsServer3D::AREA_PARAM_GRAVITY: gravity = p_value; break; + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: gravity_vector = p_value; break; + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: gravity_is_point = p_value; break; + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: gravity_distance_scale = p_value; break; + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: point_attenuation = p_value; break; + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: linear_damp = p_value; break; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: angular_damp = p_value; break; + case PhysicsServer3D::AREA_PARAM_PRIORITY: priority = p_value; break; + } +} + +Variant Area3DSW::get_param(PhysicsServer3D::AreaParameter p_param) const { + + switch (p_param) { + case PhysicsServer3D::AREA_PARAM_GRAVITY: return gravity; + case PhysicsServer3D::AREA_PARAM_GRAVITY_VECTOR: return gravity_vector; + case PhysicsServer3D::AREA_PARAM_GRAVITY_IS_POINT: return gravity_is_point; + case PhysicsServer3D::AREA_PARAM_GRAVITY_DISTANCE_SCALE: return gravity_distance_scale; + case PhysicsServer3D::AREA_PARAM_GRAVITY_POINT_ATTENUATION: return point_attenuation; + case PhysicsServer3D::AREA_PARAM_LINEAR_DAMP: return linear_damp; + case PhysicsServer3D::AREA_PARAM_ANGULAR_DAMP: return angular_damp; + case PhysicsServer3D::AREA_PARAM_PRIORITY: return priority; + } + + return Variant(); +} + +void Area3DSW::_queue_monitor_update() { + + ERR_FAIL_COND(!get_space()); + + if (!monitor_query_list.in_list()) + get_space()->area_add_to_monitor_query_list(&monitor_query_list); +} + +void Area3DSW::set_monitorable(bool p_monitorable) { + + if (monitorable == p_monitorable) + return; + + monitorable = p_monitorable; + _set_static(!monitorable); +} + +void Area3DSW::call_queries() { + + if (monitor_callback_id.is_valid() && !monitored_bodies.empty()) { + + Variant res[5]; + Variant *resptr[5]; + for (int i = 0; i < 5; i++) + resptr[i] = &res[i]; + + Object *obj = ObjectDB::get_instance(monitor_callback_id); + if (!obj) { + monitored_bodies.clear(); + monitor_callback_id = ObjectID(); + return; + } + + for (Map::Element *E = monitored_bodies.front(); E; E = E->next()) { + + if (E->get().state == 0) + continue; //nothing happened + + res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; + res[1] = E->key().rid; + res[2] = E->key().instance_id; + res[3] = E->key().body_shape; + res[4] = E->key().area_shape; + + Callable::CallError ce; + obj->call(monitor_callback_method, (const Variant **)resptr, 5, ce); + } + } + + monitored_bodies.clear(); + + if (area_monitor_callback_id.is_valid() && !monitored_areas.empty()) { + + Variant res[5]; + Variant *resptr[5]; + for (int i = 0; i < 5; i++) + resptr[i] = &res[i]; + + Object *obj = ObjectDB::get_instance(area_monitor_callback_id); + if (!obj) { + monitored_areas.clear(); + area_monitor_callback_id = ObjectID(); + return; + } + + for (Map::Element *E = monitored_areas.front(); E; E = E->next()) { + + if (E->get().state == 0) + continue; //nothing happened + + res[0] = E->get().state > 0 ? PhysicsServer3D::AREA_BODY_ADDED : PhysicsServer3D::AREA_BODY_REMOVED; + res[1] = E->key().rid; + res[2] = E->key().instance_id; + res[3] = E->key().body_shape; + res[4] = E->key().area_shape; + + Callable::CallError ce; + obj->call(area_monitor_callback_method, (const Variant **)resptr, 5, ce); + } + } + + monitored_areas.clear(); + //get_space()->area_remove_from_monitor_query_list(&monitor_query_list); +} + +Area3DSW::Area3DSW() : + CollisionObject3DSW(TYPE_AREA), + monitor_query_list(this), + moved_list(this) { + + _set_static(true); //areas are never active + space_override_mode = PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED; + gravity = 9.80665; + gravity_vector = Vector3(0, -1, 0); + gravity_is_point = false; + gravity_distance_scale = 0; + point_attenuation = 1; + angular_damp = 0.1; + linear_damp = 0.1; + priority = 0; + set_ray_pickable(false); + monitorable = false; +} + +Area3DSW::~Area3DSW() { +} diff --git a/servers/physics_3d/area_3d_sw.h b/servers/physics_3d/area_3d_sw.h new file mode 100644 index 0000000000..bc57790206 --- /dev/null +++ b/servers/physics_3d/area_3d_sw.h @@ -0,0 +1,203 @@ +/*************************************************************************/ +/* area_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef AREA_SW_H +#define AREA_SW_H + +#include "collision_object_3d_sw.h" +#include "core/self_list.h" +#include "servers/physics_server_3d.h" +//#include "servers/physics_3d/query_sw.h" + +class Space3DSW; +class Body3DSW; +class Constraint3DSW; + +class Area3DSW : public CollisionObject3DSW { + + PhysicsServer3D::AreaSpaceOverrideMode space_override_mode; + real_t gravity; + Vector3 gravity_vector; + bool gravity_is_point; + real_t gravity_distance_scale; + real_t point_attenuation; + real_t linear_damp; + real_t angular_damp; + int priority; + bool monitorable; + + ObjectID monitor_callback_id; + StringName monitor_callback_method; + + ObjectID area_monitor_callback_id; + StringName area_monitor_callback_method; + + SelfList monitor_query_list; + SelfList moved_list; + + struct BodyKey { + + RID rid; + ObjectID instance_id; + uint32_t body_shape; + uint32_t area_shape; + + _FORCE_INLINE_ bool operator<(const BodyKey &p_key) const { + + if (rid == p_key.rid) { + + if (body_shape == p_key.body_shape) { + + return area_shape < p_key.area_shape; + } else + return body_shape < p_key.body_shape; + } else + return rid < p_key.rid; + } + + _FORCE_INLINE_ BodyKey() {} + BodyKey(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + BodyKey(Area3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + }; + + struct BodyState { + + int state; + _FORCE_INLINE_ void inc() { state++; } + _FORCE_INLINE_ void dec() { state--; } + _FORCE_INLINE_ BodyState() { state = 0; } + }; + + Map monitored_bodies; + Map monitored_areas; + + //virtual void shape_changed_notify(ShapeSW *p_shape); + //virtual void shape_deleted_notify(ShapeSW *p_shape); + + Set constraints; + + virtual void _shapes_changed(); + void _queue_monitor_update(); + +public: + //_FORCE_INLINE_ const Transform& get_inverse_transform() const { return inverse_transform; } + //_FORCE_INLINE_ SpaceSW* get_owner() { return owner; } + + void set_monitor_callback(ObjectID p_id, const StringName &p_method); + _FORCE_INLINE_ bool has_monitor_callback() const { return monitor_callback_id.is_valid(); } + + void set_area_monitor_callback(ObjectID p_id, const StringName &p_method); + _FORCE_INLINE_ bool has_area_monitor_callback() const { return area_monitor_callback_id.is_valid(); } + + _FORCE_INLINE_ void add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + _FORCE_INLINE_ void remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape); + + _FORCE_INLINE_ void add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); + _FORCE_INLINE_ void remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape); + + void set_param(PhysicsServer3D::AreaParameter p_param, const Variant &p_value); + Variant get_param(PhysicsServer3D::AreaParameter p_param) const; + + void set_space_override_mode(PhysicsServer3D::AreaSpaceOverrideMode p_mode); + PhysicsServer3D::AreaSpaceOverrideMode get_space_override_mode() const { return space_override_mode; } + + _FORCE_INLINE_ void set_gravity(real_t p_gravity) { gravity = p_gravity; } + _FORCE_INLINE_ real_t get_gravity() const { return gravity; } + + _FORCE_INLINE_ void set_gravity_vector(const Vector3 &p_gravity) { gravity_vector = p_gravity; } + _FORCE_INLINE_ Vector3 get_gravity_vector() const { return gravity_vector; } + + _FORCE_INLINE_ void set_gravity_as_point(bool p_enable) { gravity_is_point = p_enable; } + _FORCE_INLINE_ bool is_gravity_point() const { return gravity_is_point; } + + _FORCE_INLINE_ void set_gravity_distance_scale(real_t scale) { gravity_distance_scale = scale; } + _FORCE_INLINE_ real_t get_gravity_distance_scale() const { return gravity_distance_scale; } + + _FORCE_INLINE_ void set_point_attenuation(real_t p_point_attenuation) { point_attenuation = p_point_attenuation; } + _FORCE_INLINE_ real_t get_point_attenuation() const { return point_attenuation; } + + _FORCE_INLINE_ void set_linear_damp(real_t p_linear_damp) { linear_damp = p_linear_damp; } + _FORCE_INLINE_ real_t get_linear_damp() const { return linear_damp; } + + _FORCE_INLINE_ void set_angular_damp(real_t p_angular_damp) { angular_damp = p_angular_damp; } + _FORCE_INLINE_ real_t get_angular_damp() const { return angular_damp; } + + _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } + _FORCE_INLINE_ int get_priority() const { return priority; } + + _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint) { constraints.insert(p_constraint); } + _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraints.erase(p_constraint); } + _FORCE_INLINE_ const Set &get_constraints() const { return constraints; } + _FORCE_INLINE_ void clear_constraints() { constraints.clear(); } + + void set_monitorable(bool p_monitorable); + _FORCE_INLINE_ bool is_monitorable() const { return monitorable; } + + void set_transform(const Transform &p_transform); + + void set_space(Space3DSW *p_space); + + void call_queries(); + + Area3DSW(); + ~Area3DSW(); +}; + +void Area3DSW::add_body_to_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { + + BodyKey bk(p_body, p_body_shape, p_area_shape); + monitored_bodies[bk].inc(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); +} +void Area3DSW::remove_body_from_query(Body3DSW *p_body, uint32_t p_body_shape, uint32_t p_area_shape) { + + BodyKey bk(p_body, p_body_shape, p_area_shape); + monitored_bodies[bk].dec(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); +} + +void Area3DSW::add_area_to_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { + + BodyKey bk(p_area, p_area_shape, p_self_shape); + monitored_areas[bk].inc(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); +} +void Area3DSW::remove_area_from_query(Area3DSW *p_area, uint32_t p_area_shape, uint32_t p_self_shape) { + + BodyKey bk(p_area, p_area_shape, p_self_shape); + monitored_areas[bk].dec(); + if (!monitor_query_list.in_list()) + _queue_monitor_update(); +} + +#endif // AREA__SW_H diff --git a/servers/physics_3d/area_pair_3d_sw.cpp b/servers/physics_3d/area_pair_3d_sw.cpp new file mode 100644 index 0000000000..3300e9dede --- /dev/null +++ b/servers/physics_3d/area_pair_3d_sw.cpp @@ -0,0 +1,159 @@ +/*************************************************************************/ +/* area_pair_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "area_pair_3d_sw.h" +#include "collision_solver_3d_sw.h" + +bool AreaPair3DSW::setup(real_t p_step) { + + bool result = false; + + if (area->is_shape_set_as_disabled(area_shape) || body->is_shape_set_as_disabled(body_shape)) { + result = false; + } else if (area->test_collision_mask(body) && CollisionSolver3DSW::solve_static(body->get_shape(body_shape), body->get_transform() * body->get_shape_transform(body_shape), area->get_shape(area_shape), area->get_transform() * area->get_shape_transform(area_shape), NULL, this)) { + result = true; + } + + if (result != colliding) { + + if (result) { + + if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) + body->add_area(area); + if (area->has_monitor_callback()) + area->add_body_to_query(body, body_shape, area_shape); + + } else { + + if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) + body->remove_area(area); + if (area->has_monitor_callback()) + area->remove_body_from_query(body, body_shape, area_shape); + } + + colliding = result; + } + + return false; //never do any post solving +} + +void AreaPair3DSW::solve(real_t p_step) { +} + +AreaPair3DSW::AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, int p_area_shape) { + + body = p_body; + area = p_area; + body_shape = p_body_shape; + area_shape = p_area_shape; + colliding = false; + body->add_constraint(this, 0); + area->add_constraint(this); + if (p_body->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) + p_body->set_active(true); +} + +AreaPair3DSW::~AreaPair3DSW() { + + if (colliding) { + + if (area->get_space_override_mode() != PhysicsServer3D::AREA_SPACE_OVERRIDE_DISABLED) + body->remove_area(area); + if (area->has_monitor_callback()) + area->remove_body_from_query(body, body_shape, area_shape); + } + body->remove_constraint(this); + area->remove_constraint(this); +} + +//////////////////////////////////////////////////// + +bool Area2Pair3DSW::setup(real_t p_step) { + + bool result = false; + if (area_a->is_shape_set_as_disabled(shape_a) || area_b->is_shape_set_as_disabled(shape_b)) { + result = false; + } else if (area_a->test_collision_mask(area_b) && CollisionSolver3DSW::solve_static(area_a->get_shape(shape_a), area_a->get_transform() * area_a->get_shape_transform(shape_a), area_b->get_shape(shape_b), area_b->get_transform() * area_b->get_shape_transform(shape_b), NULL, this)) { + result = true; + } + + if (result != colliding) { + + if (result) { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->add_area_to_query(area_a, shape_a, shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->add_area_to_query(area_b, shape_b, shape_a); + + } else { + + if (area_b->has_area_monitor_callback() && area_a->is_monitorable()) + area_b->remove_area_from_query(area_a, shape_a, shape_b); + + if (area_a->has_area_monitor_callback() && area_b->is_monitorable()) + area_a->remove_area_from_query(area_b, shape_b, shape_a); + } + + colliding = result; + } + + return false; //never do any post solving +} + +void Area2Pair3DSW::solve(real_t p_step) { +} + +Area2Pair3DSW::Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area_b, int p_shape_b) { + + area_a = p_area_a; + area_b = p_area_b; + shape_a = p_shape_a; + shape_b = p_shape_b; + colliding = false; + area_a->add_constraint(this); + area_b->add_constraint(this); +} + +Area2Pair3DSW::~Area2Pair3DSW() { + + if (colliding) { + + if (area_b->has_area_monitor_callback()) + area_b->remove_area_from_query(area_a, shape_a, shape_b); + + if (area_a->has_area_monitor_callback()) + area_a->remove_area_from_query(area_b, shape_b, shape_a); + } + + area_a->remove_constraint(this); + area_b->remove_constraint(this); +} diff --git a/servers/physics_3d/area_pair_3d_sw.h b/servers/physics_3d/area_pair_3d_sw.h new file mode 100644 index 0000000000..6f7e1ee3b5 --- /dev/null +++ b/servers/physics_3d/area_pair_3d_sw.h @@ -0,0 +1,70 @@ +/*************************************************************************/ +/* area_pair_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef AREA_PAIR_SW_H +#define AREA_PAIR_SW_H + +#include "area_3d_sw.h" +#include "body_3d_sw.h" +#include "constraint_3d_sw.h" + +class AreaPair3DSW : public Constraint3DSW { + + Body3DSW *body; + Area3DSW *area; + int body_shape; + int area_shape; + bool colliding; + +public: + bool setup(real_t p_step); + void solve(real_t p_step); + + AreaPair3DSW(Body3DSW *p_body, int p_body_shape, Area3DSW *p_area, int p_area_shape); + ~AreaPair3DSW(); +}; + +class Area2Pair3DSW : public Constraint3DSW { + + Area3DSW *area_a; + Area3DSW *area_b; + int shape_a; + int shape_b; + bool colliding; + +public: + bool setup(real_t p_step); + void solve(real_t p_step); + + Area2Pair3DSW(Area3DSW *p_area_a, int p_shape_a, Area3DSW *p_area_b, int p_shape_b); + ~Area2Pair3DSW(); +}; + +#endif // AREA_PAIR__SW_H diff --git a/servers/physics_3d/body_3d_sw.cpp b/servers/physics_3d/body_3d_sw.cpp new file mode 100644 index 0000000000..dcdc373dc9 --- /dev/null +++ b/servers/physics_3d/body_3d_sw.cpp @@ -0,0 +1,814 @@ +/*************************************************************************/ +/* body_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "body_3d_sw.h" +#include "area_3d_sw.h" +#include "space_3d_sw.h" + +void Body3DSW::_update_inertia() { + + if (get_space() && !inertia_update_list.in_list()) + get_space()->body_add_to_inertia_update_list(&inertia_update_list); +} + +void Body3DSW::_update_transform_dependant() { + + center_of_mass = get_transform().basis.xform(center_of_mass_local); + principal_inertia_axes = get_transform().basis * principal_inertia_axes_local; + + // update inertia tensor + Basis tb = principal_inertia_axes; + Basis tbt = tb.transposed(); + Basis diag; + diag.scale(_inv_inertia); + _inv_inertia_tensor = tb * diag * tbt; +} + +void Body3DSW::update_inertias() { + + //update shapes and motions + + switch (mode) { + + case PhysicsServer3D::BODY_MODE_RIGID: { + + //update tensor for all shapes, not the best way but should be somehow OK. (inspired from bullet) + real_t total_area = 0; + + for (int i = 0; i < get_shape_count(); i++) { + + total_area += get_shape_area(i); + } + + // We have to recompute the center of mass + center_of_mass_local.zero(); + + for (int i = 0; i < get_shape_count(); i++) { + real_t area = get_shape_area(i); + + real_t mass = area * this->mass / total_area; + + // NOTE: we assume that the shape origin is also its center of mass + center_of_mass_local += mass * get_shape_transform(i).origin; + } + + center_of_mass_local /= mass; + + // Recompute the inertia tensor + Basis inertia_tensor; + inertia_tensor.set_zero(); + + for (int i = 0; i < get_shape_count(); i++) { + + if (is_shape_disabled(i)) { + continue; + } + + const Shape3DSW *shape = get_shape(i); + + real_t area = get_shape_area(i); + + real_t mass = area * this->mass / total_area; + + Basis shape_inertia_tensor = shape->get_moment_of_inertia(mass).to_diagonal_matrix(); + Transform shape_transform = get_shape_transform(i); + Basis shape_basis = shape_transform.basis.orthonormalized(); + + // NOTE: we don't take the scale of collision shapes into account when computing the inertia tensor! + shape_inertia_tensor = shape_basis * shape_inertia_tensor * shape_basis.transposed(); + + Vector3 shape_origin = shape_transform.origin - center_of_mass_local; + inertia_tensor += shape_inertia_tensor + (Basis() * shape_origin.dot(shape_origin) - shape_origin.outer(shape_origin)) * mass; + } + + // Compute the principal axes of inertia + principal_inertia_axes_local = inertia_tensor.diagonalize().transposed(); + _inv_inertia = inertia_tensor.get_main_diagonal().inverse(); + + if (mass) + _inv_mass = 1.0 / mass; + else + _inv_mass = 0; + + } break; + + case PhysicsServer3D::BODY_MODE_KINEMATIC: + case PhysicsServer3D::BODY_MODE_STATIC: { + + _inv_inertia_tensor.set_zero(); + _inv_mass = 0; + } break; + case PhysicsServer3D::BODY_MODE_CHARACTER: { + + _inv_inertia_tensor.set_zero(); + _inv_mass = 1.0 / mass; + + } break; + } + + //_update_shapes(); + + _update_transform_dependant(); +} + +void Body3DSW::set_active(bool p_active) { + + if (active == p_active) + return; + + active = p_active; + if (!p_active) { + if (get_space()) + get_space()->body_remove_from_active_list(&active_list); + } else { + if (mode == PhysicsServer3D::BODY_MODE_STATIC) + return; //static bodies can't become active + if (get_space()) + get_space()->body_add_to_active_list(&active_list); + + //still_time=0; + } + /* + if (!space) + return; + + for(int i=0;i0) { + get_space()->get_broadphase()->set_active(s.bpid,active); + } + } +*/ +} + +void Body3DSW::set_param(PhysicsServer3D::BodyParameter p_param, real_t p_value) { + + switch (p_param) { + case PhysicsServer3D::BODY_PARAM_BOUNCE: { + + bounce = p_value; + } break; + case PhysicsServer3D::BODY_PARAM_FRICTION: { + + friction = p_value; + } break; + case PhysicsServer3D::BODY_PARAM_MASS: { + ERR_FAIL_COND(p_value <= 0); + mass = p_value; + _update_inertia(); + + } break; + case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: { + gravity_scale = p_value; + } break; + case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: { + + linear_damp = p_value; + } break; + case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP: { + + angular_damp = p_value; + } break; + default: { + } + } +} + +real_t Body3DSW::get_param(PhysicsServer3D::BodyParameter p_param) const { + + switch (p_param) { + case PhysicsServer3D::BODY_PARAM_BOUNCE: { + + return bounce; + } break; + case PhysicsServer3D::BODY_PARAM_FRICTION: { + + return friction; + } break; + case PhysicsServer3D::BODY_PARAM_MASS: { + return mass; + } break; + case PhysicsServer3D::BODY_PARAM_GRAVITY_SCALE: { + return gravity_scale; + } break; + case PhysicsServer3D::BODY_PARAM_LINEAR_DAMP: { + + return linear_damp; + } break; + case PhysicsServer3D::BODY_PARAM_ANGULAR_DAMP: { + + return angular_damp; + } break; + + default: { + } + } + + return 0; +} + +void Body3DSW::set_mode(PhysicsServer3D::BodyMode p_mode) { + + PhysicsServer3D::BodyMode prev = mode; + mode = p_mode; + + switch (p_mode) { + //CLEAR UP EVERYTHING IN CASE IT NOT WORKS! + case PhysicsServer3D::BODY_MODE_STATIC: + case PhysicsServer3D::BODY_MODE_KINEMATIC: { + + _set_inv_transform(get_transform().affine_inverse()); + _inv_mass = 0; + _set_static(p_mode == PhysicsServer3D::BODY_MODE_STATIC); + //set_active(p_mode==PhysicsServer3D::BODY_MODE_KINEMATIC); + set_active(p_mode == PhysicsServer3D::BODY_MODE_KINEMATIC && contacts.size()); + linear_velocity = Vector3(); + angular_velocity = Vector3(); + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && prev != mode) { + first_time_kinematic = true; + } + + } break; + case PhysicsServer3D::BODY_MODE_RIGID: { + + _inv_mass = mass > 0 ? (1.0 / mass) : 0; + _set_static(false); + set_active(true); + + } break; + case PhysicsServer3D::BODY_MODE_CHARACTER: { + + _inv_mass = mass > 0 ? (1.0 / mass) : 0; + _set_static(false); + set_active(true); + angular_velocity = Vector3(); + } break; + } + + _update_inertia(); + /* + if (get_space()) + _update_queries(); + */ +} +PhysicsServer3D::BodyMode Body3DSW::get_mode() const { + + return mode; +} + +void Body3DSW::_shapes_changed() { + + _update_inertia(); +} + +void Body3DSW::set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant) { + + switch (p_state) { + case PhysicsServer3D::BODY_STATE_TRANSFORM: { + + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { + new_transform = p_variant; + //wakeup_neighbours(); + set_active(true); + if (first_time_kinematic) { + _set_transform(p_variant); + _set_inv_transform(get_transform().affine_inverse()); + first_time_kinematic = false; + } + + } else if (mode == PhysicsServer3D::BODY_MODE_STATIC) { + _set_transform(p_variant); + _set_inv_transform(get_transform().affine_inverse()); + wakeup_neighbours(); + } else { + Transform t = p_variant; + t.orthonormalize(); + new_transform = get_transform(); //used as old to compute motion + if (new_transform == t) + break; + _set_transform(t); + _set_inv_transform(get_transform().inverse()); + } + wakeup(); + + } break; + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: { + + /* + if (mode==PhysicsServer3D::BODY_MODE_STATIC) + break; + */ + linear_velocity = p_variant; + wakeup(); + } break; + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: { + /* + if (mode!=PhysicsServer3D::BODY_MODE_RIGID) + break; + */ + angular_velocity = p_variant; + wakeup(); + + } break; + case PhysicsServer3D::BODY_STATE_SLEEPING: { + //? + if (mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) + break; + bool do_sleep = p_variant; + if (do_sleep) { + linear_velocity = Vector3(); + //biased_linear_velocity=Vector3(); + angular_velocity = Vector3(); + //biased_angular_velocity=Vector3(); + set_active(false); + } else { + set_active(true); + } + } break; + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: { + can_sleep = p_variant; + if (mode == PhysicsServer3D::BODY_MODE_RIGID && !active && !can_sleep) + set_active(true); + + } break; + } +} +Variant Body3DSW::get_state(PhysicsServer3D::BodyState p_state) const { + + switch (p_state) { + case PhysicsServer3D::BODY_STATE_TRANSFORM: { + return get_transform(); + } break; + case PhysicsServer3D::BODY_STATE_LINEAR_VELOCITY: { + return linear_velocity; + } break; + case PhysicsServer3D::BODY_STATE_ANGULAR_VELOCITY: { + return angular_velocity; + } break; + case PhysicsServer3D::BODY_STATE_SLEEPING: { + return !is_active(); + } break; + case PhysicsServer3D::BODY_STATE_CAN_SLEEP: { + return can_sleep; + } break; + } + + return Variant(); +} + +void Body3DSW::set_space(Space3DSW *p_space) { + + if (get_space()) { + + if (inertia_update_list.in_list()) + get_space()->body_remove_from_inertia_update_list(&inertia_update_list); + if (active_list.in_list()) + get_space()->body_remove_from_active_list(&active_list); + if (direct_state_query_list.in_list()) + get_space()->body_remove_from_state_query_list(&direct_state_query_list); + } + + _set_space(p_space); + + if (get_space()) { + + _update_inertia(); + if (active) + get_space()->body_add_to_active_list(&active_list); + /* + _update_queries(); + if (is_active()) { + active=false; + set_active(true); + } + */ + } + + first_integration = true; +} + +void Body3DSW::_compute_area_gravity_and_dampenings(const Area3DSW *p_area) { + + if (p_area->is_gravity_point()) { + if (p_area->get_gravity_distance_scale() > 0) { + Vector3 v = p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin(); + gravity += v.normalized() * (p_area->get_gravity() / Math::pow(v.length() * p_area->get_gravity_distance_scale() + 1, 2)); + } else { + gravity += (p_area->get_transform().xform(p_area->get_gravity_vector()) - get_transform().get_origin()).normalized() * p_area->get_gravity(); + } + } else { + gravity += p_area->get_gravity_vector() * p_area->get_gravity(); + } + + area_linear_damp += p_area->get_linear_damp(); + area_angular_damp += p_area->get_angular_damp(); +} + +void Body3DSW::set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock) { + if (lock) { + locked_axis |= p_axis; + } else { + locked_axis &= ~p_axis; + } +} + +bool Body3DSW::is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const { + return locked_axis & p_axis; +} + +void Body3DSW::integrate_forces(real_t p_step) { + + if (mode == PhysicsServer3D::BODY_MODE_STATIC) + return; + + Area3DSW *def_area = get_space()->get_default_area(); + // AreaSW *damp_area = def_area; + + ERR_FAIL_COND(!def_area); + + int ac = areas.size(); + bool stopped = false; + gravity = Vector3(0, 0, 0); + area_linear_damp = 0; + area_angular_damp = 0; + if (ac) { + areas.sort(); + const AreaCMP *aa = &areas[0]; + // damp_area = aa[ac-1].area; + for (int i = ac - 1; i >= 0 && !stopped; i--) { + PhysicsServer3D::AreaSpaceOverrideMode mode = aa[i].area->get_space_override_mode(); + switch (mode) { + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE: { + _compute_area_gravity_and_dampenings(aa[i].area); + stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_COMBINE_REPLACE; + } break; + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE: + case PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE_COMBINE: { + gravity = Vector3(0, 0, 0); + area_angular_damp = 0; + area_linear_damp = 0; + _compute_area_gravity_and_dampenings(aa[i].area); + stopped = mode == PhysicsServer3D::AREA_SPACE_OVERRIDE_REPLACE; + } break; + default: { + } + } + } + } + + if (!stopped) { + _compute_area_gravity_and_dampenings(def_area); + } + + gravity *= gravity_scale; + + // If less than 0, override dampenings with that of the Body + if (angular_damp >= 0) + area_angular_damp = angular_damp; + /* + else + area_angular_damp=damp_area->get_angular_damp(); + */ + + if (linear_damp >= 0) + area_linear_damp = linear_damp; + /* + else + area_linear_damp=damp_area->get_linear_damp(); + */ + + Vector3 motion; + bool do_motion = false; + + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { + + //compute motion, angular and etc. velocities from prev transform + linear_velocity = (new_transform.origin - get_transform().origin) / p_step; + + //compute a FAKE angular velocity, not so easy + Basis rot = new_transform.basis.orthonormalized().transposed() * get_transform().basis.orthonormalized(); + Vector3 axis; + real_t angle; + + rot.get_axis_angle(axis, angle); + axis.normalize(); + angular_velocity = axis.normalized() * (angle / p_step); + + motion = new_transform.origin - get_transform().origin; + do_motion = true; + + } else { + if (!omit_force_integration && !first_integration) { + //overridden by direct state query + + Vector3 force = gravity * mass; + force += applied_force; + Vector3 torque = applied_torque; + + real_t damp = 1.0 - p_step * area_linear_damp; + + if (damp < 0) // reached zero in the given time + damp = 0; + + real_t angular_damp = 1.0 - p_step * area_angular_damp; + + if (angular_damp < 0) // reached zero in the given time + angular_damp = 0; + + linear_velocity *= damp; + angular_velocity *= angular_damp; + + linear_velocity += _inv_mass * force * p_step; + angular_velocity += _inv_inertia_tensor.xform(torque) * p_step; + } + + if (continuous_cd) { + motion = linear_velocity * p_step; + do_motion = true; + } + } + + applied_force = Vector3(); + applied_torque = Vector3(); + first_integration = false; + + //motion=linear_velocity*p_step; + + biased_angular_velocity = Vector3(); + biased_linear_velocity = Vector3(); + + if (do_motion) { //shapes temporarily extend for raycast + _update_shapes_with_motion(motion); + } + + def_area = NULL; // clear the area, so it is set in the next frame + contact_count = 0; +} + +void Body3DSW::integrate_velocities(real_t p_step) { + + if (mode == PhysicsServer3D::BODY_MODE_STATIC) + return; + + if (fi_callback) + get_space()->body_add_to_state_query_list(&direct_state_query_list); + + //apply axis lock linear + for (int i = 0; i < 3; i++) { + if (is_axis_locked((PhysicsServer3D::BodyAxis)(1 << i))) { + linear_velocity[i] = 0; + biased_linear_velocity[i] = 0; + new_transform.origin[i] = get_transform().origin[i]; + } + } + //apply axis lock angular + for (int i = 0; i < 3; i++) { + if (is_axis_locked((PhysicsServer3D::BodyAxis)(1 << (i + 3)))) { + angular_velocity[i] = 0; + biased_angular_velocity[i] = 0; + } + } + + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC) { + + _set_transform(new_transform, false); + _set_inv_transform(new_transform.affine_inverse()); + if (contacts.size() == 0 && linear_velocity == Vector3() && angular_velocity == Vector3()) + set_active(false); //stopped moving, deactivate + + return; + } + + Vector3 total_angular_velocity = angular_velocity + biased_angular_velocity; + + real_t ang_vel = total_angular_velocity.length(); + Transform transform = get_transform(); + + if (ang_vel != 0.0) { + Vector3 ang_vel_axis = total_angular_velocity / ang_vel; + Basis rot(ang_vel_axis, ang_vel * p_step); + Basis identity3(1, 0, 0, 0, 1, 0, 0, 0, 1); + transform.origin += ((identity3 - rot) * transform.basis).xform(center_of_mass_local); + transform.basis = rot * transform.basis; + transform.orthonormalize(); + } + + Vector3 total_linear_velocity = linear_velocity + biased_linear_velocity; + /*for(int i=0;i<3;i++) { + if (axis_lock&(1<body_add_to_state_query_list(&direct_state_query_list); + */ +} + +/* +void BodySW::simulate_motion(const Transform& p_xform,real_t p_step) { + + Transform inv_xform = p_xform.affine_inverse(); + if (!get_space()) { + _set_transform(p_xform); + _set_inv_transform(inv_xform); + + return; + } + + //compute a FAKE linear velocity - this is easy + + linear_velocity=(p_xform.origin - get_transform().origin)/p_step; + + //compute a FAKE angular velocity, not so easy + Basis rot=get_transform().basis.orthonormalized().transposed() * p_xform.basis.orthonormalized(); + Vector3 axis; + real_t angle; + + rot.get_axis_angle(axis,angle); + axis.normalize(); + angular_velocity=axis.normalized() * (angle/p_step); + linear_velocity = (p_xform.origin - get_transform().origin)/p_step; + + if (!direct_state_query_list.in_list())// - callalways, so lv and av are cleared && (state_query || direct_state_query)) + get_space()->body_add_to_state_query_list(&direct_state_query_list); + simulated_motion=true; + _set_transform(p_xform); + + +} +*/ + +void Body3DSW::wakeup_neighbours() { + + for (Map::Element *E = constraint_map.front(); E; E = E->next()) { + + const Constraint3DSW *c = E->key(); + Body3DSW **n = c->get_body_ptr(); + int bc = c->get_body_count(); + + for (int i = 0; i < bc; i++) { + + if (i == E->get()) + continue; + Body3DSW *b = n[i]; + if (b->mode != PhysicsServer3D::BODY_MODE_RIGID) + continue; + + if (!b->is_active()) + b->set_active(true); + } + } +} + +void Body3DSW::call_queries() { + + if (fi_callback) { + + PhysicsDirectBodyState3DSW *dbs = PhysicsDirectBodyState3DSW::singleton; + dbs->body = this; + + Variant v = dbs; + + Object *obj = ObjectDB::get_instance(fi_callback->id); + if (!obj) { + + set_force_integration_callback(ObjectID(), StringName()); + } else { + const Variant *vp[2] = { &v, &fi_callback->udata }; + + Callable::CallError ce; + int argc = (fi_callback->udata.get_type() == Variant::NIL) ? 1 : 2; + obj->call(fi_callback->method, vp, argc, ce); + } + } +} + +bool Body3DSW::sleep_test(real_t p_step) { + + if (mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) + return true; // + else if (mode == PhysicsServer3D::BODY_MODE_CHARACTER) + return !active; // characters don't sleep unless asked to sleep + else if (!can_sleep) + return false; + + if (Math::abs(angular_velocity.length()) < get_space()->get_body_angular_velocity_sleep_threshold() && Math::abs(linear_velocity.length_squared()) < get_space()->get_body_linear_velocity_sleep_threshold() * get_space()->get_body_linear_velocity_sleep_threshold()) { + + still_time += p_step; + + return still_time > get_space()->get_body_time_to_sleep(); + } else { + + still_time = 0; //maybe this should be set to 0 on set_active? + return false; + } +} + +void Body3DSW::set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata) { + + if (fi_callback) { + + memdelete(fi_callback); + fi_callback = NULL; + } + + if (p_id.is_valid()) { + + fi_callback = memnew(ForceIntegrationCallback); + fi_callback->id = p_id; + fi_callback->method = p_method; + fi_callback->udata = p_udata; + } +} + +void Body3DSW::set_kinematic_margin(real_t p_margin) { + kinematic_safe_margin = p_margin; +} + +Body3DSW::Body3DSW() : + CollisionObject3DSW(TYPE_BODY), + locked_axis(0), + active_list(this), + inertia_update_list(this), + direct_state_query_list(this) { + + mode = PhysicsServer3D::BODY_MODE_RIGID; + active = true; + + mass = 1; + kinematic_safe_margin = 0.01; + //_inv_inertia=Transform(); + _inv_mass = 1; + bounce = 0; + friction = 1; + omit_force_integration = false; + //applied_torque=0; + island_step = 0; + island_next = NULL; + island_list_next = NULL; + first_time_kinematic = false; + first_integration = false; + _set_static(false); + + contact_count = 0; + gravity_scale = 1.0; + linear_damp = -1; + angular_damp = -1; + area_angular_damp = 0; + area_linear_damp = 0; + + still_time = 0; + continuous_cd = false; + can_sleep = true; + fi_callback = NULL; +} + +Body3DSW::~Body3DSW() { + + if (fi_callback) + memdelete(fi_callback); +} + +PhysicsDirectBodyState3DSW *PhysicsDirectBodyState3DSW::singleton = NULL; + +PhysicsDirectSpaceState3D *PhysicsDirectBodyState3DSW::get_space_state() { + + return body->get_space()->get_direct_state(); +} diff --git a/servers/physics_3d/body_3d_sw.h b/servers/physics_3d/body_3d_sw.h new file mode 100644 index 0000000000..7020805af0 --- /dev/null +++ b/servers/physics_3d/body_3d_sw.h @@ -0,0 +1,475 @@ +/*************************************************************************/ +/* body_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BODY_SW_H +#define BODY_SW_H + +#include "area_3d_sw.h" +#include "collision_object_3d_sw.h" +#include "core/vset.h" + +class Constraint3DSW; + +class Body3DSW : public CollisionObject3DSW { + + PhysicsServer3D::BodyMode mode; + + Vector3 linear_velocity; + Vector3 angular_velocity; + + Vector3 biased_linear_velocity; + Vector3 biased_angular_velocity; + real_t mass; + real_t bounce; + real_t friction; + + real_t linear_damp; + real_t angular_damp; + real_t gravity_scale; + + uint16_t locked_axis; + + real_t kinematic_safe_margin; + real_t _inv_mass; + Vector3 _inv_inertia; // Relative to the principal axes of inertia + + // Relative to the local frame of reference + Basis principal_inertia_axes_local; + Vector3 center_of_mass_local; + + // In world orientation with local origin + Basis _inv_inertia_tensor; + Basis principal_inertia_axes; + Vector3 center_of_mass; + + Vector3 gravity; + + real_t still_time; + + Vector3 applied_force; + Vector3 applied_torque; + + real_t area_angular_damp; + real_t area_linear_damp; + + SelfList active_list; + SelfList inertia_update_list; + SelfList direct_state_query_list; + + VSet exceptions; + bool omit_force_integration; + bool active; + + bool first_integration; + + bool continuous_cd; + bool can_sleep; + bool first_time_kinematic; + void _update_inertia(); + virtual void _shapes_changed(); + Transform new_transform; + + Map constraint_map; + + struct AreaCMP { + + Area3DSW *area; + int refCount; + _FORCE_INLINE_ bool operator==(const AreaCMP &p_cmp) const { return area->get_self() == p_cmp.area->get_self(); } + _FORCE_INLINE_ bool operator<(const AreaCMP &p_cmp) const { return area->get_priority() < p_cmp.area->get_priority(); } + _FORCE_INLINE_ AreaCMP() {} + _FORCE_INLINE_ AreaCMP(Area3DSW *p_area) { + area = p_area; + refCount = 1; + } + }; + + Vector areas; + + struct Contact { + + Vector3 local_pos; + Vector3 local_normal; + real_t depth; + int local_shape; + Vector3 collider_pos; + int collider_shape; + ObjectID collider_instance_id; + RID collider; + Vector3 collider_velocity_at_pos; + }; + + Vector contacts; //no contacts by default + int contact_count; + + struct ForceIntegrationCallback { + + ObjectID id; + StringName method; + Variant udata; + }; + + ForceIntegrationCallback *fi_callback; + + uint64_t island_step; + Body3DSW *island_next; + Body3DSW *island_list_next; + + _FORCE_INLINE_ void _compute_area_gravity_and_dampenings(const Area3DSW *p_area); + + _FORCE_INLINE_ void _update_transform_dependant(); + + friend class PhysicsDirectBodyState3DSW; // i give up, too many functions to expose + +public: + void set_force_integration_callback(ObjectID p_id, const StringName &p_method, const Variant &p_udata = Variant()); + + void set_kinematic_margin(real_t p_margin); + _FORCE_INLINE_ real_t get_kinematic_margin() { return kinematic_safe_margin; } + + _FORCE_INLINE_ void add_area(Area3DSW *p_area) { + int index = areas.find(AreaCMP(p_area)); + if (index > -1) { + areas.write[index].refCount += 1; + } else { + areas.ordered_insert(AreaCMP(p_area)); + } + } + + _FORCE_INLINE_ void remove_area(Area3DSW *p_area) { + int index = areas.find(AreaCMP(p_area)); + if (index > -1) { + areas.write[index].refCount -= 1; + if (areas[index].refCount < 1) + areas.remove(index); + } + } + + _FORCE_INLINE_ void set_max_contacts_reported(int p_size) { + contacts.resize(p_size); + contact_count = 0; + if (mode == PhysicsServer3D::BODY_MODE_KINEMATIC && p_size) set_active(true); + } + _FORCE_INLINE_ int get_max_contacts_reported() const { return contacts.size(); } + + _FORCE_INLINE_ bool can_report_contacts() const { return !contacts.empty(); } + _FORCE_INLINE_ void add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos); + + _FORCE_INLINE_ void add_exception(const RID &p_exception) { exceptions.insert(p_exception); } + _FORCE_INLINE_ void remove_exception(const RID &p_exception) { exceptions.erase(p_exception); } + _FORCE_INLINE_ bool has_exception(const RID &p_exception) const { return exceptions.has(p_exception); } + _FORCE_INLINE_ const VSet &get_exceptions() const { return exceptions; } + + _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } + _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } + + _FORCE_INLINE_ Body3DSW *get_island_next() const { return island_next; } + _FORCE_INLINE_ void set_island_next(Body3DSW *p_next) { island_next = p_next; } + + _FORCE_INLINE_ Body3DSW *get_island_list_next() const { return island_list_next; } + _FORCE_INLINE_ void set_island_list_next(Body3DSW *p_next) { island_list_next = p_next; } + + _FORCE_INLINE_ void add_constraint(Constraint3DSW *p_constraint, int p_pos) { constraint_map[p_constraint] = p_pos; } + _FORCE_INLINE_ void remove_constraint(Constraint3DSW *p_constraint) { constraint_map.erase(p_constraint); } + const Map &get_constraint_map() const { return constraint_map; } + _FORCE_INLINE_ void clear_constraint_map() { constraint_map.clear(); } + + _FORCE_INLINE_ void set_omit_force_integration(bool p_omit_force_integration) { omit_force_integration = p_omit_force_integration; } + _FORCE_INLINE_ bool get_omit_force_integration() const { return omit_force_integration; } + + _FORCE_INLINE_ Basis get_principal_inertia_axes() const { return principal_inertia_axes; } + _FORCE_INLINE_ Vector3 get_center_of_mass() const { return center_of_mass; } + _FORCE_INLINE_ Vector3 xform_local_to_principal(const Vector3 &p_pos) const { return principal_inertia_axes_local.xform(p_pos - center_of_mass_local); } + + _FORCE_INLINE_ void set_linear_velocity(const Vector3 &p_velocity) { linear_velocity = p_velocity; } + _FORCE_INLINE_ Vector3 get_linear_velocity() const { return linear_velocity; } + + _FORCE_INLINE_ void set_angular_velocity(const Vector3 &p_velocity) { angular_velocity = p_velocity; } + _FORCE_INLINE_ Vector3 get_angular_velocity() const { return angular_velocity; } + + _FORCE_INLINE_ const Vector3 &get_biased_linear_velocity() const { return biased_linear_velocity; } + _FORCE_INLINE_ const Vector3 &get_biased_angular_velocity() const { return biased_angular_velocity; } + + _FORCE_INLINE_ void apply_central_impulse(const Vector3 &p_j) { + linear_velocity += p_j * _inv_mass; + } + + _FORCE_INLINE_ void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { + + linear_velocity += p_j * _inv_mass; + angular_velocity += _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); + } + + _FORCE_INLINE_ void apply_torque_impulse(const Vector3 &p_j) { + + angular_velocity += _inv_inertia_tensor.xform(p_j); + } + + _FORCE_INLINE_ void apply_bias_impulse(const Vector3 &p_pos, const Vector3 &p_j, real_t p_max_delta_av = -1.0) { + + biased_linear_velocity += p_j * _inv_mass; + if (p_max_delta_av != 0.0) { + Vector3 delta_av = _inv_inertia_tensor.xform((p_pos - center_of_mass).cross(p_j)); + if (p_max_delta_av > 0 && delta_av.length() > p_max_delta_av) { + delta_av = delta_av.normalized() * p_max_delta_av; + } + biased_angular_velocity += delta_av; + } + } + + _FORCE_INLINE_ void apply_bias_torque_impulse(const Vector3 &p_j) { + + biased_angular_velocity += _inv_inertia_tensor.xform(p_j); + } + + _FORCE_INLINE_ void add_central_force(const Vector3 &p_force) { + + applied_force += p_force; + } + + _FORCE_INLINE_ void add_force(const Vector3 &p_force, const Vector3 &p_pos) { + + applied_force += p_force; + applied_torque += p_pos.cross(p_force); + } + + _FORCE_INLINE_ void add_torque(const Vector3 &p_torque) { + applied_torque += p_torque; + } + + void set_active(bool p_active); + _FORCE_INLINE_ bool is_active() const { return active; } + + _FORCE_INLINE_ void wakeup() { + if ((!get_space()) || mode == PhysicsServer3D::BODY_MODE_STATIC || mode == PhysicsServer3D::BODY_MODE_KINEMATIC) + return; + set_active(true); + } + + void set_param(PhysicsServer3D::BodyParameter p_param, real_t); + real_t get_param(PhysicsServer3D::BodyParameter p_param) const; + + void set_mode(PhysicsServer3D::BodyMode p_mode); + PhysicsServer3D::BodyMode get_mode() const; + + void set_state(PhysicsServer3D::BodyState p_state, const Variant &p_variant); + Variant get_state(PhysicsServer3D::BodyState p_state) const; + + void set_applied_force(const Vector3 &p_force) { applied_force = p_force; } + Vector3 get_applied_force() const { return applied_force; } + + void set_applied_torque(const Vector3 &p_torque) { applied_torque = p_torque; } + Vector3 get_applied_torque() const { return applied_torque; } + + _FORCE_INLINE_ void set_continuous_collision_detection(bool p_enable) { continuous_cd = p_enable; } + _FORCE_INLINE_ bool is_continuous_collision_detection_enabled() const { return continuous_cd; } + + void set_space(Space3DSW *p_space); + + void update_inertias(); + + _FORCE_INLINE_ real_t get_inv_mass() const { return _inv_mass; } + _FORCE_INLINE_ Vector3 get_inv_inertia() const { return _inv_inertia; } + _FORCE_INLINE_ Basis get_inv_inertia_tensor() const { return _inv_inertia_tensor; } + _FORCE_INLINE_ real_t get_friction() const { return friction; } + _FORCE_INLINE_ Vector3 get_gravity() const { return gravity; } + _FORCE_INLINE_ real_t get_bounce() const { return bounce; } + + void set_axis_lock(PhysicsServer3D::BodyAxis p_axis, bool lock); + bool is_axis_locked(PhysicsServer3D::BodyAxis p_axis) const; + + void integrate_forces(real_t p_step); + void integrate_velocities(real_t p_step); + + _FORCE_INLINE_ Vector3 get_velocity_in_local_point(const Vector3 &rel_pos) const { + + return linear_velocity + angular_velocity.cross(rel_pos - center_of_mass); + } + + _FORCE_INLINE_ real_t compute_impulse_denominator(const Vector3 &p_pos, const Vector3 &p_normal) const { + + Vector3 r0 = p_pos - get_transform().origin - center_of_mass; + + Vector3 c0 = (r0).cross(p_normal); + + Vector3 vec = (_inv_inertia_tensor.xform_inv(c0)).cross(r0); + + return _inv_mass + p_normal.dot(vec); + } + + _FORCE_INLINE_ real_t compute_angular_impulse_denominator(const Vector3 &p_axis) const { + + return p_axis.dot(_inv_inertia_tensor.xform_inv(p_axis)); + } + + //void simulate_motion(const Transform& p_xform,real_t p_step); + void call_queries(); + void wakeup_neighbours(); + + bool sleep_test(real_t p_step); + + Body3DSW(); + ~Body3DSW(); +}; + +//add contact inline + +void Body3DSW::add_contact(const Vector3 &p_local_pos, const Vector3 &p_local_normal, real_t p_depth, int p_local_shape, const Vector3 &p_collider_pos, int p_collider_shape, ObjectID p_collider_instance_id, const RID &p_collider, const Vector3 &p_collider_velocity_at_pos) { + + int c_max = contacts.size(); + + if (c_max == 0) + return; + + Contact *c = contacts.ptrw(); + + int idx = -1; + + if (contact_count < c_max) { + idx = contact_count++; + } else { + + real_t least_depth = 1e20; + int least_deep = -1; + for (int i = 0; i < c_max; i++) { + + if (i == 0 || c[i].depth < least_depth) { + least_deep = i; + least_depth = c[i].depth; + } + } + + if (least_deep >= 0 && least_depth < p_depth) { + + idx = least_deep; + } + if (idx == -1) + return; //none least deepe than this + } + + c[idx].local_pos = p_local_pos; + c[idx].local_normal = p_local_normal; + c[idx].depth = p_depth; + c[idx].local_shape = p_local_shape; + c[idx].collider_pos = p_collider_pos; + c[idx].collider_shape = p_collider_shape; + c[idx].collider_instance_id = p_collider_instance_id; + c[idx].collider = p_collider; + c[idx].collider_velocity_at_pos = p_collider_velocity_at_pos; +} + +class PhysicsDirectBodyState3DSW : public PhysicsDirectBodyState3D { + + GDCLASS(PhysicsDirectBodyState3DSW, PhysicsDirectBodyState3D); + +public: + static PhysicsDirectBodyState3DSW *singleton; + Body3DSW *body; + real_t step; + + virtual Vector3 get_total_gravity() const { return body->gravity; } // get gravity vector working on this body space/area + virtual real_t get_total_angular_damp() const { return body->area_angular_damp; } // get density of this body space/area + virtual real_t get_total_linear_damp() const { return body->area_linear_damp; } // get density of this body space/area + + virtual Vector3 get_center_of_mass() const { return body->get_center_of_mass(); } + virtual Basis get_principal_inertia_axes() const { return body->get_principal_inertia_axes(); } + + virtual real_t get_inverse_mass() const { return body->get_inv_mass(); } // get the mass + virtual Vector3 get_inverse_inertia() const { return body->get_inv_inertia(); } // get density of this body space + virtual Basis get_inverse_inertia_tensor() const { return body->get_inv_inertia_tensor(); } // get density of this body space + + virtual void set_linear_velocity(const Vector3 &p_velocity) { body->set_linear_velocity(p_velocity); } + virtual Vector3 get_linear_velocity() const { return body->get_linear_velocity(); } + + virtual void set_angular_velocity(const Vector3 &p_velocity) { body->set_angular_velocity(p_velocity); } + virtual Vector3 get_angular_velocity() const { return body->get_angular_velocity(); } + + virtual void set_transform(const Transform &p_transform) { body->set_state(PhysicsServer3D::BODY_STATE_TRANSFORM, p_transform); } + virtual Transform get_transform() const { return body->get_transform(); } + + virtual void add_central_force(const Vector3 &p_force) { body->add_central_force(p_force); } + virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) { body->add_force(p_force, p_pos); } + virtual void add_torque(const Vector3 &p_torque) { body->add_torque(p_torque); } + virtual void apply_central_impulse(const Vector3 &p_j) { body->apply_central_impulse(p_j); } + virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) { body->apply_impulse(p_pos, p_j); } + virtual void apply_torque_impulse(const Vector3 &p_j) { body->apply_torque_impulse(p_j); } + + virtual void set_sleep_state(bool p_enable) { body->set_active(!p_enable); } + virtual bool is_sleeping() const { return !body->is_active(); } + + virtual int get_contact_count() const { return body->contact_count; } + + virtual Vector3 get_contact_local_position(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); + return body->contacts[p_contact_idx].local_pos; + } + virtual Vector3 get_contact_local_normal(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); + return body->contacts[p_contact_idx].local_normal; + } + virtual float get_contact_impulse(int p_contact_idx) const { + return 0.0f; // Only implemented for bullet + } + virtual int get_contact_local_shape(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, -1); + return body->contacts[p_contact_idx].local_shape; + } + + virtual RID get_contact_collider(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, RID()); + return body->contacts[p_contact_idx].collider; + } + virtual Vector3 get_contact_collider_position(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); + return body->contacts[p_contact_idx].collider_pos; + } + virtual ObjectID get_contact_collider_id(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, ObjectID()); + return body->contacts[p_contact_idx].collider_instance_id; + } + virtual int get_contact_collider_shape(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, 0); + return body->contacts[p_contact_idx].collider_shape; + } + virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const { + ERR_FAIL_INDEX_V(p_contact_idx, body->contact_count, Vector3()); + return body->contacts[p_contact_idx].collider_velocity_at_pos; + } + + virtual PhysicsDirectSpaceState3D *get_space_state(); + + virtual real_t get_step() const { return step; } + PhysicsDirectBodyState3DSW() { + singleton = this; + body = NULL; + } +}; + +#endif // BODY__SW_H diff --git a/servers/physics_3d/body_pair_3d_sw.cpp b/servers/physics_3d/body_pair_3d_sw.cpp new file mode 100644 index 0000000000..9c3c847afe --- /dev/null +++ b/servers/physics_3d/body_pair_3d_sw.cpp @@ -0,0 +1,495 @@ +/*************************************************************************/ +/* body_pair_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "body_pair_3d_sw.h" + +#include "collision_solver_3d_sw.h" +#include "core/os/os.h" +#include "space_3d_sw.h" + +/* +#define NO_ACCUMULATE_IMPULSES +#define NO_SPLIT_IMPULSES + +#define NO_FRICTION +*/ + +#define NO_TANGENTIALS +/* BODY PAIR */ + +//#define ALLOWED_PENETRATION 0.01 +#define RELAXATION_TIMESTEPS 3 +#define MIN_VELOCITY 0.0001 +#define MAX_BIAS_ROTATION (Math_PI / 8) + +void BodyPair3DSW::_contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { + + BodyPair3DSW *pair = (BodyPair3DSW *)p_userdata; + pair->contact_added_callback(p_point_A, p_point_B); +} + +void BodyPair3DSW::contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B) { + + // check if we already have the contact + + //Vector3 local_A = A->get_inv_transform().xform(p_point_A); + //Vector3 local_B = B->get_inv_transform().xform(p_point_B); + + Vector3 local_A = A->get_inv_transform().basis.xform(p_point_A); + Vector3 local_B = B->get_inv_transform().basis.xform(p_point_B - offset_B); + + int new_index = contact_count; + + ERR_FAIL_COND(new_index >= (MAX_CONTACTS + 1)); + + Contact contact; + + contact.acc_normal_impulse = 0; + contact.acc_bias_impulse = 0; + contact.acc_bias_impulse_center_of_mass = 0; + contact.acc_tangent_impulse = Vector3(); + contact.local_A = local_A; + contact.local_B = local_B; + contact.normal = (p_point_A - p_point_B).normalized(); + contact.mass_normal = 0; // will be computed in setup() + + // attempt to determine if the contact will be reused + real_t contact_recycle_radius = space->get_contact_recycle_radius(); + + for (int i = 0; i < contact_count; i++) { + + Contact &c = contacts[i]; + if (c.local_A.distance_squared_to(local_A) < (contact_recycle_radius * contact_recycle_radius) && + c.local_B.distance_squared_to(local_B) < (contact_recycle_radius * contact_recycle_radius)) { + + contact.acc_normal_impulse = c.acc_normal_impulse; + contact.acc_bias_impulse = c.acc_bias_impulse; + contact.acc_bias_impulse_center_of_mass = c.acc_bias_impulse_center_of_mass; + contact.acc_tangent_impulse = c.acc_tangent_impulse; + new_index = i; + break; + } + } + + // figure out if the contact amount must be reduced to fit the new contact + + if (new_index == MAX_CONTACTS) { + + // remove the contact with the minimum depth + + int least_deep = -1; + real_t min_depth = 1e10; + + for (int i = 0; i <= contact_count; i++) { + + Contact &c = (i == contact_count) ? contact : contacts[i]; + Vector3 global_A = A->get_transform().basis.xform(c.local_A); + Vector3 global_B = B->get_transform().basis.xform(c.local_B) + offset_B; + + Vector3 axis = global_A - global_B; + real_t depth = axis.dot(c.normal); + + if (depth < min_depth) { + + min_depth = depth; + least_deep = i; + } + } + + ERR_FAIL_COND(least_deep == -1); + + if (least_deep < contact_count) { //replace the last deep contact by the new one + + contacts[least_deep] = contact; + } + + return; + } + + contacts[new_index] = contact; + + if (new_index == contact_count) { + + contact_count++; + } +} + +void BodyPair3DSW::validate_contacts() { + + //make sure to erase contacts that are no longer valid + + real_t contact_max_separation = space->get_contact_max_separation(); + for (int i = 0; i < contact_count; i++) { + + Contact &c = contacts[i]; + + Vector3 global_A = A->get_transform().basis.xform(c.local_A); + Vector3 global_B = B->get_transform().basis.xform(c.local_B) + offset_B; + Vector3 axis = global_A - global_B; + real_t depth = axis.dot(c.normal); + + if (depth < -contact_max_separation || (global_B + c.normal * depth - global_A).length() > contact_max_separation) { + // contact no longer needed, remove + + if ((i + 1) < contact_count) { + // swap with the last one + SWAP(contacts[i], contacts[contact_count - 1]); + } + + i--; + contact_count--; + } + } +} + +bool BodyPair3DSW::_test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform &p_xform_B) { + + Vector3 motion = p_A->get_linear_velocity() * p_step; + real_t mlen = motion.length(); + if (mlen < CMP_EPSILON) + return false; + + Vector3 mnormal = motion / mlen; + + real_t min, max; + p_A->get_shape(p_shape_A)->project_range(mnormal, p_xform_A, min, max); + bool fast_object = mlen > (max - min) * 0.3; //going too fast in that direction + + if (!fast_object) { //did it move enough in this direction to even attempt raycast? let's say it should move more than 1/3 the size of the object in that axis + return false; + } + + //cast a segment from support in motion normal, in the same direction of motion by motion length + //support is the worst case collision point, so real collision happened before + Vector3 s = p_A->get_shape(p_shape_A)->get_support(p_xform_A.basis.xform(mnormal).normalized()); + Vector3 from = p_xform_A.xform(s); + Vector3 to = from + motion; + + Transform from_inv = p_xform_B.affine_inverse(); + + Vector3 local_from = from_inv.xform(from - mnormal * mlen * 0.1); //start from a little inside the bounding box + Vector3 local_to = from_inv.xform(to); + + Vector3 rpos, rnorm; + if (!p_B->get_shape(p_shape_B)->intersect_segment(local_from, local_to, rpos, rnorm)) { + return false; + } + + //shorten the linear velocity so it does not hit, but gets close enough, next frame will hit softly or soft enough + Vector3 hitpos = p_xform_B.xform(rpos); + + real_t newlen = hitpos.distance_to(from) - (max - min) * 0.01; + p_A->set_linear_velocity((mnormal * newlen) / p_step); + + return true; +} + +real_t combine_bounce(Body3DSW *A, Body3DSW *B) { + return CLAMP(A->get_bounce() + B->get_bounce(), 0, 1); +} + +real_t combine_friction(Body3DSW *A, Body3DSW *B) { + return ABS(MIN(A->get_friction(), B->get_friction())); +} + +bool BodyPair3DSW::setup(real_t p_step) { + + //cannot collide + if (!A->test_collision_mask(B) || A->has_exception(B->get_self()) || B->has_exception(A->get_self()) || (A->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC && A->get_max_contacts_reported() == 0 && B->get_max_contacts_reported() == 0)) { + collided = false; + return false; + } + + if (A->is_shape_set_as_disabled(shape_A) || B->is_shape_set_as_disabled(shape_B)) { + collided = false; + return false; + } + + offset_B = B->get_transform().get_origin() - A->get_transform().get_origin(); + + validate_contacts(); + + Vector3 offset_A = A->get_transform().get_origin(); + Transform xform_Au = Transform(A->get_transform().basis, Vector3()); + Transform xform_A = xform_Au * A->get_shape_transform(shape_A); + + Transform xform_Bu = B->get_transform(); + xform_Bu.origin -= offset_A; + Transform xform_B = xform_Bu * B->get_shape_transform(shape_B); + + Shape3DSW *shape_A_ptr = A->get_shape(shape_A); + Shape3DSW *shape_B_ptr = B->get_shape(shape_B); + + bool collided = CollisionSolver3DSW::solve_static(shape_A_ptr, xform_A, shape_B_ptr, xform_B, _contact_added_callback, this, &sep_axis); + this->collided = collided; + + if (!collided) { + + //test ccd (currently just a raycast) + + if (A->is_continuous_collision_detection_enabled() && A->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC && B->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC) { + _test_ccd(p_step, A, shape_A, xform_A, B, shape_B, xform_B); + } + + if (B->is_continuous_collision_detection_enabled() && B->get_mode() > PhysicsServer3D::BODY_MODE_KINEMATIC && A->get_mode() <= PhysicsServer3D::BODY_MODE_KINEMATIC) { + _test_ccd(p_step, B, shape_B, xform_B, A, shape_A, xform_A); + } + + return false; + } + + real_t max_penetration = space->get_contact_max_allowed_penetration(); + + real_t bias = (real_t)0.3; + + if (shape_A_ptr->get_custom_bias() || shape_B_ptr->get_custom_bias()) { + + if (shape_A_ptr->get_custom_bias() == 0) + bias = shape_B_ptr->get_custom_bias(); + else if (shape_B_ptr->get_custom_bias() == 0) + bias = shape_A_ptr->get_custom_bias(); + else + bias = (shape_B_ptr->get_custom_bias() + shape_A_ptr->get_custom_bias()) * 0.5; + } + + real_t inv_dt = 1.0 / p_step; + + for (int i = 0; i < contact_count; i++) { + + Contact &c = contacts[i]; + c.active = false; + + Vector3 global_A = xform_Au.xform(c.local_A); + Vector3 global_B = xform_Bu.xform(c.local_B); + + real_t depth = c.normal.dot(global_A - global_B); + + if (depth <= 0) { + c.active = false; + continue; + } + + c.active = true; + +#ifdef DEBUG_ENABLED + + if (space->is_debugging_contacts()) { + space->add_debug_contact(global_A + offset_A); + space->add_debug_contact(global_B + offset_A); + } +#endif + + c.rA = global_A - A->get_center_of_mass(); + c.rB = global_B - B->get_center_of_mass() - offset_B; + + // contact query reporting... + + if (A->can_report_contacts()) { + Vector3 crA = A->get_angular_velocity().cross(c.rA) + A->get_linear_velocity(); + A->add_contact(global_A, -c.normal, depth, shape_A, global_B, shape_B, B->get_instance_id(), B->get_self(), crA); + } + + if (B->can_report_contacts()) { + Vector3 crB = B->get_angular_velocity().cross(c.rB) + B->get_linear_velocity(); + B->add_contact(global_B, c.normal, depth, shape_B, global_A, shape_A, A->get_instance_id(), A->get_self(), crB); + } + + c.active = true; + + // Precompute normal mass, tangent mass, and bias. + Vector3 inertia_A = A->get_inv_inertia_tensor().xform(c.rA.cross(c.normal)); + Vector3 inertia_B = B->get_inv_inertia_tensor().xform(c.rB.cross(c.normal)); + real_t kNormal = A->get_inv_mass() + B->get_inv_mass(); + kNormal += c.normal.dot(inertia_A.cross(c.rA)) + c.normal.dot(inertia_B.cross(c.rB)); + c.mass_normal = 1.0f / kNormal; + + c.bias = -bias * inv_dt * MIN(0.0f, -depth + max_penetration); + c.depth = depth; + + Vector3 j_vec = c.normal * c.acc_normal_impulse + c.acc_tangent_impulse; + A->apply_impulse(c.rA + A->get_center_of_mass(), -j_vec); + B->apply_impulse(c.rB + B->get_center_of_mass(), j_vec); + c.acc_bias_impulse = 0; + c.acc_bias_impulse_center_of_mass = 0; + + c.bounce = combine_bounce(A, B); + if (c.bounce) { + + Vector3 crA = A->get_angular_velocity().cross(c.rA); + Vector3 crB = B->get_angular_velocity().cross(c.rB); + Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; + //normal impule + c.bounce = c.bounce * dv.dot(c.normal); + } + } + + return true; +} + +void BodyPair3DSW::solve(real_t p_step) { + + if (!collided) + return; + + for (int i = 0; i < contact_count; i++) { + + Contact &c = contacts[i]; + if (!c.active) + continue; + + c.active = false; //try to deactivate, will activate itself if still needed + + //bias impulse + + Vector3 crbA = A->get_biased_angular_velocity().cross(c.rA); + Vector3 crbB = B->get_biased_angular_velocity().cross(c.rB); + Vector3 dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA; + + real_t vbn = dbv.dot(c.normal); + + if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { + + real_t jbn = (-vbn + c.bias) * c.mass_normal; + real_t jbnOld = c.acc_bias_impulse; + c.acc_bias_impulse = MAX(jbnOld + jbn, 0.0f); + + Vector3 jb = c.normal * (c.acc_bias_impulse - jbnOld); + + A->apply_bias_impulse(c.rA + A->get_center_of_mass(), -jb, MAX_BIAS_ROTATION / p_step); + B->apply_bias_impulse(c.rB + B->get_center_of_mass(), jb, MAX_BIAS_ROTATION / p_step); + + crbA = A->get_biased_angular_velocity().cross(c.rA); + crbB = B->get_biased_angular_velocity().cross(c.rB); + dbv = B->get_biased_linear_velocity() + crbB - A->get_biased_linear_velocity() - crbA; + + vbn = dbv.dot(c.normal); + + if (Math::abs(-vbn + c.bias) > MIN_VELOCITY) { + + real_t jbn_com = (-vbn + c.bias) / (A->get_inv_mass() + B->get_inv_mass()); + real_t jbnOld_com = c.acc_bias_impulse_center_of_mass; + c.acc_bias_impulse_center_of_mass = MAX(jbnOld_com + jbn_com, 0.0f); + + Vector3 jb_com = c.normal * (c.acc_bias_impulse_center_of_mass - jbnOld_com); + + A->apply_bias_impulse(A->get_center_of_mass(), -jb_com, 0.0f); + B->apply_bias_impulse(B->get_center_of_mass(), jb_com, 0.0f); + } + + c.active = true; + } + + Vector3 crA = A->get_angular_velocity().cross(c.rA); + Vector3 crB = B->get_angular_velocity().cross(c.rB); + Vector3 dv = B->get_linear_velocity() + crB - A->get_linear_velocity() - crA; + + //normal impulse + real_t vn = dv.dot(c.normal); + + if (Math::abs(vn) > MIN_VELOCITY) { + + real_t jn = -(c.bounce + vn) * c.mass_normal; + real_t jnOld = c.acc_normal_impulse; + c.acc_normal_impulse = MAX(jnOld + jn, 0.0f); + + Vector3 j = c.normal * (c.acc_normal_impulse - jnOld); + + A->apply_impulse(c.rA + A->get_center_of_mass(), -j); + B->apply_impulse(c.rB + B->get_center_of_mass(), j); + + c.active = true; + } + + //friction impulse + + real_t friction = combine_friction(A, B); + + Vector3 lvA = A->get_linear_velocity() + A->get_angular_velocity().cross(c.rA); + Vector3 lvB = B->get_linear_velocity() + B->get_angular_velocity().cross(c.rB); + + Vector3 dtv = lvB - lvA; + real_t tn = c.normal.dot(dtv); + + // tangential velocity + Vector3 tv = dtv - c.normal * tn; + real_t tvl = tv.length(); + + if (tvl > MIN_VELOCITY) { + + tv /= tvl; + + Vector3 temp1 = A->get_inv_inertia_tensor().xform(c.rA.cross(tv)); + Vector3 temp2 = B->get_inv_inertia_tensor().xform(c.rB.cross(tv)); + + real_t t = -tvl / + (A->get_inv_mass() + B->get_inv_mass() + tv.dot(temp1.cross(c.rA) + temp2.cross(c.rB))); + + Vector3 jt = t * tv; + + Vector3 jtOld = c.acc_tangent_impulse; + c.acc_tangent_impulse += jt; + + real_t fi_len = c.acc_tangent_impulse.length(); + real_t jtMax = c.acc_normal_impulse * friction; + + if (fi_len > CMP_EPSILON && fi_len > jtMax) { + + c.acc_tangent_impulse *= jtMax / fi_len; + } + + jt = c.acc_tangent_impulse - jtOld; + + A->apply_impulse(c.rA + A->get_center_of_mass(), -jt); + B->apply_impulse(c.rB + B->get_center_of_mass(), jt); + + c.active = true; + } + } +} + +BodyPair3DSW::BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B) : + Constraint3DSW(_arr, 2) { + + A = p_A; + B = p_B; + shape_A = p_shape_A; + shape_B = p_shape_B; + space = A->get_space(); + A->add_constraint(this, 0); + B->add_constraint(this, 1); + contact_count = 0; + collided = false; +} + +BodyPair3DSW::~BodyPair3DSW() { + + A->remove_constraint(this); + B->remove_constraint(this); +} diff --git a/servers/physics_3d/body_pair_3d_sw.h b/servers/physics_3d/body_pair_3d_sw.h new file mode 100644 index 0000000000..61c219657c --- /dev/null +++ b/servers/physics_3d/body_pair_3d_sw.h @@ -0,0 +1,97 @@ +/*************************************************************************/ +/* body_pair_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BODY_PAIR_SW_H +#define BODY_PAIR_SW_H + +#include "body_3d_sw.h" +#include "constraint_3d_sw.h" + +class BodyPair3DSW : public Constraint3DSW { + enum { + + MAX_CONTACTS = 4 + }; + + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + int shape_A; + int shape_B; + + struct Contact { + + Vector3 position; + Vector3 normal; + Vector3 local_A, local_B; + real_t acc_normal_impulse; // accumulated normal impulse (Pn) + Vector3 acc_tangent_impulse; // accumulated tangent impulse (Pt) + real_t acc_bias_impulse; // accumulated normal impulse for position bias (Pnb) + real_t acc_bias_impulse_center_of_mass; // accumulated normal impulse for position bias applied to com + real_t mass_normal; + real_t bias; + real_t bounce; + + real_t depth; + bool active; + Vector3 rA, rB; // Offset in world orientation with respect to center of mass + }; + + Vector3 offset_B; //use local A coordinates to avoid numerical issues on collision detection + + Vector3 sep_axis; + Contact contacts[MAX_CONTACTS]; + int contact_count; + bool collided; + + static void _contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); + + void contact_added_callback(const Vector3 &p_point_A, const Vector3 &p_point_B); + + void validate_contacts(); + bool _test_ccd(real_t p_step, Body3DSW *p_A, int p_shape_A, const Transform &p_xform_A, Body3DSW *p_B, int p_shape_B, const Transform &p_xform_B); + + Space3DSW *space; + +public: + bool setup(real_t p_step); + void solve(real_t p_step); + + BodyPair3DSW(Body3DSW *p_A, int p_shape_A, Body3DSW *p_B, int p_shape_B); + ~BodyPair3DSW(); +}; + +#endif // BODY_PAIR__SW_H diff --git a/servers/physics_3d/broad_phase_3d_basic.cpp b/servers/physics_3d/broad_phase_3d_basic.cpp new file mode 100644 index 0000000000..bc0af98e4a --- /dev/null +++ b/servers/physics_3d/broad_phase_3d_basic.cpp @@ -0,0 +1,225 @@ +/*************************************************************************/ +/* broad_phase_basic.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "broad_phase_3d_basic.h" +#include "core/list.h" +#include "core/print_string.h" + +BroadPhase3DSW::ID BroadPhase3DBasic::create(CollisionObject3DSW *p_object, int p_subindex) { + + ERR_FAIL_COND_V(p_object == NULL, 0); + + current++; + + Element e; + e.owner = p_object; + e._static = false; + e.subindex = p_subindex; + + element_map[current] = e; + return current; +} + +void BroadPhase3DBasic::move(ID p_id, const AABB &p_aabb) { + + Map::Element *E = element_map.find(p_id); + ERR_FAIL_COND(!E); + E->get().aabb = p_aabb; +} +void BroadPhase3DBasic::set_static(ID p_id, bool p_static) { + + Map::Element *E = element_map.find(p_id); + ERR_FAIL_COND(!E); + E->get()._static = p_static; +} +void BroadPhase3DBasic::remove(ID p_id) { + + Map::Element *E = element_map.find(p_id); + ERR_FAIL_COND(!E); + List to_erase; + //unpair must be done immediately on removal to avoid potential invalid pointers + for (Map::Element *F = pair_map.front(); F; F = F->next()) { + + if (F->key().a == p_id || F->key().b == p_id) { + + if (unpair_callback) { + Element *elem_A = &element_map[F->key().a]; + Element *elem_B = &element_map[F->key().b]; + unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, F->get(), unpair_userdata); + } + to_erase.push_back(F->key()); + } + } + while (to_erase.size()) { + + pair_map.erase(to_erase.front()->get()); + to_erase.pop_front(); + } + element_map.erase(E); +} + +CollisionObject3DSW *BroadPhase3DBasic::get_object(ID p_id) const { + + const Map::Element *E = element_map.find(p_id); + ERR_FAIL_COND_V(!E, NULL); + return E->get().owner; +} +bool BroadPhase3DBasic::is_static(ID p_id) const { + + const Map::Element *E = element_map.find(p_id); + ERR_FAIL_COND_V(!E, false); + return E->get()._static; +} +int BroadPhase3DBasic::get_subindex(ID p_id) const { + + const Map::Element *E = element_map.find(p_id); + ERR_FAIL_COND_V(!E, -1); + return E->get().subindex; +} + +int BroadPhase3DBasic::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + + int rc = 0; + + for (Map::Element *E = element_map.front(); E; E = E->next()) { + + const AABB aabb = E->get().aabb; + if (aabb.has_point(p_point)) { + + p_results[rc] = E->get().owner; + p_result_indices[rc] = E->get().subindex; + rc++; + if (rc >= p_max_results) + break; + } + } + + return rc; +} + +int BroadPhase3DBasic::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + + int rc = 0; + + for (Map::Element *E = element_map.front(); E; E = E->next()) { + + const AABB aabb = E->get().aabb; + if (aabb.intersects_segment(p_from, p_to)) { + + p_results[rc] = E->get().owner; + p_result_indices[rc] = E->get().subindex; + rc++; + if (rc >= p_max_results) + break; + } + } + + return rc; +} +int BroadPhase3DBasic::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + + int rc = 0; + + for (Map::Element *E = element_map.front(); E; E = E->next()) { + + const AABB aabb = E->get().aabb; + if (aabb.intersects(p_aabb)) { + + p_results[rc] = E->get().owner; + p_result_indices[rc] = E->get().subindex; + rc++; + if (rc >= p_max_results) + break; + } + } + + return rc; +} + +void BroadPhase3DBasic::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { + + pair_userdata = p_userdata; + pair_callback = p_pair_callback; +} +void BroadPhase3DBasic::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { + + unpair_userdata = p_userdata; + unpair_callback = p_unpair_callback; +} + +void BroadPhase3DBasic::update() { + + // recompute pairs + for (Map::Element *I = element_map.front(); I; I = I->next()) { + + for (Map::Element *J = I->next(); J; J = J->next()) { + + Element *elem_A = &I->get(); + Element *elem_B = &J->get(); + + if (elem_A->owner == elem_B->owner) + continue; + + bool pair_ok = elem_A->aabb.intersects(elem_B->aabb) && (!elem_A->_static || !elem_B->_static); + + PairKey key(I->key(), J->key()); + + Map::Element *E = pair_map.find(key); + + if (!pair_ok && E) { + if (unpair_callback) + unpair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, E->get(), unpair_userdata); + pair_map.erase(key); + } + + if (pair_ok && !E) { + + void *data = NULL; + if (pair_callback) + data = pair_callback(elem_A->owner, elem_A->subindex, elem_B->owner, elem_B->subindex, unpair_userdata); + pair_map.insert(key, data); + } + } + } +} + +BroadPhase3DSW *BroadPhase3DBasic::_create() { + + return memnew(BroadPhase3DBasic); +} + +BroadPhase3DBasic::BroadPhase3DBasic() { + + current = 1; + unpair_callback = NULL; + unpair_userdata = NULL; + pair_callback = NULL; + pair_userdata = NULL; +} diff --git a/servers/physics_3d/broad_phase_3d_basic.h b/servers/physics_3d/broad_phase_3d_basic.h new file mode 100644 index 0000000000..00263dad0a --- /dev/null +++ b/servers/physics_3d/broad_phase_3d_basic.h @@ -0,0 +1,108 @@ +/*************************************************************************/ +/* broad_phase_basic.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BROAD_PHASE_BASIC_H +#define BROAD_PHASE_BASIC_H + +#include "broad_phase_3d_sw.h" +#include "core/map.h" + +class BroadPhase3DBasic : public BroadPhase3DSW { + + struct Element { + + CollisionObject3DSW *owner; + bool _static; + AABB aabb; + int subindex; + }; + + Map element_map; + + ID current; + + struct PairKey { + + union { + struct { + ID a; + ID b; + }; + uint64_t key; + }; + + _FORCE_INLINE_ bool operator<(const PairKey &p_key) const { + return key < p_key.key; + } + + PairKey() { key = 0; } + PairKey(ID p_a, ID p_b) { + if (p_a > p_b) { + a = p_b; + b = p_a; + } else { + a = p_a; + b = p_b; + } + } + }; + + Map pair_map; + + PairCallback pair_callback; + void *pair_userdata; + UnpairCallback unpair_callback; + void *unpair_userdata; + +public: + // 0 is an invalid ID + virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0); + virtual void move(ID p_id, const AABB &p_aabb); + virtual void set_static(ID p_id, bool p_static); + virtual void remove(ID p_id); + + virtual CollisionObject3DSW *get_object(ID p_id) const; + virtual bool is_static(ID p_id) const; + virtual int get_subindex(ID p_id) const; + + virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL); + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL); + virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL); + + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); + + virtual void update(); + + static BroadPhase3DSW *_create(); + BroadPhase3DBasic(); +}; + +#endif // BROAD_PHASE_BASIC_H diff --git a/servers/physics_3d/broad_phase_3d_sw.cpp b/servers/physics_3d/broad_phase_3d_sw.cpp new file mode 100644 index 0000000000..b15b08ddfe --- /dev/null +++ b/servers/physics_3d/broad_phase_3d_sw.cpp @@ -0,0 +1,36 @@ +/*************************************************************************/ +/* broad_phase_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "broad_phase_3d_sw.h" + +BroadPhase3DSW::CreateFunction BroadPhase3DSW::create_func = NULL; + +BroadPhase3DSW::~BroadPhase3DSW() { +} diff --git a/servers/physics_3d/broad_phase_3d_sw.h b/servers/physics_3d/broad_phase_3d_sw.h new file mode 100644 index 0000000000..dd6984cbca --- /dev/null +++ b/servers/physics_3d/broad_phase_3d_sw.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* broad_phase_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BROAD_PHASE_SW_H +#define BROAD_PHASE_SW_H + +#include "core/math/aabb.h" +#include "core/math/math_funcs.h" + +class CollisionObject3DSW; + +class BroadPhase3DSW { + +public: + typedef BroadPhase3DSW *(*CreateFunction)(); + + static CreateFunction create_func; + + typedef uint32_t ID; + + typedef void *(*PairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_userdata); + typedef void (*UnpairCallback)(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_userdata); + + // 0 is an invalid ID + virtual ID create(CollisionObject3DSW *p_object_, int p_subindex = 0) = 0; + virtual void move(ID p_id, const AABB &p_aabb) = 0; + virtual void set_static(ID p_id, bool p_static) = 0; + virtual void remove(ID p_id) = 0; + + virtual CollisionObject3DSW *get_object(ID p_id) const = 0; + virtual bool is_static(ID p_id) const = 0; + virtual int get_subindex(ID p_id) const = 0; + + virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0; + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0; + virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL) = 0; + + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata) = 0; + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) = 0; + + virtual void update() = 0; + + virtual ~BroadPhase3DSW(); +}; + +#endif // BROAD_PHASE__SW_H diff --git a/servers/physics_3d/broad_phase_octree.cpp b/servers/physics_3d/broad_phase_octree.cpp new file mode 100644 index 0000000000..50ac17e027 --- /dev/null +++ b/servers/physics_3d/broad_phase_octree.cpp @@ -0,0 +1,129 @@ +/*************************************************************************/ +/* broad_phase_octree.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "broad_phase_octree.h" +#include "collision_object_3d_sw.h" + +BroadPhase3DSW::ID BroadPhaseOctree::create(CollisionObject3DSW *p_object, int p_subindex) { + + ID oid = octree.create(p_object, AABB(), p_subindex, false, 1 << p_object->get_type(), 0); + return oid; +} + +void BroadPhaseOctree::move(ID p_id, const AABB &p_aabb) { + + octree.move(p_id, p_aabb); +} + +void BroadPhaseOctree::set_static(ID p_id, bool p_static) { + + CollisionObject3DSW *it = octree.get(p_id); + octree.set_pairable(p_id, !p_static, 1 << it->get_type(), p_static ? 0 : 0xFFFFF); //pair everything, don't care 1? +} +void BroadPhaseOctree::remove(ID p_id) { + + octree.erase(p_id); +} + +CollisionObject3DSW *BroadPhaseOctree::get_object(ID p_id) const { + + CollisionObject3DSW *it = octree.get(p_id); + ERR_FAIL_COND_V(!it, NULL); + return it; +} +bool BroadPhaseOctree::is_static(ID p_id) const { + + return !octree.is_pairable(p_id); +} +int BroadPhaseOctree::get_subindex(ID p_id) const { + + return octree.get_subindex(p_id); +} + +int BroadPhaseOctree::cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + + return octree.cull_point(p_point, p_results, p_max_results, p_result_indices); +} + +int BroadPhaseOctree::cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + + return octree.cull_segment(p_from, p_to, p_results, p_max_results, p_result_indices); +} + +int BroadPhaseOctree::cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices) { + + return octree.cull_aabb(p_aabb, p_results, p_max_results, p_result_indices); +} + +void *BroadPhaseOctree::_pair_callback(void *self, OctreeElementID p_A, CollisionObject3DSW *p_object_A, int subindex_A, OctreeElementID p_B, CollisionObject3DSW *p_object_B, int subindex_B) { + + BroadPhaseOctree *bpo = (BroadPhaseOctree *)(self); + if (!bpo->pair_callback) + return NULL; + + return bpo->pair_callback(p_object_A, subindex_A, p_object_B, subindex_B, bpo->pair_userdata); +} + +void BroadPhaseOctree::_unpair_callback(void *self, OctreeElementID p_A, CollisionObject3DSW *p_object_A, int subindex_A, OctreeElementID p_B, CollisionObject3DSW *p_object_B, int subindex_B, void *pairdata) { + + BroadPhaseOctree *bpo = (BroadPhaseOctree *)(self); + if (!bpo->unpair_callback) + return; + + bpo->unpair_callback(p_object_A, subindex_A, p_object_B, subindex_B, pairdata, bpo->unpair_userdata); +} + +void BroadPhaseOctree::set_pair_callback(PairCallback p_pair_callback, void *p_userdata) { + + pair_callback = p_pair_callback; + pair_userdata = p_userdata; +} +void BroadPhaseOctree::set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata) { + + unpair_callback = p_unpair_callback; + unpair_userdata = p_userdata; +} + +void BroadPhaseOctree::update() { + // does.. not? +} + +BroadPhase3DSW *BroadPhaseOctree::_create() { + + return memnew(BroadPhaseOctree); +} + +BroadPhaseOctree::BroadPhaseOctree() { + octree.set_pair_callback(_pair_callback, this); + octree.set_unpair_callback(_unpair_callback, this); + pair_callback = NULL; + pair_userdata = NULL; + unpair_userdata = NULL; +} diff --git a/servers/physics_3d/broad_phase_octree.h b/servers/physics_3d/broad_phase_octree.h new file mode 100644 index 0000000000..25cf5b32da --- /dev/null +++ b/servers/physics_3d/broad_phase_octree.h @@ -0,0 +1,73 @@ +/*************************************************************************/ +/* broad_phase_octree.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef BROAD_PHASE_OCTREE_H +#define BROAD_PHASE_OCTREE_H + +#include "broad_phase_3d_sw.h" +#include "core/math/octree.h" + +class BroadPhaseOctree : public BroadPhase3DSW { + + Octree octree; + + static void *_pair_callback(void *, OctreeElementID, CollisionObject3DSW *, int, OctreeElementID, CollisionObject3DSW *, int); + static void _unpair_callback(void *, OctreeElementID, CollisionObject3DSW *, int, OctreeElementID, CollisionObject3DSW *, int, void *); + + PairCallback pair_callback; + void *pair_userdata; + UnpairCallback unpair_callback; + void *unpair_userdata; + +public: + // 0 is an invalid ID + virtual ID create(CollisionObject3DSW *p_object, int p_subindex = 0); + virtual void move(ID p_id, const AABB &p_aabb); + virtual void set_static(ID p_id, bool p_static); + virtual void remove(ID p_id); + + virtual CollisionObject3DSW *get_object(ID p_id) const; + virtual bool is_static(ID p_id) const; + virtual int get_subindex(ID p_id) const; + + virtual int cull_point(const Vector3 &p_point, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL); + virtual int cull_segment(const Vector3 &p_from, const Vector3 &p_to, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL); + virtual int cull_aabb(const AABB &p_aabb, CollisionObject3DSW **p_results, int p_max_results, int *p_result_indices = NULL); + + virtual void set_pair_callback(PairCallback p_pair_callback, void *p_userdata); + virtual void set_unpair_callback(UnpairCallback p_unpair_callback, void *p_userdata); + + virtual void update(); + + static BroadPhase3DSW *_create(); + BroadPhaseOctree(); +}; + +#endif // BROAD_PHASE_OCTREE_H diff --git a/servers/physics_3d/collision_object_3d_sw.cpp b/servers/physics_3d/collision_object_3d_sw.cpp new file mode 100644 index 0000000000..34e1c0f736 --- /dev/null +++ b/servers/physics_3d/collision_object_3d_sw.cpp @@ -0,0 +1,239 @@ +/*************************************************************************/ +/* collision_object_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collision_object_3d_sw.h" +#include "servers/physics_3d/physics_server_3d_sw.h" +#include "space_3d_sw.h" + +void CollisionObject3DSW::add_shape(Shape3DSW *p_shape, const Transform &p_transform, bool p_disabled) { + + Shape s; + s.shape = p_shape; + s.xform = p_transform; + s.xform_inv = s.xform.affine_inverse(); + s.bpid = 0; //needs update + s.disabled = p_disabled; + shapes.push_back(s); + p_shape->add_owner(this); + + if (!pending_shape_update_list.in_list()) { + PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); +} + +void CollisionObject3DSW::set_shape(int p_index, Shape3DSW *p_shape) { + + ERR_FAIL_INDEX(p_index, shapes.size()); + shapes[p_index].shape->remove_owner(this); + shapes.write[p_index].shape = p_shape; + + p_shape->add_owner(this); + if (!pending_shape_update_list.in_list()) { + PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); +} +void CollisionObject3DSW::set_shape_transform(int p_index, const Transform &p_transform) { + + ERR_FAIL_INDEX(p_index, shapes.size()); + + shapes.write[p_index].xform = p_transform; + shapes.write[p_index].xform_inv = p_transform.affine_inverse(); + if (!pending_shape_update_list.in_list()) { + PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); +} + +void CollisionObject3DSW::set_shape_as_disabled(int p_idx, bool p_enable) { + shapes.write[p_idx].disabled = p_enable; + if (!pending_shape_update_list.in_list()) { + PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } +} + +void CollisionObject3DSW::remove_shape(Shape3DSW *p_shape) { + + //remove a shape, all the times it appears + for (int i = 0; i < shapes.size(); i++) { + + if (shapes[i].shape == p_shape) { + remove_shape(i); + i--; + } + } +} + +void CollisionObject3DSW::remove_shape(int p_index) { + + //remove anything from shape to be erased to end, so subindices don't change + ERR_FAIL_INDEX(p_index, shapes.size()); + for (int i = p_index; i < shapes.size(); i++) { + + if (shapes[i].bpid == 0) + continue; + //should never get here with a null owner + space->get_broadphase()->remove(shapes[i].bpid); + shapes.write[i].bpid = 0; + } + shapes[p_index].shape->remove_owner(this); + shapes.remove(p_index); + + if (!pending_shape_update_list.in_list()) { + PhysicsServer3DSW::singleton->pending_shape_update_list.add(&pending_shape_update_list); + } + //_update_shapes(); + //_shapes_changed(); +} + +void CollisionObject3DSW::_set_static(bool p_static) { + if (_static == p_static) + return; + _static = p_static; + + if (!space) + return; + for (int i = 0; i < get_shape_count(); i++) { + const Shape &s = shapes[i]; + if (s.bpid > 0) { + space->get_broadphase()->set_static(s.bpid, _static); + } + } +} + +void CollisionObject3DSW::_unregister_shapes() { + + for (int i = 0; i < shapes.size(); i++) { + + Shape &s = shapes.write[i]; + if (s.bpid > 0) { + space->get_broadphase()->remove(s.bpid); + s.bpid = 0; + } + } +} + +void CollisionObject3DSW::_update_shapes() { + + if (!space) + return; + + for (int i = 0; i < shapes.size(); i++) { + + Shape &s = shapes.write[i]; + if (s.bpid == 0) { + s.bpid = space->get_broadphase()->create(this, i); + space->get_broadphase()->set_static(s.bpid, _static); + } + + //not quite correct, should compute the next matrix.. + AABB shape_aabb = s.shape->get_aabb(); + Transform xform = transform * s.xform; + shape_aabb = xform.xform(shape_aabb); + s.aabb_cache = shape_aabb; + s.aabb_cache = s.aabb_cache.grow((s.aabb_cache.size.x + s.aabb_cache.size.y) * 0.5 * 0.05); + + Vector3 scale = xform.get_basis().get_scale(); + s.area_cache = s.shape->get_area() * scale.x * scale.y * scale.z; + + space->get_broadphase()->move(s.bpid, s.aabb_cache); + } +} + +void CollisionObject3DSW::_update_shapes_with_motion(const Vector3 &p_motion) { + + if (!space) + return; + + for (int i = 0; i < shapes.size(); i++) { + + Shape &s = shapes.write[i]; + if (s.bpid == 0) { + s.bpid = space->get_broadphase()->create(this, i); + space->get_broadphase()->set_static(s.bpid, _static); + } + + //not quite correct, should compute the next matrix.. + AABB shape_aabb = s.shape->get_aabb(); + Transform xform = transform * s.xform; + shape_aabb = xform.xform(shape_aabb); + shape_aabb = shape_aabb.merge(AABB(shape_aabb.position + p_motion, shape_aabb.size)); //use motion + s.aabb_cache = shape_aabb; + + space->get_broadphase()->move(s.bpid, shape_aabb); + } +} + +void CollisionObject3DSW::_set_space(Space3DSW *p_space) { + + if (space) { + + space->remove_object(this); + + for (int i = 0; i < shapes.size(); i++) { + + Shape &s = shapes.write[i]; + if (s.bpid) { + space->get_broadphase()->remove(s.bpid); + s.bpid = 0; + } + } + } + + space = p_space; + + if (space) { + + space->add_object(this); + _update_shapes(); + } +} + +void CollisionObject3DSW::_shape_changed() { + + _update_shapes(); + _shapes_changed(); +} + +CollisionObject3DSW::CollisionObject3DSW(Type p_type) : + pending_shape_update_list(this) { + + _static = true; + type = p_type; + space = NULL; + + collision_layer = 1; + collision_mask = 1; + ray_pickable = true; +} diff --git a/servers/physics_3d/collision_object_3d_sw.h b/servers/physics_3d/collision_object_3d_sw.h new file mode 100644 index 0000000000..582d447189 --- /dev/null +++ b/servers/physics_3d/collision_object_3d_sw.h @@ -0,0 +1,164 @@ +/*************************************************************************/ +/* collision_object_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLISION_OBJECT_SW_H +#define COLLISION_OBJECT_SW_H + +#include "broad_phase_3d_sw.h" +#include "core/self_list.h" +#include "servers/physics_server_3d.h" +#include "shape_3d_sw.h" + +#ifdef DEBUG_ENABLED +#define MAX_OBJECT_DISTANCE 3.1622776601683791e+18 + +#define MAX_OBJECT_DISTANCE_X2 (MAX_OBJECT_DISTANCE * MAX_OBJECT_DISTANCE) +#endif + +class Space3DSW; + +class CollisionObject3DSW : public ShapeOwner3DSW { +public: + enum Type { + TYPE_AREA, + TYPE_BODY + }; + +private: + Type type; + RID self; + ObjectID instance_id; + uint32_t collision_layer; + uint32_t collision_mask; + + struct Shape { + + Transform xform; + Transform xform_inv; + BroadPhase3DSW::ID bpid; + AABB aabb_cache; //for rayqueries + real_t area_cache; + Shape3DSW *shape; + bool disabled; + + Shape() { disabled = false; } + }; + + Vector shapes; + Space3DSW *space; + Transform transform; + Transform inv_transform; + bool _static; + + SelfList pending_shape_update_list; + + void _update_shapes(); + +protected: + void _update_shapes_with_motion(const Vector3 &p_motion); + void _unregister_shapes(); + + _FORCE_INLINE_ void _set_transform(const Transform &p_transform, bool p_update_shapes = true) { +#ifdef DEBUG_ENABLED + + ERR_FAIL_COND_MSG(p_transform.origin.length_squared() > MAX_OBJECT_DISTANCE_X2, "Object went too far away (more than '" + itos(MAX_OBJECT_DISTANCE) + "' units from origin)."); +#endif + + transform = p_transform; + if (p_update_shapes) _update_shapes(); + } + _FORCE_INLINE_ void _set_inv_transform(const Transform &p_transform) { inv_transform = p_transform; } + void _set_static(bool p_static); + + virtual void _shapes_changed() = 0; + void _set_space(Space3DSW *p_space); + + bool ray_pickable; + + CollisionObject3DSW(Type p_type); + +public: + _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } + _FORCE_INLINE_ RID get_self() const { return self; } + + _FORCE_INLINE_ void set_instance_id(const ObjectID &p_instance_id) { instance_id = p_instance_id; } + _FORCE_INLINE_ ObjectID get_instance_id() const { return instance_id; } + + void _shape_changed(); + + _FORCE_INLINE_ Type get_type() const { return type; } + void add_shape(Shape3DSW *p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); + void set_shape(int p_index, Shape3DSW *p_shape); + void set_shape_transform(int p_index, const Transform &p_transform); + _FORCE_INLINE_ int get_shape_count() const { return shapes.size(); } + _FORCE_INLINE_ bool is_shape_disabled(int p_index) const { + CRASH_BAD_INDEX(p_index, shapes.size()); + return shapes[p_index].disabled; + } + _FORCE_INLINE_ Shape3DSW *get_shape(int p_index) const { return shapes[p_index].shape; } + _FORCE_INLINE_ const Transform &get_shape_transform(int p_index) const { return shapes[p_index].xform; } + _FORCE_INLINE_ const Transform &get_shape_inv_transform(int p_index) const { return shapes[p_index].xform_inv; } + _FORCE_INLINE_ const AABB &get_shape_aabb(int p_index) const { return shapes[p_index].aabb_cache; } + _FORCE_INLINE_ real_t get_shape_area(int p_index) const { return shapes[p_index].area_cache; } + + _FORCE_INLINE_ Transform get_transform() const { return transform; } + _FORCE_INLINE_ Transform get_inv_transform() const { return inv_transform; } + _FORCE_INLINE_ Space3DSW *get_space() const { return space; } + + _FORCE_INLINE_ void set_ray_pickable(bool p_enable) { ray_pickable = p_enable; } + _FORCE_INLINE_ bool is_ray_pickable() const { return ray_pickable; } + + void set_shape_as_disabled(int p_idx, bool p_enable); + _FORCE_INLINE_ bool is_shape_set_as_disabled(int p_idx) const { + CRASH_BAD_INDEX(p_idx, shapes.size()); + return shapes[p_idx].disabled; + } + + _FORCE_INLINE_ void set_collision_layer(uint32_t p_layer) { collision_layer = p_layer; } + _FORCE_INLINE_ uint32_t get_collision_layer() const { return collision_layer; } + + _FORCE_INLINE_ void set_collision_mask(uint32_t p_mask) { collision_mask = p_mask; } + _FORCE_INLINE_ uint32_t get_collision_mask() const { return collision_mask; } + + _FORCE_INLINE_ bool test_collision_mask(CollisionObject3DSW *p_other) const { + return collision_layer & p_other->collision_mask || p_other->collision_layer & collision_mask; + } + + void remove_shape(Shape3DSW *p_shape); + void remove_shape(int p_index); + + virtual void set_space(Space3DSW *p_space) = 0; + + _FORCE_INLINE_ bool is_static() const { return _static; } + + virtual ~CollisionObject3DSW() {} +}; + +#endif // COLLISION_OBJECT_SW_H diff --git a/servers/physics_3d/collision_solver_3d_sat.cpp b/servers/physics_3d/collision_solver_3d_sat.cpp new file mode 100644 index 0000000000..ae205ceb48 --- /dev/null +++ b/servers/physics_3d/collision_solver_3d_sat.cpp @@ -0,0 +1,1591 @@ +/*************************************************************************/ +/* collision_solver_sat.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collision_solver_3d_sat.h" +#include "core/math/geometry.h" + +#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.02 + +struct _CollectorCallback { + + CollisionSolver3DSW::CallbackResult callback; + void *userdata; + bool swap; + bool collided; + Vector3 normal; + Vector3 *prev_axis; + + _FORCE_INLINE_ void call(const Vector3 &p_point_A, const Vector3 &p_point_B) { + + if (swap) + callback(p_point_B, p_point_A, userdata); + else + callback(p_point_A, p_point_B, userdata); + } +}; + +typedef void (*GenerateContactsFunc)(const Vector3 *, int, const Vector3 *, int, _CollectorCallback *); + +static void _generate_contacts_point_point(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(p_point_count_A != 1); + ERR_FAIL_COND(p_point_count_B != 1); +#endif + + p_callback->call(*p_points_A, *p_points_B); +} + +static void _generate_contacts_point_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(p_point_count_A != 1); + ERR_FAIL_COND(p_point_count_B != 2); +#endif + + Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(*p_points_A, p_points_B); + p_callback->call(*p_points_A, closest_B); +} + +static void _generate_contacts_point_face(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(p_point_count_A != 1); + ERR_FAIL_COND(p_point_count_B < 3); +#endif + + Vector3 closest_B = Plane(p_points_B[0], p_points_B[1], p_points_B[2]).project(*p_points_A); + + p_callback->call(*p_points_A, closest_B); +} + +static void _generate_contacts_edge_edge(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(p_point_count_A != 2); + ERR_FAIL_COND(p_point_count_B != 2); // circle is actually a 4x3 matrix +#endif + + Vector3 rel_A = p_points_A[1] - p_points_A[0]; + Vector3 rel_B = p_points_B[1] - p_points_B[0]; + + Vector3 c = rel_A.cross(rel_B).cross(rel_B); + + if (Math::is_zero_approx(rel_A.dot(c))) { + + // should handle somehow.. + //ERR_PRINT("TODO FIX"); + //return; + + Vector3 axis = rel_A.normalized(); //make an axis + Vector3 base_A = p_points_A[0] - axis * axis.dot(p_points_A[0]); + Vector3 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]); + + //sort all 4 points in axis + real_t dvec[4] = { axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) }; + + SortArray sa; + sa.sort(dvec, 4); + + //use the middle ones as contacts + p_callback->call(base_A + axis * dvec[1], base_B + axis * dvec[1]); + p_callback->call(base_A + axis * dvec[2], base_B + axis * dvec[2]); + + return; + } + + real_t d = (c.dot(p_points_B[0]) - p_points_A[0].dot(c)) / rel_A.dot(c); + + if (d < 0.0) + d = 0.0; + else if (d > 1.0) + d = 1.0; + + Vector3 closest_A = p_points_A[0] + rel_A * d; + Vector3 closest_B = Geometry::get_closest_point_to_segment_uncapped(closest_A, p_points_B); + p_callback->call(closest_A, closest_B); +} + +static void _generate_contacts_face_face(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(p_point_count_A < 2); + ERR_FAIL_COND(p_point_count_B < 3); +#endif + + static const int max_clip = 32; + + Vector3 _clipbuf1[max_clip]; + Vector3 _clipbuf2[max_clip]; + Vector3 *clipbuf_src = _clipbuf1; + Vector3 *clipbuf_dst = _clipbuf2; + int clipbuf_len = p_point_count_A; + + // copy A points to clipbuf_src + for (int i = 0; i < p_point_count_A; i++) { + + clipbuf_src[i] = p_points_A[i]; + } + + Plane plane_B(p_points_B[0], p_points_B[1], p_points_B[2]); + + // go through all of B points + for (int i = 0; i < p_point_count_B; i++) { + + int i_n = (i + 1) % p_point_count_B; + + Vector3 edge0_B = p_points_B[i]; + Vector3 edge1_B = p_points_B[i_n]; + + Vector3 clip_normal = (edge0_B - edge1_B).cross(plane_B.normal).normalized(); + // make a clip plane + + Plane clip(edge0_B, clip_normal); + // avoid double clip if A is edge + int dst_idx = 0; + bool edge = clipbuf_len == 2; + for (int j = 0; j < clipbuf_len; j++) { + + int j_n = (j + 1) % clipbuf_len; + + Vector3 edge0_A = clipbuf_src[j]; + Vector3 edge1_A = clipbuf_src[j_n]; + + real_t dist0 = clip.distance_to(edge0_A); + real_t dist1 = clip.distance_to(edge1_A); + + if (dist0 <= 0) { // behind plane + + ERR_FAIL_COND(dst_idx >= max_clip); + clipbuf_dst[dst_idx++] = clipbuf_src[j]; + } + + // check for different sides and non coplanar + //if ( (dist0*dist1) < -CMP_EPSILON && !(edge && j)) { + if ((dist0 * dist1) < 0 && !(edge && j)) { + + // calculate intersection + Vector3 rel = edge1_A - edge0_A; + real_t den = clip.normal.dot(rel); + real_t dist = -(clip.normal.dot(edge0_A) - clip.d) / den; + Vector3 inters = edge0_A + rel * dist; + + ERR_FAIL_COND(dst_idx >= max_clip); + clipbuf_dst[dst_idx] = inters; + dst_idx++; + } + } + + clipbuf_len = dst_idx; + SWAP(clipbuf_src, clipbuf_dst); + } + + // generate contacts + //Plane plane_A(p_points_A[0],p_points_A[1],p_points_A[2]); + + for (int i = 0; i < clipbuf_len; i++) { + + real_t d = plane_B.distance_to(clipbuf_src[i]); + /* + if (d>CMP_EPSILON) + continue; + */ + + Vector3 closest_B = clipbuf_src[i] - plane_B.normal * d; + + if (p_callback->normal.dot(clipbuf_src[i]) >= p_callback->normal.dot(closest_B)) + continue; + + p_callback->call(clipbuf_src[i], closest_B); + } +} + +static void _generate_contacts_from_supports(const Vector3 *p_points_A, int p_point_count_A, const Vector3 *p_points_B, int p_point_count_B, _CollectorCallback *p_callback) { + +#ifdef DEBUG_ENABLED + ERR_FAIL_COND(p_point_count_A < 1); + ERR_FAIL_COND(p_point_count_B < 1); +#endif + + static const GenerateContactsFunc generate_contacts_func_table[3][3] = { + { + _generate_contacts_point_point, + _generate_contacts_point_edge, + _generate_contacts_point_face, + }, + { + 0, + _generate_contacts_edge_edge, + _generate_contacts_face_face, + }, + { + 0, + 0, + _generate_contacts_face_face, + } + }; + + int pointcount_B; + int pointcount_A; + const Vector3 *points_A; + const Vector3 *points_B; + + if (p_point_count_A > p_point_count_B) { + //swap + p_callback->swap = !p_callback->swap; + p_callback->normal = -p_callback->normal; + + pointcount_B = p_point_count_A; + pointcount_A = p_point_count_B; + points_A = p_points_B; + points_B = p_points_A; + } else { + + pointcount_B = p_point_count_B; + pointcount_A = p_point_count_A; + points_A = p_points_A; + points_B = p_points_B; + } + + int version_A = (pointcount_A > 3 ? 3 : pointcount_A) - 1; + int version_B = (pointcount_B > 3 ? 3 : pointcount_B) - 1; + + GenerateContactsFunc contacts_func = generate_contacts_func_table[version_A][version_B]; + ERR_FAIL_COND(!contacts_func); + contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_callback); +} + +template +class SeparatorAxisTest { + + const ShapeA *shape_A; + const ShapeB *shape_B; + const Transform *transform_A; + const Transform *transform_B; + real_t best_depth; + Vector3 best_axis; + _CollectorCallback *callback; + real_t margin_A; + real_t margin_B; + Vector3 separator_axis; + +public: + _FORCE_INLINE_ bool test_previous_axis() { + + if (callback && callback->prev_axis && *callback->prev_axis != Vector3()) + return test_axis(*callback->prev_axis); + else + return true; + } + + _FORCE_INLINE_ bool test_axis(const Vector3 &p_axis) { + + Vector3 axis = p_axis; + + if (Math::abs(axis.x) < CMP_EPSILON && + Math::abs(axis.y) < CMP_EPSILON && + Math::abs(axis.z) < CMP_EPSILON) { + // strange case, try an upwards separator + axis = Vector3(0.0, 1.0, 0.0); + } + + real_t min_A, max_A, min_B, max_B; + + shape_A->project_range(axis, *transform_A, min_A, max_A); + shape_B->project_range(axis, *transform_B, min_B, max_B); + + if (withMargin) { + min_A -= margin_A; + max_A += margin_A; + min_B -= margin_B; + max_B += margin_B; + } + + min_B -= (max_A - min_A) * 0.5; + max_B += (max_A - min_A) * 0.5; + + min_B -= (min_A + max_A) * 0.5; + max_B -= (min_A + max_A) * 0.5; + + if (min_B > 0.0 || max_B < 0.0) { + separator_axis = axis; + return false; // doesn't contain 0 + } + + //use the smallest depth + + if (min_B < 0.0) { // could be +0.0, we don't want it to become -0.0 + min_B = -min_B; + } + + if (max_B < min_B) { + if (max_B < best_depth) { + best_depth = max_B; + best_axis = axis; + } + } else { + if (min_B < best_depth) { + best_depth = min_B; + best_axis = -axis; // keep it as A axis + } + } + + return true; + } + + _FORCE_INLINE_ void generate_contacts() { + + // nothing to do, don't generate + if (best_axis == Vector3(0.0, 0.0, 0.0)) + return; + + if (!callback->callback) { + //just was checking intersection? + callback->collided = true; + if (callback->prev_axis) + *callback->prev_axis = best_axis; + return; + } + + static const int max_supports = 16; + + Vector3 supports_A[max_supports]; + int support_count_A; + shape_A->get_supports(transform_A->basis.xform_inv(-best_axis).normalized(), max_supports, supports_A, support_count_A); + for (int i = 0; i < support_count_A; i++) { + supports_A[i] = transform_A->xform(supports_A[i]); + } + + if (withMargin) { + + for (int i = 0; i < support_count_A; i++) { + supports_A[i] += -best_axis * margin_A; + } + } + + Vector3 supports_B[max_supports]; + int support_count_B; + shape_B->get_supports(transform_B->basis.xform_inv(best_axis).normalized(), max_supports, supports_B, support_count_B); + for (int i = 0; i < support_count_B; i++) { + supports_B[i] = transform_B->xform(supports_B[i]); + } + + if (withMargin) { + + for (int i = 0; i < support_count_B; i++) { + supports_B[i] += best_axis * margin_B; + } + } + + callback->normal = best_axis; + if (callback->prev_axis) + *callback->prev_axis = best_axis; + _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback); + + callback->collided = true; + } + + _FORCE_INLINE_ SeparatorAxisTest(const ShapeA *p_shape_A, const Transform &p_transform_A, const ShapeB *p_shape_B, const Transform &p_transform_B, _CollectorCallback *p_callback, real_t p_margin_A = 0, real_t p_margin_B = 0) { + best_depth = 1e15; + shape_A = p_shape_A; + shape_B = p_shape_B; + transform_A = &p_transform_A; + transform_B = &p_transform_B; + callback = p_callback; + margin_A = p_margin_A; + margin_B = p_margin_B; + } +}; + +/****** SAT TESTS *******/ + +typedef void (*CollisionFunc)(const Shape3DSW *, const Transform &, const Shape3DSW *, const Transform &, _CollectorCallback *p_callback, real_t, real_t); + +template +static void _collision_sphere_sphere(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const SphereShape3DSW *sphere_A = static_cast(p_a); + const SphereShape3DSW *sphere_B = static_cast(p_b); + + SeparatorAxisTest separator(sphere_A, p_transform_a, sphere_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + // previous axis + + if (!separator.test_previous_axis()) + return; + + if (!separator.test_axis((p_transform_a.origin - p_transform_b.origin).normalized())) + return; + + separator.generate_contacts(); +} + +template +static void _collision_sphere_box(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const SphereShape3DSW *sphere_A = static_cast(p_a); + const BoxShape3DSW *box_B = static_cast(p_b); + + SeparatorAxisTest separator(sphere_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + // test faces + + for (int i = 0; i < 3; i++) { + + Vector3 axis = p_transform_b.basis.get_axis(i).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // calculate closest point to sphere + + Vector3 cnormal = p_transform_b.xform_inv(p_transform_a.origin); + + Vector3 cpoint = p_transform_b.xform(Vector3( + + (cnormal.x < 0) ? -box_B->get_half_extents().x : box_B->get_half_extents().x, + (cnormal.y < 0) ? -box_B->get_half_extents().y : box_B->get_half_extents().y, + (cnormal.z < 0) ? -box_B->get_half_extents().z : box_B->get_half_extents().z)); + + // use point to test axis + Vector3 point_axis = (p_transform_a.origin - cpoint).normalized(); + + if (!separator.test_axis(point_axis)) + return; + + // test edges + + for (int i = 0; i < 3; i++) { + + Vector3 axis = point_axis.cross(p_transform_b.basis.get_axis(i)).cross(p_transform_b.basis.get_axis(i)).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + separator.generate_contacts(); +} + +template +static void _collision_sphere_capsule(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const SphereShape3DSW *sphere_A = static_cast(p_a); + const CapsuleShape3DSW *capsule_B = static_cast(p_b); + + SeparatorAxisTest separator(sphere_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + //capsule sphere 1, sphere + + Vector3 capsule_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5); + + Vector3 capsule_ball_1 = p_transform_b.origin + capsule_axis; + + if (!separator.test_axis((capsule_ball_1 - p_transform_a.origin).normalized())) + return; + + //capsule sphere 2, sphere + + Vector3 capsule_ball_2 = p_transform_b.origin - capsule_axis; + + if (!separator.test_axis((capsule_ball_2 - p_transform_a.origin).normalized())) + return; + + //capsule edge, sphere + + Vector3 b2a = p_transform_a.origin - p_transform_b.origin; + + Vector3 axis = b2a.cross(capsule_axis).cross(capsule_axis).normalized(); + + if (!separator.test_axis(axis)) + return; + + separator.generate_contacts(); +} + +template +static void _collision_sphere_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { +} + +template +static void _collision_sphere_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const SphereShape3DSW *sphere_A = static_cast(p_a); + const ConvexPolygonShape3DSW *convex_polygon_B = static_cast(p_b); + + SeparatorAxisTest separator(sphere_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + const Geometry::MeshData &mesh = convex_polygon_B->get_mesh(); + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int face_count = mesh.faces.size(); + const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); + int edge_count = mesh.edges.size(); + const Vector3 *vertices = mesh.vertices.ptr(); + int vertex_count = mesh.vertices.size(); + + // faces of B + for (int i = 0; i < face_count; i++) { + + Vector3 axis = p_transform_b.xform(faces[i].plane).normal; + + if (!separator.test_axis(axis)) + return; + } + + // edges of B + for (int i = 0; i < edge_count; i++) { + + Vector3 v1 = p_transform_b.xform(vertices[edges[i].a]); + Vector3 v2 = p_transform_b.xform(vertices[edges[i].b]); + Vector3 v3 = p_transform_a.origin; + + Vector3 n1 = v2 - v1; + Vector3 n2 = v2 - v3; + + Vector3 axis = n1.cross(n2).cross(n1).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // vertices of B + for (int i = 0; i < vertex_count; i++) { + + Vector3 v1 = p_transform_b.xform(vertices[i]); + Vector3 v2 = p_transform_a.origin; + + Vector3 axis = (v2 - v1).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + separator.generate_contacts(); +} + +template +static void _collision_sphere_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const SphereShape3DSW *sphere_A = static_cast(p_a); + const FaceShape3DSW *face_B = static_cast(p_b); + + SeparatorAxisTest separator(sphere_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + Vector3 vertex[3] = { + p_transform_b.xform(face_B->vertex[0]), + p_transform_b.xform(face_B->vertex[1]), + p_transform_b.xform(face_B->vertex[2]), + }; + + if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) + return; + + // edges and points of B + for (int i = 0; i < 3; i++) { + + Vector3 n1 = vertex[i] - p_transform_a.origin; + + if (!separator.test_axis(n1.normalized())) { + return; + } + + Vector3 n2 = vertex[(i + 1) % 3] - vertex[i]; + + Vector3 axis = n1.cross(n2).cross(n2).normalized(); + + if (!separator.test_axis(axis)) { + return; + } + } + + separator.generate_contacts(); +} + +template +static void _collision_box_box(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const BoxShape3DSW *box_A = static_cast(p_a); + const BoxShape3DSW *box_B = static_cast(p_b); + + SeparatorAxisTest separator(box_A, p_transform_a, box_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + // test faces of A + + for (int i = 0; i < 3; i++) { + + Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // test faces of B + + for (int i = 0; i < 3; i++) { + + Vector3 axis = p_transform_b.basis.get_axis(i).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // test combined edges + for (int i = 0; i < 3; i++) { + + for (int j = 0; j < 3; j++) { + + Vector3 axis = p_transform_a.basis.get_axis(i).cross(p_transform_b.basis.get_axis(j)); + + if (Math::is_zero_approx(axis.length_squared())) + continue; + axis.normalize(); + + if (!separator.test_axis(axis)) { + return; + } + } + } + + if (withMargin) { + //add endpoint test between closest vertices and edges + + // calculate closest point to sphere + + Vector3 ab_vec = p_transform_b.origin - p_transform_a.origin; + + Vector3 cnormal_a = p_transform_a.basis.xform_inv(ab_vec); + + Vector3 support_a = p_transform_a.xform(Vector3( + + (cnormal_a.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, + (cnormal_a.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, + (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); + + Vector3 cnormal_b = p_transform_b.basis.xform_inv(-ab_vec); + + Vector3 support_b = p_transform_b.xform(Vector3( + + (cnormal_b.x < 0) ? -box_B->get_half_extents().x : box_B->get_half_extents().x, + (cnormal_b.y < 0) ? -box_B->get_half_extents().y : box_B->get_half_extents().y, + (cnormal_b.z < 0) ? -box_B->get_half_extents().z : box_B->get_half_extents().z)); + + Vector3 axis_ab = (support_a - support_b); + + if (!separator.test_axis(axis_ab.normalized())) { + return; + } + + //now try edges, which become cylinders! + + for (int i = 0; i < 3; i++) { + + //a ->b + Vector3 axis_a = p_transform_a.basis.get_axis(i); + + if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) + return; + + //b ->a + Vector3 axis_b = p_transform_b.basis.get_axis(i); + + if (!separator.test_axis(axis_ab.cross(axis_b).cross(axis_b).normalized())) + return; + } + } + + separator.generate_contacts(); +} + +template +static void _collision_box_capsule(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const BoxShape3DSW *box_A = static_cast(p_a); + const CapsuleShape3DSW *capsule_B = static_cast(p_b); + + SeparatorAxisTest separator(box_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + // faces of A + for (int i = 0; i < 3; i++) { + + Vector3 axis = p_transform_a.basis.get_axis(i); + + if (!separator.test_axis(axis)) + return; + } + + Vector3 cyl_axis = p_transform_b.basis.get_axis(2).normalized(); + + // edges of A, capsule cylinder + + for (int i = 0; i < 3; i++) { + + // cylinder + Vector3 box_axis = p_transform_a.basis.get_axis(i); + Vector3 axis = box_axis.cross(cyl_axis); + if (Math::is_zero_approx(axis.length_squared())) + continue; + + if (!separator.test_axis(axis.normalized())) + return; + } + + // points of A, capsule cylinder + // this sure could be made faster somehow.. + + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + Vector3 he = box_A->get_half_extents(); + he.x *= (i * 2 - 1); + he.y *= (j * 2 - 1); + he.z *= (k * 2 - 1); + Vector3 point = p_transform_a.origin; + for (int l = 0; l < 3; l++) + point += p_transform_a.basis.get_axis(l) * he[l]; + + //Vector3 axis = (point - cyl_axis * cyl_axis.dot(point)).normalized(); + Vector3 axis = Plane(cyl_axis, 0).project(point).normalized(); + + if (!separator.test_axis(axis)) + return; + } + } + } + + // capsule balls, edges of A + + for (int i = 0; i < 2; i++) { + + Vector3 capsule_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5); + + Vector3 sphere_pos = p_transform_b.origin + ((i == 0) ? capsule_axis : -capsule_axis); + + Vector3 cnormal = p_transform_a.xform_inv(sphere_pos); + + Vector3 cpoint = p_transform_a.xform(Vector3( + + (cnormal.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, + (cnormal.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, + (cnormal.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); + + // use point to test axis + Vector3 point_axis = (sphere_pos - cpoint).normalized(); + + if (!separator.test_axis(point_axis)) + return; + + // test edges of A + + for (int j = 0; j < 3; j++) { + + Vector3 axis = point_axis.cross(p_transform_a.basis.get_axis(j)).cross(p_transform_a.basis.get_axis(j)).normalized(); + + if (!separator.test_axis(axis)) + return; + } + } + + separator.generate_contacts(); +} + +template +static void _collision_box_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { +} + +template +static void _collision_box_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const BoxShape3DSW *box_A = static_cast(p_a); + const ConvexPolygonShape3DSW *convex_polygon_B = static_cast(p_b); + + SeparatorAxisTest separator(box_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + const Geometry::MeshData &mesh = convex_polygon_B->get_mesh(); + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int face_count = mesh.faces.size(); + const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); + int edge_count = mesh.edges.size(); + const Vector3 *vertices = mesh.vertices.ptr(); + int vertex_count = mesh.vertices.size(); + + // faces of A + for (int i = 0; i < 3; i++) { + + Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // faces of B + for (int i = 0; i < face_count; i++) { + + Vector3 axis = p_transform_b.xform(faces[i].plane).normal; + + if (!separator.test_axis(axis)) + return; + } + + // A<->B edges + for (int i = 0; i < 3; i++) { + + Vector3 e1 = p_transform_a.basis.get_axis(i); + + for (int j = 0; j < edge_count; j++) { + + Vector3 e2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]); + + Vector3 axis = e1.cross(e2).normalized(); + + if (!separator.test_axis(axis)) + return; + } + } + + if (withMargin) { + + // calculate closest points between vertices and box edges + for (int v = 0; v < vertex_count; v++) { + + Vector3 vtxb = p_transform_b.xform(vertices[v]); + Vector3 ab_vec = vtxb - p_transform_a.origin; + + Vector3 cnormal_a = p_transform_a.basis.xform_inv(ab_vec); + + Vector3 support_a = p_transform_a.xform(Vector3( + + (cnormal_a.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, + (cnormal_a.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, + (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); + + Vector3 axis_ab = support_a - vtxb; + + if (!separator.test_axis(axis_ab.normalized())) { + return; + } + + //now try edges, which become cylinders! + + for (int i = 0; i < 3; i++) { + + //a ->b + Vector3 axis_a = p_transform_a.basis.get_axis(i); + + if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) + return; + } + } + + //convex edges and box points + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + Vector3 he = box_A->get_half_extents(); + he.x *= (i * 2 - 1); + he.y *= (j * 2 - 1); + he.z *= (k * 2 - 1); + Vector3 point = p_transform_a.origin; + for (int l = 0; l < 3; l++) + point += p_transform_a.basis.get_axis(l) * he[l]; + + for (int e = 0; e < edge_count; e++) { + + Vector3 p1 = p_transform_b.xform(vertices[edges[e].a]); + Vector3 p2 = p_transform_b.xform(vertices[edges[e].b]); + Vector3 n = (p2 - p1); + + if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) + return; + } + } + } + } + } + + separator.generate_contacts(); +} + +template +static void _collision_box_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const BoxShape3DSW *box_A = static_cast(p_a); + const FaceShape3DSW *face_B = static_cast(p_b); + + SeparatorAxisTest separator(box_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + Vector3 vertex[3] = { + p_transform_b.xform(face_B->vertex[0]), + p_transform_b.xform(face_B->vertex[1]), + p_transform_b.xform(face_B->vertex[2]), + }; + + if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) + return; + + // faces of A + for (int i = 0; i < 3; i++) { + + Vector3 axis = p_transform_a.basis.get_axis(i).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // combined edges + + for (int i = 0; i < 3; i++) { + + Vector3 e = vertex[i] - vertex[(i + 1) % 3]; + + for (int j = 0; j < 3; j++) { + + Vector3 axis = p_transform_a.basis.get_axis(j); + + if (!separator.test_axis(e.cross(axis).normalized())) + return; + } + } + + if (withMargin) { + + // calculate closest points between vertices and box edges + for (int v = 0; v < 3; v++) { + + Vector3 ab_vec = vertex[v] - p_transform_a.origin; + + Vector3 cnormal_a = p_transform_a.basis.xform_inv(ab_vec); + + Vector3 support_a = p_transform_a.xform(Vector3( + + (cnormal_a.x < 0) ? -box_A->get_half_extents().x : box_A->get_half_extents().x, + (cnormal_a.y < 0) ? -box_A->get_half_extents().y : box_A->get_half_extents().y, + (cnormal_a.z < 0) ? -box_A->get_half_extents().z : box_A->get_half_extents().z)); + + Vector3 axis_ab = support_a - vertex[v]; + + if (!separator.test_axis(axis_ab.normalized())) { + return; + } + + //now try edges, which become cylinders! + + for (int i = 0; i < 3; i++) { + + //a ->b + Vector3 axis_a = p_transform_a.basis.get_axis(i); + + if (!separator.test_axis(axis_ab.cross(axis_a).cross(axis_a).normalized())) + return; + } + } + + //convex edges and box points, there has to be a way to speed up this (get closest point?) + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 2; j++) { + for (int k = 0; k < 2; k++) { + Vector3 he = box_A->get_half_extents(); + he.x *= (i * 2 - 1); + he.y *= (j * 2 - 1); + he.z *= (k * 2 - 1); + Vector3 point = p_transform_a.origin; + for (int l = 0; l < 3; l++) + point += p_transform_a.basis.get_axis(l) * he[l]; + + for (int e = 0; e < 3; e++) { + + Vector3 p1 = vertex[e]; + Vector3 p2 = vertex[(e + 1) % 3]; + + Vector3 n = (p2 - p1); + + if (!separator.test_axis((point - p2).cross(n).cross(n).normalized())) + return; + } + } + } + } + } + + separator.generate_contacts(); +} + +template +static void _collision_capsule_capsule(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const CapsuleShape3DSW *capsule_A = static_cast(p_a); + const CapsuleShape3DSW *capsule_B = static_cast(p_b); + + SeparatorAxisTest separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + // some values + + Vector3 capsule_A_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5); + Vector3 capsule_B_axis = p_transform_b.basis.get_axis(2) * (capsule_B->get_height() * 0.5); + + Vector3 capsule_A_ball_1 = p_transform_a.origin + capsule_A_axis; + Vector3 capsule_A_ball_2 = p_transform_a.origin - capsule_A_axis; + Vector3 capsule_B_ball_1 = p_transform_b.origin + capsule_B_axis; + Vector3 capsule_B_ball_2 = p_transform_b.origin - capsule_B_axis; + + //balls-balls + + if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_1).normalized())) + return; + if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_2).normalized())) + return; + + if (!separator.test_axis((capsule_A_ball_2 - capsule_B_ball_1).normalized())) + return; + if (!separator.test_axis((capsule_A_ball_2 - capsule_B_ball_2).normalized())) + return; + + // edges-balls + + if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_1).cross(capsule_A_axis).cross(capsule_A_axis).normalized())) + return; + + if (!separator.test_axis((capsule_A_ball_1 - capsule_B_ball_2).cross(capsule_A_axis).cross(capsule_A_axis).normalized())) + return; + + if (!separator.test_axis((capsule_B_ball_1 - capsule_A_ball_1).cross(capsule_B_axis).cross(capsule_B_axis).normalized())) + return; + + if (!separator.test_axis((capsule_B_ball_1 - capsule_A_ball_2).cross(capsule_B_axis).cross(capsule_B_axis).normalized())) + return; + + // edges + + if (!separator.test_axis(capsule_A_axis.cross(capsule_B_axis).normalized())) + return; + + separator.generate_contacts(); +} + +template +static void _collision_capsule_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { +} + +template +static void _collision_capsule_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const CapsuleShape3DSW *capsule_A = static_cast(p_a); + const ConvexPolygonShape3DSW *convex_polygon_B = static_cast(p_b); + + SeparatorAxisTest separator(capsule_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + const Geometry::MeshData &mesh = convex_polygon_B->get_mesh(); + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int face_count = mesh.faces.size(); + const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); + int edge_count = mesh.edges.size(); + const Vector3 *vertices = mesh.vertices.ptr(); + + // faces of B + for (int i = 0; i < face_count; i++) { + + Vector3 axis = p_transform_b.xform(faces[i].plane).normal; + + if (!separator.test_axis(axis)) + return; + } + + // edges of B, capsule cylinder + + for (int i = 0; i < edge_count; i++) { + + // cylinder + Vector3 edge_axis = p_transform_b.basis.xform(vertices[edges[i].a]) - p_transform_b.basis.xform(vertices[edges[i].b]); + Vector3 axis = edge_axis.cross(p_transform_a.basis.get_axis(2)).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // capsule balls, edges of B + + for (int i = 0; i < 2; i++) { + + // edges of B, capsule cylinder + + Vector3 capsule_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5); + + Vector3 sphere_pos = p_transform_a.origin + ((i == 0) ? capsule_axis : -capsule_axis); + + for (int j = 0; j < edge_count; j++) { + + Vector3 n1 = sphere_pos - p_transform_b.xform(vertices[edges[j].a]); + Vector3 n2 = p_transform_b.basis.xform(vertices[edges[j].a]) - p_transform_b.basis.xform(vertices[edges[j].b]); + + Vector3 axis = n1.cross(n2).cross(n2).normalized(); + + if (!separator.test_axis(axis)) + return; + } + } + + separator.generate_contacts(); +} + +template +static void _collision_capsule_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const CapsuleShape3DSW *capsule_A = static_cast(p_a); + const FaceShape3DSW *face_B = static_cast(p_b); + + SeparatorAxisTest separator(capsule_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + Vector3 vertex[3] = { + p_transform_b.xform(face_B->vertex[0]), + p_transform_b.xform(face_B->vertex[1]), + p_transform_b.xform(face_B->vertex[2]), + }; + + if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) + return; + + // edges of B, capsule cylinder + + Vector3 capsule_axis = p_transform_a.basis.get_axis(2) * (capsule_A->get_height() * 0.5); + + for (int i = 0; i < 3; i++) { + + // edge-cylinder + Vector3 edge_axis = vertex[i] - vertex[(i + 1) % 3]; + Vector3 axis = edge_axis.cross(capsule_axis).normalized(); + + if (!separator.test_axis(axis)) + return; + + if (!separator.test_axis((p_transform_a.origin - vertex[i]).cross(capsule_axis).cross(capsule_axis).normalized())) + return; + + for (int j = 0; j < 2; j++) { + + // point-spheres + Vector3 sphere_pos = p_transform_a.origin + ((j == 0) ? capsule_axis : -capsule_axis); + + Vector3 n1 = sphere_pos - vertex[i]; + + if (!separator.test_axis(n1.normalized())) + return; + + Vector3 n2 = edge_axis; + + axis = n1.cross(n2).cross(n2); + + if (!separator.test_axis(axis.normalized())) + return; + } + } + + separator.generate_contacts(); +} + +template +static void _collision_cylinder_cylinder(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { +} + +template +static void _collision_cylinder_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { +} + +template +static void _collision_cylinder_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { +} + +template +static void _collision_convex_polygon_convex_polygon(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const ConvexPolygonShape3DSW *convex_polygon_A = static_cast(p_a); + const ConvexPolygonShape3DSW *convex_polygon_B = static_cast(p_b); + + SeparatorAxisTest separator(convex_polygon_A, p_transform_a, convex_polygon_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + if (!separator.test_previous_axis()) + return; + + const Geometry::MeshData &mesh_A = convex_polygon_A->get_mesh(); + + const Geometry::MeshData::Face *faces_A = mesh_A.faces.ptr(); + int face_count_A = mesh_A.faces.size(); + const Geometry::MeshData::Edge *edges_A = mesh_A.edges.ptr(); + int edge_count_A = mesh_A.edges.size(); + const Vector3 *vertices_A = mesh_A.vertices.ptr(); + int vertex_count_A = mesh_A.vertices.size(); + + const Geometry::MeshData &mesh_B = convex_polygon_B->get_mesh(); + + const Geometry::MeshData::Face *faces_B = mesh_B.faces.ptr(); + int face_count_B = mesh_B.faces.size(); + const Geometry::MeshData::Edge *edges_B = mesh_B.edges.ptr(); + int edge_count_B = mesh_B.edges.size(); + const Vector3 *vertices_B = mesh_B.vertices.ptr(); + int vertex_count_B = mesh_B.vertices.size(); + + // faces of A + for (int i = 0; i < face_count_A; i++) { + + Vector3 axis = p_transform_a.xform(faces_A[i].plane).normal; + //Vector3 axis = p_transform_a.basis.xform( faces_A[i].plane.normal ).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // faces of B + for (int i = 0; i < face_count_B; i++) { + + Vector3 axis = p_transform_b.xform(faces_B[i].plane).normal; + //Vector3 axis = p_transform_b.basis.xform( faces_B[i].plane.normal ).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // A<->B edges + for (int i = 0; i < edge_count_A; i++) { + + Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]) - p_transform_a.basis.xform(vertices_A[edges_A[i].b]); + + for (int j = 0; j < edge_count_B; j++) { + + Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[j].a]) - p_transform_b.basis.xform(vertices_B[edges_B[j].b]); + + Vector3 axis = e1.cross(e2).normalized(); + + if (!separator.test_axis(axis)) + return; + } + } + + if (withMargin) { + + //vertex-vertex + for (int i = 0; i < vertex_count_A; i++) { + + Vector3 va = p_transform_a.xform(vertices_A[i]); + + for (int j = 0; j < vertex_count_B; j++) { + + if (!separator.test_axis((va - p_transform_b.xform(vertices_B[j])).normalized())) + return; + } + } + //edge-vertex (shell) + + for (int i = 0; i < edge_count_A; i++) { + + Vector3 e1 = p_transform_a.basis.xform(vertices_A[edges_A[i].a]); + Vector3 e2 = p_transform_a.basis.xform(vertices_A[edges_A[i].b]); + Vector3 n = (e2 - e1); + + for (int j = 0; j < vertex_count_B; j++) { + + Vector3 e3 = p_transform_b.xform(vertices_B[j]); + + if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) + return; + } + } + + for (int i = 0; i < edge_count_B; i++) { + + Vector3 e1 = p_transform_b.basis.xform(vertices_B[edges_B[i].a]); + Vector3 e2 = p_transform_b.basis.xform(vertices_B[edges_B[i].b]); + Vector3 n = (e2 - e1); + + for (int j = 0; j < vertex_count_A; j++) { + + Vector3 e3 = p_transform_a.xform(vertices_A[j]); + + if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) + return; + } + } + } + + separator.generate_contacts(); +} + +template +static void _collision_convex_polygon_face(const Shape3DSW *p_a, const Transform &p_transform_a, const Shape3DSW *p_b, const Transform &p_transform_b, _CollectorCallback *p_collector, real_t p_margin_a, real_t p_margin_b) { + + const ConvexPolygonShape3DSW *convex_polygon_A = static_cast(p_a); + const FaceShape3DSW *face_B = static_cast(p_b); + + SeparatorAxisTest separator(convex_polygon_A, p_transform_a, face_B, p_transform_b, p_collector, p_margin_a, p_margin_b); + + const Geometry::MeshData &mesh = convex_polygon_A->get_mesh(); + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int face_count = mesh.faces.size(); + const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); + int edge_count = mesh.edges.size(); + const Vector3 *vertices = mesh.vertices.ptr(); + int vertex_count = mesh.vertices.size(); + + Vector3 vertex[3] = { + p_transform_b.xform(face_B->vertex[0]), + p_transform_b.xform(face_B->vertex[1]), + p_transform_b.xform(face_B->vertex[2]), + }; + + if (!separator.test_axis((vertex[0] - vertex[2]).cross(vertex[0] - vertex[1]).normalized())) + return; + + // faces of A + for (int i = 0; i < face_count; i++) { + + //Vector3 axis = p_transform_a.xform( faces[i].plane ).normal; + Vector3 axis = p_transform_a.basis.xform(faces[i].plane.normal).normalized(); + + if (!separator.test_axis(axis)) + return; + } + + // A<->B edges + for (int i = 0; i < edge_count; i++) { + + Vector3 e1 = p_transform_a.xform(vertices[edges[i].a]) - p_transform_a.xform(vertices[edges[i].b]); + + for (int j = 0; j < 3; j++) { + + Vector3 e2 = vertex[j] - vertex[(j + 1) % 3]; + + Vector3 axis = e1.cross(e2).normalized(); + + if (!separator.test_axis(axis)) + return; + } + } + + if (withMargin) { + + //vertex-vertex + for (int i = 0; i < vertex_count; i++) { + + Vector3 va = p_transform_a.xform(vertices[i]); + + for (int j = 0; j < 3; j++) { + + if (!separator.test_axis((va - vertex[j]).normalized())) + return; + } + } + //edge-vertex (shell) + + for (int i = 0; i < edge_count; i++) { + + Vector3 e1 = p_transform_a.basis.xform(vertices[edges[i].a]); + Vector3 e2 = p_transform_a.basis.xform(vertices[edges[i].b]); + Vector3 n = (e2 - e1); + + for (int j = 0; j < 3; j++) { + + Vector3 e3 = vertex[j]; + + if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) + return; + } + } + + for (int i = 0; i < 3; i++) { + + Vector3 e1 = vertex[i]; + Vector3 e2 = vertex[(i + 1) % 3]; + Vector3 n = (e2 - e1); + + for (int j = 0; j < vertex_count; j++) { + + Vector3 e3 = p_transform_a.xform(vertices[j]); + + if (!separator.test_axis((e1 - e3).cross(n).cross(n).normalized())) + return; + } + } + } + + separator.generate_contacts(); +} + +bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector3 *r_prev_axis, real_t p_margin_a, real_t p_margin_b) { + + PhysicsServer3D::ShapeType type_A = p_shape_A->get_type(); + + ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_PLANE, false); + ERR_FAIL_COND_V(type_A == PhysicsServer3D::SHAPE_RAY, false); + ERR_FAIL_COND_V(p_shape_A->is_concave(), false); + + PhysicsServer3D::ShapeType type_B = p_shape_B->get_type(); + + ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_PLANE, false); + ERR_FAIL_COND_V(type_B == PhysicsServer3D::SHAPE_RAY, false); + ERR_FAIL_COND_V(p_shape_B->is_concave(), false); + + static const CollisionFunc collision_table[6][6] = { + { _collision_sphere_sphere, + _collision_sphere_box, + _collision_sphere_capsule, + _collision_sphere_cylinder, + _collision_sphere_convex_polygon, + _collision_sphere_face }, + { 0, + _collision_box_box, + _collision_box_capsule, + _collision_box_cylinder, + _collision_box_convex_polygon, + _collision_box_face }, + { 0, + 0, + _collision_capsule_capsule, + _collision_capsule_cylinder, + _collision_capsule_convex_polygon, + _collision_capsule_face }, + { 0, + 0, + 0, + _collision_cylinder_cylinder, + _collision_cylinder_convex_polygon, + _collision_cylinder_face }, + { 0, + 0, + 0, + 0, + _collision_convex_polygon_convex_polygon, + _collision_convex_polygon_face }, + { 0, + 0, + 0, + 0, + 0, + 0 }, + }; + + static const CollisionFunc collision_table_margin[6][6] = { + { _collision_sphere_sphere, + _collision_sphere_box, + _collision_sphere_capsule, + _collision_sphere_cylinder, + _collision_sphere_convex_polygon, + _collision_sphere_face }, + { 0, + _collision_box_box, + _collision_box_capsule, + _collision_box_cylinder, + _collision_box_convex_polygon, + _collision_box_face }, + { 0, + 0, + _collision_capsule_capsule, + _collision_capsule_cylinder, + _collision_capsule_convex_polygon, + _collision_capsule_face }, + { 0, + 0, + 0, + _collision_cylinder_cylinder, + _collision_cylinder_convex_polygon, + _collision_cylinder_face }, + { 0, + 0, + 0, + 0, + _collision_convex_polygon_convex_polygon, + _collision_convex_polygon_face }, + { 0, + 0, + 0, + 0, + 0, + 0 }, + }; + + _CollectorCallback callback; + callback.callback = p_result_callback; + callback.swap = p_swap; + callback.userdata = p_userdata; + callback.collided = false; + callback.prev_axis = r_prev_axis; + + const Shape3DSW *A = p_shape_A; + const Shape3DSW *B = p_shape_B; + const Transform *transform_A = &p_transform_A; + const Transform *transform_B = &p_transform_B; + real_t margin_A = p_margin_a; + real_t margin_B = p_margin_b; + + if (type_A > type_B) { + SWAP(A, B); + SWAP(transform_A, transform_B); + SWAP(type_A, type_B); + SWAP(margin_A, margin_B); + callback.swap = !callback.swap; + } + + CollisionFunc collision_func; + if (margin_A != 0.0 || margin_B != 0.0) { + collision_func = collision_table_margin[type_A - 2][type_B - 2]; + + } else { + collision_func = collision_table[type_A - 2][type_B - 2]; + } + ERR_FAIL_COND_V(!collision_func, false); + + collision_func(A, *transform_A, B, *transform_B, &callback, margin_A, margin_B); + + return callback.collided; +} diff --git a/servers/physics_3d/collision_solver_3d_sat.h b/servers/physics_3d/collision_solver_3d_sat.h new file mode 100644 index 0000000000..ed564395ab --- /dev/null +++ b/servers/physics_3d/collision_solver_3d_sat.h @@ -0,0 +1,38 @@ +/*************************************************************************/ +/* collision_solver_sat.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLISION_SOLVER_SAT_H +#define COLLISION_SOLVER_SAT_H + +#include "collision_solver_3d_sw.h" + +bool sat_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false, Vector3 *r_prev_axis = NULL, real_t p_margin_a = 0, real_t p_margin_b = 0); + +#endif // COLLISION_SOLVER_SAT_H diff --git a/servers/physics_3d/collision_solver_3d_sw.cpp b/servers/physics_3d/collision_solver_3d_sw.cpp new file mode 100644 index 0000000000..34ea836cd0 --- /dev/null +++ b/servers/physics_3d/collision_solver_3d_sw.cpp @@ -0,0 +1,372 @@ +/*************************************************************************/ +/* collision_solver_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "collision_solver_3d_sw.h" +#include "collision_solver_3d_sat.h" + +#include "gjk_epa.h" + +#define collision_solver sat_calculate_penetration +//#define collision_solver gjk_epa_calculate_penetration + +bool CollisionSolver3DSW::solve_static_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { + + const PlaneShape3DSW *plane = static_cast(p_shape_A); + if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) + return false; + Plane p = p_transform_A.xform(plane->get_plane()); + + static const int max_supports = 16; + Vector3 supports[max_supports]; + int support_count; + + p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count); + + bool found = false; + + for (int i = 0; i < support_count; i++) { + + supports[i] = p_transform_B.xform(supports[i]); + if (p.distance_to(supports[i]) >= 0) + continue; + found = true; + + Vector3 support_A = p.project(supports[i]); + + if (p_result_callback) { + if (p_swap_result) + p_result_callback(supports[i], support_A, p_userdata); + else + p_result_callback(support_A, supports[i], p_userdata); + } + } + + return found; +} + +bool CollisionSolver3DSW::solve_ray(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result) { + + const RayShape3DSW *ray = static_cast(p_shape_A); + + Vector3 from = p_transform_A.origin; + Vector3 to = from + p_transform_A.basis.get_axis(2) * ray->get_length(); + Vector3 support_A = to; + + Transform ai = p_transform_B.affine_inverse(); + + from = ai.xform(from); + to = ai.xform(to); + + Vector3 p, n; + if (!p_shape_B->intersect_segment(from, to, p, n)) + return false; + + Vector3 support_B = p_transform_B.xform(p); + if (ray->get_slips_on_slope()) { + Vector3 global_n = ai.basis.xform_inv(n).normalized(); + support_B = support_A + (support_B - support_A).length() * global_n; + } + + if (p_result_callback) { + if (p_swap_result) + p_result_callback(support_B, support_A, p_userdata); + else + p_result_callback(support_A, support_B, p_userdata); + } + return true; +} + +struct _ConcaveCollisionInfo { + + const Transform *transform_A; + const Shape3DSW *shape_A; + const Transform *transform_B; + CollisionSolver3DSW::CallbackResult result_callback; + void *userdata; + bool swap_result; + bool collided; + int aabb_tests; + int collisions; + bool tested; + real_t margin_A; + real_t margin_B; + Vector3 close_A, close_B; +}; + +void CollisionSolver3DSW::concave_callback(void *p_userdata, Shape3DSW *p_convex) { + + _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); + cinfo.aabb_tests++; + + bool collided = collision_solver(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, cinfo.result_callback, cinfo.userdata, cinfo.swap_result, NULL, cinfo.margin_A, cinfo.margin_B); + if (!collided) + return; + + cinfo.collided = true; + cinfo.collisions++; +} + +bool CollisionSolver3DSW::solve_concave(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A, real_t p_margin_B) { + + const ConcaveShape3DSW *concave_B = static_cast(p_shape_B); + + _ConcaveCollisionInfo cinfo; + cinfo.transform_A = &p_transform_A; + cinfo.shape_A = p_shape_A; + cinfo.transform_B = &p_transform_B; + cinfo.result_callback = p_result_callback; + cinfo.userdata = p_userdata; + cinfo.swap_result = p_swap_result; + cinfo.collided = false; + cinfo.collisions = 0; + cinfo.margin_A = p_margin_A; + cinfo.margin_B = p_margin_B; + + cinfo.aabb_tests = 0; + + Transform rel_transform = p_transform_A; + rel_transform.origin -= p_transform_B.origin; + + //quickly compute a local AABB + + AABB local_aabb; + for (int i = 0; i < 3; i++) { + + Vector3 axis(p_transform_B.basis.get_axis(i)); + real_t axis_scale = 1.0 / axis.length(); + axis *= axis_scale; + + real_t smin, smax; + p_shape_A->project_range(axis, rel_transform, smin, smax); + smin -= p_margin_A; + smax += p_margin_A; + smin *= axis_scale; + smax *= axis_scale; + + local_aabb.position[i] = smin; + local_aabb.size[i] = smax - smin; + } + + concave_B->cull(local_aabb, concave_callback, &cinfo); + + return cinfo.collided; +} + +bool CollisionSolver3DSW::solve_static(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis, real_t p_margin_A, real_t p_margin_B) { + + PhysicsServer3D::ShapeType type_A = p_shape_A->get_type(); + PhysicsServer3D::ShapeType type_B = p_shape_B->get_type(); + bool concave_A = p_shape_A->is_concave(); + bool concave_B = p_shape_B->is_concave(); + + bool swap = false; + + if (type_A > type_B) { + SWAP(type_A, type_B); + SWAP(concave_A, concave_B); + swap = true; + } + + if (type_A == PhysicsServer3D::SHAPE_PLANE) { + + if (type_B == PhysicsServer3D::SHAPE_PLANE) + return false; + if (type_B == PhysicsServer3D::SHAPE_RAY) { + return false; + } + + if (swap) { + return solve_static_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + } else { + return solve_static_plane(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + } + + } else if (type_A == PhysicsServer3D::SHAPE_RAY) { + + if (type_B == PhysicsServer3D::SHAPE_RAY) + return false; + + if (swap) { + return solve_ray(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true); + } else { + return solve_ray(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false); + } + + } else if (concave_B) { + + if (concave_A) + return false; + + if (!swap) + return solve_concave(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, p_margin_A, p_margin_B); + else + return solve_concave(p_shape_B, p_transform_B, p_shape_A, p_transform_A, p_result_callback, p_userdata, true, p_margin_A, p_margin_B); + + } else { + + return collision_solver(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_result_callback, p_userdata, false, r_sep_axis, p_margin_A, p_margin_B); + } +} + +void CollisionSolver3DSW::concave_distance_callback(void *p_userdata, Shape3DSW *p_convex) { + + _ConcaveCollisionInfo &cinfo = *(_ConcaveCollisionInfo *)(p_userdata); + cinfo.aabb_tests++; + if (cinfo.collided) + return; + + Vector3 close_A, close_B; + cinfo.collided = !gjk_epa_calculate_distance(cinfo.shape_A, *cinfo.transform_A, p_convex, *cinfo.transform_B, close_A, close_B); + + if (cinfo.collided) + return; + if (!cinfo.tested || close_A.distance_squared_to(close_B) < cinfo.close_A.distance_squared_to(cinfo.close_B)) { + + cinfo.close_A = close_A; + cinfo.close_B = close_B; + cinfo.tested = true; + } + + cinfo.collisions++; +} + +bool CollisionSolver3DSW::solve_distance_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B) { + + const PlaneShape3DSW *plane = static_cast(p_shape_A); + if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) + return false; + Plane p = p_transform_A.xform(plane->get_plane()); + + static const int max_supports = 16; + Vector3 supports[max_supports]; + int support_count; + + p_shape_B->get_supports(p_transform_B.basis.xform_inv(-p.normal).normalized(), max_supports, supports, support_count); + + bool collided = false; + Vector3 closest; + real_t closest_d = 0; + + for (int i = 0; i < support_count; i++) { + + supports[i] = p_transform_B.xform(supports[i]); + real_t d = p.distance_to(supports[i]); + if (i == 0 || d < closest_d) { + closest = supports[i]; + closest_d = d; + if (d <= 0) + collided = true; + } + } + + r_point_A = p.project(closest); + r_point_B = closest; + + return collided; +} + +bool CollisionSolver3DSW::solve_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis) { + + if (p_shape_A->is_concave()) + return false; + + if (p_shape_B->get_type() == PhysicsServer3D::SHAPE_PLANE) { + + Vector3 a, b; + bool col = solve_distance_plane(p_shape_B, p_transform_B, p_shape_A, p_transform_A, a, b); + r_point_A = b; + r_point_B = a; + return !col; + + } else if (p_shape_B->is_concave()) { + + if (p_shape_A->is_concave()) + return false; + + const ConcaveShape3DSW *concave_B = static_cast(p_shape_B); + + _ConcaveCollisionInfo cinfo; + cinfo.transform_A = &p_transform_A; + cinfo.shape_A = p_shape_A; + cinfo.transform_B = &p_transform_B; + cinfo.result_callback = NULL; + cinfo.userdata = NULL; + cinfo.swap_result = false; + cinfo.collided = false; + cinfo.collisions = 0; + cinfo.aabb_tests = 0; + cinfo.tested = false; + + Transform rel_transform = p_transform_A; + rel_transform.origin -= p_transform_B.origin; + + //quickly compute a local AABB + + bool use_cc_hint = p_concave_hint != AABB(); + AABB cc_hint_aabb; + if (use_cc_hint) { + cc_hint_aabb = p_concave_hint; + cc_hint_aabb.position -= p_transform_B.origin; + } + + AABB local_aabb; + for (int i = 0; i < 3; i++) { + + Vector3 axis(p_transform_B.basis.get_axis(i)); + real_t axis_scale = ((real_t)1.0) / axis.length(); + axis *= axis_scale; + + real_t smin, smax; + + if (use_cc_hint) { + cc_hint_aabb.project_range_in_plane(Plane(axis, 0), smin, smax); + } else { + p_shape_A->project_range(axis, rel_transform, smin, smax); + } + + smin *= axis_scale; + smax *= axis_scale; + + local_aabb.position[i] = smin; + local_aabb.size[i] = smax - smin; + } + + concave_B->cull(local_aabb, concave_distance_callback, &cinfo); + if (!cinfo.collided) { + r_point_A = cinfo.close_A; + r_point_B = cinfo.close_B; + } + + return !cinfo.collided; + } else { + + return gjk_epa_calculate_distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, r_point_A, r_point_B); //should pass sepaxis.. + } +} diff --git a/servers/physics_3d/collision_solver_3d_sw.h b/servers/physics_3d/collision_solver_3d_sw.h new file mode 100644 index 0000000000..5f60d94e7f --- /dev/null +++ b/servers/physics_3d/collision_solver_3d_sw.h @@ -0,0 +1,53 @@ +/*************************************************************************/ +/* collision_solver_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef COLLISION_SOLVER_SW_H +#define COLLISION_SOLVER_SW_H + +#include "shape_3d_sw.h" + +class CollisionSolver3DSW { +public: + typedef void (*CallbackResult)(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); + +private: + static void concave_callback(void *p_userdata, Shape3DSW *p_convex); + static bool solve_static_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_ray(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result); + static bool solve_concave(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, bool p_swap_result, real_t p_margin_A = 0, real_t p_margin_B = 0); + static void concave_distance_callback(void *p_userdata, Shape3DSW *p_convex); + static bool solve_distance_plane(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B); + +public: + static bool solve_static(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CallbackResult p_result_callback, void *p_userdata, Vector3 *r_sep_axis = NULL, real_t p_margin_A = 0, real_t p_margin_B = 0); + static bool solve_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_point_A, Vector3 &r_point_B, const AABB &p_concave_hint, Vector3 *r_sep_axis = NULL); +}; + +#endif // COLLISION_SOLVER__SW_H diff --git a/servers/physics_3d/constraint_3d_sw.h b/servers/physics_3d/constraint_3d_sw.h new file mode 100644 index 0000000000..23bc5d3b32 --- /dev/null +++ b/servers/physics_3d/constraint_3d_sw.h @@ -0,0 +1,85 @@ +/*************************************************************************/ +/* constraint_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef CONSTRAINT_SW_H +#define CONSTRAINT_SW_H + +#include "body_3d_sw.h" + +class Constraint3DSW { + + Body3DSW **_body_ptr; + int _body_count; + uint64_t island_step; + Constraint3DSW *island_next; + Constraint3DSW *island_list_next; + int priority; + bool disabled_collisions_between_bodies; + + RID self; + +protected: + Constraint3DSW(Body3DSW **p_body_ptr = NULL, int p_body_count = 0) { + _body_ptr = p_body_ptr; + _body_count = p_body_count; + island_step = 0; + priority = 1; + disabled_collisions_between_bodies = true; + } + +public: + _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } + _FORCE_INLINE_ RID get_self() const { return self; } + + _FORCE_INLINE_ uint64_t get_island_step() const { return island_step; } + _FORCE_INLINE_ void set_island_step(uint64_t p_step) { island_step = p_step; } + + _FORCE_INLINE_ Constraint3DSW *get_island_next() const { return island_next; } + _FORCE_INLINE_ void set_island_next(Constraint3DSW *p_next) { island_next = p_next; } + + _FORCE_INLINE_ Constraint3DSW *get_island_list_next() const { return island_list_next; } + _FORCE_INLINE_ void set_island_list_next(Constraint3DSW *p_next) { island_list_next = p_next; } + + _FORCE_INLINE_ Body3DSW **get_body_ptr() const { return _body_ptr; } + _FORCE_INLINE_ int get_body_count() const { return _body_count; } + + _FORCE_INLINE_ void set_priority(int p_priority) { priority = p_priority; } + _FORCE_INLINE_ int get_priority() const { return priority; } + + _FORCE_INLINE_ void disable_collisions_between_bodies(const bool p_disabled) { disabled_collisions_between_bodies = p_disabled; } + _FORCE_INLINE_ bool is_disabled_collisions_between_bodies() const { return disabled_collisions_between_bodies; } + + virtual bool setup(real_t p_step) = 0; + virtual void solve(real_t p_step) = 0; + + virtual ~Constraint3DSW() {} +}; + +#endif // CONSTRAINT__SW_H diff --git a/servers/physics_3d/gjk_epa.cpp b/servers/physics_3d/gjk_epa.cpp new file mode 100644 index 0000000000..bd0d429e7b --- /dev/null +++ b/servers/physics_3d/gjk_epa.cpp @@ -0,0 +1,946 @@ +/*************************************************************************/ +/* gjk_epa.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "gjk_epa.h" + +/* Disabling formatting for thirdparty code snippet */ +/* clang-format off */ + +/*************** Bullet's GJK-EPA2 IMPLEMENTATION *******************/ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2008 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the +use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it +freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not +claim that you wrote the original software. If you use this software in a +product, an acknowledgment in the product documentation would be appreciated +but is not required. +2. Altered source versions must be plainly marked as such, and must not be +misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +GJK-EPA collision solver by Nathanael Presson, 2008 +*/ + + // Config + +/* GJK */ +#define GJK_MAX_ITERATIONS 128 +#define GJK_ACCURARY ((real_t)0.0001) +#define GJK_MIN_DISTANCE ((real_t)0.0001) +#define GJK_DUPLICATED_EPS ((real_t)0.0001) +#define GJK_SIMPLEX2_EPS ((real_t)0.0) +#define GJK_SIMPLEX3_EPS ((real_t)0.0) +#define GJK_SIMPLEX4_EPS ((real_t)0.0) + +/* EPA */ +#define EPA_MAX_VERTICES 64 +#define EPA_MAX_FACES (EPA_MAX_VERTICES*2) +#define EPA_MAX_ITERATIONS 255 +#define EPA_ACCURACY ((real_t)0.0001) +#define EPA_FALLBACK (10*EPA_ACCURACY) +#define EPA_PLANE_EPS ((real_t)0.00001) +#define EPA_INSIDE_EPS ((real_t)0.01) + +namespace GjkEpa2 { + + +struct sResults { + enum eStatus { + Separated, /* Shapes doesn't penetrate */ + Penetrating, /* Shapes are penetrating */ + GJK_Failed, /* GJK phase fail, no big issue, shapes are probably just 'touching' */ + EPA_Failed /* EPA phase fail, bigger problem, need to save parameters, and debug */ + } status; + + Vector3 witnesses[2]; + Vector3 normal; + real_t distance; +}; + +// Shorthands +typedef unsigned int U; +typedef unsigned char U1; + +// MinkowskiDiff +struct MinkowskiDiff { + + const Shape3DSW* m_shapes[2]; + + Transform transform_A; + Transform transform_B; + + // i wonder how this could be sped up... if it can + _FORCE_INLINE_ Vector3 Support0 ( const Vector3& d ) const { + return transform_A.xform( m_shapes[0]->get_support( transform_A.basis.xform_inv(d).normalized() ) ); + } + + _FORCE_INLINE_ Vector3 Support1 ( const Vector3& d ) const { + return transform_B.xform( m_shapes[1]->get_support( transform_B.basis.xform_inv(d).normalized() ) ); + } + + _FORCE_INLINE_ Vector3 Support ( const Vector3& d ) const { + return ( Support0 ( d )-Support1 ( -d ) ); + } + + _FORCE_INLINE_ Vector3 Support ( const Vector3& d,U index ) const + { + if ( index ) + return ( Support1 ( d ) ); + else + return ( Support0 ( d ) ); + } +}; + +typedef MinkowskiDiff tShape; + + +// GJK +struct GJK +{ + /* Types */ + struct sSV + { + Vector3 d,w; + }; + struct sSimplex + { + sSV* c[4]; + real_t p[4]; + U rank; + }; + struct eStatus { enum _ { + Valid, + Inside, + Failed };}; + /* Fields */ + tShape m_shape; + Vector3 m_ray; + real_t m_distance; + sSimplex m_simplices[2]; + sSV m_store[4]; + sSV* m_free[4]; + U m_nfree; + U m_current; + sSimplex* m_simplex; + eStatus::_ m_status; + /* Methods */ + GJK() + { + Initialize(); + } + void Initialize() + { + m_ray = Vector3(0,0,0); + m_nfree = 0; + m_status = eStatus::Failed; + m_current = 0; + m_distance = 0; + } + eStatus::_ Evaluate(const tShape& shapearg,const Vector3& guess) + { + U iterations=0; + real_t sqdist=0; + real_t alpha=0; + Vector3 lastw[4]; + U clastw=0; + /* Initialize solver */ + m_free[0] = &m_store[0]; + m_free[1] = &m_store[1]; + m_free[2] = &m_store[2]; + m_free[3] = &m_store[3]; + m_nfree = 4; + m_current = 0; + m_status = eStatus::Valid; + m_shape = shapearg; + m_distance = 0; + /* Initialize simplex */ + m_simplices[0].rank = 0; + m_ray = guess; + const real_t sqrl= m_ray.length_squared(); + appendvertice(m_simplices[0],sqrl>0?-m_ray:Vector3(1,0,0)); + m_simplices[0].p[0] = 1; + m_ray = m_simplices[0].c[0]->w; + sqdist = sqrl; + lastw[0] = + lastw[1] = + lastw[2] = + lastw[3] = m_ray; + /* Loop */ + do { + const U next=1-m_current; + sSimplex& cs=m_simplices[m_current]; + sSimplex& ns=m_simplices[next]; + /* Check zero */ + const real_t rl=m_ray.length(); + if(rlw; + bool found=false; + for(U i=0;i<4;++i) + { + if((w-lastw[i]).length_squared()w, + cs.c[1]->w, + weights,mask);break; + case 3: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + weights,mask);break; + case 4: sqdist=projectorigin( cs.c[0]->w, + cs.c[1]->w, + cs.c[2]->w, + cs.c[3]->w, + weights,mask);break; + } + if(sqdist>=0) + {/* Valid */ + ns.rank = 0; + m_ray = Vector3(0,0,0); + m_current = next; + for(U i=0,ni=cs.rank;iw*weights[i]; + } + else + { + m_free[m_nfree++] = cs.c[i]; + } + } + if(mask==15) m_status=eStatus::Inside; + } + else + {/* Return old simplex */ + removevertice(m_simplices[m_current]); + break; + } + m_status=((++iterations)rank) + { + case 1: + { + for(U i=0;i<3;++i) + { + Vector3 axis=Vector3(0,0,0); + axis[i]=1; + appendvertice(*m_simplex, axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-axis); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 2: + { + const Vector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w; + for(U i=0;i<3;++i) + { + Vector3 axis=Vector3(0,0,0); + axis[i]=1; + const Vector3 p=vec3_cross(d,axis); + if(p.length_squared()>0) + { + appendvertice(*m_simplex, p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-p); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + } + break; + case 3: + { + const Vector3 n=vec3_cross(m_simplex->c[1]->w-m_simplex->c[0]->w, + m_simplex->c[2]->w-m_simplex->c[0]->w); + if(n.length_squared()>0) + { + appendvertice(*m_simplex,n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + appendvertice(*m_simplex,-n); + if(EncloseOrigin()) return(true); + removevertice(*m_simplex); + } + } + break; + case 4: + { + if(Math::abs(det( m_simplex->c[0]->w-m_simplex->c[3]->w, + m_simplex->c[1]->w-m_simplex->c[3]->w, + m_simplex->c[2]->w-m_simplex->c[3]->w))>0) + return(true); + } + break; + } + return(false); + } + /* Internals */ + void getsupport(const Vector3& d,sSV& sv) const + { + sv.d = d/d.length(); + sv.w = m_shape.Support(sv.d); + } + void removevertice(sSimplex& simplex) + { + m_free[m_nfree++]=simplex.c[--simplex.rank]; + } + void appendvertice(sSimplex& simplex,const Vector3& v) + { + simplex.p[simplex.rank]=0; + simplex.c[simplex.rank]=m_free[--m_nfree]; + getsupport(v,*simplex.c[simplex.rank++]); + } + static real_t det(const Vector3& a,const Vector3& b,const Vector3& c) + { + return( a.y*b.z*c.x+a.z*b.x*c.y- + a.x*b.z*c.y-a.y*b.x*c.z+ + a.x*b.y*c.z-a.z*b.y*c.x); + } + static real_t projectorigin( const Vector3& a, + const Vector3& b, + real_t* w,U& m) + { + const Vector3 d=b-a; + const real_t l=d.length_squared(); + if(l>GJK_SIMPLEX2_EPS) + { + const real_t t(l>0?-vec3_dot(a,d)/l:0); + if(t>=1) { w[0]=0;w[1]=1;m=2;return(b.length_squared()); } + else if(t<=0) { w[0]=1;w[1]=0;m=1;return(a.length_squared()); } + else { w[0]=1-(w[1]=t);m=3;return((a+d*t).length_squared()); } + } + return(-1); + } + static real_t projectorigin( const Vector3& a, + const Vector3& b, + const Vector3& c, + real_t* w,U& m) + { + static const U imd3[]={1,2,0}; + const Vector3* vt[]={&a,&b,&c}; + const Vector3 dl[]={a-b,b-c,c-a}; + const Vector3 n=vec3_cross(dl[0],dl[1]); + const real_t l=n.length_squared(); + if(l>GJK_SIMPLEX3_EPS) + { + real_t mindist=-1; + real_t subw[2] = { 0 , 0}; + U subm = 0; + for(U i=0;i<3;++i) + { + if(vec3_dot(*vt[i],vec3_cross(dl[i],n))>0) + { + const U j=imd3[i]; + const real_t subd(projectorigin(*vt[i],*vt[j],subw,subm)); + if((mindist<0)||(subd(((subm&1)?1<GJK_SIMPLEX4_EPS)) + { + real_t mindist=-1; + real_t subw[3]; + U subm=0; + for(U i=0;i<3;++i) + { + const U j=imd3[i]; + const real_t s=vl*vec3_dot(d,vec3_cross(dl[i],dl[j])); + if(s>0) + { + const real_t subd=projectorigin(*vt[i],*vt[j],d,subw,subm); + if((mindist<0)||(subd((subm&1?1<e[ea]=(U1)eb;fa->f[ea]=fb; + fb->e[eb]=(U1)ea;fb->f[eb]=fa; + } + static inline void append(sList& list,sFace* face) + { + face->l[0] = 0; + face->l[1] = list.root; + if(list.root) list.root->l[0]=face; + list.root = face; + ++list.count; + } + static inline void remove(sList& list,sFace* face) + { + if(face->l[1]) face->l[1]->l[0]=face->l[0]; + if(face->l[0]) face->l[0]->l[1]=face->l[1]; + if(face==list.root) list.root=face->l[1]; + --list.count; + } + + + void Initialize() + { + m_status = eStatus::Failed; + m_normal = Vector3(0,0,0); + m_depth = 0; + m_nextsv = 0; + for(U i=0;i1)&&gjk.EncloseOrigin()) + { + + /* Clean up */ + while(m_hull.root) + { + sFace* f = m_hull.root; + remove(m_hull,f); + append(m_stock,f); + } + m_status = eStatus::Valid; + m_nextsv = 0; + /* Orient simplex */ + if(gjk.det( simplex.c[0]->w-simplex.c[3]->w, + simplex.c[1]->w-simplex.c[3]->w, + simplex.c[2]->w-simplex.c[3]->w)<0) + { + SWAP(simplex.c[0],simplex.c[1]); + SWAP(simplex.p[0],simplex.p[1]); + } + /* Build initial hull */ + sFace* tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true), + newface(simplex.c[1],simplex.c[0],simplex.c[3],true), + newface(simplex.c[2],simplex.c[1],simplex.c[3],true), + newface(simplex.c[0],simplex.c[2],simplex.c[3],true)}; + if(m_hull.count==4) + { + sFace* best=findbest(); + sFace outer=*best; + U pass=0; + U iterations=0; + bind(tetra[0],0,tetra[1],0); + bind(tetra[0],1,tetra[2],0); + bind(tetra[0],2,tetra[3],0); + bind(tetra[1],1,tetra[3],2); + bind(tetra[1],2,tetra[2],1); + bind(tetra[2],2,tetra[3],1); + m_status=eStatus::Valid; + for(;iterationspass = (U1)(++pass); + gjk.getsupport(best->n,*w); + const real_t wdist=vec3_dot(best->n,w->w)-best->d; + if(wdist>EPA_ACCURACY) + { + for(U j=0;(j<3)&&valid;++j) + { + valid&=expand( pass,w, + best->f[j],best->e[j], + horizon); + } + if(valid&&(horizon.nf>=3)) + { + bind(horizon.cf,1,horizon.ff,2); + remove(m_hull,best); + append(m_stock,best); + best=findbest(); + if(best->p>=outer.p) outer=*best; + } else { m_status=eStatus::InvalidHull;break; } + } else { m_status=eStatus::AccuraryReached;break; } + } else { m_status=eStatus::OutOfVertices;break; } + } + const Vector3 projection=outer.n*outer.d; + m_normal = outer.n; + m_depth = outer.d; + m_result.rank = 3; + m_result.c[0] = outer.c[0]; + m_result.c[1] = outer.c[1]; + m_result.c[2] = outer.c[2]; + m_result.p[0] = vec3_cross( outer.c[1]->w-projection, + outer.c[2]->w-projection).length(); + m_result.p[1] = vec3_cross( outer.c[2]->w-projection, + outer.c[0]->w-projection).length(); + m_result.p[2] = vec3_cross( outer.c[0]->w-projection, + outer.c[1]->w-projection).length(); + const real_t sum=m_result.p[0]+m_result.p[1]+m_result.p[2]; + m_result.p[0] /= sum; + m_result.p[1] /= sum; + m_result.p[2] /= sum; + return(m_status); + } + } + /* Fallback */ + m_status = eStatus::FallBack; + m_normal = -guess; + const real_t nl=m_normal.length(); + if(nl>0) + m_normal = m_normal/nl; + else + m_normal = Vector3(1,0,0); + m_depth = 0; + m_result.rank=1; + m_result.c[0]=simplex.c[0]; + m_result.p[0]=1; + return(m_status); + } + sFace* newface(sSV* a,sSV* b,sSV* c,bool forced) + { + if(m_stock.root) + { + sFace* face=m_stock.root; + remove(m_stock,face); + append(m_hull,face); + face->pass = 0; + face->c[0] = a; + face->c[1] = b; + face->c[2] = c; + face->n = vec3_cross(b->w-a->w,c->w-a->w); + const real_t l=face->n.length(); + const bool v=l>EPA_ACCURACY; + face->p = MIN(MIN( + vec3_dot(a->w,vec3_cross(face->n,a->w-b->w)), + vec3_dot(b->w,vec3_cross(face->n,b->w-c->w))), + vec3_dot(c->w,vec3_cross(face->n,c->w-a->w))) / + (v?l:1); + face->p = face->p>=-EPA_INSIDE_EPS?0:face->p; + if(v) + { + face->d = vec3_dot(a->w,face->n)/l; + face->n /= l; + if(forced||(face->d>=-EPA_PLANE_EPS)) + { + return(face); + } else m_status=eStatus::NonConvex; + } else m_status=eStatus::Degenerated; + remove(m_hull,face); + append(m_stock,face); + return(0); + } + // -- GODOT start -- + //m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces; + m_status=eStatus::OutOfFaces; + // -- GODOT end -- + return(0); + } + sFace* findbest() + { + sFace* minf=m_hull.root; + real_t mind=minf->d*minf->d; + real_t maxp=minf->p; + for(sFace* f=minf->l[1];f;f=f->l[1]) + { + const real_t sqd=f->d*f->d; + if((f->p>=maxp)&&(sqdp; + } + } + return(minf); + } + bool expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon) + { + static const U i1m3[]={1,2,0}; + static const U i2m3[]={2,0,1}; + if(f->pass!=pass) + { + const U e1=i1m3[e]; + if((vec3_dot(f->n,w->w)-f->d)<-EPA_PLANE_EPS) + { + sFace* nf=newface(f->c[e1],f->c[e],w,false); + if(nf) + { + bind(nf,0,f,e); + if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf; + horizon.cf=nf; + ++horizon.nf; + return(true); + } + } + else + { + const U e2=i2m3[e]; + f->pass = (U1)pass; + if( expand(pass,w,f->f[e1],f->e[e1],horizon)&& + expand(pass,w,f->f[e2],f->e[e2],horizon)) + { + remove(m_hull,f); + append(m_stock,f); + return(true); + } + } + } + return(false); + } + + }; + + // + static void Initialize( const Shape3DSW* shape0,const Transform& wtrs0, + const Shape3DSW* shape1,const Transform& wtrs1, + sResults& results, + tShape& shape, + bool withmargins) + { + /* Results */ + results.witnesses[0] = + results.witnesses[1] = Vector3(0,0,0); + results.status = sResults::Separated; + /* Shape */ + shape.m_shapes[0] = shape0; + shape.m_shapes[1] = shape1; + shape.transform_A = wtrs0; + shape.transform_B = wtrs1; + + } + + + +// +// Api +// + +// + +// +bool Distance( const Shape3DSW* shape0, + const Transform& wtrs0, + const Shape3DSW* shape1, + const Transform& wtrs1, + const Vector3& guess, + sResults& results) +{ + tShape shape; + Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess); + if(gjk_status==GJK::eStatus::Valid) + { + Vector3 w0=Vector3(0,0,0); + Vector3 w1=Vector3(0,0,0); + for(U i=0;irank;++i) + { + const real_t p=gjk.m_simplex->p[i]; + w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p; + w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p; + } + results.witnesses[0] = w0; + results.witnesses[1] = w1; + results.normal = w0-w1; + results.distance = results.normal.length(); + results.normal /= results.distance>GJK_MIN_DISTANCE?results.distance:1; + return(true); + } + else + { + results.status = gjk_status==GJK::eStatus::Inside? + sResults::Penetrating : + sResults::GJK_Failed ; + return(false); + } +} + +// +bool Penetration( const Shape3DSW* shape0, + const Transform& wtrs0, + const Shape3DSW* shape1, + const Transform& wtrs1, + const Vector3& guess, + sResults& results + ) +{ + tShape shape; + Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false); + GJK gjk; + GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess); + switch(gjk_status) + { + case GJK::eStatus::Inside: + { + EPA epa; + EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess); + if(epa_status!=EPA::eStatus::Failed) + { + Vector3 w0=Vector3(0,0,0); + for(U i=0;id,0)*epa.m_result.p[i]; + } + results.status = sResults::Penetrating; + results.witnesses[0] = w0; + results.witnesses[1] = w0-epa.m_normal*epa.m_depth; + results.normal = -epa.m_normal; + results.distance = -epa.m_depth; + return(true); + } else results.status=sResults::EPA_Failed; + } + break; + case GJK::eStatus::Failed: + results.status=sResults::GJK_Failed; + break; + default: {} + } + return(false); +} + + +/* Symbols cleanup */ + +#undef GJK_MAX_ITERATIONS +#undef GJK_ACCURARY +#undef GJK_MIN_DISTANCE +#undef GJK_DUPLICATED_EPS +#undef GJK_SIMPLEX2_EPS +#undef GJK_SIMPLEX3_EPS +#undef GJK_SIMPLEX4_EPS + +#undef EPA_MAX_VERTICES +#undef EPA_MAX_FACES +#undef EPA_MAX_ITERATIONS +#undef EPA_ACCURACY +#undef EPA_FALLBACK +#undef EPA_PLANE_EPS +#undef EPA_INSIDE_EPS + + +} // end of namespace + +/* clang-format on */ + +bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B) { + + GjkEpa2::sResults res; + + if (GjkEpa2::Distance(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) { + + r_result_A = res.witnesses[0]; + r_result_B = res.witnesses[1]; + return true; + } + + return false; +} + +bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap) { + + GjkEpa2::sResults res; + + if (GjkEpa2::Penetration(p_shape_A, p_transform_A, p_shape_B, p_transform_B, p_transform_B.origin - p_transform_A.origin, res)) { + if (p_result_callback) { + if (p_swap) + p_result_callback(res.witnesses[1], res.witnesses[0], p_userdata); + else + p_result_callback(res.witnesses[0], res.witnesses[1], p_userdata); + } + return true; + } + + return false; +} diff --git a/servers/physics_3d/gjk_epa.h b/servers/physics_3d/gjk_epa.h new file mode 100644 index 0000000000..dec0f269e1 --- /dev/null +++ b/servers/physics_3d/gjk_epa.h @@ -0,0 +1,40 @@ +/*************************************************************************/ +/* gjk_epa.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef GJK_EPA_H +#define GJK_EPA_H + +#include "collision_solver_3d_sw.h" +#include "shape_3d_sw.h" + +bool gjk_epa_calculate_penetration(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, CollisionSolver3DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap = false); +bool gjk_epa_calculate_distance(const Shape3DSW *p_shape_A, const Transform &p_transform_A, const Shape3DSW *p_shape_B, const Transform &p_transform_B, Vector3 &r_result_A, Vector3 &r_result_B); + +#endif diff --git a/servers/physics_3d/joints/SCsub b/servers/physics_3d/joints/SCsub new file mode 100644 index 0000000000..d730144861 --- /dev/null +++ b/servers/physics_3d/joints/SCsub @@ -0,0 +1,5 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.servers_sources, "*.cpp") diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp new file mode 100644 index 0000000000..782e8322fe --- /dev/null +++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.cpp @@ -0,0 +1,366 @@ +/*************************************************************************/ +/* cone_twist_joint_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +/* +Bullet Continuous Collision Detection and Physics Library +ConeTwistJointSW is Copyright (c) 2007 Starbreeze Studios + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Written by: Marcus Hennix +*/ + +#include "cone_twist_joint_3d_sw.h" + +static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { + + if (Math::abs(n.z) > Math_SQRT12) { + // choose p in y-z plane + real_t a = n[1] * n[1] + n[2] * n[2]; + real_t k = 1.0 / Math::sqrt(a); + p = Vector3(0, -n[2] * k, n[1] * k); + // set q = n x p + q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); + } else { + // choose p in x-y plane + real_t a = n.x * n.x + n.y * n.y; + real_t k = 1.0 / Math::sqrt(a); + p = Vector3(-n.y * k, n.x * k, 0); + // set q = n x p + q = Vector3(-n.z * p.y, n.z * p.x, a * k); + } +} + +static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { + real_t coeff_1 = Math_PI / 4.0f; + real_t coeff_2 = 3.0f * coeff_1; + real_t abs_y = Math::abs(y); + real_t angle; + if (x >= 0.0f) { + real_t r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + real_t r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; +} + +ConeTwistJoint3DSW::ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &rbAFrame, const Transform &rbBFrame) : + Joint3DSW(_arr, 2) { + + A = rbA; + B = rbB; + + m_rbAFrame = rbAFrame; + m_rbBFrame = rbBFrame; + + m_swingSpan1 = Math_PI / 4.0; + m_swingSpan2 = Math_PI / 4.0; + m_twistSpan = Math_PI * 2; + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + + m_angularOnly = false; + m_solveTwistLimit = false; + m_solveSwingLimit = false; + + A->add_constraint(this, 0); + B->add_constraint(this, 1); + + m_appliedImpulse = 0; +} + +bool ConeTwistJoint3DSW::setup(real_t p_timestep) { + m_appliedImpulse = real_t(0.); + + //set bias, sign, clear accumulator + m_swingCorrection = real_t(0.); + m_twistLimitSign = real_t(0.); + m_solveTwistLimit = false; + m_solveSwingLimit = false; + m_accTwistLimitImpulse = real_t(0.); + m_accSwingLimitImpulse = real_t(0.); + + if (!m_angularOnly) { + Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); + Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); + Vector3 relPos = pivotBInW - pivotAInW; + + Vector3 normal[3]; + if (Math::is_zero_approx(relPos.length_squared())) { + normal[0] = Vector3(real_t(1.0), 0, 0); + } else { + normal[0] = relPos.normalized(); + } + + plane_space(normal[0], normal[1], normal[2]); + + for (int i = 0; i < 3; i++) { + memnew_placement(&m_jac[i], JacobianEntry3DSW( + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + pivotAInW - A->get_transform().origin - A->get_center_of_mass(), + pivotBInW - B->get_transform().origin - B->get_center_of_mass(), + normal[i], + A->get_inv_inertia(), + A->get_inv_mass(), + B->get_inv_inertia(), + B->get_inv_mass())); + } + } + + Vector3 b1Axis1, b1Axis2, b1Axis3; + Vector3 b2Axis1, b2Axis2; + + b1Axis1 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(0)); + b2Axis1 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(0)); + + real_t swing1 = real_t(0.), swing2 = real_t(0.); + + real_t swx = real_t(0.), swy = real_t(0.); + real_t thresh = real_t(10.); + real_t fact; + + // Get Frame into world space + if (m_swingSpan1 >= real_t(0.05f)) { + b1Axis2 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(1)); + //swing1 = btAtan2Fast( b2Axis1.dot(b1Axis2),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis2); + swing1 = atan2fast(swy, swx); + fact = (swy * swy + swx * swx) * thresh * thresh; + fact = fact / (fact + real_t(1.0)); + swing1 *= fact; + } + + if (m_swingSpan2 >= real_t(0.05f)) { + b1Axis3 = A->get_transform().basis.xform(this->m_rbAFrame.basis.get_axis(2)); + //swing2 = btAtan2Fast( b2Axis1.dot(b1Axis3),b2Axis1.dot(b1Axis1) ); + swx = b2Axis1.dot(b1Axis1); + swy = b2Axis1.dot(b1Axis3); + swing2 = atan2fast(swy, swx); + fact = (swy * swy + swx * swx) * thresh * thresh; + fact = fact / (fact + real_t(1.0)); + swing2 *= fact; + } + + real_t RMaxAngle1Sq = 1.0f / (m_swingSpan1 * m_swingSpan1); + real_t RMaxAngle2Sq = 1.0f / (m_swingSpan2 * m_swingSpan2); + real_t EllipseAngle = Math::abs(swing1 * swing1) * RMaxAngle1Sq + Math::abs(swing2 * swing2) * RMaxAngle2Sq; + + if (EllipseAngle > 1.0f) { + m_swingCorrection = EllipseAngle - 1.0f; + m_solveSwingLimit = true; + + // Calculate necessary axis & factors + m_swingAxis = b2Axis1.cross(b1Axis2 * b2Axis1.dot(b1Axis2) + b1Axis3 * b2Axis1.dot(b1Axis3)); + m_swingAxis.normalize(); + + real_t swingAxisSign = (b2Axis1.dot(b1Axis1) >= 0.0f) ? 1.0f : -1.0f; + m_swingAxis *= swingAxisSign; + + m_kSwing = real_t(1.) / (A->compute_angular_impulse_denominator(m_swingAxis) + + B->compute_angular_impulse_denominator(m_swingAxis)); + } + + // Twist limits + if (m_twistSpan >= real_t(0.)) { + Vector3 b2Axis22 = B->get_transform().basis.xform(this->m_rbBFrame.basis.get_axis(1)); + Quat rotationArc = Quat(b2Axis1, b1Axis1); + Vector3 TwistRef = rotationArc.xform(b2Axis22); + real_t twist = atan2fast(TwistRef.dot(b1Axis3), TwistRef.dot(b1Axis2)); + + real_t lockedFreeFactor = (m_twistSpan > real_t(0.05f)) ? m_limitSoftness : real_t(0.); + if (twist <= -m_twistSpan * lockedFreeFactor) { + m_twistCorrection = -(twist + m_twistSpan); + m_solveTwistLimit = true; + + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + m_twistAxis *= -1.0f; + + m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) + + B->compute_angular_impulse_denominator(m_twistAxis)); + + } else if (twist > m_twistSpan * lockedFreeFactor) { + m_twistCorrection = (twist - m_twistSpan); + m_solveTwistLimit = true; + + m_twistAxis = (b2Axis1 + b1Axis1) * 0.5f; + m_twistAxis.normalize(); + + m_kTwist = real_t(1.) / (A->compute_angular_impulse_denominator(m_twistAxis) + + B->compute_angular_impulse_denominator(m_twistAxis)); + } + } + + return true; +} + +void ConeTwistJoint3DSW::solve(real_t p_timestep) { + + Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); + Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); + + real_t tau = real_t(0.3); + + //linear part + if (!m_angularOnly) { + Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; + Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; + + Vector3 vel1 = A->get_velocity_in_local_point(rel_pos1); + Vector3 vel2 = B->get_velocity_in_local_point(rel_pos2); + Vector3 vel = vel1 - vel2; + + for (int i = 0; i < 3; i++) { + const Vector3 &normal = m_jac[i].m_linearJointAxis; + real_t jacDiagABInv = real_t(1.) / m_jac[i].getDiagonal(); + + real_t rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + real_t depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + real_t impulse = depth * tau / p_timestep * jacDiagABInv - rel_vel * jacDiagABInv; + m_appliedImpulse += impulse; + Vector3 impulse_vector = normal * impulse; + A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); + B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); + } + } + + { + ///solve angular part + const Vector3 &angVelA = A->get_angular_velocity(); + const Vector3 &angVelB = B->get_angular_velocity(); + + // solve swing limit + if (m_solveSwingLimit) { + real_t amplitude = ((angVelB - angVelA).dot(m_swingAxis) * m_relaxationFactor * m_relaxationFactor + m_swingCorrection * (real_t(1.) / p_timestep) * m_biasFactor); + real_t impulseMag = amplitude * m_kSwing; + + // Clamp the accumulated impulse + real_t temp = m_accSwingLimitImpulse; + m_accSwingLimitImpulse = MAX(m_accSwingLimitImpulse + impulseMag, real_t(0.0)); + impulseMag = m_accSwingLimitImpulse - temp; + + Vector3 impulse = m_swingAxis * impulseMag; + + A->apply_torque_impulse(impulse); + B->apply_torque_impulse(-impulse); + } + + // solve twist limit + if (m_solveTwistLimit) { + real_t amplitude = ((angVelB - angVelA).dot(m_twistAxis) * m_relaxationFactor * m_relaxationFactor + m_twistCorrection * (real_t(1.) / p_timestep) * m_biasFactor); + real_t impulseMag = amplitude * m_kTwist; + + // Clamp the accumulated impulse + real_t temp = m_accTwistLimitImpulse; + m_accTwistLimitImpulse = MAX(m_accTwistLimitImpulse + impulseMag, real_t(0.0)); + impulseMag = m_accTwistLimitImpulse - temp; + + Vector3 impulse = m_twistAxis * impulseMag; + + A->apply_torque_impulse(impulse); + B->apply_torque_impulse(-impulse); + } + } +} + +void ConeTwistJoint3DSW::set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value) { + + switch (p_param) { + case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: { + + m_swingSpan1 = p_value; + m_swingSpan2 = p_value; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN: { + + m_twistSpan = p_value; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_BIAS: { + + m_biasFactor = p_value; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS: { + + m_limitSoftness = p_value; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION: { + + m_relaxationFactor = p_value; + } break; + case PhysicsServer3D::CONE_TWIST_MAX: break; // Can't happen, but silences warning + } +} + +real_t ConeTwistJoint3DSW::get_param(PhysicsServer3D::ConeTwistJointParam p_param) const { + + switch (p_param) { + case PhysicsServer3D::CONE_TWIST_JOINT_SWING_SPAN: { + + return m_swingSpan1; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_TWIST_SPAN: { + + return m_twistSpan; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_BIAS: { + + return m_biasFactor; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_SOFTNESS: { + + return m_limitSoftness; + } break; + case PhysicsServer3D::CONE_TWIST_JOINT_RELAXATION: { + + return m_relaxationFactor; + } break; + case PhysicsServer3D::CONE_TWIST_MAX: break; // Can't happen, but silences warning + } + + return 0; +} diff --git a/servers/physics_3d/joints/cone_twist_joint_3d_sw.h b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h new file mode 100644 index 0000000000..5521419e89 --- /dev/null +++ b/servers/physics_3d/joints/cone_twist_joint_3d_sw.h @@ -0,0 +1,142 @@ +/*************************************************************************/ +/* cone_twist_joint_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +/* +Bullet Continuous Collision Detection and Physics Library +ConeTwistJointSW is Copyright (c) 2007 Starbreeze Studios + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. + +Written by: Marcus Hennix +*/ + +#ifndef CONE_TWIST_JOINT_SW_H +#define CONE_TWIST_JOINT_SW_H + +#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" +#include "servers/physics_3d/joints_3d_sw.h" + +///ConeTwistJointSW can be used to simulate ragdoll joints (upper arm, leg etc) +class ConeTwistJoint3DSW : public Joint3DSW { +#ifdef IN_PARALLELL_SOLVER +public: +#endif + + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints + + real_t m_appliedImpulse; + Transform m_rbAFrame; + Transform m_rbBFrame; + + real_t m_limitSoftness; + real_t m_biasFactor; + real_t m_relaxationFactor; + + real_t m_swingSpan1; + real_t m_swingSpan2; + real_t m_twistSpan; + + Vector3 m_swingAxis; + Vector3 m_twistAxis; + + real_t m_kSwing; + real_t m_kTwist; + + real_t m_twistLimitSign; + real_t m_swingCorrection; + real_t m_twistCorrection; + + real_t m_accSwingLimitImpulse; + real_t m_accTwistLimitImpulse; + + bool m_angularOnly; + bool m_solveTwistLimit; + bool m_solveSwingLimit; + +public: + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_CONE_TWIST; } + + virtual bool setup(real_t p_timestep); + virtual void solve(real_t p_timestep); + + ConeTwistJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &rbAFrame, const Transform &rbBFrame); + + void setAngularOnly(bool angularOnly) { + m_angularOnly = angularOnly; + } + + void setLimit(real_t _swingSpan1, real_t _swingSpan2, real_t _twistSpan, real_t _softness = 0.8f, real_t _biasFactor = 0.3f, real_t _relaxationFactor = 1.0f) { + m_swingSpan1 = _swingSpan1; + m_swingSpan2 = _swingSpan2; + m_twistSpan = _twistSpan; + + m_limitSoftness = _softness; + m_biasFactor = _biasFactor; + m_relaxationFactor = _relaxationFactor; + } + + inline int getSolveTwistLimit() { + return m_solveTwistLimit; + } + + inline int getSolveSwingLimit() { + return m_solveTwistLimit; + } + + inline real_t getTwistLimitSign() { + return m_twistLimitSign; + } + + void set_param(PhysicsServer3D::ConeTwistJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::ConeTwistJointParam p_param) const; +}; + +#endif // CONE_TWIST_JOINT_SW_H diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp new file mode 100644 index 0000000000..d28fafdb00 --- /dev/null +++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.cpp @@ -0,0 +1,686 @@ +/*************************************************************************/ +/* generic_6dof_joint_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +2007-09-09 +Generic6DOFJointSW Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + +#include "generic_6dof_joint_3d_sw.h" + +#define GENERIC_D6_DISABLE_WARMSTARTING 1 + +//////////////////////////// G6DOFRotationalLimitMotorSW //////////////////////////////////// + +int G6DOFRotationalLimitMotor3DSW::testLimitValue(real_t test_value) { + if (m_loLimit > m_hiLimit) { + m_currentLimit = 0; //Free from violation + return 0; + } + + if (test_value < m_loLimit) { + m_currentLimit = 1; //low limit violation + m_currentLimitError = test_value - m_loLimit; + return 1; + } else if (test_value > m_hiLimit) { + m_currentLimit = 2; //High limit violation + m_currentLimitError = test_value - m_hiLimit; + return 2; + }; + + m_currentLimit = 0; //Free from violation + return 0; +} + +real_t G6DOFRotationalLimitMotor3DSW::solveAngularLimits( + real_t timeStep, Vector3 &axis, real_t jacDiagABInv, + Body3DSW *body0, Body3DSW *body1) { + if (!needApplyTorques()) return 0.0f; + + real_t target_velocity = m_targetVelocity; + real_t maxMotorForce = m_maxMotorForce; + + //current error correction + if (m_currentLimit != 0) { + target_velocity = -m_ERP * m_currentLimitError / (timeStep); + maxMotorForce = m_maxLimitForce; + } + + maxMotorForce *= timeStep; + + // current velocity difference + Vector3 vel_diff = body0->get_angular_velocity(); + if (body1) { + vel_diff -= body1->get_angular_velocity(); + } + + real_t rel_vel = axis.dot(vel_diff); + + // correction velocity + real_t motor_relvel = m_limitSoftness * (target_velocity - m_damping * rel_vel); + + if (Math::is_zero_approx(motor_relvel)) { + return 0.0f; //no need for applying force + } + + // correction impulse + real_t unclippedMotorImpulse = (1 + m_bounce) * motor_relvel * jacDiagABInv; + + // clip correction impulse + real_t clippedMotorImpulse; + + ///@todo: should clip against accumulated impulse + if (unclippedMotorImpulse > 0.0f) { + clippedMotorImpulse = unclippedMotorImpulse > maxMotorForce ? maxMotorForce : unclippedMotorImpulse; + } else { + clippedMotorImpulse = unclippedMotorImpulse < -maxMotorForce ? -maxMotorForce : unclippedMotorImpulse; + } + + // sort with accumulated impulses + real_t lo = real_t(-1e30); + real_t hi = real_t(1e30); + + real_t oldaccumImpulse = m_accumulatedImpulse; + real_t sum = oldaccumImpulse + clippedMotorImpulse; + m_accumulatedImpulse = sum > hi ? real_t(0.) : sum < lo ? real_t(0.) : sum; + + clippedMotorImpulse = m_accumulatedImpulse - oldaccumImpulse; + + Vector3 motorImp = clippedMotorImpulse * axis; + + body0->apply_torque_impulse(motorImp); + if (body1) body1->apply_torque_impulse(-motorImp); + + return clippedMotorImpulse; +} + +//////////////////////////// End G6DOFRotationalLimitMotorSW //////////////////////////////////// + +//////////////////////////// G6DOFTranslationalLimitMotorSW //////////////////////////////////// +real_t G6DOFTranslationalLimitMotor3DSW::solveLinearAxis( + real_t timeStep, + real_t jacDiagABInv, + Body3DSW *body1, const Vector3 &pointInA, + Body3DSW *body2, const Vector3 &pointInB, + int limit_index, + const Vector3 &axis_normal_on_a, + const Vector3 &anchorPos) { + + ///find relative velocity + // Vector3 rel_pos1 = pointInA - body1->get_transform().origin; + // Vector3 rel_pos2 = pointInB - body2->get_transform().origin; + Vector3 rel_pos1 = anchorPos - body1->get_transform().origin; + Vector3 rel_pos2 = anchorPos - body2->get_transform().origin; + + Vector3 vel1 = body1->get_velocity_in_local_point(rel_pos1); + Vector3 vel2 = body2->get_velocity_in_local_point(rel_pos2); + Vector3 vel = vel1 - vel2; + + real_t rel_vel = axis_normal_on_a.dot(vel); + + /// apply displacement correction + + //positional error (zeroth order error) + real_t depth = -(pointInA - pointInB).dot(axis_normal_on_a); + real_t lo = real_t(-1e30); + real_t hi = real_t(1e30); + + real_t minLimit = m_lowerLimit[limit_index]; + real_t maxLimit = m_upperLimit[limit_index]; + + //handle the limits + if (minLimit < maxLimit) { + { + if (depth > maxLimit) { + depth -= maxLimit; + lo = real_t(0.); + + } else { + if (depth < minLimit) { + depth -= minLimit; + hi = real_t(0.); + } else { + return 0.0f; + } + } + } + } + + real_t normalImpulse = m_limitSoftness[limit_index] * (m_restitution[limit_index] * depth / timeStep - m_damping[limit_index] * rel_vel) * jacDiagABInv; + + real_t oldNormalImpulse = m_accumulatedImpulse[limit_index]; + real_t sum = oldNormalImpulse + normalImpulse; + m_accumulatedImpulse[limit_index] = sum > hi ? real_t(0.) : sum < lo ? real_t(0.) : sum; + normalImpulse = m_accumulatedImpulse[limit_index] - oldNormalImpulse; + + Vector3 impulse_vector = axis_normal_on_a * normalImpulse; + body1->apply_impulse(rel_pos1, impulse_vector); + body2->apply_impulse(rel_pos2, -impulse_vector); + return normalImpulse; +} + +//////////////////////////// G6DOFTranslationalLimitMotorSW //////////////////////////////////// + +Generic6DOFJoint3DSW::Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA) : + Joint3DSW(_arr, 2), + m_frameInA(frameInA), + m_frameInB(frameInB), + m_useLinearReferenceFrameA(useLinearReferenceFrameA) { + A = rbA; + B = rbB; + A->add_constraint(this, 0); + B->add_constraint(this, 1); +} + +void Generic6DOFJoint3DSW::calculateAngleInfo() { + Basis relative_frame = m_calculatedTransformB.basis.inverse() * m_calculatedTransformA.basis; + + m_calculatedAxisAngleDiff = relative_frame.get_euler_xyz(); + + // in euler angle mode we do not actually constrain the angular velocity + // along the axes axis[0] and axis[2] (although we do use axis[1]) : + // + // to get constrain w2-w1 along ...not + // ------ --------------------- ------ + // d(angle[0])/dt = 0 ax[1] x ax[2] ax[0] + // d(angle[1])/dt = 0 ax[1] + // d(angle[2])/dt = 0 ax[0] x ax[1] ax[2] + // + // constraining w2-w1 along an axis 'a' means that a'*(w2-w1)=0. + // to prove the result for angle[0], write the expression for angle[0] from + // GetInfo1 then take the derivative. to prove this for angle[2] it is + // easier to take the euler rate expression for d(angle[2])/dt with respect + // to the components of w and set that to 0. + + Vector3 axis0 = m_calculatedTransformB.basis.get_axis(0); + Vector3 axis2 = m_calculatedTransformA.basis.get_axis(2); + + m_calculatedAxis[1] = axis2.cross(axis0); + m_calculatedAxis[0] = m_calculatedAxis[1].cross(axis2); + m_calculatedAxis[2] = axis0.cross(m_calculatedAxis[1]); + + /* + if(m_debugDrawer) + { + + char buff[300]; + sprintf(buff,"\n X: %.2f ; Y: %.2f ; Z: %.2f ", + m_calculatedAxisAngleDiff[0], + m_calculatedAxisAngleDiff[1], + m_calculatedAxisAngleDiff[2]); + m_debugDrawer->reportErrorWarning(buff); + } + */ +} + +void Generic6DOFJoint3DSW::calculateTransforms() { + m_calculatedTransformA = A->get_transform() * m_frameInA; + m_calculatedTransformB = B->get_transform() * m_frameInB; + + calculateAngleInfo(); +} + +void Generic6DOFJoint3DSW::buildLinearJacobian( + JacobianEntry3DSW &jacLinear, const Vector3 &normalWorld, + const Vector3 &pivotAInW, const Vector3 &pivotBInW) { + memnew_placement(&jacLinear, JacobianEntry3DSW( + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + pivotAInW - A->get_transform().origin - A->get_center_of_mass(), + pivotBInW - B->get_transform().origin - B->get_center_of_mass(), + normalWorld, + A->get_inv_inertia(), + A->get_inv_mass(), + B->get_inv_inertia(), + B->get_inv_mass())); +} + +void Generic6DOFJoint3DSW::buildAngularJacobian( + JacobianEntry3DSW &jacAngular, const Vector3 &jointAxisW) { + memnew_placement(&jacAngular, JacobianEntry3DSW(jointAxisW, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_inv_inertia(), + B->get_inv_inertia())); +} + +bool Generic6DOFJoint3DSW::testAngularLimitMotor(int axis_index) { + real_t angle = m_calculatedAxisAngleDiff[axis_index]; + + //test limits + m_angularLimits[axis_index].testLimitValue(angle); + return m_angularLimits[axis_index].needApplyTorques(); +} + +bool Generic6DOFJoint3DSW::setup(real_t p_timestep) { + + // Clear accumulated impulses for the next simulation step + m_linearLimits.m_accumulatedImpulse = Vector3(real_t(0.), real_t(0.), real_t(0.)); + int i; + for (i = 0; i < 3; i++) { + m_angularLimits[i].m_accumulatedImpulse = real_t(0.); + } + //calculates transform + calculateTransforms(); + + // const Vector3& pivotAInW = m_calculatedTransformA.origin; + // const Vector3& pivotBInW = m_calculatedTransformB.origin; + calcAnchorPos(); + Vector3 pivotAInW = m_AnchorPos; + Vector3 pivotBInW = m_AnchorPos; + + // not used here + // Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; + // Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; + + Vector3 normalWorld; + //linear part + for (i = 0; i < 3; i++) { + if (m_linearLimits.enable_limit[i] && m_linearLimits.isLimited(i)) { + if (m_useLinearReferenceFrameA) + normalWorld = m_calculatedTransformA.basis.get_axis(i); + else + normalWorld = m_calculatedTransformB.basis.get_axis(i); + + buildLinearJacobian( + m_jacLinear[i], normalWorld, + pivotAInW, pivotBInW); + } + } + + // angular part + for (i = 0; i < 3; i++) { + //calculates error angle + if (m_angularLimits[i].m_enableLimit && testAngularLimitMotor(i)) { + normalWorld = this->getAxis(i); + // Create angular atom + buildAngularJacobian(m_jacAng[i], normalWorld); + } + } + + return true; +} + +void Generic6DOFJoint3DSW::solve(real_t p_timestep) { + m_timeStep = p_timestep; + + //calculateTransforms(); + + int i; + + // linear + + Vector3 pointInA = m_calculatedTransformA.origin; + Vector3 pointInB = m_calculatedTransformB.origin; + + real_t jacDiagABInv; + Vector3 linear_axis; + for (i = 0; i < 3; i++) { + if (m_linearLimits.enable_limit[i] && m_linearLimits.isLimited(i)) { + jacDiagABInv = real_t(1.) / m_jacLinear[i].getDiagonal(); + + if (m_useLinearReferenceFrameA) + linear_axis = m_calculatedTransformA.basis.get_axis(i); + else + linear_axis = m_calculatedTransformB.basis.get_axis(i); + + m_linearLimits.solveLinearAxis( + m_timeStep, + jacDiagABInv, + A, pointInA, + B, pointInB, + i, linear_axis, m_AnchorPos); + } + } + + // angular + Vector3 angular_axis; + real_t angularJacDiagABInv; + for (i = 0; i < 3; i++) { + if (m_angularLimits[i].m_enableLimit && m_angularLimits[i].needApplyTorques()) { + + // get axis + angular_axis = getAxis(i); + + angularJacDiagABInv = real_t(1.) / m_jacAng[i].getDiagonal(); + + m_angularLimits[i].solveAngularLimits(m_timeStep, angular_axis, angularJacDiagABInv, A, B); + } + } +} + +void Generic6DOFJoint3DSW::updateRHS(real_t timeStep) { + (void)timeStep; +} + +Vector3 Generic6DOFJoint3DSW::getAxis(int axis_index) const { + return m_calculatedAxis[axis_index]; +} + +real_t Generic6DOFJoint3DSW::getAngle(int axis_index) const { + return m_calculatedAxisAngleDiff[axis_index]; +} + +void Generic6DOFJoint3DSW::calcAnchorPos(void) { + real_t imA = A->get_inv_mass(); + real_t imB = B->get_inv_mass(); + real_t weight; + if (imB == real_t(0.0)) { + weight = real_t(1.0); + } else { + weight = imA / (imA + imB); + } + const Vector3 &pA = m_calculatedTransformA.origin; + const Vector3 &pB = m_calculatedTransformB.origin; + m_AnchorPos = pA * weight + pB * (real_t(1.0) - weight); +} // Generic6DOFJointSW::calcAnchorPos() + +void Generic6DOFJoint3DSW::set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value) { + + ERR_FAIL_INDEX(p_axis, 3); + switch (p_param) { + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { + + m_linearLimits.m_lowerLimit[p_axis] = p_value; + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: { + + m_linearLimits.m_upperLimit[p_axis] = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: { + + m_linearLimits.m_limitSoftness[p_axis] = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION: { + + m_linearLimits.m_restitution[p_axis] = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING: { + + m_linearLimits.m_damping[p_axis] = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: { + + m_angularLimits[p_axis].m_loLimit = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: { + + m_angularLimits[p_axis].m_hiLimit = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: { + + m_angularLimits[p_axis].m_limitSoftness = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING: { + + m_angularLimits[p_axis].m_damping = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: { + + m_angularLimits[p_axis].m_bounce = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: { + + m_angularLimits[p_axis].m_maxLimitForce = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: { + + m_angularLimits[p_axis].m_ERP = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: { + + m_angularLimits[p_axis].m_targetVelocity = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: { + + m_angularLimits[p_axis].m_maxLimitForce = p_value; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning + } +} + +real_t Generic6DOFJoint3DSW::get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const { + ERR_FAIL_INDEX_V(p_axis, 3, 0); + switch (p_param) { + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LOWER_LIMIT: { + + return m_linearLimits.m_lowerLimit[p_axis]; + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_UPPER_LIMIT: { + + return m_linearLimits.m_upperLimit[p_axis]; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS: { + + return m_linearLimits.m_limitSoftness[p_axis]; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_RESTITUTION: { + + return m_linearLimits.m_restitution[p_axis]; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_DAMPING: { + + return m_linearLimits.m_damping[p_axis]; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LOWER_LIMIT: { + + return m_angularLimits[p_axis].m_loLimit; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_UPPER_LIMIT: { + + return m_angularLimits[p_axis].m_hiLimit; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS: { + + return m_angularLimits[p_axis].m_limitSoftness; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_DAMPING: { + + return m_angularLimits[p_axis].m_damping; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_RESTITUTION: { + + return m_angularLimits[p_axis].m_bounce; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_FORCE_LIMIT: { + + return m_angularLimits[p_axis].m_maxLimitForce; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_ERP: { + + return m_angularLimits[p_axis].m_ERP; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY: { + + return m_angularLimits[p_axis].m_targetVelocity; + + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT: { + + return m_angularLimits[p_axis].m_maxMotorForce; + + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_DAMPING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_MAX: break; // Can't happen, but silences warning + } + return 0; +} + +void Generic6DOFJoint3DSW::set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value) { + + ERR_FAIL_INDEX(p_axis, 3); + + switch (p_flag) { + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: { + + m_linearLimits.enable_limit[p_axis] = p_value; + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: { + + m_angularLimits[p_axis].m_enableLimit = p_value; + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: { + + m_angularLimits[p_axis].m_enableMotor = p_value; + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning + } +} +bool Generic6DOFJoint3DSW::get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const { + + ERR_FAIL_INDEX_V(p_axis, 3, 0); + switch (p_flag) { + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT: { + + return m_linearLimits.enable_limit[p_axis]; + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT: { + + return m_angularLimits[p_axis].m_enableLimit; + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_MOTOR: { + + return m_angularLimits[p_axis].m_enableMotor; + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING: { + // Not implemented in GodotPhysics backend + } break; + case PhysicsServer3D::G6DOF_JOINT_FLAG_MAX: break; // Can't happen, but silences warning + } + + return 0; +} diff --git a/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h new file mode 100644 index 0000000000..ba6e6ffb01 --- /dev/null +++ b/servers/physics_3d/joints/generic_6dof_joint_3d_sw.h @@ -0,0 +1,401 @@ +/*************************************************************************/ +/* generic_6dof_joint_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +#ifndef GENERIC_6DOF_JOINT_SW_H +#define GENERIC_6DOF_JOINT_SW_H + +#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" +#include "servers/physics_3d/joints_3d_sw.h" + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +2007-09-09 +Generic6DOFJointSW Refactored by Francisco Le?n +email: projectileman@yahoo.com +http://gimpact.sf.net +*/ + +//! Rotation Limit structure for generic joints +class G6DOFRotationalLimitMotor3DSW { +public: + //! limit_parameters + //!@{ + real_t m_loLimit; //!< joint limit + real_t m_hiLimit; //!< joint limit + real_t m_targetVelocity; //!< target motor velocity + real_t m_maxMotorForce; //!< max force on motor + real_t m_maxLimitForce; //!< max force on limit + real_t m_damping; //!< Damping. + real_t m_limitSoftness; //! Relaxation factor + real_t m_ERP; //!< Error tolerance factor when joint is at limit + real_t m_bounce; //!< restitution factor + bool m_enableMotor; + bool m_enableLimit; + + //!@} + + //! temp_variables + //!@{ + real_t m_currentLimitError; //! How much is violated this limit + int m_currentLimit; //!< 0=free, 1=at lo limit, 2=at hi limit + real_t m_accumulatedImpulse; + //!@} + + G6DOFRotationalLimitMotor3DSW() { + m_accumulatedImpulse = 0.f; + m_targetVelocity = 0; + m_maxMotorForce = 0.1f; + m_maxLimitForce = 300.0f; + m_loLimit = -1e30; + m_hiLimit = 1e30; + m_ERP = 0.5f; + m_bounce = 0.0f; + m_damping = 1.0f; + m_limitSoftness = 0.5f; + m_currentLimit = 0; + m_currentLimitError = 0; + m_enableMotor = false; + m_enableLimit = false; + } + + G6DOFRotationalLimitMotor3DSW(const G6DOFRotationalLimitMotor3DSW &limot) { + m_targetVelocity = limot.m_targetVelocity; + m_maxMotorForce = limot.m_maxMotorForce; + m_limitSoftness = limot.m_limitSoftness; + m_loLimit = limot.m_loLimit; + m_hiLimit = limot.m_hiLimit; + m_ERP = limot.m_ERP; + m_bounce = limot.m_bounce; + m_currentLimit = limot.m_currentLimit; + m_currentLimitError = limot.m_currentLimitError; + m_enableMotor = limot.m_enableMotor; + } + + //! Is limited + bool isLimited() { + return (m_loLimit < m_hiLimit); + } + + //! Need apply correction + bool needApplyTorques() { + return (m_enableMotor || m_currentLimit != 0); + } + + //! calculates error + /*! + calculates m_currentLimit and m_currentLimitError. + */ + int testLimitValue(real_t test_value); + + //! apply the correction impulses for two bodies + real_t solveAngularLimits(real_t timeStep, Vector3 &axis, real_t jacDiagABInv, Body3DSW *body0, Body3DSW *body1); +}; + +class G6DOFTranslationalLimitMotor3DSW { +public: + Vector3 m_lowerLimit; //!< the constraint lower limits + Vector3 m_upperLimit; //!< the constraint upper limits + Vector3 m_accumulatedImpulse; + //! Linear_Limit_parameters + //!@{ + Vector3 m_limitSoftness; //!< Softness for linear limit + Vector3 m_damping; //!< Damping for linear limit + Vector3 m_restitution; //! Bounce parameter for linear limit + //!@} + bool enable_limit[3]; + + G6DOFTranslationalLimitMotor3DSW() { + m_lowerLimit = Vector3(0.f, 0.f, 0.f); + m_upperLimit = Vector3(0.f, 0.f, 0.f); + m_accumulatedImpulse = Vector3(0.f, 0.f, 0.f); + + m_limitSoftness = Vector3(1, 1, 1) * 0.7f; + m_damping = Vector3(1, 1, 1) * real_t(1.0f); + m_restitution = Vector3(1, 1, 1) * real_t(0.5f); + + enable_limit[0] = true; + enable_limit[1] = true; + enable_limit[2] = true; + } + + G6DOFTranslationalLimitMotor3DSW(const G6DOFTranslationalLimitMotor3DSW &other) { + m_lowerLimit = other.m_lowerLimit; + m_upperLimit = other.m_upperLimit; + m_accumulatedImpulse = other.m_accumulatedImpulse; + + m_limitSoftness = other.m_limitSoftness; + m_damping = other.m_damping; + m_restitution = other.m_restitution; + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + inline bool isLimited(int limitIndex) { + return (m_upperLimit[limitIndex] >= m_lowerLimit[limitIndex]); + } + + real_t solveLinearAxis( + real_t timeStep, + real_t jacDiagABInv, + Body3DSW *body1, const Vector3 &pointInA, + Body3DSW *body2, const Vector3 &pointInB, + int limit_index, + const Vector3 &axis_normal_on_a, + const Vector3 &anchorPos); +}; + +class Generic6DOFJoint3DSW : public Joint3DSW { +protected: + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + //! relative_frames + //!@{ + Transform m_frameInA; //!< the constraint space w.r.t body A + Transform m_frameInB; //!< the constraint space w.r.t body B + //!@} + + //! Jacobians + //!@{ + JacobianEntry3DSW m_jacLinear[3]; //!< 3 orthogonal linear constraints + JacobianEntry3DSW m_jacAng[3]; //!< 3 orthogonal angular constraints + //!@} + + //! Linear_Limit_parameters + //!@{ + G6DOFTranslationalLimitMotor3DSW m_linearLimits; + //!@} + + //! hinge_parameters + //!@{ + G6DOFRotationalLimitMotor3DSW m_angularLimits[3]; + //!@} + +protected: + //! temporal variables + //!@{ + real_t m_timeStep; + Transform m_calculatedTransformA; + Transform m_calculatedTransformB; + Vector3 m_calculatedAxisAngleDiff; + Vector3 m_calculatedAxis[3]; + + Vector3 m_AnchorPos; // point between pivots of bodies A and B to solve linear axes + + bool m_useLinearReferenceFrameA; + + //!@} + + Generic6DOFJoint3DSW &operator=(Generic6DOFJoint3DSW &other) { + ERR_PRINT("pito"); + (void)other; + return *this; + } + + void buildLinearJacobian( + JacobianEntry3DSW &jacLinear, const Vector3 &normalWorld, + const Vector3 &pivotAInW, const Vector3 &pivotBInW); + + void buildAngularJacobian(JacobianEntry3DSW &jacAngular, const Vector3 &jointAxisW); + + //! calcs the euler angles between the two bodies. + void calculateAngleInfo(); + +public: + Generic6DOFJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB, bool useLinearReferenceFrameA); + + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_6DOF; } + + virtual bool setup(real_t p_timestep); + virtual void solve(real_t p_timestep); + + //! Calcs global transform of the offsets + /*! + Calcs the global transform for the joint offset for body A an B, and also calcs the agle differences between the bodies. + \sa Generic6DOFJointSW.getCalculatedTransformA , Generic6DOFJointSW.getCalculatedTransformB, Generic6DOFJointSW.calculateAngleInfo + */ + void calculateTransforms(); + + //! Gets the global transform of the offset for body A + /*! + \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo. + */ + const Transform &getCalculatedTransformA() const { + return m_calculatedTransformA; + } + + //! Gets the global transform of the offset for body B + /*! + \sa Generic6DOFJointSW.getFrameOffsetA, Generic6DOFJointSW.getFrameOffsetB, Generic6DOFJointSW.calculateAngleInfo. + */ + const Transform &getCalculatedTransformB() const { + return m_calculatedTransformB; + } + + const Transform &getFrameOffsetA() const { + return m_frameInA; + } + + const Transform &getFrameOffsetB() const { + return m_frameInB; + } + + Transform &getFrameOffsetA() { + return m_frameInA; + } + + Transform &getFrameOffsetB() { + return m_frameInB; + } + + //! performs Jacobian calculation, and also calculates angle differences and axis + + void updateRHS(real_t timeStep); + + //! Get the rotation axis in global coordinates + /*! + \pre Generic6DOFJointSW.buildJacobian must be called previously. + */ + Vector3 getAxis(int axis_index) const; + + //! Get the relative Euler angle + /*! + \pre Generic6DOFJointSW.buildJacobian must be called previously. + */ + real_t getAngle(int axis_index) const; + + //! Test angular limit. + /*! + Calculates angular correction and returns true if limit needs to be corrected. + \pre Generic6DOFJointSW.buildJacobian must be called previously. + */ + bool testAngularLimitMotor(int axis_index); + + void setLinearLowerLimit(const Vector3 &linearLower) { + m_linearLimits.m_lowerLimit = linearLower; + } + + void setLinearUpperLimit(const Vector3 &linearUpper) { + m_linearLimits.m_upperLimit = linearUpper; + } + + void setAngularLowerLimit(const Vector3 &angularLower) { + m_angularLimits[0].m_loLimit = angularLower.x; + m_angularLimits[1].m_loLimit = angularLower.y; + m_angularLimits[2].m_loLimit = angularLower.z; + } + + void setAngularUpperLimit(const Vector3 &angularUpper) { + m_angularLimits[0].m_hiLimit = angularUpper.x; + m_angularLimits[1].m_hiLimit = angularUpper.y; + m_angularLimits[2].m_hiLimit = angularUpper.z; + } + + //! Retrieves the angular limit informacion + G6DOFRotationalLimitMotor3DSW *getRotationalLimitMotor(int index) { + return &m_angularLimits[index]; + } + + //! Retrieves the limit informacion + G6DOFTranslationalLimitMotor3DSW *getTranslationalLimitMotor() { + return &m_linearLimits; + } + + //first 3 are linear, next 3 are angular + void setLimit(int axis, real_t lo, real_t hi) { + if (axis < 3) { + m_linearLimits.m_lowerLimit[axis] = lo; + m_linearLimits.m_upperLimit[axis] = hi; + } else { + m_angularLimits[axis - 3].m_loLimit = lo; + m_angularLimits[axis - 3].m_hiLimit = hi; + } + } + + //! Test limit + /*! + - free means upper < lower, + - locked means upper == lower + - limited means upper > lower + - limitIndex: first 3 are linear, next 3 are angular + */ + bool isLimited(int limitIndex) { + if (limitIndex < 3) { + return m_linearLimits.isLimited(limitIndex); + } + return m_angularLimits[limitIndex - 3].isLimited(); + } + + const Body3DSW *getRigidBodyA() const { + return A; + } + const Body3DSW *getRigidBodyB() const { + return B; + } + + virtual void calcAnchorPos(void); // overridable + + void set_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param, real_t p_value); + real_t get_param(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisParam p_param) const; + + void set_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag, bool p_value); + bool get_flag(Vector3::Axis p_axis, PhysicsServer3D::G6DOFJointAxisFlag p_flag) const; +}; + +#endif // GENERIC_6DOF_JOINT_SW_H diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.cpp b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp new file mode 100644 index 0000000000..57605aac7b --- /dev/null +++ b/servers/physics_3d/joints/hinge_joint_3d_sw.cpp @@ -0,0 +1,450 @@ +/*************************************************************************/ +/* hinge_joint_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "hinge_joint_3d_sw.h" + +static void plane_space(const Vector3 &n, Vector3 &p, Vector3 &q) { + + if (Math::abs(n.z) > Math_SQRT12) { + // choose p in y-z plane + real_t a = n[1] * n[1] + n[2] * n[2]; + real_t k = 1.0 / Math::sqrt(a); + p = Vector3(0, -n[2] * k, n[1] * k); + // set q = n x p + q = Vector3(a * k, -n[0] * p[2], n[0] * p[1]); + } else { + // choose p in x-y plane + real_t a = n.x * n.x + n.y * n.y; + real_t k = 1.0 / Math::sqrt(a); + p = Vector3(-n.y * k, n.x * k, 0); + // set q = n x p + q = Vector3(-n.z * p.y, n.z * p.x, a * k); + } +} + +HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameA, const Transform &frameB) : + Joint3DSW(_arr, 2) { + + A = rbA; + B = rbB; + + m_rbAFrame = frameA; + m_rbBFrame = frameB; + // flip axis + m_rbBFrame.basis[0][2] *= real_t(-1.); + m_rbBFrame.basis[1][2] *= real_t(-1.); + m_rbBFrame.basis[2][2] *= real_t(-1.); + + //start with free + m_lowerLimit = Math_PI; + m_upperLimit = -Math_PI; + + m_useLimit = false; + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; + + tau = 0.3; + + m_angularOnly = false; + m_enableAngularMotor = false; + + A->add_constraint(this, 0); + B->add_constraint(this, 1); +} + +HingeJoint3DSW::HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, + const Vector3 &axisInA, const Vector3 &axisInB) : + Joint3DSW(_arr, 2) { + + A = rbA; + B = rbB; + + m_rbAFrame.origin = pivotInA; + + // since no frame is given, assume this to be zero angle and just pick rb transform axis + Vector3 rbAxisA1 = rbA->get_transform().basis.get_axis(0); + + Vector3 rbAxisA2; + real_t projection = axisInA.dot(rbAxisA1); + if (projection >= 1.0f - CMP_EPSILON) { + rbAxisA1 = -rbA->get_transform().basis.get_axis(2); + rbAxisA2 = rbA->get_transform().basis.get_axis(1); + } else if (projection <= -1.0f + CMP_EPSILON) { + rbAxisA1 = rbA->get_transform().basis.get_axis(2); + rbAxisA2 = rbA->get_transform().basis.get_axis(1); + } else { + rbAxisA2 = axisInA.cross(rbAxisA1); + rbAxisA1 = rbAxisA2.cross(axisInA); + } + + m_rbAFrame.basis = Basis(rbAxisA1.x, rbAxisA2.x, axisInA.x, + rbAxisA1.y, rbAxisA2.y, axisInA.y, + rbAxisA1.z, rbAxisA2.z, axisInA.z); + + Quat rotationArc = Quat(axisInA, axisInB); + Vector3 rbAxisB1 = rotationArc.xform(rbAxisA1); + Vector3 rbAxisB2 = axisInB.cross(rbAxisB1); + + m_rbBFrame.origin = pivotInB; + m_rbBFrame.basis = Basis(rbAxisB1.x, rbAxisB2.x, -axisInB.x, + rbAxisB1.y, rbAxisB2.y, -axisInB.y, + rbAxisB1.z, rbAxisB2.z, -axisInB.z); + + //start with free + m_lowerLimit = Math_PI; + m_upperLimit = -Math_PI; + + m_useLimit = false; + m_biasFactor = 0.3f; + m_relaxationFactor = 1.0f; + m_limitSoftness = 0.9f; + m_solveLimit = false; + + tau = 0.3; + + m_angularOnly = false; + m_enableAngularMotor = false; + + A->add_constraint(this, 0); + B->add_constraint(this, 1); +} + +bool HingeJoint3DSW::setup(real_t p_step) { + + m_appliedImpulse = real_t(0.); + + if (!m_angularOnly) { + Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); + Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); + Vector3 relPos = pivotBInW - pivotAInW; + + Vector3 normal[3]; + if (Math::is_zero_approx(relPos.length_squared())) { + normal[0] = Vector3(real_t(1.0), 0, 0); + } else { + normal[0] = relPos.normalized(); + } + + plane_space(normal[0], normal[1], normal[2]); + + for (int i = 0; i < 3; i++) { + memnew_placement(&m_jac[i], JacobianEntry3DSW( + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + pivotAInW - A->get_transform().origin - A->get_center_of_mass(), + pivotBInW - B->get_transform().origin - B->get_center_of_mass(), + normal[i], + A->get_inv_inertia(), + A->get_inv_mass(), + B->get_inv_inertia(), + B->get_inv_mass())); + } + } + + //calculate two perpendicular jointAxis, orthogonal to hingeAxis + //these two jointAxis require equal angular velocities for both bodies + + //this is unused for now, it's a todo + Vector3 jointAxis0local; + Vector3 jointAxis1local; + + plane_space(m_rbAFrame.basis.get_axis(2), jointAxis0local, jointAxis1local); + + Vector3 jointAxis0 = A->get_transform().basis.xform(jointAxis0local); + Vector3 jointAxis1 = A->get_transform().basis.xform(jointAxis1local); + Vector3 hingeAxisWorld = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); + + memnew_placement(&m_jacAng[0], JacobianEntry3DSW(jointAxis0, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_inv_inertia(), + B->get_inv_inertia())); + + memnew_placement(&m_jacAng[1], JacobianEntry3DSW(jointAxis1, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_inv_inertia(), + B->get_inv_inertia())); + + memnew_placement(&m_jacAng[2], JacobianEntry3DSW(hingeAxisWorld, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_inv_inertia(), + B->get_inv_inertia())); + + // Compute limit information + real_t hingeAngle = get_hinge_angle(); + + //set bias, sign, clear accumulator + m_correction = real_t(0.); + m_limitSign = real_t(0.); + m_solveLimit = false; + m_accLimitImpulse = real_t(0.); + + //if (m_lowerLimit < m_upperLimit) + if (m_useLimit && m_lowerLimit <= m_upperLimit) { + //if (hingeAngle <= m_lowerLimit*m_limitSoftness) + if (hingeAngle <= m_lowerLimit) { + m_correction = (m_lowerLimit - hingeAngle); + m_limitSign = 1.0f; + m_solveLimit = true; + } + //else if (hingeAngle >= m_upperLimit*m_limitSoftness) + else if (hingeAngle >= m_upperLimit) { + m_correction = m_upperLimit - hingeAngle; + m_limitSign = -1.0f; + m_solveLimit = true; + } + } + + //Compute K = J*W*J' for hinge axis + Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); + m_kHinge = 1.0f / (A->compute_angular_impulse_denominator(axisA) + + B->compute_angular_impulse_denominator(axisA)); + + return true; +} + +void HingeJoint3DSW::solve(real_t p_step) { + + Vector3 pivotAInW = A->get_transform().xform(m_rbAFrame.origin); + Vector3 pivotBInW = B->get_transform().xform(m_rbBFrame.origin); + + //real_t tau = real_t(0.3); + + //linear part + if (!m_angularOnly) { + Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; + Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; + + Vector3 vel1 = A->get_velocity_in_local_point(rel_pos1); + Vector3 vel2 = B->get_velocity_in_local_point(rel_pos2); + Vector3 vel = vel1 - vel2; + + for (int i = 0; i < 3; i++) { + const Vector3 &normal = m_jac[i].m_linearJointAxis; + real_t jacDiagABInv = real_t(1.) / m_jac[i].getDiagonal(); + + real_t rel_vel; + rel_vel = normal.dot(vel); + //positional error (zeroth order error) + real_t depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + real_t impulse = depth * tau / p_step * jacDiagABInv - rel_vel * jacDiagABInv; + m_appliedImpulse += impulse; + Vector3 impulse_vector = normal * impulse; + A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); + B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); + } + } + + { + ///solve angular part + + // get axes in world space + Vector3 axisA = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(2)); + Vector3 axisB = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(2)); + + const Vector3 &angVelA = A->get_angular_velocity(); + const Vector3 &angVelB = B->get_angular_velocity(); + + Vector3 angVelAroundHingeAxisA = axisA * axisA.dot(angVelA); + Vector3 angVelAroundHingeAxisB = axisB * axisB.dot(angVelB); + + Vector3 angAorthog = angVelA - angVelAroundHingeAxisA; + Vector3 angBorthog = angVelB - angVelAroundHingeAxisB; + Vector3 velrelOrthog = angAorthog - angBorthog; + { + //solve orthogonal angular velocity correction + real_t relaxation = real_t(1.); + real_t len = velrelOrthog.length(); + if (len > real_t(0.00001)) { + Vector3 normal = velrelOrthog.normalized(); + real_t denom = A->compute_angular_impulse_denominator(normal) + + B->compute_angular_impulse_denominator(normal); + // scale for mass and relaxation + velrelOrthog *= (real_t(1.) / denom) * m_relaxationFactor; + } + + //solve angular positional correction + Vector3 angularError = -axisA.cross(axisB) * (real_t(1.) / p_step); + real_t len2 = angularError.length(); + if (len2 > real_t(0.00001)) { + Vector3 normal2 = angularError.normalized(); + real_t denom2 = A->compute_angular_impulse_denominator(normal2) + + B->compute_angular_impulse_denominator(normal2); + angularError *= (real_t(1.) / denom2) * relaxation; + } + + A->apply_torque_impulse(-velrelOrthog + angularError); + B->apply_torque_impulse(velrelOrthog - angularError); + + // solve limit + if (m_solveLimit) { + real_t amplitude = ((angVelB - angVelA).dot(axisA) * m_relaxationFactor + m_correction * (real_t(1.) / p_step) * m_biasFactor) * m_limitSign; + + real_t impulseMag = amplitude * m_kHinge; + + // Clamp the accumulated impulse + real_t temp = m_accLimitImpulse; + m_accLimitImpulse = MAX(m_accLimitImpulse + impulseMag, real_t(0)); + impulseMag = m_accLimitImpulse - temp; + + Vector3 impulse = axisA * impulseMag * m_limitSign; + A->apply_torque_impulse(impulse); + B->apply_torque_impulse(-impulse); + } + } + + //apply motor + if (m_enableAngularMotor) { + //todo: add limits too + Vector3 angularLimit(0, 0, 0); + + Vector3 velrel = angVelAroundHingeAxisA - angVelAroundHingeAxisB; + real_t projRelVel = velrel.dot(axisA); + + real_t desiredMotorVel = m_motorTargetVelocity; + real_t motor_relvel = desiredMotorVel - projRelVel; + + real_t unclippedMotorImpulse = m_kHinge * motor_relvel; + //todo: should clip against accumulated impulse + real_t clippedMotorImpulse = unclippedMotorImpulse > m_maxMotorImpulse ? m_maxMotorImpulse : unclippedMotorImpulse; + clippedMotorImpulse = clippedMotorImpulse < -m_maxMotorImpulse ? -m_maxMotorImpulse : clippedMotorImpulse; + Vector3 motorImp = clippedMotorImpulse * axisA; + + A->apply_torque_impulse(motorImp + angularLimit); + B->apply_torque_impulse(-motorImp - angularLimit); + } + } +} +/* +void HingeJointSW::updateRHS(real_t timeStep) +{ + (void)timeStep; + +} +*/ + +static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { + real_t coeff_1 = Math_PI / 4.0f; + real_t coeff_2 = 3.0f * coeff_1; + real_t abs_y = Math::abs(y); + real_t angle; + if (x >= 0.0f) { + real_t r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + real_t r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; +} + +real_t HingeJoint3DSW::get_hinge_angle() { + const Vector3 refAxis0 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(0)); + const Vector3 refAxis1 = A->get_transform().basis.xform(m_rbAFrame.basis.get_axis(1)); + const Vector3 swingAxis = B->get_transform().basis.xform(m_rbBFrame.basis.get_axis(1)); + + return atan2fast(swingAxis.dot(refAxis0), swingAxis.dot(refAxis1)); +} + +void HingeJoint3DSW::set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value) { + + switch (p_param) { + + case PhysicsServer3D::HINGE_JOINT_BIAS: tau = p_value; break; + case PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER: m_upperLimit = p_value; break; + case PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER: m_lowerLimit = p_value; break; + case PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS: m_biasFactor = p_value; break; + case PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS: m_limitSoftness = p_value; break; + case PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION: m_relaxationFactor = p_value; break; + case PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY: m_motorTargetVelocity = p_value; break; + case PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE: m_maxMotorImpulse = p_value; break; + case PhysicsServer3D::HINGE_JOINT_MAX: break; // Can't happen, but silences warning + } +} + +real_t HingeJoint3DSW::get_param(PhysicsServer3D::HingeJointParam p_param) const { + + switch (p_param) { + + case PhysicsServer3D::HINGE_JOINT_BIAS: return tau; + case PhysicsServer3D::HINGE_JOINT_LIMIT_UPPER: return m_upperLimit; + case PhysicsServer3D::HINGE_JOINT_LIMIT_LOWER: return m_lowerLimit; + case PhysicsServer3D::HINGE_JOINT_LIMIT_BIAS: return m_biasFactor; + case PhysicsServer3D::HINGE_JOINT_LIMIT_SOFTNESS: return m_limitSoftness; + case PhysicsServer3D::HINGE_JOINT_LIMIT_RELAXATION: return m_relaxationFactor; + case PhysicsServer3D::HINGE_JOINT_MOTOR_TARGET_VELOCITY: return m_motorTargetVelocity; + case PhysicsServer3D::HINGE_JOINT_MOTOR_MAX_IMPULSE: return m_maxMotorImpulse; + case PhysicsServer3D::HINGE_JOINT_MAX: break; // Can't happen, but silences warning + } + + return 0; +} + +void HingeJoint3DSW::set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value) { + + switch (p_flag) { + case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: m_useLimit = p_value; break; + case PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR: m_enableAngularMotor = p_value; break; + case PhysicsServer3D::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning + } +} +bool HingeJoint3DSW::get_flag(PhysicsServer3D::HingeJointFlag p_flag) const { + + switch (p_flag) { + case PhysicsServer3D::HINGE_JOINT_FLAG_USE_LIMIT: return m_useLimit; + case PhysicsServer3D::HINGE_JOINT_FLAG_ENABLE_MOTOR: return m_enableAngularMotor; + case PhysicsServer3D::HINGE_JOINT_FLAG_MAX: break; // Can't happen, but silences warning + } + + return false; +} diff --git a/servers/physics_3d/joints/hinge_joint_3d_sw.h b/servers/physics_3d/joints/hinge_joint_3d_sw.h new file mode 100644 index 0000000000..8da32885bc --- /dev/null +++ b/servers/physics_3d/joints/hinge_joint_3d_sw.h @@ -0,0 +1,117 @@ +/*************************************************************************/ +/* hinge_joint_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +#ifndef HINGE_JOINT_SW_H +#define HINGE_JOINT_SW_H + +#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" +#include "servers/physics_3d/joints_3d_sw.h" + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +class HingeJoint3DSW : public Joint3DSW { + + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints + JacobianEntry3DSW m_jacAng[3]; //2 orthogonal angular constraints+ 1 for limit/motor + + Transform m_rbAFrame; // constraint axii. Assumes z is hinge axis. + Transform m_rbBFrame; + + real_t m_motorTargetVelocity; + real_t m_maxMotorImpulse; + + real_t m_limitSoftness; + real_t m_biasFactor; + real_t m_relaxationFactor; + + real_t m_lowerLimit; + real_t m_upperLimit; + + real_t m_kHinge; + + real_t m_limitSign; + real_t m_correction; + + real_t m_accLimitImpulse; + + real_t tau; + + bool m_useLimit; + bool m_angularOnly; + bool m_enableAngularMotor; + bool m_solveLimit; + + real_t m_appliedImpulse; + +public: + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_HINGE; } + + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); + + real_t get_hinge_angle(); + + void set_param(PhysicsServer3D::HingeJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::HingeJointParam p_param) const; + + void set_flag(PhysicsServer3D::HingeJointFlag p_flag, bool p_value); + bool get_flag(PhysicsServer3D::HingeJointFlag p_flag) const; + + HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameA, const Transform &frameB); + HingeJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Vector3 &pivotInA, const Vector3 &pivotInB, const Vector3 &axisInA, const Vector3 &axisInB); +}; + +#endif // HINGE_JOINT_SW_H diff --git a/servers/physics_3d/joints/jacobian_entry_3d_sw.h b/servers/physics_3d/joints/jacobian_entry_3d_sw.h new file mode 100644 index 0000000000..e298d40d8d --- /dev/null +++ b/servers/physics_3d/joints/jacobian_entry_3d_sw.h @@ -0,0 +1,169 @@ +/*************************************************************************/ +/* jacobian_entry_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +#ifndef JACOBIAN_ENTRY_SW_H +#define JACOBIAN_ENTRY_SW_H + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "core/math/transform.h" + +class JacobianEntry3DSW { +public: + JacobianEntry3DSW(){}; + //constraint between two different rigidbodies + JacobianEntry3DSW( + const Basis &world2A, + const Basis &world2B, + const Vector3 &rel_pos1, const Vector3 &rel_pos2, + const Vector3 &jointAxis, + const Vector3 &inertiaInvA, + const real_t massInvA, + const Vector3 &inertiaInvB, + const real_t massInvB) : + m_linearJointAxis(jointAxis) { + m_aJ = world2A.xform(rel_pos1.cross(m_linearJointAxis)); + m_bJ = world2B.xform(rel_pos2.cross(-m_linearJointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ) + massInvB + m_1MinvJt.dot(m_bJ); + + ERR_FAIL_COND(m_Adiag <= real_t(0.0)); + } + + //angular constraint between two different rigidbodies + JacobianEntry3DSW(const Vector3 &jointAxis, + const Basis &world2A, + const Basis &world2B, + const Vector3 &inertiaInvA, + const Vector3 &inertiaInvB) : + m_linearJointAxis(Vector3(real_t(0.), real_t(0.), real_t(0.))) { + m_aJ = world2A.xform(jointAxis); + m_bJ = world2B.xform(-jointAxis); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + ERR_FAIL_COND(m_Adiag <= real_t(0.0)); + } + + //angular constraint between two different rigidbodies + JacobianEntry3DSW(const Vector3 &axisInA, + const Vector3 &axisInB, + const Vector3 &inertiaInvA, + const Vector3 &inertiaInvB) : + m_linearJointAxis(Vector3(real_t(0.), real_t(0.), real_t(0.))), + m_aJ(axisInA), + m_bJ(-axisInB) { + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = inertiaInvB * m_bJ; + m_Adiag = m_0MinvJt.dot(m_aJ) + m_1MinvJt.dot(m_bJ); + + ERR_FAIL_COND(m_Adiag <= real_t(0.0)); + } + + //constraint on one rigidbody + JacobianEntry3DSW( + const Basis &world2A, + const Vector3 &rel_pos1, const Vector3 &rel_pos2, + const Vector3 &jointAxis, + const Vector3 &inertiaInvA, + const real_t massInvA) : + m_linearJointAxis(jointAxis) { + m_aJ = world2A.xform(rel_pos1.cross(jointAxis)); + m_bJ = world2A.xform(rel_pos2.cross(-jointAxis)); + m_0MinvJt = inertiaInvA * m_aJ; + m_1MinvJt = Vector3(real_t(0.), real_t(0.), real_t(0.)); + m_Adiag = massInvA + m_0MinvJt.dot(m_aJ); + + ERR_FAIL_COND(m_Adiag <= real_t(0.0)); + } + + real_t getDiagonal() const { return m_Adiag; } + + // for two constraints on the same rigidbody (for example vehicle friction) + real_t getNonDiagonal(const JacobianEntry3DSW &jacB, const real_t massInvA) const { + const JacobianEntry3DSW &jacA = *this; + real_t lin = massInvA * jacA.m_linearJointAxis.dot(jacB.m_linearJointAxis); + real_t ang = jacA.m_0MinvJt.dot(jacB.m_aJ); + return lin + ang; + } + + // for two constraints on sharing two same rigidbodies (for example two contact points between two rigidbodies) + real_t getNonDiagonal(const JacobianEntry3DSW &jacB, const real_t massInvA, const real_t massInvB) const { + const JacobianEntry3DSW &jacA = *this; + Vector3 lin = jacA.m_linearJointAxis * jacB.m_linearJointAxis; + Vector3 ang0 = jacA.m_0MinvJt * jacB.m_aJ; + Vector3 ang1 = jacA.m_1MinvJt * jacB.m_bJ; + Vector3 lin0 = massInvA * lin; + Vector3 lin1 = massInvB * lin; + Vector3 sum = ang0 + ang1 + lin0 + lin1; + return sum[0] + sum[1] + sum[2]; + } + + real_t getRelativeVelocity(const Vector3 &linvelA, const Vector3 &angvelA, const Vector3 &linvelB, const Vector3 &angvelB) { + Vector3 linrel = linvelA - linvelB; + Vector3 angvela = angvelA * m_aJ; + Vector3 angvelb = angvelB * m_bJ; + linrel *= m_linearJointAxis; + angvela += angvelb; + angvela += linrel; + real_t rel_vel2 = angvela[0] + angvela[1] + angvela[2]; + return rel_vel2 + CMP_EPSILON; + } + //private: + + Vector3 m_linearJointAxis; + Vector3 m_aJ; + Vector3 m_bJ; + Vector3 m_0MinvJt; + Vector3 m_1MinvJt; + //Optimization: can be stored in the w/last component of one of the vectors + real_t m_Adiag; +}; + +#endif // JACOBIAN_ENTRY_SW_H diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.cpp b/servers/physics_3d/joints/pin_joint_3d_sw.cpp new file mode 100644 index 0000000000..67f2d78d54 --- /dev/null +++ b/servers/physics_3d/joints/pin_joint_3d_sw.cpp @@ -0,0 +1,167 @@ +/*************************************************************************/ +/* pin_joint_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +#include "pin_joint_3d_sw.h" + +bool PinJoint3DSW::setup(real_t p_step) { + + m_appliedImpulse = real_t(0.); + + Vector3 normal(0, 0, 0); + + for (int i = 0; i < 3; i++) { + normal[i] = 1; + memnew_placement(&m_jac[i], JacobianEntry3DSW( + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_transform().xform(m_pivotInA) - A->get_transform().origin - A->get_center_of_mass(), + B->get_transform().xform(m_pivotInB) - B->get_transform().origin - B->get_center_of_mass(), + normal, + A->get_inv_inertia(), + A->get_inv_mass(), + B->get_inv_inertia(), + B->get_inv_mass())); + normal[i] = 0; + } + + return true; +} + +void PinJoint3DSW::solve(real_t p_step) { + + Vector3 pivotAInW = A->get_transform().xform(m_pivotInA); + Vector3 pivotBInW = B->get_transform().xform(m_pivotInB); + + Vector3 normal(0, 0, 0); + + //Vector3 angvelA = A->get_transform().origin.getBasis().transpose() * A->getAngularVelocity(); + //Vector3 angvelB = B->get_transform().origin.getBasis().transpose() * B->getAngularVelocity(); + + for (int i = 0; i < 3; i++) { + normal[i] = 1; + real_t jacDiagABInv = real_t(1.) / m_jac[i].getDiagonal(); + + Vector3 rel_pos1 = pivotAInW - A->get_transform().origin; + Vector3 rel_pos2 = pivotBInW - B->get_transform().origin; + //this jacobian entry could be re-used for all iterations + + Vector3 vel1 = A->get_velocity_in_local_point(rel_pos1); + Vector3 vel2 = B->get_velocity_in_local_point(rel_pos2); + Vector3 vel = vel1 - vel2; + + real_t rel_vel; + rel_vel = normal.dot(vel); + + /* + //velocity error (first order error) + real_t rel_vel = m_jac[i].getRelativeVelocity(A->getLinearVelocity(),angvelA, + B->getLinearVelocity(),angvelB); + */ + + //positional error (zeroth order error) + real_t depth = -(pivotAInW - pivotBInW).dot(normal); //this is the error projected on the normal + + real_t impulse = depth * m_tau / p_step * jacDiagABInv - m_damping * rel_vel * jacDiagABInv; + + real_t impulseClamp = m_impulseClamp; + if (impulseClamp > 0) { + if (impulse < -impulseClamp) + impulse = -impulseClamp; + if (impulse > impulseClamp) + impulse = impulseClamp; + } + + m_appliedImpulse += impulse; + Vector3 impulse_vector = normal * impulse; + A->apply_impulse(pivotAInW - A->get_transform().origin, impulse_vector); + B->apply_impulse(pivotBInW - B->get_transform().origin, -impulse_vector); + + normal[i] = 0; + } +} + +void PinJoint3DSW::set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value) { + + switch (p_param) { + case PhysicsServer3D::PIN_JOINT_BIAS: m_tau = p_value; break; + case PhysicsServer3D::PIN_JOINT_DAMPING: m_damping = p_value; break; + case PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP: m_impulseClamp = p_value; break; + } +} + +real_t PinJoint3DSW::get_param(PhysicsServer3D::PinJointParam p_param) const { + + switch (p_param) { + case PhysicsServer3D::PIN_JOINT_BIAS: return m_tau; + case PhysicsServer3D::PIN_JOINT_DAMPING: return m_damping; + case PhysicsServer3D::PIN_JOINT_IMPULSE_CLAMP: return m_impulseClamp; + } + + return 0; +} + +PinJoint3DSW::PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW *p_body_b, const Vector3 &p_pos_b) : + Joint3DSW(_arr, 2) { + + A = p_body_a; + B = p_body_b; + m_pivotInA = p_pos_a; + m_pivotInB = p_pos_b; + + m_tau = 0.3; + m_damping = 1; + m_impulseClamp = 0; + m_appliedImpulse = 0; + + A->add_constraint(this, 0); + B->add_constraint(this, 1); +} + +PinJoint3DSW::~PinJoint3DSW() { +} diff --git a/servers/physics_3d/joints/pin_joint_3d_sw.h b/servers/physics_3d/joints/pin_joint_3d_sw.h new file mode 100644 index 0000000000..25876327a3 --- /dev/null +++ b/servers/physics_3d/joints/pin_joint_3d_sw.h @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* pin_joint_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +#ifndef PIN_JOINT_SW_H +#define PIN_JOINT_SW_H + +#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" +#include "servers/physics_3d/joints_3d_sw.h" + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +class PinJoint3DSW : public Joint3DSW { + + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + real_t m_tau; //bias + real_t m_damping; + real_t m_impulseClamp; + real_t m_appliedImpulse; + + JacobianEntry3DSW m_jac[3]; //3 orthogonal linear constraints + + Vector3 m_pivotInA; + Vector3 m_pivotInB; + +public: + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_PIN; } + + virtual bool setup(real_t p_step); + virtual void solve(real_t p_step); + + void set_param(PhysicsServer3D::PinJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::PinJointParam p_param) const; + + void set_pos_a(const Vector3 &p_pos) { m_pivotInA = p_pos; } + void set_pos_b(const Vector3 &p_pos) { m_pivotInB = p_pos; } + + Vector3 get_position_a() { return m_pivotInA; } + Vector3 get_position_b() { return m_pivotInB; } + + PinJoint3DSW(Body3DSW *p_body_a, const Vector3 &p_pos_a, Body3DSW *p_body_b, const Vector3 &p_pos_b); + ~PinJoint3DSW(); +}; + +#endif // PIN_JOINT_SW_H diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.cpp b/servers/physics_3d/joints/slider_joint_3d_sw.cpp new file mode 100644 index 0000000000..01336e2d7c --- /dev/null +++ b/servers/physics_3d/joints/slider_joint_3d_sw.cpp @@ -0,0 +1,443 @@ +/*************************************************************************/ +/* slider_joint_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +*/ + +#include "slider_joint_3d_sw.h" + +//----------------------------------------------------------------------------- + +static _FORCE_INLINE_ real_t atan2fast(real_t y, real_t x) { + real_t coeff_1 = Math_PI / 4.0f; + real_t coeff_2 = 3.0f * coeff_1; + real_t abs_y = Math::abs(y); + real_t angle; + if (x >= 0.0f) { + real_t r = (x - abs_y) / (x + abs_y); + angle = coeff_1 - coeff_1 * r; + } else { + real_t r = (x + abs_y) / (abs_y - x); + angle = coeff_2 - coeff_1 * r; + } + return (y < 0.0f) ? -angle : angle; +} + +void SliderJoint3DSW::initParams() { + m_lowerLinLimit = real_t(1.0); + m_upperLinLimit = real_t(-1.0); + m_lowerAngLimit = real_t(0.); + m_upperAngLimit = real_t(0.); + m_softnessDirLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirLin = real_t(0.); + m_softnessDirAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionDirAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingDirAng = real_t(0.); + m_softnessOrthoLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessOrthoAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionOrthoAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingOrthoAng = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessLimLin = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimLin = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimLin = SLIDER_CONSTRAINT_DEF_DAMPING; + m_softnessLimAng = SLIDER_CONSTRAINT_DEF_SOFTNESS; + m_restitutionLimAng = SLIDER_CONSTRAINT_DEF_RESTITUTION; + m_dampingLimAng = SLIDER_CONSTRAINT_DEF_DAMPING; + + m_poweredLinMotor = false; + m_targetLinMotorVelocity = real_t(0.); + m_maxLinMotorForce = real_t(0.); + m_accumulatedLinMotorImpulse = real_t(0.0); + + m_poweredAngMotor = false; + m_targetAngMotorVelocity = real_t(0.); + m_maxAngMotorForce = real_t(0.); + m_accumulatedAngMotorImpulse = real_t(0.0); + +} // SliderJointSW::initParams() + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +SliderJoint3DSW::SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB) : + Joint3DSW(_arr, 2), + m_frameInA(frameInA), + m_frameInB(frameInB) { + + A = rbA; + B = rbB; + + A->add_constraint(this, 0); + B->add_constraint(this, 1); + + initParams(); +} // SliderJointSW::SliderJointSW() + +//----------------------------------------------------------------------------- + +bool SliderJoint3DSW::setup(real_t p_step) { + + //calculate transforms + m_calculatedTransformA = A->get_transform() * m_frameInA; + m_calculatedTransformB = B->get_transform() * m_frameInB; + m_realPivotAInW = m_calculatedTransformA.origin; + m_realPivotBInW = m_calculatedTransformB.origin; + m_sliderAxis = m_calculatedTransformA.basis.get_axis(0); // along X + m_delta = m_realPivotBInW - m_realPivotAInW; + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + m_relPosA = m_projPivotInW - A->get_transform().origin; + m_relPosB = m_realPivotBInW - B->get_transform().origin; + Vector3 normalWorld; + int i; + //linear part + for (i = 0; i < 3; i++) { + normalWorld = m_calculatedTransformA.basis.get_axis(i); + memnew_placement(&m_jacLin[i], JacobianEntry3DSW( + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + m_relPosA - A->get_center_of_mass(), + m_relPosB - B->get_center_of_mass(), + normalWorld, + A->get_inv_inertia(), + A->get_inv_mass(), + B->get_inv_inertia(), + B->get_inv_mass())); + m_jacLinDiagABInv[i] = real_t(1.) / m_jacLin[i].getDiagonal(); + m_depth[i] = m_delta.dot(normalWorld); + } + testLinLimits(); + // angular part + for (i = 0; i < 3; i++) { + normalWorld = m_calculatedTransformA.basis.get_axis(i); + memnew_placement(&m_jacAng[i], JacobianEntry3DSW( + normalWorld, + A->get_principal_inertia_axes().transposed(), + B->get_principal_inertia_axes().transposed(), + A->get_inv_inertia(), + B->get_inv_inertia())); + } + testAngLimits(); + Vector3 axisA = m_calculatedTransformA.basis.get_axis(0); + m_kAngle = real_t(1.0) / (A->compute_angular_impulse_denominator(axisA) + B->compute_angular_impulse_denominator(axisA)); + // clear accumulator for motors + m_accumulatedLinMotorImpulse = real_t(0.0); + m_accumulatedAngMotorImpulse = real_t(0.0); + + return true; +} // SliderJointSW::buildJacobianInt() + +//----------------------------------------------------------------------------- + +void SliderJoint3DSW::solve(real_t p_step) { + + int i; + // linear + Vector3 velA = A->get_velocity_in_local_point(m_relPosA); + Vector3 velB = B->get_velocity_in_local_point(m_relPosB); + Vector3 vel = velA - velB; + for (i = 0; i < 3; i++) { + const Vector3 &normal = m_jacLin[i].m_linearJointAxis; + real_t rel_vel = normal.dot(vel); + // calculate positional error + real_t depth = m_depth[i]; + // get parameters + real_t softness = (i) ? m_softnessOrthoLin : (m_solveLinLim ? m_softnessLimLin : m_softnessDirLin); + real_t restitution = (i) ? m_restitutionOrthoLin : (m_solveLinLim ? m_restitutionLimLin : m_restitutionDirLin); + real_t damping = (i) ? m_dampingOrthoLin : (m_solveLinLim ? m_dampingLimLin : m_dampingDirLin); + // calcutate and apply impulse + real_t normalImpulse = softness * (restitution * depth / p_step - damping * rel_vel) * m_jacLinDiagABInv[i]; + Vector3 impulse_vector = normal * normalImpulse; + A->apply_impulse(m_relPosA, impulse_vector); + B->apply_impulse(m_relPosB, -impulse_vector); + if (m_poweredLinMotor && (!i)) { // apply linear motor + if (m_accumulatedLinMotorImpulse < m_maxLinMotorForce) { + real_t desiredMotorVel = m_targetLinMotorVelocity; + real_t motor_relvel = desiredMotorVel + rel_vel; + normalImpulse = -motor_relvel * m_jacLinDiagABInv[i]; + // clamp accumulated impulse + real_t new_acc = m_accumulatedLinMotorImpulse + Math::abs(normalImpulse); + if (new_acc > m_maxLinMotorForce) { + new_acc = m_maxLinMotorForce; + } + real_t del = new_acc - m_accumulatedLinMotorImpulse; + if (normalImpulse < real_t(0.0)) { + normalImpulse = -del; + } else { + normalImpulse = del; + } + m_accumulatedLinMotorImpulse = new_acc; + // apply clamped impulse + impulse_vector = normal * normalImpulse; + A->apply_impulse(m_relPosA, impulse_vector); + B->apply_impulse(m_relPosB, -impulse_vector); + } + } + } + // angular + // get axes in world space + Vector3 axisA = m_calculatedTransformA.basis.get_axis(0); + Vector3 axisB = m_calculatedTransformB.basis.get_axis(0); + + const Vector3 &angVelA = A->get_angular_velocity(); + const Vector3 &angVelB = B->get_angular_velocity(); + + Vector3 angVelAroundAxisA = axisA * axisA.dot(angVelA); + Vector3 angVelAroundAxisB = axisB * axisB.dot(angVelB); + + Vector3 angAorthog = angVelA - angVelAroundAxisA; + Vector3 angBorthog = angVelB - angVelAroundAxisB; + Vector3 velrelOrthog = angAorthog - angBorthog; + //solve orthogonal angular velocity correction + real_t len = velrelOrthog.length(); + if (len > real_t(0.00001)) { + Vector3 normal = velrelOrthog.normalized(); + real_t denom = A->compute_angular_impulse_denominator(normal) + B->compute_angular_impulse_denominator(normal); + velrelOrthog *= (real_t(1.) / denom) * m_dampingOrthoAng * m_softnessOrthoAng; + } + //solve angular positional correction + Vector3 angularError = axisA.cross(axisB) * (real_t(1.) / p_step); + real_t len2 = angularError.length(); + if (len2 > real_t(0.00001)) { + Vector3 normal2 = angularError.normalized(); + real_t denom2 = A->compute_angular_impulse_denominator(normal2) + B->compute_angular_impulse_denominator(normal2); + angularError *= (real_t(1.) / denom2) * m_restitutionOrthoAng * m_softnessOrthoAng; + } + // apply impulse + A->apply_torque_impulse(-velrelOrthog + angularError); + B->apply_torque_impulse(velrelOrthog - angularError); + real_t impulseMag; + //solve angular limits + if (m_solveAngLim) { + impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingLimAng + m_angDepth * m_restitutionLimAng / p_step; + impulseMag *= m_kAngle * m_softnessLimAng; + } else { + impulseMag = (angVelB - angVelA).dot(axisA) * m_dampingDirAng + m_angDepth * m_restitutionDirAng / p_step; + impulseMag *= m_kAngle * m_softnessDirAng; + } + Vector3 impulse = axisA * impulseMag; + A->apply_torque_impulse(impulse); + B->apply_torque_impulse(-impulse); + //apply angular motor + if (m_poweredAngMotor) { + if (m_accumulatedAngMotorImpulse < m_maxAngMotorForce) { + Vector3 velrel = angVelAroundAxisA - angVelAroundAxisB; + real_t projRelVel = velrel.dot(axisA); + + real_t desiredMotorVel = m_targetAngMotorVelocity; + real_t motor_relvel = desiredMotorVel - projRelVel; + + real_t angImpulse = m_kAngle * motor_relvel; + // clamp accumulated impulse + real_t new_acc = m_accumulatedAngMotorImpulse + Math::abs(angImpulse); + if (new_acc > m_maxAngMotorForce) { + new_acc = m_maxAngMotorForce; + } + real_t del = new_acc - m_accumulatedAngMotorImpulse; + if (angImpulse < real_t(0.0)) { + angImpulse = -del; + } else { + angImpulse = del; + } + m_accumulatedAngMotorImpulse = new_acc; + // apply clamped impulse + Vector3 motorImp = angImpulse * axisA; + A->apply_torque_impulse(motorImp); + B->apply_torque_impulse(-motorImp); + } + } +} // SliderJointSW::solveConstraint() + +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- + +void SliderJoint3DSW::calculateTransforms(void) { + m_calculatedTransformA = A->get_transform() * m_frameInA; + m_calculatedTransformB = B->get_transform() * m_frameInB; + m_realPivotAInW = m_calculatedTransformA.origin; + m_realPivotBInW = m_calculatedTransformB.origin; + m_sliderAxis = m_calculatedTransformA.basis.get_axis(0); // along X + m_delta = m_realPivotBInW - m_realPivotAInW; + m_projPivotInW = m_realPivotAInW + m_sliderAxis.dot(m_delta) * m_sliderAxis; + Vector3 normalWorld; + int i; + //linear part + for (i = 0; i < 3; i++) { + normalWorld = m_calculatedTransformA.basis.get_axis(i); + m_depth[i] = m_delta.dot(normalWorld); + } +} // SliderJointSW::calculateTransforms() + +//----------------------------------------------------------------------------- + +void SliderJoint3DSW::testLinLimits(void) { + m_solveLinLim = false; + m_linPos = m_depth[0]; + if (m_lowerLinLimit <= m_upperLinLimit) { + if (m_depth[0] > m_upperLinLimit) { + m_depth[0] -= m_upperLinLimit; + m_solveLinLim = true; + } else if (m_depth[0] < m_lowerLinLimit) { + m_depth[0] -= m_lowerLinLimit; + m_solveLinLim = true; + } else { + m_depth[0] = real_t(0.); + } + } else { + m_depth[0] = real_t(0.); + } +} // SliderJointSW::testLinLimits() + +//----------------------------------------------------------------------------- + +void SliderJoint3DSW::testAngLimits(void) { + m_angDepth = real_t(0.); + m_solveAngLim = false; + if (m_lowerAngLimit <= m_upperAngLimit) { + const Vector3 axisA0 = m_calculatedTransformA.basis.get_axis(1); + const Vector3 axisA1 = m_calculatedTransformA.basis.get_axis(2); + const Vector3 axisB0 = m_calculatedTransformB.basis.get_axis(1); + real_t rot = atan2fast(axisB0.dot(axisA1), axisB0.dot(axisA0)); + if (rot < m_lowerAngLimit) { + m_angDepth = rot - m_lowerAngLimit; + m_solveAngLim = true; + } else if (rot > m_upperAngLimit) { + m_angDepth = rot - m_upperAngLimit; + m_solveAngLim = true; + } + } +} // SliderJointSW::testAngLimits() + +//----------------------------------------------------------------------------- + +Vector3 SliderJoint3DSW::getAncorInA(void) { + Vector3 ancorInA; + ancorInA = m_realPivotAInW + (m_lowerLinLimit + m_upperLinLimit) * real_t(0.5) * m_sliderAxis; + ancorInA = A->get_transform().inverse().xform(ancorInA); + return ancorInA; +} // SliderJointSW::getAncorInA() + +//----------------------------------------------------------------------------- + +Vector3 SliderJoint3DSW::getAncorInB(void) { + Vector3 ancorInB; + ancorInB = m_frameInB.origin; + return ancorInB; +} // SliderJointSW::getAncorInB(); + +void SliderJoint3DSW::set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value) { + + switch (p_param) { + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: m_upperLinLimit = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER: m_lowerLinLimit = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: m_softnessLimLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: m_restitutionLimLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: m_dampingLimLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: m_softnessDirLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: m_restitutionDirLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING: m_dampingDirLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: m_softnessOrthoLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: m_restitutionOrthoLin = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: m_dampingOrthoLin = p_value; break; + + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: m_upperAngLimit = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: m_lowerAngLimit = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: m_softnessLimAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: m_restitutionLimAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: m_dampingLimAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: m_softnessDirAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: m_restitutionDirAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: m_dampingDirAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: m_softnessOrthoAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: m_restitutionOrthoAng = p_value; break; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: m_dampingOrthoAng = p_value; break; + + case PhysicsServer3D::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning + } +} + +real_t SliderJoint3DSW::get_param(PhysicsServer3D::SliderJointParam p_param) const { + + switch (p_param) { + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_UPPER: return m_upperLinLimit; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_LOWER: return m_lowerLinLimit; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS: return m_softnessLimLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION: return m_restitutionLimLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_LIMIT_DAMPING: return m_dampingLimLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_SOFTNESS: return m_softnessDirLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_RESTITUTION: return m_restitutionDirLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_MOTION_DAMPING: return m_dampingDirLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS: return m_softnessOrthoLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION: return m_restitutionOrthoLin; + case PhysicsServer3D::SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING: return m_dampingOrthoLin; + + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_UPPER: return m_upperAngLimit; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_LOWER: return m_lowerAngLimit; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS: return m_softnessLimAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION: return m_restitutionLimAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_LIMIT_DAMPING: return m_dampingLimAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS: return m_softnessDirAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION: return m_restitutionDirAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_MOTION_DAMPING: return m_dampingDirAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS: return m_softnessOrthoAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION: return m_restitutionOrthoAng; + case PhysicsServer3D::SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING: return m_dampingOrthoAng; + + case PhysicsServer3D::SLIDER_JOINT_MAX: break; // Can't happen, but silences warning + } + + return 0; +} diff --git a/servers/physics_3d/joints/slider_joint_3d_sw.h b/servers/physics_3d/joints/slider_joint_3d_sw.h new file mode 100644 index 0000000000..a70ba2597d --- /dev/null +++ b/servers/physics_3d/joints/slider_joint_3d_sw.h @@ -0,0 +1,249 @@ +/*************************************************************************/ +/* slider_joint_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +/* +Adapted to Godot from the Bullet library. +*/ + +#ifndef SLIDER_JOINT_SW_H +#define SLIDER_JOINT_SW_H + +#include "servers/physics_3d/joints/jacobian_entry_3d_sw.h" +#include "servers/physics_3d/joints_3d_sw.h" + +/* +Bullet Continuous Collision Detection and Physics Library +Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ + +This software is provided 'as-is', without any express or implied warranty. +In no event will the authors be held liable for any damages arising from the use of this software. +Permission is granted to anyone to use this software for any purpose, +including commercial applications, and to alter it and redistribute it freely, +subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. +3. This notice may not be removed or altered from any source distribution. +*/ + +/* +Added by Roman Ponomarev (rponom@gmail.com) +April 04, 2008 + +*/ + +#define SLIDER_CONSTRAINT_DEF_SOFTNESS (real_t(1.0)) +#define SLIDER_CONSTRAINT_DEF_DAMPING (real_t(1.0)) +#define SLIDER_CONSTRAINT_DEF_RESTITUTION (real_t(0.7)) + +//----------------------------------------------------------------------------- + +class SliderJoint3DSW : public Joint3DSW { +protected: + union { + struct { + Body3DSW *A; + Body3DSW *B; + }; + + Body3DSW *_arr[2]; + }; + + Transform m_frameInA; + Transform m_frameInB; + + // linear limits + real_t m_lowerLinLimit; + real_t m_upperLinLimit; + // angular limits + real_t m_lowerAngLimit; + real_t m_upperAngLimit; + // softness, restitution and damping for different cases + // DirLin - moving inside linear limits + // LimLin - hitting linear limit + // DirAng - moving inside angular limits + // LimAng - hitting angular limit + // OrthoLin, OrthoAng - against constraint axis + real_t m_softnessDirLin; + real_t m_restitutionDirLin; + real_t m_dampingDirLin; + real_t m_softnessDirAng; + real_t m_restitutionDirAng; + real_t m_dampingDirAng; + real_t m_softnessLimLin; + real_t m_restitutionLimLin; + real_t m_dampingLimLin; + real_t m_softnessLimAng; + real_t m_restitutionLimAng; + real_t m_dampingLimAng; + real_t m_softnessOrthoLin; + real_t m_restitutionOrthoLin; + real_t m_dampingOrthoLin; + real_t m_softnessOrthoAng; + real_t m_restitutionOrthoAng; + real_t m_dampingOrthoAng; + + // for interlal use + bool m_solveLinLim; + bool m_solveAngLim; + + JacobianEntry3DSW m_jacLin[3]; + real_t m_jacLinDiagABInv[3]; + + JacobianEntry3DSW m_jacAng[3]; + + real_t m_timeStep; + Transform m_calculatedTransformA; + Transform m_calculatedTransformB; + + Vector3 m_sliderAxis; + Vector3 m_realPivotAInW; + Vector3 m_realPivotBInW; + Vector3 m_projPivotInW; + Vector3 m_delta; + Vector3 m_depth; + Vector3 m_relPosA; + Vector3 m_relPosB; + + real_t m_linPos; + + real_t m_angDepth; + real_t m_kAngle; + + bool m_poweredLinMotor; + real_t m_targetLinMotorVelocity; + real_t m_maxLinMotorForce; + real_t m_accumulatedLinMotorImpulse; + + bool m_poweredAngMotor; + real_t m_targetAngMotorVelocity; + real_t m_maxAngMotorForce; + real_t m_accumulatedAngMotorImpulse; + + //------------------------ + void initParams(); + +public: + // constructors + SliderJoint3DSW(Body3DSW *rbA, Body3DSW *rbB, const Transform &frameInA, const Transform &frameInB); + //SliderJointSW(); + // overrides + + // access + const Body3DSW *getRigidBodyA() const { return A; } + const Body3DSW *getRigidBodyB() const { return B; } + const Transform &getCalculatedTransformA() const { return m_calculatedTransformA; } + const Transform &getCalculatedTransformB() const { return m_calculatedTransformB; } + const Transform &getFrameOffsetA() const { return m_frameInA; } + const Transform &getFrameOffsetB() const { return m_frameInB; } + Transform &getFrameOffsetA() { return m_frameInA; } + Transform &getFrameOffsetB() { return m_frameInB; } + real_t getLowerLinLimit() { return m_lowerLinLimit; } + void setLowerLinLimit(real_t lowerLimit) { m_lowerLinLimit = lowerLimit; } + real_t getUpperLinLimit() { return m_upperLinLimit; } + void setUpperLinLimit(real_t upperLimit) { m_upperLinLimit = upperLimit; } + real_t getLowerAngLimit() { return m_lowerAngLimit; } + void setLowerAngLimit(real_t lowerLimit) { m_lowerAngLimit = lowerLimit; } + real_t getUpperAngLimit() { return m_upperAngLimit; } + void setUpperAngLimit(real_t upperLimit) { m_upperAngLimit = upperLimit; } + + real_t getSoftnessDirLin() { return m_softnessDirLin; } + real_t getRestitutionDirLin() { return m_restitutionDirLin; } + real_t getDampingDirLin() { return m_dampingDirLin; } + real_t getSoftnessDirAng() { return m_softnessDirAng; } + real_t getRestitutionDirAng() { return m_restitutionDirAng; } + real_t getDampingDirAng() { return m_dampingDirAng; } + real_t getSoftnessLimLin() { return m_softnessLimLin; } + real_t getRestitutionLimLin() { return m_restitutionLimLin; } + real_t getDampingLimLin() { return m_dampingLimLin; } + real_t getSoftnessLimAng() { return m_softnessLimAng; } + real_t getRestitutionLimAng() { return m_restitutionLimAng; } + real_t getDampingLimAng() { return m_dampingLimAng; } + real_t getSoftnessOrthoLin() { return m_softnessOrthoLin; } + real_t getRestitutionOrthoLin() { return m_restitutionOrthoLin; } + real_t getDampingOrthoLin() { return m_dampingOrthoLin; } + real_t getSoftnessOrthoAng() { return m_softnessOrthoAng; } + real_t getRestitutionOrthoAng() { return m_restitutionOrthoAng; } + real_t getDampingOrthoAng() { return m_dampingOrthoAng; } + void setSoftnessDirLin(real_t softnessDirLin) { m_softnessDirLin = softnessDirLin; } + void setRestitutionDirLin(real_t restitutionDirLin) { m_restitutionDirLin = restitutionDirLin; } + void setDampingDirLin(real_t dampingDirLin) { m_dampingDirLin = dampingDirLin; } + void setSoftnessDirAng(real_t softnessDirAng) { m_softnessDirAng = softnessDirAng; } + void setRestitutionDirAng(real_t restitutionDirAng) { m_restitutionDirAng = restitutionDirAng; } + void setDampingDirAng(real_t dampingDirAng) { m_dampingDirAng = dampingDirAng; } + void setSoftnessLimLin(real_t softnessLimLin) { m_softnessLimLin = softnessLimLin; } + void setRestitutionLimLin(real_t restitutionLimLin) { m_restitutionLimLin = restitutionLimLin; } + void setDampingLimLin(real_t dampingLimLin) { m_dampingLimLin = dampingLimLin; } + void setSoftnessLimAng(real_t softnessLimAng) { m_softnessLimAng = softnessLimAng; } + void setRestitutionLimAng(real_t restitutionLimAng) { m_restitutionLimAng = restitutionLimAng; } + void setDampingLimAng(real_t dampingLimAng) { m_dampingLimAng = dampingLimAng; } + void setSoftnessOrthoLin(real_t softnessOrthoLin) { m_softnessOrthoLin = softnessOrthoLin; } + void setRestitutionOrthoLin(real_t restitutionOrthoLin) { m_restitutionOrthoLin = restitutionOrthoLin; } + void setDampingOrthoLin(real_t dampingOrthoLin) { m_dampingOrthoLin = dampingOrthoLin; } + void setSoftnessOrthoAng(real_t softnessOrthoAng) { m_softnessOrthoAng = softnessOrthoAng; } + void setRestitutionOrthoAng(real_t restitutionOrthoAng) { m_restitutionOrthoAng = restitutionOrthoAng; } + void setDampingOrthoAng(real_t dampingOrthoAng) { m_dampingOrthoAng = dampingOrthoAng; } + void setPoweredLinMotor(bool onOff) { m_poweredLinMotor = onOff; } + bool getPoweredLinMotor() { return m_poweredLinMotor; } + void setTargetLinMotorVelocity(real_t targetLinMotorVelocity) { m_targetLinMotorVelocity = targetLinMotorVelocity; } + real_t getTargetLinMotorVelocity() { return m_targetLinMotorVelocity; } + void setMaxLinMotorForce(real_t maxLinMotorForce) { m_maxLinMotorForce = maxLinMotorForce; } + real_t getMaxLinMotorForce() { return m_maxLinMotorForce; } + void setPoweredAngMotor(bool onOff) { m_poweredAngMotor = onOff; } + bool getPoweredAngMotor() { return m_poweredAngMotor; } + void setTargetAngMotorVelocity(real_t targetAngMotorVelocity) { m_targetAngMotorVelocity = targetAngMotorVelocity; } + real_t getTargetAngMotorVelocity() { return m_targetAngMotorVelocity; } + void setMaxAngMotorForce(real_t maxAngMotorForce) { m_maxAngMotorForce = maxAngMotorForce; } + real_t getMaxAngMotorForce() { return m_maxAngMotorForce; } + real_t getLinearPos() { return m_linPos; } + + // access for ODE solver + bool getSolveLinLimit() { return m_solveLinLim; } + real_t getLinDepth() { return m_depth[0]; } + bool getSolveAngLimit() { return m_solveAngLim; } + real_t getAngDepth() { return m_angDepth; } + // shared code used by ODE solver + void calculateTransforms(void); + void testLinLimits(void); + void testAngLimits(void); + // access for PE Solver + Vector3 getAncorInA(void); + Vector3 getAncorInB(void); + + void set_param(PhysicsServer3D::SliderJointParam p_param, real_t p_value); + real_t get_param(PhysicsServer3D::SliderJointParam p_param) const; + + bool setup(real_t p_step); + void solve(real_t p_step); + + virtual PhysicsServer3D::JointType get_type() const { return PhysicsServer3D::JOINT_SLIDER; } +}; + +#endif // SLIDER_JOINT_SW_H diff --git a/servers/physics_3d/joints_3d_sw.h b/servers/physics_3d/joints_3d_sw.h new file mode 100644 index 0000000000..097aeb22b9 --- /dev/null +++ b/servers/physics_3d/joints_3d_sw.h @@ -0,0 +1,46 @@ +/*************************************************************************/ +/* joints_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef JOINTS_SW_H +#define JOINTS_SW_H + +#include "body_3d_sw.h" +#include "constraint_3d_sw.h" + +class Joint3DSW : public Constraint3DSW { + +public: + virtual PhysicsServer3D::JointType get_type() const = 0; + _FORCE_INLINE_ Joint3DSW(Body3DSW **p_body_ptr = NULL, int p_body_count = 0) : + Constraint3DSW(p_body_ptr, p_body_count) { + } +}; + +#endif // JOINTS_SW_H diff --git a/servers/physics_3d/physics_server_3d_sw.cpp b/servers/physics_3d/physics_server_3d_sw.cpp new file mode 100644 index 0000000000..27fcedc45f --- /dev/null +++ b/servers/physics_3d/physics_server_3d_sw.cpp @@ -0,0 +1,1589 @@ +/*************************************************************************/ +/* physics_server_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_3d_sw.h" + +#include "broad_phase_3d_basic.h" +#include "broad_phase_octree.h" +#include "core/debugger/engine_debugger.h" +#include "core/os/os.h" +#include "joints/cone_twist_joint_3d_sw.h" +#include "joints/generic_6dof_joint_3d_sw.h" +#include "joints/hinge_joint_3d_sw.h" +#include "joints/pin_joint_3d_sw.h" +#include "joints/slider_joint_3d_sw.h" + +#define FLUSH_QUERY_CHECK(m_object) \ + ERR_FAIL_COND_MSG(m_object->get_space() && flushing_queries, "Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead."); + +RID PhysicsServer3DSW::shape_create(ShapeType p_shape) { + + Shape3DSW *shape = NULL; + switch (p_shape) { + + case SHAPE_PLANE: { + + shape = memnew(PlaneShape3DSW); + } break; + case SHAPE_RAY: { + + shape = memnew(RayShape3DSW); + } break; + case SHAPE_SPHERE: { + + shape = memnew(SphereShape3DSW); + } break; + case SHAPE_BOX: { + + shape = memnew(BoxShape3DSW); + } break; + case SHAPE_CAPSULE: { + + shape = memnew(CapsuleShape3DSW); + } break; + case SHAPE_CYLINDER: { + + ERR_FAIL_V_MSG(RID(), "CylinderShape is not supported in GodotPhysics. Please switch to Bullet in the Project Settings."); + } break; + case SHAPE_CONVEX_POLYGON: { + + shape = memnew(ConvexPolygonShape3DSW); + } break; + case SHAPE_CONCAVE_POLYGON: { + + shape = memnew(ConcavePolygonShape3DSW); + } break; + case SHAPE_HEIGHTMAP: { + + shape = memnew(HeightMapShape3DSW); + } break; + case SHAPE_CUSTOM: { + + ERR_FAIL_V(RID()); + + } break; + } + + RID id = shape_owner.make_rid(shape); + shape->set_self(id); + + return id; +}; + +void PhysicsServer3DSW::shape_set_data(RID p_shape, const Variant &p_data) { + + Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + shape->set_data(p_data); +}; + +void PhysicsServer3DSW::shape_set_custom_solver_bias(RID p_shape, real_t p_bias) { + + Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + shape->set_custom_bias(p_bias); +} + +PhysicsServer3D::ShapeType PhysicsServer3DSW::shape_get_type(RID p_shape) const { + + const Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, SHAPE_CUSTOM); + return shape->get_type(); +}; + +Variant PhysicsServer3DSW::shape_get_data(RID p_shape) const { + + const Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, Variant()); + ERR_FAIL_COND_V(!shape->is_configured(), Variant()); + return shape->get_data(); +}; + +void PhysicsServer3DSW::shape_set_margin(RID p_shape, real_t p_margin) { +} + +real_t PhysicsServer3DSW::shape_get_margin(RID p_shape) const { + return 0.0; +} + +real_t PhysicsServer3DSW::shape_get_custom_solver_bias(RID p_shape) const { + + const Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); + return shape->get_custom_bias(); +} + +RID PhysicsServer3DSW::space_create() { + + Space3DSW *space = memnew(Space3DSW); + RID id = space_owner.make_rid(space); + space->set_self(id); + RID area_id = area_create(); + Area3DSW *area = area_owner.getornull(area_id); + ERR_FAIL_COND_V(!area, RID()); + space->set_default_area(area); + area->set_space(space); + area->set_priority(-1); + RID sgb = body_create(); + body_set_space(sgb, id); + body_set_mode(sgb, BODY_MODE_STATIC); + space->set_static_global_body(sgb); + + return id; +}; + +void PhysicsServer3DSW::space_set_active(RID p_space, bool p_active) { + + Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + if (p_active) + active_spaces.insert(space); + else + active_spaces.erase(space); +} + +bool PhysicsServer3DSW::space_is_active(RID p_space) const { + + const Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, false); + + return active_spaces.has(space); +} + +void PhysicsServer3DSW::space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) { + + Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + + space->set_param(p_param, p_value); +} + +real_t PhysicsServer3DSW::space_get_param(RID p_space, SpaceParameter p_param) const { + + const Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_param(p_param); +} + +PhysicsDirectSpaceState3D *PhysicsServer3DSW::space_get_direct_state(RID p_space) { + + Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, NULL); + ERR_FAIL_COND_V_MSG(!doing_sync || space->is_locked(), NULL, "Space state is inaccessible right now, wait for iteration or physics process notification."); + + return space->get_direct_state(); +} + +void PhysicsServer3DSW::space_set_debug_contacts(RID p_space, int p_max_contacts) { + + Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + space->set_debug_contacts(p_max_contacts); +} + +Vector PhysicsServer3DSW::space_get_contacts(RID p_space) const { + + Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, Vector()); + return space->get_debug_contacts(); +} + +int PhysicsServer3DSW::space_get_contact_count(RID p_space) const { + + Space3DSW *space = space_owner.getornull(p_space); + ERR_FAIL_COND_V(!space, 0); + return space->get_debug_contact_count(); +} + +RID PhysicsServer3DSW::area_create() { + + Area3DSW *area = memnew(Area3DSW); + RID rid = area_owner.make_rid(area); + area->set_self(rid); + return rid; +}; + +void PhysicsServer3DSW::area_set_space(RID p_area, RID p_space) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + Space3DSW *space = NULL; + if (p_space.is_valid()) { + space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + } + + if (area->get_space() == space) + return; //pointless + + area->clear_constraints(); + area->set_space(space); +}; + +RID PhysicsServer3DSW::area_get_space(RID p_area) const { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, RID()); + + Space3DSW *space = area->get_space(); + if (!space) + return RID(); + return space->get_self(); +}; + +void PhysicsServer3DSW::area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_space_override_mode(p_mode); +} + +PhysicsServer3D::AreaSpaceOverrideMode PhysicsServer3DSW::area_get_space_override_mode(RID p_area) const { + + const Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, AREA_SPACE_OVERRIDE_DISABLED); + + return area->get_space_override_mode(); +} + +void PhysicsServer3DSW::area_add_shape(RID p_area, RID p_shape, const Transform &p_transform, bool p_disabled) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + + area->add_shape(shape, p_transform, p_disabled); +} + +void PhysicsServer3DSW::area_set_shape(RID p_area, int p_shape_idx, RID p_shape) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + area->set_shape(p_shape_idx, shape); +} + +void PhysicsServer3DSW::area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_shape_transform(p_shape_idx, p_transform); +} + +int PhysicsServer3DSW::area_get_shape_count(RID p_area) const { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, -1); + + return area->get_shape_count(); +} +RID PhysicsServer3DSW::area_get_shape(RID p_area, int p_shape_idx) const { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, RID()); + + Shape3DSW *shape = area->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} +Transform PhysicsServer3DSW::area_get_shape_transform(RID p_area, int p_shape_idx) const { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, Transform()); + + return area->get_shape_transform(p_shape_idx); +} + +void PhysicsServer3DSW::area_remove_shape(RID p_area, int p_shape_idx) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->remove_shape(p_shape_idx); +} + +void PhysicsServer3DSW::area_clear_shapes(RID p_area) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + while (area->get_shape_count()) + area->remove_shape(0); +} + +void PhysicsServer3DSW::area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + ERR_FAIL_INDEX(p_shape_idx, area->get_shape_count()); + FLUSH_QUERY_CHECK(area); + area->set_shape_as_disabled(p_shape_idx, p_disabled); +} + +void PhysicsServer3DSW::area_attach_object_instance_id(RID p_area, ObjectID p_id) { + + if (space_owner.owns(p_area)) { + Space3DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_instance_id(p_id); +} +ObjectID PhysicsServer3DSW::area_get_object_instance_id(RID p_area) const { + + if (space_owner.owns(p_area)) { + Space3DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, ObjectID()); + return area->get_instance_id(); +} + +void PhysicsServer3DSW::area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) { + + if (space_owner.owns(p_area)) { + Space3DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_param(p_param, p_value); +}; + +void PhysicsServer3DSW::area_set_transform(RID p_area, const Transform &p_transform) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + area->set_transform(p_transform); +}; + +Variant PhysicsServer3DSW::area_get_param(RID p_area, AreaParameter p_param) const { + + if (space_owner.owns(p_area)) { + Space3DSW *space = space_owner.getornull(p_area); + p_area = space->get_default_area()->get_self(); + } + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, Variant()); + + return area->get_param(p_param); +}; + +Transform PhysicsServer3DSW::area_get_transform(RID p_area) const { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, Transform()); + + return area->get_transform(); +}; + +void PhysicsServer3DSW::area_set_collision_layer(RID p_area, uint32_t p_layer) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_layer(p_layer); +} + +void PhysicsServer3DSW::area_set_collision_mask(RID p_area, uint32_t p_mask) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_collision_mask(p_mask); +} + +void PhysicsServer3DSW::area_set_monitorable(RID p_area, bool p_monitorable) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + FLUSH_QUERY_CHECK(area); + + area->set_monitorable(p_monitorable); +} + +void PhysicsServer3DSW::area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +void PhysicsServer3DSW::area_set_ray_pickable(RID p_area, bool p_enable) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_ray_pickable(p_enable); +} + +bool PhysicsServer3DSW::area_is_ray_pickable(RID p_area) const { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND_V(!area, false); + + return area->is_ray_pickable(); +} + +void PhysicsServer3DSW::area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) { + + Area3DSW *area = area_owner.getornull(p_area); + ERR_FAIL_COND(!area); + + area->set_area_monitor_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method); +} + +/* BODY API */ + +RID PhysicsServer3DSW::body_create(BodyMode p_mode, bool p_init_sleeping) { + + Body3DSW *body = memnew(Body3DSW); + if (p_mode != BODY_MODE_RIGID) + body->set_mode(p_mode); + if (p_init_sleeping) + body->set_state(BODY_STATE_SLEEPING, p_init_sleeping); + RID rid = body_owner.make_rid(body); + body->set_self(rid); + return rid; +}; + +void PhysicsServer3DSW::body_set_space(RID p_body, RID p_space) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + Space3DSW *space = NULL; + if (p_space.is_valid()) { + space = space_owner.getornull(p_space); + ERR_FAIL_COND(!space); + } + + if (body->get_space() == space) + return; //pointless + + body->clear_constraint_map(); + body->set_space(space); +}; + +RID PhysicsServer3DSW::body_get_space(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, RID()); + + Space3DSW *space = body->get_space(); + if (!space) + return RID(); + return space->get_self(); +}; + +void PhysicsServer3DSW::body_set_mode(RID p_body, BodyMode p_mode) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_mode(p_mode); +}; + +PhysicsServer3D::BodyMode PhysicsServer3DSW::body_get_mode(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, BODY_MODE_STATIC); + + return body->get_mode(); +}; + +void PhysicsServer3DSW::body_add_shape(RID p_body, RID p_shape, const Transform &p_transform, bool p_disabled) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + + body->add_shape(shape, p_transform, p_disabled); +} + +void PhysicsServer3DSW::body_set_shape(RID p_body, int p_shape_idx, RID p_shape) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + Shape3DSW *shape = shape_owner.getornull(p_shape); + ERR_FAIL_COND(!shape); + ERR_FAIL_COND(!shape->is_configured()); + + body->set_shape(p_shape_idx, shape); +} +void PhysicsServer3DSW::body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_shape_transform(p_shape_idx, p_transform); +} + +int PhysicsServer3DSW::body_get_shape_count(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, -1); + + return body->get_shape_count(); +} +RID PhysicsServer3DSW::body_get_shape(RID p_body, int p_shape_idx) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, RID()); + + Shape3DSW *shape = body->get_shape(p_shape_idx); + ERR_FAIL_COND_V(!shape, RID()); + + return shape->get_self(); +} + +void PhysicsServer3DSW::body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + ERR_FAIL_INDEX(p_shape_idx, body->get_shape_count()); + FLUSH_QUERY_CHECK(body); + + body->set_shape_as_disabled(p_shape_idx, p_disabled); +} + +Transform PhysicsServer3DSW::body_get_shape_transform(RID p_body, int p_shape_idx) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Transform()); + + return body->get_shape_transform(p_shape_idx); +} + +void PhysicsServer3DSW::body_remove_shape(RID p_body, int p_shape_idx) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->remove_shape(p_shape_idx); +} + +void PhysicsServer3DSW::body_clear_shapes(RID p_body) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + while (body->get_shape_count()) + body->remove_shape(0); +} + +void PhysicsServer3DSW::body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_continuous_collision_detection(p_enable); +} + +bool PhysicsServer3DSW::body_is_continuous_collision_detection_enabled(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + + return body->is_continuous_collision_detection_enabled(); +} + +void PhysicsServer3DSW::body_set_collision_layer(RID p_body, uint32_t p_layer) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_layer(p_layer); + body->wakeup(); +} + +uint32_t PhysicsServer3DSW::body_get_collision_layer(RID p_body) const { + + const Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_layer(); +} + +void PhysicsServer3DSW::body_set_collision_mask(RID p_body, uint32_t p_mask) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_collision_mask(p_mask); + body->wakeup(); +} + +uint32_t PhysicsServer3DSW::body_get_collision_mask(RID p_body) const { + + const Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_collision_mask(); +} + +void PhysicsServer3DSW::body_attach_object_instance_id(RID p_body, ObjectID p_id) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_instance_id(p_id); +}; + +ObjectID PhysicsServer3DSW::body_get_object_instance_id(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, ObjectID()); + + return body->get_instance_id(); +}; + +void PhysicsServer3DSW::body_set_user_flags(RID p_body, uint32_t p_flags) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); +}; + +uint32_t PhysicsServer3DSW::body_get_user_flags(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return 0; +}; + +void PhysicsServer3DSW::body_set_param(RID p_body, BodyParameter p_param, real_t p_value) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_param(p_param, p_value); +}; + +real_t PhysicsServer3DSW::body_get_param(RID p_body, BodyParameter p_param) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_param(p_param); +}; + +void PhysicsServer3DSW::body_set_kinematic_safe_margin(RID p_body, real_t p_margin) { + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_kinematic_margin(p_margin); +} + +real_t PhysicsServer3DSW::body_get_kinematic_safe_margin(RID p_body) const { + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + + return body->get_kinematic_margin(); +} + +void PhysicsServer3DSW::body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_state(p_state, p_variant); +}; + +Variant PhysicsServer3DSW::body_get_state(RID p_body, BodyState p_state) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Variant()); + + return body->get_state(p_state); +}; + +void PhysicsServer3DSW::body_set_applied_force(RID p_body, const Vector3 &p_force) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_force(p_force); + body->wakeup(); +}; + +Vector3 PhysicsServer3DSW::body_get_applied_force(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + return body->get_applied_force(); +}; + +void PhysicsServer3DSW::body_set_applied_torque(RID p_body, const Vector3 &p_torque) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_applied_torque(p_torque); + body->wakeup(); +}; + +Vector3 PhysicsServer3DSW::body_get_applied_torque(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, Vector3()); + + return body->get_applied_torque(); +}; + +void PhysicsServer3DSW::body_add_central_force(RID p_body, const Vector3 &p_force) { + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_central_force(p_force); + body->wakeup(); +} + +void PhysicsServer3DSW::body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) { + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_force(p_force, p_pos); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_add_torque(RID p_body, const Vector3 &p_torque) { + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_torque(p_torque); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) { + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_central_impulse(p_impulse); + body->wakeup(); +} + +void PhysicsServer3DSW::body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_impulse(p_pos, p_impulse); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + body->apply_torque_impulse(p_impulse); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + _update_shapes(); + + Vector3 v = body->get_linear_velocity(); + Vector3 axis = p_axis_velocity.normalized(); + v -= axis * axis.dot(v); + v += p_axis_velocity; + body->set_linear_velocity(v); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_axis_lock(p_axis, p_lock); + body->wakeup(); +} + +bool PhysicsServer3DSW::body_is_axis_locked(RID p_body, BodyAxis p_axis) const { + + const Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + return body->is_axis_locked(p_axis); +} + +void PhysicsServer3DSW::body_add_collision_exception(RID p_body, RID p_body_b) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->add_exception(p_body_b); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_remove_collision_exception(RID p_body, RID p_body_b) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->remove_exception(p_body_b); + body->wakeup(); +}; + +void PhysicsServer3DSW::body_get_collision_exceptions(RID p_body, List *p_exceptions) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + for (int i = 0; i < body->get_exceptions().size(); i++) { + p_exceptions->push_back(body->get_exceptions()[i]); + } +}; + +void PhysicsServer3DSW::body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); +}; + +real_t PhysicsServer3DSW::body_get_contacts_reported_depth_threshold(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, 0); + return 0; +}; + +void PhysicsServer3DSW::body_set_omit_force_integration(RID p_body, bool p_omit) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + + body->set_omit_force_integration(p_omit); +}; + +bool PhysicsServer3DSW::body_is_omitting_force_integration(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + return body->get_omit_force_integration(); +}; + +void PhysicsServer3DSW::body_set_max_contacts_reported(RID p_body, int p_contacts) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_max_contacts_reported(p_contacts); +} + +int PhysicsServer3DSW::body_get_max_contacts_reported(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, -1); + return body->get_max_contacts_reported(); +} + +void PhysicsServer3DSW::body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_force_integration_callback(p_receiver ? p_receiver->get_instance_id() : ObjectID(), p_method, p_udata); +} + +void PhysicsServer3DSW::body_set_ray_pickable(RID p_body, bool p_enable) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND(!body); + body->set_ray_pickable(p_enable); +} + +bool PhysicsServer3DSW::body_is_ray_pickable(RID p_body) const { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + return body->is_ray_pickable(); +} + +bool PhysicsServer3DSW::body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result, bool p_exclude_raycast_shapes) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + _update_shapes(); + + return body->get_space()->test_body_motion(body, p_from, p_motion, p_infinite_inertia, body->get_kinematic_margin(), r_result, p_exclude_raycast_shapes); +} + +int PhysicsServer3DSW::body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, false); + ERR_FAIL_COND_V(!body->get_space(), false); + ERR_FAIL_COND_V(body->get_space()->is_locked(), false); + + _update_shapes(); + + return body->get_space()->test_body_ray_separation(body, p_transform, p_infinite_inertia, r_recover_motion, r_results, p_result_max, p_margin); +} + +PhysicsDirectBodyState3D *PhysicsServer3DSW::body_get_direct_state(RID p_body) { + + Body3DSW *body = body_owner.getornull(p_body); + ERR_FAIL_COND_V(!body, NULL); + ERR_FAIL_COND_V_MSG(!doing_sync || body->get_space()->is_locked(), NULL, "Body state is inaccessible right now, wait for iteration or physics process notification."); + + direct_state->body = body; + return direct_state; +} + +/* JOINT API */ + +RID PhysicsServer3DSW::joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) { + + Body3DSW *body_A = body_owner.getornull(p_body_A); + ERR_FAIL_COND_V(!body_A, RID()); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND_V(!body_A->get_space(), RID()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + Body3DSW *body_B = body_owner.getornull(p_body_B); + ERR_FAIL_COND_V(!body_B, RID()); + + ERR_FAIL_COND_V(body_A == body_B, RID()); + + Joint3DSW *joint = memnew(PinJoint3DSW(body_A, p_local_A, body_B, p_local_B)); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +void PhysicsServer3DSW::pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_PIN); + PinJoint3DSW *pin_joint = static_cast(joint); + pin_joint->set_param(p_param, p_value); +} +real_t PhysicsServer3DSW::pin_joint_get_param(RID p_joint, PinJointParam p_param) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, 0); + PinJoint3DSW *pin_joint = static_cast(joint); + return pin_joint->get_param(p_param); +} + +void PhysicsServer3DSW::pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_PIN); + PinJoint3DSW *pin_joint = static_cast(joint); + pin_joint->set_pos_a(p_A); +} +Vector3 PhysicsServer3DSW::pin_joint_get_local_a(RID p_joint) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, Vector3()); + ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); + PinJoint3DSW *pin_joint = static_cast(joint); + return pin_joint->get_position_a(); +} + +void PhysicsServer3DSW::pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_PIN); + PinJoint3DSW *pin_joint = static_cast(joint); + pin_joint->set_pos_b(p_B); +} +Vector3 PhysicsServer3DSW::pin_joint_get_local_b(RID p_joint) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, Vector3()); + ERR_FAIL_COND_V(joint->get_type() != JOINT_PIN, Vector3()); + PinJoint3DSW *pin_joint = static_cast(joint); + return pin_joint->get_position_b(); +} + +RID PhysicsServer3DSW::joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B) { + + Body3DSW *body_A = body_owner.getornull(p_body_A); + ERR_FAIL_COND_V(!body_A, RID()); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND_V(!body_A->get_space(), RID()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + Body3DSW *body_B = body_owner.getornull(p_body_B); + ERR_FAIL_COND_V(!body_B, RID()); + + ERR_FAIL_COND_V(body_A == body_B, RID()); + + Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_frame_A, p_frame_B)); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +RID PhysicsServer3DSW::joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) { + + Body3DSW *body_A = body_owner.getornull(p_body_A); + ERR_FAIL_COND_V(!body_A, RID()); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND_V(!body_A->get_space(), RID()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + Body3DSW *body_B = body_owner.getornull(p_body_B); + ERR_FAIL_COND_V(!body_B, RID()); + + ERR_FAIL_COND_V(body_A == body_B, RID()); + + Joint3DSW *joint = memnew(HingeJoint3DSW(body_A, body_B, p_pivot_A, p_pivot_B, p_axis_A, p_axis_B)); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +void PhysicsServer3DSW::hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); + HingeJoint3DSW *hinge_joint = static_cast(joint); + hinge_joint->set_param(p_param, p_value); +} +real_t PhysicsServer3DSW::hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, 0); + HingeJoint3DSW *hinge_joint = static_cast(joint); + return hinge_joint->get_param(p_param); +} + +void PhysicsServer3DSW::hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_HINGE); + HingeJoint3DSW *hinge_joint = static_cast(joint); + hinge_joint->set_flag(p_flag, p_value); +} +bool PhysicsServer3DSW::hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, false); + ERR_FAIL_COND_V(joint->get_type() != JOINT_HINGE, false); + HingeJoint3DSW *hinge_joint = static_cast(joint); + return hinge_joint->get_flag(p_flag); +} + +void PhysicsServer3DSW::joint_set_solver_priority(RID p_joint, int p_priority) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + joint->set_priority(p_priority); +} + +int PhysicsServer3DSW::joint_get_solver_priority(RID p_joint) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, 0); + return joint->get_priority(); +} + +void PhysicsServer3DSW::joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) { + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + + joint->disable_collisions_between_bodies(p_disable); + + if (2 == joint->get_body_count()) { + Body3DSW *body_a = *joint->get_body_ptr(); + Body3DSW *body_b = *(joint->get_body_ptr() + 1); + + if (p_disable) { + body_add_collision_exception(body_a->get_self(), body_b->get_self()); + body_add_collision_exception(body_b->get_self(), body_a->get_self()); + } else { + body_remove_collision_exception(body_a->get_self(), body_b->get_self()); + body_remove_collision_exception(body_b->get_self(), body_a->get_self()); + } + } +} + +bool PhysicsServer3DSW::joint_is_disabled_collisions_between_bodies(RID p_joint) const { + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, true); + + return joint->is_disabled_collisions_between_bodies(); +} + +PhysicsServer3DSW::JointType PhysicsServer3DSW::joint_get_type(RID p_joint) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, JOINT_PIN); + return joint->get_type(); +} + +RID PhysicsServer3DSW::joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { + + Body3DSW *body_A = body_owner.getornull(p_body_A); + ERR_FAIL_COND_V(!body_A, RID()); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND_V(!body_A->get_space(), RID()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + Body3DSW *body_B = body_owner.getornull(p_body_B); + ERR_FAIL_COND_V(!body_B, RID()); + + ERR_FAIL_COND_V(body_A == body_B, RID()); + + Joint3DSW *joint = memnew(SliderJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B)); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +void PhysicsServer3DSW::slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_SLIDER); + SliderJoint3DSW *slider_joint = static_cast(joint); + slider_joint->set_param(p_param, p_value); +} +real_t PhysicsServer3DSW::slider_joint_get_param(RID p_joint, SliderJointParam p_param) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0); + SliderJoint3DSW *slider_joint = static_cast(joint); + return slider_joint->get_param(p_param); +} + +RID PhysicsServer3DSW::joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { + + Body3DSW *body_A = body_owner.getornull(p_body_A); + ERR_FAIL_COND_V(!body_A, RID()); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND_V(!body_A->get_space(), RID()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + Body3DSW *body_B = body_owner.getornull(p_body_B); + ERR_FAIL_COND_V(!body_B, RID()); + + ERR_FAIL_COND_V(body_A == body_B, RID()); + + Joint3DSW *joint = memnew(ConeTwistJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B)); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +void PhysicsServer3DSW::cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_CONE_TWIST); + ConeTwistJoint3DSW *cone_twist_joint = static_cast(joint); + cone_twist_joint->set_param(p_param, p_value); +} +real_t PhysicsServer3DSW::cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_CONE_TWIST, 0); + ConeTwistJoint3DSW *cone_twist_joint = static_cast(joint); + return cone_twist_joint->get_param(p_param); +} + +RID PhysicsServer3DSW::joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) { + + Body3DSW *body_A = body_owner.getornull(p_body_A); + ERR_FAIL_COND_V(!body_A, RID()); + + if (!p_body_B.is_valid()) { + ERR_FAIL_COND_V(!body_A->get_space(), RID()); + p_body_B = body_A->get_space()->get_static_global_body(); + } + + Body3DSW *body_B = body_owner.getornull(p_body_B); + ERR_FAIL_COND_V(!body_B, RID()); + + ERR_FAIL_COND_V(body_A == body_B, RID()); + + Joint3DSW *joint = memnew(Generic6DOFJoint3DSW(body_A, body_B, p_local_frame_A, p_local_frame_B, true)); + RID rid = joint_owner.make_rid(joint); + joint->set_self(rid); + return rid; +} + +void PhysicsServer3DSW::generic_6dof_joint_set_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param, real_t p_value) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); + Generic6DOFJoint3DSW *generic_6dof_joint = static_cast(joint); + generic_6dof_joint->set_param(p_axis, p_param, p_value); +} +real_t PhysicsServer3DSW::generic_6dof_joint_get_param(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisParam p_param) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, 0); + ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, 0); + Generic6DOFJoint3DSW *generic_6dof_joint = static_cast(joint); + return generic_6dof_joint->get_param(p_axis, p_param); +} + +void PhysicsServer3DSW::generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag, bool p_enable) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND(!joint); + ERR_FAIL_COND(joint->get_type() != JOINT_6DOF); + Generic6DOFJoint3DSW *generic_6dof_joint = static_cast(joint); + generic_6dof_joint->set_flag(p_axis, p_flag, p_enable); +} +bool PhysicsServer3DSW::generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis p_axis, G6DOFJointAxisFlag p_flag) { + + Joint3DSW *joint = joint_owner.getornull(p_joint); + ERR_FAIL_COND_V(!joint, false); + ERR_FAIL_COND_V(joint->get_type() != JOINT_6DOF, false); + Generic6DOFJoint3DSW *generic_6dof_joint = static_cast(joint); + return generic_6dof_joint->get_flag(p_axis, p_flag); +} + +void PhysicsServer3DSW::free(RID p_rid) { + + _update_shapes(); //just in case + + if (shape_owner.owns(p_rid)) { + + Shape3DSW *shape = shape_owner.getornull(p_rid); + + while (shape->get_owners().size()) { + ShapeOwner3DSW *so = shape->get_owners().front()->key(); + so->remove_shape(shape); + } + + shape_owner.free(p_rid); + memdelete(shape); + } else if (body_owner.owns(p_rid)) { + + Body3DSW *body = body_owner.getornull(p_rid); + + /* + if (body->get_state_query()) + _clear_query(body->get_state_query()); + + if (body->get_direct_state_query()) + _clear_query(body->get_direct_state_query()); + */ + + body->set_space(NULL); + + while (body->get_shape_count()) { + + body->remove_shape(0); + } + + body_owner.free(p_rid); + memdelete(body); + + } else if (area_owner.owns(p_rid)) { + + Area3DSW *area = area_owner.getornull(p_rid); + + /* + if (area->get_monitor_query()) + _clear_query(area->get_monitor_query()); + */ + + area->set_space(NULL); + + while (area->get_shape_count()) { + + area->remove_shape(0); + } + + area_owner.free(p_rid); + memdelete(area); + } else if (space_owner.owns(p_rid)) { + + Space3DSW *space = space_owner.getornull(p_rid); + + while (space->get_objects().size()) { + CollisionObject3DSW *co = (CollisionObject3DSW *)space->get_objects().front()->get(); + co->set_space(NULL); + } + + active_spaces.erase(space); + free(space->get_default_area()->get_self()); + free(space->get_static_global_body()); + + space_owner.free(p_rid); + memdelete(space); + } else if (joint_owner.owns(p_rid)) { + + Joint3DSW *joint = joint_owner.getornull(p_rid); + + for (int i = 0; i < joint->get_body_count(); i++) { + + joint->get_body_ptr()[i]->remove_constraint(joint); + } + joint_owner.free(p_rid); + memdelete(joint); + + } else { + + ERR_FAIL_MSG("Invalid ID."); + } +}; + +void PhysicsServer3DSW::set_active(bool p_active) { + + active = p_active; +}; + +void PhysicsServer3DSW::init() { + + doing_sync = true; + last_step = 0.001; + iterations = 8; // 8? + stepper = memnew(Step3DSW); + direct_state = memnew(PhysicsDirectBodyState3DSW); +}; + +void PhysicsServer3DSW::step(real_t p_step) { + +#ifndef _3D_DISABLED + + if (!active) + return; + + _update_shapes(); + + doing_sync = false; + + last_step = p_step; + PhysicsDirectBodyState3DSW::singleton->step = p_step; + + island_count = 0; + active_objects = 0; + collision_pairs = 0; + for (Set::Element *E = active_spaces.front(); E; E = E->next()) { + + stepper->step((Space3DSW *)E->get(), p_step, iterations); + island_count += E->get()->get_island_count(); + active_objects += E->get()->get_active_objects(); + collision_pairs += E->get()->get_collision_pairs(); + } +#endif +} + +void PhysicsServer3DSW::sync(){ + +}; + +void PhysicsServer3DSW::flush_queries() { + +#ifndef _3D_DISABLED + + if (!active) + return; + + doing_sync = true; + + flushing_queries = true; + + uint64_t time_beg = OS::get_singleton()->get_ticks_usec(); + + for (Set::Element *E = active_spaces.front(); E; E = E->next()) { + + Space3DSW *space = (Space3DSW *)E->get(); + space->call_queries(); + } + + flushing_queries = false; + + if (EngineDebugger::is_profiling("servers")) { + + uint64_t total_time[Space3DSW::ELAPSED_TIME_MAX]; + static const char *time_name[Space3DSW::ELAPSED_TIME_MAX] = { + "integrate_forces", + "generate_islands", + "setup_constraints", + "solve_constraints", + "integrate_velocities" + }; + + for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) { + total_time[i] = 0; + } + + for (Set::Element *E = active_spaces.front(); E; E = E->next()) { + + for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) { + total_time[i] += E->get()->get_elapsed_time(Space3DSW::ElapsedTime(i)); + } + } + + Array values; + values.resize(Space3DSW::ELAPSED_TIME_MAX * 2); + for (int i = 0; i < Space3DSW::ELAPSED_TIME_MAX; i++) { + values[i * 2 + 0] = time_name[i]; + values[i * 2 + 1] = USEC_TO_SEC(total_time[i]); + } + values.push_back("flush_queries"); + values.push_back(USEC_TO_SEC(OS::get_singleton()->get_ticks_usec() - time_beg)); + + values.push_front("physics"); + EngineDebugger::profiler_add_frame_data("server", values); + } +#endif +}; + +void PhysicsServer3DSW::finish() { + + memdelete(stepper); + memdelete(direct_state); +}; + +int PhysicsServer3DSW::get_process_info(ProcessInfo p_info) { + + switch (p_info) { + + case INFO_ACTIVE_OBJECTS: { + + return active_objects; + } break; + case INFO_COLLISION_PAIRS: { + return collision_pairs; + } break; + case INFO_ISLAND_COUNT: { + + return island_count; + } break; + } + + return 0; +} + +void PhysicsServer3DSW::_update_shapes() { + + while (pending_shape_update_list.first()) { + pending_shape_update_list.first()->self()->_shape_changed(); + pending_shape_update_list.remove(pending_shape_update_list.first()); + } +} + +void PhysicsServer3DSW::_shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { + + CollCbkData *cbk = (CollCbkData *)p_userdata; + + if (cbk->max == 0) + return; + + if (cbk->amount == cbk->max) { + //find least deep + real_t min_depth = 1e20; + int min_depth_idx = 0; + for (int i = 0; i < cbk->amount; i++) { + + real_t d = cbk->ptr[i * 2 + 0].distance_squared_to(cbk->ptr[i * 2 + 1]); + if (d < min_depth) { + min_depth = d; + min_depth_idx = i; + } + } + + real_t d = p_point_A.distance_squared_to(p_point_B); + if (d < min_depth) + return; + cbk->ptr[min_depth_idx * 2 + 0] = p_point_A; + cbk->ptr[min_depth_idx * 2 + 1] = p_point_B; + + } else { + + cbk->ptr[cbk->amount * 2 + 0] = p_point_A; + cbk->ptr[cbk->amount * 2 + 1] = p_point_B; + cbk->amount++; + } +} + +PhysicsServer3DSW *PhysicsServer3DSW::singleton = NULL; +PhysicsServer3DSW::PhysicsServer3DSW() { + singleton = this; + BroadPhase3DSW::create_func = BroadPhaseOctree::_create; + island_count = 0; + active_objects = 0; + collision_pairs = 0; + + active = true; + flushing_queries = false; +}; + +PhysicsServer3DSW::~PhysicsServer3DSW(){ + +}; diff --git a/servers/physics_3d/physics_server_3d_sw.h b/servers/physics_3d/physics_server_3d_sw.h new file mode 100644 index 0000000000..7f0cd0ba9f --- /dev/null +++ b/servers/physics_3d/physics_server_3d_sw.h @@ -0,0 +1,382 @@ +/*************************************************************************/ +/* physics_server_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_SERVER_SW +#define PHYSICS_SERVER_SW + +#include "core/rid_owner.h" +#include "joints_3d_sw.h" +#include "servers/physics_server_3d.h" +#include "shape_3d_sw.h" +#include "space_3d_sw.h" +#include "step_3d_sw.h" + +class PhysicsServer3DSW : public PhysicsServer3D { + + GDCLASS(PhysicsServer3DSW, PhysicsServer3D); + + friend class PhysicsDirectSpaceState3DSW; + bool active; + int iterations; + bool doing_sync; + real_t last_step; + + int island_count; + int active_objects; + int collision_pairs; + + bool flushing_queries; + + Step3DSW *stepper; + Set active_spaces; + + PhysicsDirectBodyState3DSW *direct_state; + + mutable RID_PtrOwner shape_owner; + mutable RID_PtrOwner space_owner; + mutable RID_PtrOwner area_owner; + mutable RID_PtrOwner body_owner; + mutable RID_PtrOwner joint_owner; + + //void _clear_query(QuerySW *p_query); + friend class CollisionObject3DSW; + SelfList::List pending_shape_update_list; + void _update_shapes(); + +public: + static PhysicsServer3DSW *singleton; + + struct CollCbkData { + + int max; + int amount; + Vector3 *ptr; + }; + + static void _shape_col_cbk(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata); + + virtual RID shape_create(ShapeType p_shape); + virtual void shape_set_data(RID p_shape, const Variant &p_data); + virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias); + + virtual ShapeType shape_get_type(RID p_shape) const; + virtual Variant shape_get_data(RID p_shape) const; + + virtual void shape_set_margin(RID p_shape, real_t p_margin); + virtual real_t shape_get_margin(RID p_shape) const; + + virtual real_t shape_get_custom_solver_bias(RID p_shape) const; + + /* SPACE API */ + + virtual RID space_create(); + virtual void space_set_active(RID p_space, bool p_active); + virtual bool space_is_active(RID p_space) const; + + virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value); + virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const; + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space); + + virtual void space_set_debug_contacts(RID p_space, int p_max_contacts); + virtual Vector space_get_contacts(RID p_space) const; + virtual int space_get_contact_count(RID p_space) const; + + /* AREA API */ + + virtual RID area_create(); + + virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode); + virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const; + + virtual void area_set_space(RID p_area, RID p_space); + virtual RID area_get_space(RID p_area) const; + + virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); + virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape); + virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform); + + virtual int area_get_shape_count(RID p_area) const; + virtual RID area_get_shape(RID p_area, int p_shape_idx) const; + virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const; + + virtual void area_remove_shape(RID p_area, int p_shape_idx); + virtual void area_clear_shapes(RID p_area); + + virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled); + + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id); + virtual ObjectID area_get_object_instance_id(RID p_area) const; + + virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value); + virtual void area_set_transform(RID p_area, const Transform &p_transform); + + virtual Variant area_get_param(RID p_area, AreaParameter p_param) const; + virtual Transform area_get_transform(RID p_area) const; + + virtual void area_set_ray_pickable(RID p_area, bool p_enable); + virtual bool area_is_ray_pickable(RID p_area) const; + + virtual void area_set_collision_mask(RID p_area, uint32_t p_mask); + virtual void area_set_collision_layer(RID p_area, uint32_t p_layer); + + virtual void area_set_monitorable(RID p_area, bool p_monitorable); + + virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); + virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method); + + /* BODY API */ + + // create a body of a given type + virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false); + + virtual void body_set_space(RID p_body, RID p_space); + virtual RID body_get_space(RID p_body) const; + + virtual void body_set_mode(RID p_body, BodyMode p_mode); + virtual BodyMode body_get_mode(RID p_body) const; + + virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false); + virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape); + virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform); + + virtual int body_get_shape_count(RID p_body) const; + virtual RID body_get_shape(RID p_body, int p_shape_idx) const; + virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const; + + virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled); + + virtual void body_remove_shape(RID p_body, int p_shape_idx); + virtual void body_clear_shapes(RID p_body); + + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id); + virtual ObjectID body_get_object_instance_id(RID p_body) const; + + virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable); + virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const; + + virtual void body_set_collision_layer(RID p_body, uint32_t p_layer); + virtual uint32_t body_get_collision_layer(RID p_body) const; + + virtual void body_set_collision_mask(RID p_body, uint32_t p_mask); + virtual uint32_t body_get_collision_mask(RID p_body) const; + + virtual void body_set_user_flags(RID p_body, uint32_t p_flags); + virtual uint32_t body_get_user_flags(RID p_body) const; + + virtual void body_set_param(RID p_body, BodyParameter p_param, real_t p_value); + virtual real_t body_get_param(RID p_body, BodyParameter p_param) const; + + virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin); + virtual real_t body_get_kinematic_safe_margin(RID p_body) const; + + virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant); + virtual Variant body_get_state(RID p_body, BodyState p_state) const; + + virtual void body_set_applied_force(RID p_body, const Vector3 &p_force); + virtual Vector3 body_get_applied_force(RID p_body) const; + + virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque); + virtual Vector3 body_get_applied_torque(RID p_body) const; + + virtual void body_add_central_force(RID p_body, const Vector3 &p_force); + virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos); + virtual void body_add_torque(RID p_body, const Vector3 &p_torque); + + virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse); + virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse); + virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse); + virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity); + + virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock); + virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const; + + virtual void body_add_collision_exception(RID p_body, RID p_body_b); + virtual void body_remove_collision_exception(RID p_body, RID p_body_b); + virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions); + + virtual void body_set_contacts_reported_depth_threshold(RID p_body, real_t p_threshold); + virtual real_t body_get_contacts_reported_depth_threshold(RID p_body) const; + + virtual void body_set_omit_force_integration(RID p_body, bool p_omit); + virtual bool body_is_omitting_force_integration(RID p_body) const; + + virtual void body_set_max_contacts_reported(RID p_body, int p_contacts); + virtual int body_get_max_contacts_reported(RID p_body) const; + + virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()); + + virtual void body_set_ray_pickable(RID p_body, bool p_enable); + virtual bool body_is_ray_pickable(RID p_body) const; + + virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true); + virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001); + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body); + + /* SOFT BODY */ + + virtual RID soft_body_create(bool p_init_sleeping = false) { return RID(); } + + virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) {} + + virtual void soft_body_set_space(RID p_body, RID p_space) {} + virtual RID soft_body_get_space(RID p_body) const { return RID(); } + + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) {} + virtual uint32_t soft_body_get_collision_layer(RID p_body) const { return 0; } + + virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) {} + virtual uint32_t soft_body_get_collision_mask(RID p_body) const { return 0; } + + virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) {} + virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) {} + virtual void soft_body_get_collision_exceptions(RID p_body, List *p_exceptions) {} + + virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) {} + virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const { return Variant(); } + + virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) {} + virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const { return Vector3(); } + + virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) {} + virtual bool soft_body_is_ray_pickable(RID p_body) const { return false; } + + virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) {} + virtual int soft_body_get_simulation_precision(RID p_body) { return 0; } + + virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) {} + virtual real_t soft_body_get_total_mass(RID p_body) { return 0.; } + + virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) {} + virtual real_t soft_body_get_linear_stiffness(RID p_body) { return 0.; } + + virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) {} + virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) { return 0.; } + + virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) {} + virtual real_t soft_body_get_volume_stiffness(RID p_body) { return 0.; } + + virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) {} + virtual real_t soft_body_get_pressure_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) {} + virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) {} + virtual real_t soft_body_get_damping_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) {} + virtual real_t soft_body_get_drag_coefficient(RID p_body) { return 0.; } + + virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) {} + + virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) {} + virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) { return Vector3(); } + + virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const { return Vector3(); } + + virtual void soft_body_remove_all_pinned_points(RID p_body) {} + virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) {} + virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) { return 0; } + + /* JOINT API */ + + virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B); + + virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value); + virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const; + + virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A); + virtual Vector3 pin_joint_get_local_a(RID p_joint) const; + + virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B); + virtual Vector3 pin_joint_get_local_b(RID p_joint) const; + + virtual RID joint_create_hinge(RID p_body_A, const Transform &p_frame_A, RID p_body_B, const Transform &p_frame_B); + virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B); + + virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, real_t p_value); + virtual real_t hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const; + + virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value); + virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const; + + virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B); //reference frame is A + + virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, real_t p_value); + virtual real_t slider_joint_get_param(RID p_joint, SliderJointParam p_param) const; + + virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B); //reference frame is A + + virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, real_t p_value); + virtual real_t cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const; + + virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B); //reference frame is A + + virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, real_t p_value); + virtual real_t generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param); + + virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable); + virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag); + + virtual void generic_6dof_joint_set_precision(RID p_joint, int precision) {} + virtual int generic_6dof_joint_get_precision(RID p_joint) { return 0; } + + virtual JointType joint_get_type(RID p_joint) const; + + virtual void joint_set_solver_priority(RID p_joint, int p_priority); + virtual int joint_get_solver_priority(RID p_joint) const; + + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable); + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const; + + /* MISC */ + + virtual void free(RID p_rid); + + virtual void set_active(bool p_active); + virtual void init(); + virtual void step(real_t p_step); + virtual void sync(); + virtual void flush_queries(); + virtual void finish(); + + virtual bool is_flushing_queries() const { return flushing_queries; } + + int get_process_info(ProcessInfo p_info); + + PhysicsServer3DSW(); + ~PhysicsServer3DSW(); +}; + +#endif diff --git a/servers/physics_3d/shape_3d_sw.cpp b/servers/physics_3d/shape_3d_sw.cpp new file mode 100644 index 0000000000..53b162636e --- /dev/null +++ b/servers/physics_3d/shape_3d_sw.cpp @@ -0,0 +1,1655 @@ +/*************************************************************************/ +/* shape_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shape_3d_sw.h" + +#include "core/math/geometry.h" +#include "core/math/quick_hull.h" +#include "core/sort_array.h" + +#define _POINT_SNAP 0.001953125 +#define _EDGE_IS_VALID_SUPPORT_THRESHOLD 0.0002 +#define _FACE_IS_VALID_SUPPORT_THRESHOLD 0.9998 + +void Shape3DSW::configure(const AABB &p_aabb) { + aabb = p_aabb; + configured = true; + for (Map::Element *E = owners.front(); E; E = E->next()) { + ShapeOwner3DSW *co = (ShapeOwner3DSW *)E->key(); + co->_shape_changed(); + } +} + +Vector3 Shape3DSW::get_support(const Vector3 &p_normal) const { + + Vector3 res; + int amnt; + get_supports(p_normal, 1, &res, amnt); + return res; +} + +void Shape3DSW::add_owner(ShapeOwner3DSW *p_owner) { + + Map::Element *E = owners.find(p_owner); + if (E) { + E->get()++; + } else { + owners[p_owner] = 1; + } +} + +void Shape3DSW::remove_owner(ShapeOwner3DSW *p_owner) { + + Map::Element *E = owners.find(p_owner); + ERR_FAIL_COND(!E); + E->get()--; + if (E->get() == 0) { + owners.erase(E); + } +} + +bool Shape3DSW::is_owner(ShapeOwner3DSW *p_owner) const { + + return owners.has(p_owner); +} + +const Map &Shape3DSW::get_owners() const { + return owners; +} + +Shape3DSW::Shape3DSW() { + + custom_bias = 0; + configured = false; +} + +Shape3DSW::~Shape3DSW() { + + ERR_FAIL_COND(owners.size()); +} + +Plane PlaneShape3DSW::get_plane() const { + + return plane; +} + +void PlaneShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + // gibberish, a plane is infinity + r_min = -1e7; + r_max = 1e7; +} + +Vector3 PlaneShape3DSW::get_support(const Vector3 &p_normal) const { + + return p_normal * 1e15; +} + +bool PlaneShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + bool inters = plane.intersects_segment(p_begin, p_end, &r_result); + if (inters) + r_normal = plane.normal; + return inters; +} + +bool PlaneShape3DSW::intersect_point(const Vector3 &p_point) const { + + return plane.distance_to(p_point) < 0; +} + +Vector3 PlaneShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + if (plane.is_point_over(p_point)) { + return plane.project(p_point); + } else { + return p_point; + } +} + +Vector3 PlaneShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + return Vector3(); //wtf +} + +void PlaneShape3DSW::_setup(const Plane &p_plane) { + + plane = p_plane; + configure(AABB(Vector3(-1e4, -1e4, -1e4), Vector3(1e4 * 2, 1e4 * 2, 1e4 * 2))); +} + +void PlaneShape3DSW::set_data(const Variant &p_data) { + + _setup(p_data); +} + +Variant PlaneShape3DSW::get_data() const { + + return plane; +} + +PlaneShape3DSW::PlaneShape3DSW() { +} + +// + +real_t RayShape3DSW::get_length() const { + + return length; +} + +bool RayShape3DSW::get_slips_on_slope() const { + return slips_on_slope; +} + +void RayShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + // don't think this will be even used + r_min = 0; + r_max = 1; +} + +Vector3 RayShape3DSW::get_support(const Vector3 &p_normal) const { + + if (p_normal.z > 0) + return Vector3(0, 0, length); + else + return Vector3(0, 0, 0); +} + +void RayShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { + + if (Math::abs(p_normal.z) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + + r_amount = 2; + r_supports[0] = Vector3(0, 0, 0); + r_supports[1] = Vector3(0, 0, length); + } else if (p_normal.z > 0) { + r_amount = 1; + *r_supports = Vector3(0, 0, length); + } else { + r_amount = 1; + *r_supports = Vector3(0, 0, 0); + } +} + +bool RayShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + return false; //simply not possible +} + +bool RayShape3DSW::intersect_point(const Vector3 &p_point) const { + + return false; //simply not possible +} + +Vector3 RayShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + Vector3 s[2] = { + Vector3(0, 0, 0), + Vector3(0, 0, length) + }; + + return Geometry::get_closest_point_to_segment(p_point, s); +} + +Vector3 RayShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + return Vector3(); +} + +void RayShape3DSW::_setup(real_t p_length, bool p_slips_on_slope) { + + length = p_length; + slips_on_slope = p_slips_on_slope; + configure(AABB(Vector3(0, 0, 0), Vector3(0.1, 0.1, length))); +} + +void RayShape3DSW::set_data(const Variant &p_data) { + + Dictionary d = p_data; + _setup(d["length"], d["slips_on_slope"]); +} + +Variant RayShape3DSW::get_data() const { + + Dictionary d; + d["length"] = length; + d["slips_on_slope"] = slips_on_slope; + return d; +} + +RayShape3DSW::RayShape3DSW() { + + length = 1; + slips_on_slope = false; +} + +/********** SPHERE *************/ + +real_t SphereShape3DSW::get_radius() const { + + return radius; +} + +void SphereShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + real_t d = p_normal.dot(p_transform.origin); + + // figure out scale at point + Vector3 local_normal = p_transform.basis.xform_inv(p_normal); + real_t scale = local_normal.length(); + + r_min = d - (radius)*scale; + r_max = d + (radius)*scale; +} + +Vector3 SphereShape3DSW::get_support(const Vector3 &p_normal) const { + + return p_normal * radius; +} + +void SphereShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { + + *r_supports = p_normal * radius; + r_amount = 1; +} + +bool SphereShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + return Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(), radius, &r_result, &r_normal); +} + +bool SphereShape3DSW::intersect_point(const Vector3 &p_point) const { + + return p_point.length() < radius; +} + +Vector3 SphereShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + Vector3 p = p_point; + float l = p.length(); + if (l < radius) + return p_point; + return (p / l) * radius; +} + +Vector3 SphereShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + real_t s = 0.4 * p_mass * radius * radius; + return Vector3(s, s, s); +} + +void SphereShape3DSW::_setup(real_t p_radius) { + + radius = p_radius; + configure(AABB(Vector3(-radius, -radius, -radius), Vector3(radius * 2.0, radius * 2.0, radius * 2.0))); +} + +void SphereShape3DSW::set_data(const Variant &p_data) { + + _setup(p_data); +} + +Variant SphereShape3DSW::get_data() const { + + return radius; +} + +SphereShape3DSW::SphereShape3DSW() { + + radius = 0; +} + +/********** BOX *************/ + +void BoxShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + // no matter the angle, the box is mirrored anyway + Vector3 local_normal = p_transform.basis.xform_inv(p_normal); + + real_t length = local_normal.abs().dot(half_extents); + real_t distance = p_normal.dot(p_transform.origin); + + r_min = distance - length; + r_max = distance + length; +} + +Vector3 BoxShape3DSW::get_support(const Vector3 &p_normal) const { + + Vector3 point( + (p_normal.x < 0) ? -half_extents.x : half_extents.x, + (p_normal.y < 0) ? -half_extents.y : half_extents.y, + (p_normal.z < 0) ? -half_extents.z : half_extents.z); + + return point; +} + +void BoxShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { + + static const int next[3] = { 1, 2, 0 }; + static const int next2[3] = { 2, 0, 1 }; + + for (int i = 0; i < 3; i++) { + + Vector3 axis; + axis[i] = 1.0; + real_t dot = p_normal.dot(axis); + if (Math::abs(dot) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + + //Vector3 axis_b; + + bool neg = dot < 0; + r_amount = 4; + + Vector3 point; + point[i] = half_extents[i]; + + int i_n = next[i]; + int i_n2 = next2[i]; + + static const real_t sign[4][2] = { + + { -1.0, 1.0 }, + { 1.0, 1.0 }, + { 1.0, -1.0 }, + { -1.0, -1.0 }, + }; + + for (int j = 0; j < 4; j++) { + + point[i_n] = sign[j][0] * half_extents[i_n]; + point[i_n2] = sign[j][1] * half_extents[i_n2]; + r_supports[j] = neg ? -point : point; + } + + if (neg) { + SWAP(r_supports[1], r_supports[2]); + SWAP(r_supports[0], r_supports[3]); + } + + return; + } + + r_amount = 0; + } + + for (int i = 0; i < 3; i++) { + + Vector3 axis; + axis[i] = 1.0; + + if (Math::abs(p_normal.dot(axis)) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + + r_amount = 2; + + int i_n = next[i]; + int i_n2 = next2[i]; + + Vector3 point = half_extents; + + if (p_normal[i_n] < 0) { + point[i_n] = -point[i_n]; + } + if (p_normal[i_n2] < 0) { + point[i_n2] = -point[i_n2]; + } + + r_supports[0] = point; + point[i] = -point[i]; + r_supports[1] = point; + return; + } + } + /* USE POINT */ + + Vector3 point( + (p_normal.x < 0) ? -half_extents.x : half_extents.x, + (p_normal.y < 0) ? -half_extents.y : half_extents.y, + (p_normal.z < 0) ? -half_extents.z : half_extents.z); + + r_amount = 1; + r_supports[0] = point; +} + +bool BoxShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + AABB aabb(-half_extents, half_extents * 2.0); + + return aabb.intersects_segment(p_begin, p_end, &r_result, &r_normal); +} + +bool BoxShape3DSW::intersect_point(const Vector3 &p_point) const { + + return (Math::abs(p_point.x) < half_extents.x && Math::abs(p_point.y) < half_extents.y && Math::abs(p_point.z) < half_extents.z); +} + +Vector3 BoxShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + int outside = 0; + Vector3 min_point; + + for (int i = 0; i < 3; i++) { + + if (Math::abs(p_point[i]) > half_extents[i]) { + outside++; + if (outside == 1) { + //use plane if only one side matches + Vector3 n; + n[i] = SGN(p_point[i]); + + Plane p(n, half_extents[i]); + min_point = p.project(p_point); + } + } + } + + if (!outside) + return p_point; //it's inside, don't do anything else + + if (outside == 1) //if only above one plane, this plane clearly wins + return min_point; + + //check segments + float min_distance = 1e20; + Vector3 closest_vertex = half_extents * p_point.sign(); + Vector3 s[2] = { + closest_vertex, + closest_vertex + }; + + for (int i = 0; i < 3; i++) { + + s[1] = closest_vertex; + s[1][i] = -s[1][i]; //edge + + Vector3 closest_edge = Geometry::get_closest_point_to_segment(p_point, s); + + float d = p_point.distance_to(closest_edge); + if (d < min_distance) { + min_point = closest_edge; + min_distance = d; + } + } + + return min_point; +} + +Vector3 BoxShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + real_t lx = half_extents.x; + real_t ly = half_extents.y; + real_t lz = half_extents.z; + + return Vector3((p_mass / 3.0) * (ly * ly + lz * lz), (p_mass / 3.0) * (lx * lx + lz * lz), (p_mass / 3.0) * (lx * lx + ly * ly)); +} + +void BoxShape3DSW::_setup(const Vector3 &p_half_extents) { + + half_extents = p_half_extents.abs(); + + configure(AABB(-half_extents, half_extents * 2)); +} + +void BoxShape3DSW::set_data(const Variant &p_data) { + + _setup(p_data); +} + +Variant BoxShape3DSW::get_data() const { + + return half_extents; +} + +BoxShape3DSW::BoxShape3DSW() { +} + +/********** CAPSULE *************/ + +void CapsuleShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + Vector3 n = p_transform.basis.xform_inv(p_normal).normalized(); + real_t h = (n.z > 0) ? height : -height; + + n *= radius; + n.z += h * 0.5; + + r_max = p_normal.dot(p_transform.xform(n)); + r_min = p_normal.dot(p_transform.xform(-n)); +} + +Vector3 CapsuleShape3DSW::get_support(const Vector3 &p_normal) const { + + Vector3 n = p_normal; + + real_t h = (n.z > 0) ? height : -height; + + n *= radius; + n.z += h * 0.5; + return n; +} + +void CapsuleShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { + + Vector3 n = p_normal; + + real_t d = n.z; + + if (Math::abs(d) < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + + // make it flat + n.z = 0.0; + n.normalize(); + n *= radius; + + r_amount = 2; + r_supports[0] = n; + r_supports[0].z += height * 0.5; + r_supports[1] = n; + r_supports[1].z -= height * 0.5; + + } else { + + real_t h = (d > 0) ? height : -height; + + n *= radius; + n.z += h * 0.5; + r_amount = 1; + *r_supports = n; + } +} + +bool CapsuleShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + Vector3 norm = (p_end - p_begin).normalized(); + real_t min_d = 1e20; + + Vector3 res, n; + bool collision = false; + + Vector3 auxres, auxn; + bool collided; + + // test against cylinder and spheres :-| + + collided = Geometry::segment_intersects_cylinder(p_begin, p_end, height, radius, &auxres, &auxn); + + if (collided) { + real_t d = norm.dot(auxres); + if (d < min_d) { + min_d = d; + res = auxres; + n = auxn; + collision = true; + } + } + + collided = Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * 0.5), radius, &auxres, &auxn); + + if (collided) { + real_t d = norm.dot(auxres); + if (d < min_d) { + min_d = d; + res = auxres; + n = auxn; + collision = true; + } + } + + collided = Geometry::segment_intersects_sphere(p_begin, p_end, Vector3(0, 0, height * -0.5), radius, &auxres, &auxn); + + if (collided) { + real_t d = norm.dot(auxres); + + if (d < min_d) { + min_d = d; + res = auxres; + n = auxn; + collision = true; + } + } + + if (collision) { + + r_result = res; + r_normal = n; + } + return collision; +} + +bool CapsuleShape3DSW::intersect_point(const Vector3 &p_point) const { + + if (Math::abs(p_point.z) < height * 0.5) { + return Vector3(p_point.x, p_point.y, 0).length() < radius; + } else { + Vector3 p = p_point; + p.z = Math::abs(p.z) - height * 0.5; + return p.length() < radius; + } +} + +Vector3 CapsuleShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + Vector3 s[2] = { + Vector3(0, 0, -height * 0.5), + Vector3(0, 0, height * 0.5), + }; + + Vector3 p = Geometry::get_closest_point_to_segment(p_point, s); + + if (p.distance_to(p_point) < radius) + return p_point; + + return p + (p_point - p).normalized() * radius; +} + +Vector3 CapsuleShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + // use bad AABB approximation + Vector3 extents = get_aabb().size * 0.5; + + return Vector3( + (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), + (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), + (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); +} + +void CapsuleShape3DSW::_setup(real_t p_height, real_t p_radius) { + + height = p_height; + radius = p_radius; + configure(AABB(Vector3(-radius, -radius, -height * 0.5 - radius), Vector3(radius * 2, radius * 2, height + radius * 2.0))); +} + +void CapsuleShape3DSW::set_data(const Variant &p_data) { + + Dictionary d = p_data; + ERR_FAIL_COND(!d.has("radius")); + ERR_FAIL_COND(!d.has("height")); + _setup(d["height"], d["radius"]); +} + +Variant CapsuleShape3DSW::get_data() const { + + Dictionary d; + d["radius"] = radius; + d["height"] = height; + return d; +} + +CapsuleShape3DSW::CapsuleShape3DSW() { + + height = radius = 0; +} + +/********** CONVEX POLYGON *************/ + +void ConvexPolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + int vertex_count = mesh.vertices.size(); + if (vertex_count == 0) + return; + + const Vector3 *vrts = &mesh.vertices[0]; + + for (int i = 0; i < vertex_count; i++) { + + real_t d = p_normal.dot(p_transform.xform(vrts[i])); + + if (i == 0 || d > r_max) + r_max = d; + if (i == 0 || d < r_min) + r_min = d; + } +} + +Vector3 ConvexPolygonShape3DSW::get_support(const Vector3 &p_normal) const { + + Vector3 n = p_normal; + + int vert_support_idx = -1; + real_t support_max = 0; + + int vertex_count = mesh.vertices.size(); + if (vertex_count == 0) + return Vector3(); + + const Vector3 *vrts = &mesh.vertices[0]; + + for (int i = 0; i < vertex_count; i++) { + + real_t d = n.dot(vrts[i]); + + if (i == 0 || d > support_max) { + support_max = d; + vert_support_idx = i; + } + } + + return vrts[vert_support_idx]; +} + +void ConvexPolygonShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int fc = mesh.faces.size(); + + const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); + int ec = mesh.edges.size(); + + const Vector3 *vertices = mesh.vertices.ptr(); + int vc = mesh.vertices.size(); + + //find vertex first + real_t max = 0; + int vtx = 0; + + for (int i = 0; i < vc; i++) { + + real_t d = p_normal.dot(vertices[i]); + + if (i == 0 || d > max) { + max = d; + vtx = i; + } + } + + for (int i = 0; i < fc; i++) { + + if (faces[i].plane.normal.dot(p_normal) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + + int ic = faces[i].indices.size(); + const int *ind = faces[i].indices.ptr(); + + bool valid = false; + for (int j = 0; j < ic; j++) { + if (ind[j] == vtx) { + valid = true; + break; + } + } + + if (!valid) + continue; + + int m = MIN(p_max, ic); + for (int j = 0; j < m; j++) { + + r_supports[j] = vertices[ind[j]]; + } + r_amount = m; + return; + } + } + + for (int i = 0; i < ec; i++) { + + real_t dot = (vertices[edges[i].a] - vertices[edges[i].b]).normalized().dot(p_normal); + dot = ABS(dot); + if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD && (edges[i].a == vtx || edges[i].b == vtx)) { + + r_amount = 2; + r_supports[0] = vertices[edges[i].a]; + r_supports[1] = vertices[edges[i].b]; + return; + } + } + + r_supports[0] = vertices[vtx]; + r_amount = 1; +} + +bool ConvexPolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int fc = mesh.faces.size(); + + const Vector3 *vertices = mesh.vertices.ptr(); + + Vector3 n = p_end - p_begin; + real_t min = 1e20; + bool col = false; + + for (int i = 0; i < fc; i++) { + + if (faces[i].plane.normal.dot(n) > 0) + continue; //opposing face + + int ic = faces[i].indices.size(); + const int *ind = faces[i].indices.ptr(); + + for (int j = 1; j < ic - 1; j++) { + + Face3 f(vertices[ind[0]], vertices[ind[j]], vertices[ind[j + 1]]); + Vector3 result; + if (f.intersects_segment(p_begin, p_end, &result)) { + real_t d = n.dot(result); + if (d < min) { + min = d; + r_result = result; + r_normal = faces[i].plane.normal; + col = true; + } + + break; + } + } + } + + return col; +} + +bool ConvexPolygonShape3DSW::intersect_point(const Vector3 &p_point) const { + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int fc = mesh.faces.size(); + + for (int i = 0; i < fc; i++) { + + if (faces[i].plane.distance_to(p_point) >= 0) + return false; + } + + return true; +} + +Vector3 ConvexPolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + const Geometry::MeshData::Face *faces = mesh.faces.ptr(); + int fc = mesh.faces.size(); + const Vector3 *vertices = mesh.vertices.ptr(); + + bool all_inside = true; + for (int i = 0; i < fc; i++) { + + if (!faces[i].plane.is_point_over(p_point)) + continue; + + all_inside = false; + bool is_inside = true; + int ic = faces[i].indices.size(); + const int *indices = faces[i].indices.ptr(); + + for (int j = 0; j < ic; j++) { + + Vector3 a = vertices[indices[j]]; + Vector3 b = vertices[indices[(j + 1) % ic]]; + Vector3 n = (a - b).cross(faces[i].plane.normal).normalized(); + if (Plane(a, n).is_point_over(p_point)) { + is_inside = false; + break; + } + } + + if (is_inside) { + return faces[i].plane.project(p_point); + } + } + + if (all_inside) { + return p_point; + } + + float min_distance = 1e20; + Vector3 min_point; + + //check edges + const Geometry::MeshData::Edge *edges = mesh.edges.ptr(); + int ec = mesh.edges.size(); + for (int i = 0; i < ec; i++) { + + Vector3 s[2] = { + vertices[edges[i].a], + vertices[edges[i].b] + }; + + Vector3 closest = Geometry::get_closest_point_to_segment(p_point, s); + float d = closest.distance_to(p_point); + if (d < min_distance) { + min_distance = d; + min_point = closest; + } + } + + return min_point; +} + +Vector3 ConvexPolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + // use bad AABB approximation + Vector3 extents = get_aabb().size * 0.5; + + return Vector3( + (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), + (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), + (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); +} + +void ConvexPolygonShape3DSW::_setup(const Vector &p_vertices) { + + Error err = QuickHull::build(p_vertices, mesh); + if (err != OK) + ERR_PRINT("Failed to build QuickHull"); + + AABB _aabb; + + for (int i = 0; i < mesh.vertices.size(); i++) { + + if (i == 0) + _aabb.position = mesh.vertices[i]; + else + _aabb.expand_to(mesh.vertices[i]); + } + + configure(_aabb); +} + +void ConvexPolygonShape3DSW::set_data(const Variant &p_data) { + + _setup(p_data); +} + +Variant ConvexPolygonShape3DSW::get_data() const { + + return mesh.vertices; +} + +ConvexPolygonShape3DSW::ConvexPolygonShape3DSW() { +} + +/********** FACE POLYGON *************/ + +void FaceShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + for (int i = 0; i < 3; i++) { + + Vector3 v = p_transform.xform(vertex[i]); + real_t d = p_normal.dot(v); + + if (i == 0 || d > r_max) + r_max = d; + + if (i == 0 || d < r_min) + r_min = d; + } +} + +Vector3 FaceShape3DSW::get_support(const Vector3 &p_normal) const { + + int vert_support_idx = -1; + real_t support_max = 0; + + for (int i = 0; i < 3; i++) { + + real_t d = p_normal.dot(vertex[i]); + + if (i == 0 || d > support_max) { + support_max = d; + vert_support_idx = i; + } + } + + return vertex[vert_support_idx]; +} + +void FaceShape3DSW::get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { + + Vector3 n = p_normal; + + /** TEST FACE AS SUPPORT **/ + if (normal.dot(n) > _FACE_IS_VALID_SUPPORT_THRESHOLD) { + + r_amount = 3; + for (int i = 0; i < 3; i++) { + + r_supports[i] = vertex[i]; + } + return; + } + + /** FIND SUPPORT VERTEX **/ + + int vert_support_idx = -1; + real_t support_max = 0; + + for (int i = 0; i < 3; i++) { + + real_t d = n.dot(vertex[i]); + + if (i == 0 || d > support_max) { + support_max = d; + vert_support_idx = i; + } + } + + /** TEST EDGES AS SUPPORT **/ + + for (int i = 0; i < 3; i++) { + + int nx = (i + 1) % 3; + if (i != vert_support_idx && nx != vert_support_idx) + continue; + + // check if edge is valid as a support + real_t dot = (vertex[i] - vertex[nx]).normalized().dot(n); + dot = ABS(dot); + if (dot < _EDGE_IS_VALID_SUPPORT_THRESHOLD) { + + r_amount = 2; + r_supports[0] = vertex[i]; + r_supports[1] = vertex[nx]; + return; + } + } + + r_amount = 1; + r_supports[0] = vertex[vert_support_idx]; +} + +bool FaceShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + bool c = Geometry::segment_intersects_triangle(p_begin, p_end, vertex[0], vertex[1], vertex[2], &r_result); + if (c) { + r_normal = Plane(vertex[0], vertex[1], vertex[2]).normal; + if (r_normal.dot(p_end - p_begin) > 0) { + r_normal = -r_normal; + } + } + + return c; +} + +bool FaceShape3DSW::intersect_point(const Vector3 &p_point) const { + + return false; //face is flat +} + +Vector3 FaceShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + return Face3(vertex[0], vertex[1], vertex[2]).get_closest_point_to(p_point); +} + +Vector3 FaceShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + return Vector3(); // Sorry, but i don't think anyone cares, FaceShape! +} + +FaceShape3DSW::FaceShape3DSW() { + + configure(AABB()); +} + +Vector ConcavePolygonShape3DSW::get_faces() const { + + Vector rfaces; + rfaces.resize(faces.size() * 3); + + for (int i = 0; i < faces.size(); i++) { + + Face f = faces.get(i); + + for (int j = 0; j < 3; j++) { + + rfaces.set(i * 3 + j, vertices.get(f.indices[j])); + } + } + + return rfaces; +} + +void ConcavePolygonShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + int count = vertices.size(); + if (count == 0) { + r_min = 0; + r_max = 0; + return; + } + const Vector3 *vptr = vertices.ptr(); + + for (int i = 0; i < count; i++) { + + real_t d = p_normal.dot(p_transform.xform(vptr[i])); + + if (i == 0 || d > r_max) + r_max = d; + if (i == 0 || d < r_min) + r_min = d; + } +} + +Vector3 ConcavePolygonShape3DSW::get_support(const Vector3 &p_normal) const { + + int count = vertices.size(); + if (count == 0) + return Vector3(); + + const Vector3 *vptr = vertices.ptr(); + + Vector3 n = p_normal; + + int vert_support_idx = -1; + real_t support_max = 0; + + for (int i = 0; i < count; i++) { + + real_t d = n.dot(vptr[i]); + + if (i == 0 || d > support_max) { + support_max = d; + vert_support_idx = i; + } + } + + return vptr[vert_support_idx]; +} + +void ConcavePolygonShape3DSW::_cull_segment(int p_idx, _SegmentCullParams *p_params) const { + + const BVH *bvh = &p_params->bvh[p_idx]; + + /* + if (p_params->dir.dot(bvh->aabb.get_support(-p_params->dir))>p_params->min_d) + return; //test against whole AABB, which isn't very costly + */ + + //printf("addr: %p\n",bvh); + if (!bvh->aabb.intersects_segment(p_params->from, p_params->to)) { + + return; + } + + if (bvh->face_index >= 0) { + + Vector3 res; + Vector3 vertices[3] = { + p_params->vertices[p_params->faces[bvh->face_index].indices[0]], + p_params->vertices[p_params->faces[bvh->face_index].indices[1]], + p_params->vertices[p_params->faces[bvh->face_index].indices[2]] + }; + + if (Geometry::segment_intersects_triangle( + p_params->from, + p_params->to, + vertices[0], + vertices[1], + vertices[2], + &res)) { + + real_t d = p_params->dir.dot(res) - p_params->dir.dot(p_params->from); + //TODO, seems segmen/triangle intersection is broken :( + if (d > 0 && d < p_params->min_d) { + + p_params->min_d = d; + p_params->result = res; + p_params->normal = Plane(vertices[0], vertices[1], vertices[2]).normal; + p_params->collisions++; + } + } + + } else { + + if (bvh->left >= 0) + _cull_segment(bvh->left, p_params); + if (bvh->right >= 0) + _cull_segment(bvh->right, p_params); + } +} + +bool ConcavePolygonShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { + + if (faces.size() == 0) + return false; + + // unlock data + const Face *fr = faces.ptr(); + const Vector3 *vr = vertices.ptr(); + const BVH *br = bvh.ptr(); + + _SegmentCullParams params; + params.from = p_begin; + params.to = p_end; + params.collisions = 0; + params.dir = (p_end - p_begin).normalized(); + + params.faces = fr; + params.vertices = vr; + params.bvh = br; + + params.min_d = 1e20; + // cull + _cull_segment(0, ¶ms); + + if (params.collisions > 0) { + + r_result = params.result; + r_normal = params.normal; + return true; + } else { + + return false; + } +} + +bool ConcavePolygonShape3DSW::intersect_point(const Vector3 &p_point) const { + + return false; //face is flat +} + +Vector3 ConcavePolygonShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + return Vector3(); +} + +void ConcavePolygonShape3DSW::_cull(int p_idx, _CullParams *p_params) const { + + const BVH *bvh = &p_params->bvh[p_idx]; + + if (!p_params->aabb.intersects(bvh->aabb)) + return; + + if (bvh->face_index >= 0) { + + const Face *f = &p_params->faces[bvh->face_index]; + FaceShape3DSW *face = p_params->face; + face->normal = f->normal; + face->vertex[0] = p_params->vertices[f->indices[0]]; + face->vertex[1] = p_params->vertices[f->indices[1]]; + face->vertex[2] = p_params->vertices[f->indices[2]]; + p_params->callback(p_params->userdata, face); + + } else { + + if (bvh->left >= 0) { + + _cull(bvh->left, p_params); + } + + if (bvh->right >= 0) { + + _cull(bvh->right, p_params); + } + } +} + +void ConcavePolygonShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const { + + // make matrix local to concave + if (faces.size() == 0) + return; + + AABB local_aabb = p_local_aabb; + + // unlock data + const Face *fr = faces.ptr(); + const Vector3 *vr = vertices.ptr(); + const BVH *br = bvh.ptr(); + + FaceShape3DSW face; // use this to send in the callback + + _CullParams params; + params.aabb = local_aabb; + params.face = &face; + params.faces = fr; + params.vertices = vr; + params.bvh = br; + params.callback = p_callback; + params.userdata = p_userdata; + + // cull + _cull(0, ¶ms); +} + +Vector3 ConcavePolygonShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + // use bad AABB approximation + Vector3 extents = get_aabb().size * 0.5; + + return Vector3( + (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), + (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), + (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); +} + +struct _VolumeSW_BVH_Element { + + AABB aabb; + Vector3 center; + int face_index; +}; + +struct _VolumeSW_BVH_CompareX { + + _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { + + return a.center.x < b.center.x; + } +}; + +struct _VolumeSW_BVH_CompareY { + + _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { + + return a.center.y < b.center.y; + } +}; + +struct _VolumeSW_BVH_CompareZ { + + _FORCE_INLINE_ bool operator()(const _VolumeSW_BVH_Element &a, const _VolumeSW_BVH_Element &b) const { + + return a.center.z < b.center.z; + } +}; + +struct _VolumeSW_BVH { + + AABB aabb; + _VolumeSW_BVH *left; + _VolumeSW_BVH *right; + + int face_index; +}; + +_VolumeSW_BVH *_volume_sw_build_bvh(_VolumeSW_BVH_Element *p_elements, int p_size, int &count) { + + _VolumeSW_BVH *bvh = memnew(_VolumeSW_BVH); + + if (p_size == 1) { + //leaf + bvh->aabb = p_elements[0].aabb; + bvh->left = NULL; + bvh->right = NULL; + bvh->face_index = p_elements->face_index; + count++; + return bvh; + } else { + + bvh->face_index = -1; + } + + AABB aabb; + for (int i = 0; i < p_size; i++) { + + if (i == 0) + aabb = p_elements[i].aabb; + else + aabb.merge_with(p_elements[i].aabb); + } + bvh->aabb = aabb; + switch (aabb.get_longest_axis_index()) { + + case 0: { + + SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareX> sort_x; + sort_x.sort(p_elements, p_size); + + } break; + case 1: { + + SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareY> sort_y; + sort_y.sort(p_elements, p_size); + } break; + case 2: { + + SortArray<_VolumeSW_BVH_Element, _VolumeSW_BVH_CompareZ> sort_z; + sort_z.sort(p_elements, p_size); + } break; + } + + int split = p_size / 2; + bvh->left = _volume_sw_build_bvh(p_elements, split, count); + bvh->right = _volume_sw_build_bvh(&p_elements[split], p_size - split, count); + + //printf("branch at %p - %i: %i\n",bvh,count,bvh->face_index); + count++; + return bvh; +} + +void ConcavePolygonShape3DSW::_fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx) { + + int idx = p_idx; + + p_bvh_array[idx].aabb = p_bvh_tree->aabb; + p_bvh_array[idx].face_index = p_bvh_tree->face_index; + //printf("%p - %i: %i(%p) -- %p:%p\n",%p_bvh_array[idx],p_idx,p_bvh_array[i]->face_index,&p_bvh_tree->face_index,p_bvh_tree->left,p_bvh_tree->right); + + if (p_bvh_tree->left) { + p_bvh_array[idx].left = ++p_idx; + _fill_bvh(p_bvh_tree->left, p_bvh_array, p_idx); + + } else { + + p_bvh_array[p_idx].left = -1; + } + + if (p_bvh_tree->right) { + p_bvh_array[idx].right = ++p_idx; + _fill_bvh(p_bvh_tree->right, p_bvh_array, p_idx); + + } else { + + p_bvh_array[p_idx].right = -1; + } + + memdelete(p_bvh_tree); +} + +void ConcavePolygonShape3DSW::_setup(Vector p_faces) { + + int src_face_count = p_faces.size(); + if (src_face_count == 0) { + configure(AABB()); + return; + } + ERR_FAIL_COND(src_face_count % 3); + src_face_count /= 3; + + const Vector3 *facesr = p_faces.ptr(); + + Vector<_VolumeSW_BVH_Element> bvh_array; + bvh_array.resize(src_face_count); + + _VolumeSW_BVH_Element *bvh_arrayw = bvh_array.ptrw(); + + faces.resize(src_face_count); + Face *facesw = faces.ptrw(); + + vertices.resize(src_face_count * 3); + + Vector3 *verticesw = vertices.ptrw(); + + AABB _aabb; + + for (int i = 0; i < src_face_count; i++) { + + Face3 face(facesr[i * 3 + 0], facesr[i * 3 + 1], facesr[i * 3 + 2]); + + bvh_arrayw[i].aabb = face.get_aabb(); + bvh_arrayw[i].center = bvh_arrayw[i].aabb.position + bvh_arrayw[i].aabb.size * 0.5; + bvh_arrayw[i].face_index = i; + facesw[i].indices[0] = i * 3 + 0; + facesw[i].indices[1] = i * 3 + 1; + facesw[i].indices[2] = i * 3 + 2; + facesw[i].normal = face.get_plane().normal; + verticesw[i * 3 + 0] = face.vertex[0]; + verticesw[i * 3 + 1] = face.vertex[1]; + verticesw[i * 3 + 2] = face.vertex[2]; + if (i == 0) + _aabb = bvh_arrayw[i].aabb; + else + _aabb.merge_with(bvh_arrayw[i].aabb); + } + + int count = 0; + _VolumeSW_BVH *bvh_tree = _volume_sw_build_bvh(bvh_arrayw, src_face_count, count); + + bvh.resize(count + 1); + + BVH *bvh_arrayw2 = bvh.ptrw(); + + int idx = 0; + _fill_bvh(bvh_tree, bvh_arrayw2, idx); + + configure(_aabb); // this type of shape has no margin +} + +void ConcavePolygonShape3DSW::set_data(const Variant &p_data) { + + _setup(p_data); +} + +Variant ConcavePolygonShape3DSW::get_data() const { + + return get_faces(); +} + +ConcavePolygonShape3DSW::ConcavePolygonShape3DSW() { +} + +/* HEIGHT MAP SHAPE */ + +Vector HeightMapShape3DSW::get_heights() const { + + return heights; +} +int HeightMapShape3DSW::get_width() const { + + return width; +} +int HeightMapShape3DSW::get_depth() const { + + return depth; +} +real_t HeightMapShape3DSW::get_cell_size() const { + + return cell_size; +} + +void HeightMapShape3DSW::project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + //not very useful, but not very used either + p_transform.xform(get_aabb()).project_range_in_plane(Plane(p_normal, 0), r_min, r_max); +} + +Vector3 HeightMapShape3DSW::get_support(const Vector3 &p_normal) const { + + //not very useful, but not very used either + return get_aabb().get_support(p_normal); +} + +bool HeightMapShape3DSW::intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const { + + return false; +} + +bool HeightMapShape3DSW::intersect_point(const Vector3 &p_point) const { + return false; +} + +Vector3 HeightMapShape3DSW::get_closest_point_to(const Vector3 &p_point) const { + + return Vector3(); +} + +void HeightMapShape3DSW::cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const { +} + +Vector3 HeightMapShape3DSW::get_moment_of_inertia(real_t p_mass) const { + + // use bad AABB approximation + Vector3 extents = get_aabb().size * 0.5; + + return Vector3( + (p_mass / 3.0) * (extents.y * extents.y + extents.z * extents.z), + (p_mass / 3.0) * (extents.x * extents.x + extents.z * extents.z), + (p_mass / 3.0) * (extents.y * extents.y + extents.y * extents.y)); +} + +void HeightMapShape3DSW::_setup(Vector p_heights, int p_width, int p_depth, real_t p_cell_size) { + + heights = p_heights; + width = p_width; + depth = p_depth; + cell_size = p_cell_size; + + const real_t *r = heights.ptr(); + + AABB aabb; + + for (int i = 0; i < depth; i++) { + + for (int j = 0; j < width; j++) { + + real_t h = r[i * width + j]; + + Vector3 pos(j * cell_size, h, i * cell_size); + if (i == 0 || j == 0) + aabb.position = pos; + else + aabb.expand_to(pos); + } + } + + configure(aabb); +} + +void HeightMapShape3DSW::set_data(const Variant &p_data) { + + ERR_FAIL_COND(p_data.get_type() != Variant::DICTIONARY); + Dictionary d = p_data; + ERR_FAIL_COND(!d.has("width")); + ERR_FAIL_COND(!d.has("depth")); + ERR_FAIL_COND(!d.has("cell_size")); + ERR_FAIL_COND(!d.has("heights")); + + int width = d["width"]; + int depth = d["depth"]; + real_t cell_size = d["cell_size"]; + Vector heights = d["heights"]; + + ERR_FAIL_COND(width <= 0); + ERR_FAIL_COND(depth <= 0); + ERR_FAIL_COND(cell_size <= CMP_EPSILON); + ERR_FAIL_COND(heights.size() != (width * depth)); + _setup(heights, width, depth, cell_size); +} + +Variant HeightMapShape3DSW::get_data() const { + + ERR_FAIL_V(Variant()); +} + +HeightMapShape3DSW::HeightMapShape3DSW() { + + width = 0; + depth = 0; + cell_size = 0; +} diff --git a/servers/physics_3d/shape_3d_sw.h b/servers/physics_3d/shape_3d_sw.h new file mode 100644 index 0000000000..f10bd0771b --- /dev/null +++ b/servers/physics_3d/shape_3d_sw.h @@ -0,0 +1,470 @@ +/*************************************************************************/ +/* shape_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHAPE_SW_H +#define SHAPE_SW_H + +#include "core/math/geometry.h" +#include "servers/physics_server_3d.h" +/* + +SHAPE_LINE, ///< plane:"plane" +SHAPE_SEGMENT, ///< real_t:"length" +SHAPE_CIRCLE, ///< real_t:"radius" +SHAPE_RECTANGLE, ///< vec3:"extents" +SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" +SHAPE_CONCAVE_POLYGON, ///< Vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) +SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error + +*/ + +class Shape3DSW; + +class ShapeOwner3DSW { +public: + virtual void _shape_changed() = 0; + virtual void remove_shape(Shape3DSW *p_shape) = 0; + + virtual ~ShapeOwner3DSW() {} +}; + +class Shape3DSW { + + RID self; + AABB aabb; + bool configured; + real_t custom_bias; + + Map owners; + +protected: + void configure(const AABB &p_aabb); + +public: + enum { + MAX_SUPPORTS = 8 + }; + + virtual real_t get_area() const { return aabb.get_area(); } + + _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } + _FORCE_INLINE_ RID get_self() const { return self; } + + virtual PhysicsServer3D::ShapeType get_type() const = 0; + + _FORCE_INLINE_ AABB get_aabb() const { return aabb; } + _FORCE_INLINE_ bool is_configured() const { return configured; } + + virtual bool is_concave() const { return false; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const = 0; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const = 0; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const = 0; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const = 0; + virtual bool intersect_point(const Vector3 &p_point) const = 0; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const = 0; + + virtual void set_data(const Variant &p_data) = 0; + virtual Variant get_data() const = 0; + + _FORCE_INLINE_ void set_custom_bias(real_t p_bias) { custom_bias = p_bias; } + _FORCE_INLINE_ real_t get_custom_bias() const { return custom_bias; } + + void add_owner(ShapeOwner3DSW *p_owner); + void remove_owner(ShapeOwner3DSW *p_owner); + bool is_owner(ShapeOwner3DSW *p_owner) const; + const Map &get_owners() const; + + Shape3DSW(); + virtual ~Shape3DSW(); +}; + +class ConcaveShape3DSW : public Shape3DSW { + +public: + virtual bool is_concave() const { return true; } + typedef void (*Callback)(void *p_userdata, Shape3DSW *p_convex); + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; } + + virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const = 0; + + ConcaveShape3DSW() {} +}; + +class PlaneShape3DSW : public Shape3DSW { + + Plane plane; + + void _setup(const Plane &p_plane); + +public: + Plane get_plane() const; + + virtual real_t get_area() const { return Math_INF; } + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_PLANE; } + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; } + + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + PlaneShape3DSW(); +}; + +class RayShape3DSW : public Shape3DSW { + + real_t length; + bool slips_on_slope; + + void _setup(real_t p_length, bool p_slips_on_slope); + +public: + real_t get_length() const; + bool get_slips_on_slope() const; + + virtual real_t get_area() const { return 0.0; } + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_RAY; } + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; + + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + RayShape3DSW(); +}; + +class SphereShape3DSW : public Shape3DSW { + + real_t radius; + + void _setup(real_t p_radius); + +public: + real_t get_radius() const; + + virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius; } + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_SPHERE; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + SphereShape3DSW(); +}; + +class BoxShape3DSW : public Shape3DSW { + + Vector3 half_extents; + void _setup(const Vector3 &p_half_extents); + +public: + _FORCE_INLINE_ Vector3 get_half_extents() const { return half_extents; } + virtual real_t get_area() const { return 8 * half_extents.x * half_extents.y * half_extents.z; } + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_BOX; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + BoxShape3DSW(); +}; + +class CapsuleShape3DSW : public Shape3DSW { + + real_t height; + real_t radius; + + void _setup(real_t p_height, real_t p_radius); + +public: + _FORCE_INLINE_ real_t get_height() const { return height; } + _FORCE_INLINE_ real_t get_radius() const { return radius; } + + virtual real_t get_area() const { return 4.0 / 3.0 * Math_PI * radius * radius * radius + height * Math_PI * radius * radius; } + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CAPSULE; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + CapsuleShape3DSW(); +}; + +struct ConvexPolygonShape3DSW : public Shape3DSW { + + Geometry::MeshData mesh; + + void _setup(const Vector &p_vertices); + +public: + const Geometry::MeshData &get_mesh() const { return mesh; } + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + ConvexPolygonShape3DSW(); +}; + +struct _VolumeSW_BVH; +struct FaceShape3DSW; + +struct ConcavePolygonShape3DSW : public ConcaveShape3DSW { + // always a trimesh + + struct Face { + + Vector3 normal; + int indices[3]; + }; + + Vector faces; + Vector vertices; + + struct BVH { + + AABB aabb; + int left; + int right; + + int face_index; + }; + + Vector bvh; + + struct _CullParams { + + AABB aabb; + Callback callback; + void *userdata; + const Face *faces; + const Vector3 *vertices; + const BVH *bvh; + FaceShape3DSW *face; + }; + + struct _SegmentCullParams { + + Vector3 from; + Vector3 to; + const Face *faces; + const Vector3 *vertices; + const BVH *bvh; + Vector3 dir; + + Vector3 result; + Vector3 normal; + real_t min_d; + int collisions; + }; + + void _cull_segment(int p_idx, _SegmentCullParams *p_params) const; + void _cull(int p_idx, _CullParams *p_params) const; + + void _fill_bvh(_VolumeSW_BVH *p_bvh_tree, BVH *p_bvh_array, int &p_idx); + + void _setup(Vector p_faces); + +public: + Vector get_faces() const; + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + ConcavePolygonShape3DSW(); +}; + +struct HeightMapShape3DSW : public ConcaveShape3DSW { + + Vector heights; + int width; + int depth; + real_t cell_size; + + //void _cull_segment(int p_idx,_SegmentCullParams *p_params) const; + //void _cull(int p_idx,_CullParams *p_params) const; + + void _setup(Vector p_heights, int p_width, int p_depth, real_t p_cell_size); + +public: + Vector get_heights() const; + int get_width() const; + int get_depth() const; + real_t get_cell_size() const; + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_HEIGHTMAP; } + + virtual void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + virtual Vector3 get_support(const Vector3 &p_normal) const; + virtual bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_point, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + virtual void cull(const AABB &p_local_aabb, Callback p_callback, void *p_userdata) const; + + virtual Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data); + virtual Variant get_data() const; + + HeightMapShape3DSW(); +}; + +//used internally +struct FaceShape3DSW : public Shape3DSW { + + Vector3 normal; //cache + Vector3 vertex[3]; + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONCAVE_POLYGON; } + + const Vector3 &get_vertex(int p_idx) const { return vertex[p_idx]; } + + void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const; + Vector3 get_support(const Vector3 &p_normal) const; + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const; + bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const; + virtual bool intersect_point(const Vector3 &p_point) const; + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const; + + Vector3 get_moment_of_inertia(real_t p_mass) const; + + virtual void set_data(const Variant &p_data) {} + virtual Variant get_data() const { return Variant(); } + + FaceShape3DSW(); +}; + +struct MotionShape3DSW : public Shape3DSW { + + Shape3DSW *shape; + Vector3 motion; + + virtual PhysicsServer3D::ShapeType get_type() const { return PhysicsServer3D::SHAPE_CONVEX_POLYGON; } + + void project_range(const Vector3 &p_normal, const Transform &p_transform, real_t &r_min, real_t &r_max) const { + + Vector3 cast = p_transform.basis.xform(motion); + real_t mina, maxa; + real_t minb, maxb; + Transform ofsb = p_transform; + ofsb.origin += cast; + shape->project_range(p_normal, p_transform, mina, maxa); + shape->project_range(p_normal, ofsb, minb, maxb); + r_min = MIN(mina, minb); + r_max = MAX(maxa, maxb); + } + + Vector3 get_support(const Vector3 &p_normal) const { + + Vector3 support = shape->get_support(p_normal); + if (p_normal.dot(motion) > 0) { + support += motion; + } + return support; + } + virtual void get_supports(const Vector3 &p_normal, int p_max, Vector3 *r_supports, int &r_amount) const { r_amount = 0; } + bool intersect_segment(const Vector3 &p_begin, const Vector3 &p_end, Vector3 &r_result, Vector3 &r_normal) const { return false; } + virtual bool intersect_point(const Vector3 &p_point) const { return false; } + virtual Vector3 get_closest_point_to(const Vector3 &p_point) const { return p_point; } + + Vector3 get_moment_of_inertia(real_t p_mass) const { return Vector3(); } + + virtual void set_data(const Variant &p_data) {} + virtual Variant get_data() const { return Variant(); } + + MotionShape3DSW() { configure(AABB()); } +}; + +#endif // SHAPE_SW_H diff --git a/servers/physics_3d/space_3d_sw.cpp b/servers/physics_3d/space_3d_sw.cpp new file mode 100644 index 0000000000..e7b2c7bfd7 --- /dev/null +++ b/servers/physics_3d/space_3d_sw.cpp @@ -0,0 +1,1242 @@ +/*************************************************************************/ +/* space_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "space_3d_sw.h" + +#include "collision_solver_3d_sw.h" +#include "core/project_settings.h" +#include "physics_server_3d_sw.h" + +_FORCE_INLINE_ static bool _can_collide_with(CollisionObject3DSW *p_object, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + + if (!(p_object->get_collision_layer() & p_collision_mask)) { + return false; + } + + if (p_object->get_type() == CollisionObject3DSW::TYPE_AREA && !p_collide_with_areas) + return false; + + if (p_object->get_type() == CollisionObject3DSW::TYPE_BODY && !p_collide_with_bodies) + return false; + + return true; +} + +int PhysicsDirectSpaceState3DSW::intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + + ERR_FAIL_COND_V(space->locked, false); + int amount = space->broadphase->cull_point(p_point, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + int cc = 0; + + //Transform ai = p_xform.affine_inverse(); + + for (int i = 0; i < amount; i++) { + + if (cc >= p_result_max) + break; + + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) + continue; + + //area can't be picked by ray (default) + + if (p_exclude.has(space->intersection_query_results[i]->get_self())) + continue; + + const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + int shape_idx = space->intersection_query_subindex_results[i]; + + Transform inv_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + inv_xform.affine_invert(); + + if (!col_obj->get_shape(shape_idx)->intersect_point(inv_xform.xform(p_point))) + continue; + + r_results[cc].collider_id = col_obj->get_instance_id(); + if (r_results[cc].collider_id.is_valid()) + r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); + else + r_results[cc].collider = NULL; + r_results[cc].rid = col_obj->get_self(); + r_results[cc].shape = shape_idx; + + cc++; + } + + return cc; +} + +bool PhysicsDirectSpaceState3DSW::intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_pick_ray) { + + ERR_FAIL_COND_V(space->locked, false); + + Vector3 begin, end; + Vector3 normal; + begin = p_from; + end = p_to; + normal = (end - begin).normalized(); + + int amount = space->broadphase->cull_segment(begin, end, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + + //todo, create another array that references results, compute AABBs and check closest point to ray origin, sort, and stop evaluating results when beyond first collision + + bool collided = false; + Vector3 res_point, res_normal; + int res_shape; + const CollisionObject3DSW *res_obj; + real_t min_d = 1e10; + + for (int i = 0; i < amount; i++) { + + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) + continue; + + if (p_pick_ray && !(space->intersection_query_results[i]->is_ray_pickable())) + continue; + + if (p_exclude.has(space->intersection_query_results[i]->get_self())) + continue; + + const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + + int shape_idx = space->intersection_query_subindex_results[i]; + Transform inv_xform = col_obj->get_shape_inv_transform(shape_idx) * col_obj->get_inv_transform(); + + Vector3 local_from = inv_xform.xform(begin); + Vector3 local_to = inv_xform.xform(end); + + const Shape3DSW *shape = col_obj->get_shape(shape_idx); + + Vector3 shape_point, shape_normal; + + if (shape->intersect_segment(local_from, local_to, shape_point, shape_normal)) { + + Transform xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + shape_point = xform.xform(shape_point); + + real_t ld = normal.dot(shape_point); + + if (ld < min_d) { + + min_d = ld; + res_point = shape_point; + res_normal = inv_xform.basis.xform_inv(shape_normal).normalized(); + res_shape = shape_idx; + res_obj = col_obj; + collided = true; + } + } + } + + if (!collided) + return false; + + r_result.collider_id = res_obj->get_instance_id(); + if (r_result.collider_id.is_valid()) + r_result.collider = ObjectDB::get_instance(r_result.collider_id); + else + r_result.collider = NULL; + r_result.normal = res_normal; + r_result.position = res_point; + r_result.rid = res_obj->get_self(); + r_result.shape = res_shape; + + return true; +} + +int PhysicsDirectSpaceState3DSW::intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + + if (p_result_max <= 0) + return 0; + + Shape3DSW *shape = static_cast(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); + + AABB aabb = p_xform.xform(shape->get_aabb()); + + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + + int cc = 0; + + //Transform ai = p_xform.affine_inverse(); + + for (int i = 0; i < amount; i++) { + + if (cc >= p_result_max) + break; + + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) + continue; + + //area can't be picked by ray (default) + + if (p_exclude.has(space->intersection_query_results[i]->get_self())) + continue; + + const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + int shape_idx = space->intersection_query_subindex_results[i]; + + if (!CollisionSolver3DSW::solve_static(shape, p_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), NULL, NULL, NULL, p_margin, 0)) + continue; + + if (r_results) { + r_results[cc].collider_id = col_obj->get_instance_id(); + if (r_results[cc].collider_id.is_valid()) + r_results[cc].collider = ObjectDB::get_instance(r_results[cc].collider_id); + else + r_results[cc].collider = NULL; + r_results[cc].rid = col_obj->get_self(); + r_results[cc].shape = shape_idx; + } + + cc++; + } + + return cc; +} + +bool PhysicsDirectSpaceState3DSW::cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas, ShapeRestInfo *r_info) { + + Shape3DSW *shape = static_cast(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, false); + + AABB aabb = p_xform.xform(shape->get_aabb()); + aabb = aabb.merge(AABB(aabb.position + p_motion, aabb.size)); //motion + aabb = aabb.grow(p_margin); + + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + + real_t best_safe = 1; + real_t best_unsafe = 1; + + Transform xform_inv = p_xform.affine_inverse(); + MotionShape3DSW mshape; + mshape.shape = shape; + mshape.motion = xform_inv.basis.xform(p_motion); + + bool best_first = true; + + Vector3 closest_A, closest_B; + + for (int i = 0; i < amount; i++) { + + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) + continue; + + if (p_exclude.has(space->intersection_query_results[i]->get_self())) + continue; //ignore excluded + + const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + int shape_idx = space->intersection_query_subindex_results[i]; + + Vector3 point_A, point_B; + Vector3 sep_axis = p_motion.normalized(); + + Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + //test initial overlap, does it collide if going all the way? + if (CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + continue; + } + + //test initial overlap + sep_axis = p_motion.normalized(); + + if (!CollisionSolver3DSW::solve_distance(shape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, aabb, &sep_axis)) { + return false; + } + + //just do kinematic solving + real_t low = 0; + real_t hi = 1; + Vector3 mnormal = p_motion.normalized(); + + for (int j = 0; j < 8; j++) { //steps should be customizable.. + + real_t ofs = (low + hi) * 0.5; + + Vector3 sep = mnormal; //important optimization for this to work fast enough + + mshape.motion = xform_inv.basis.xform(p_motion * ofs); + + Vector3 lA, lB; + + bool collided = !CollisionSolver3DSW::solve_distance(&mshape, p_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, aabb, &sep); + + if (collided) { + + hi = ofs; + } else { + + point_A = lA; + point_B = lB; + low = ofs; + } + } + + if (low < best_safe) { + best_first = true; //force reset + best_safe = low; + best_unsafe = hi; + } + + if (r_info && (best_first || (point_A.distance_squared_to(point_B) < closest_A.distance_squared_to(closest_B) && low <= best_safe))) { + closest_A = point_A; + closest_B = point_B; + r_info->collider_id = col_obj->get_instance_id(); + r_info->rid = col_obj->get_self(); + r_info->shape = shape_idx; + r_info->point = closest_B; + r_info->normal = (closest_A - closest_B).normalized(); + best_first = false; + if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) { + const Body3DSW *body = static_cast(col_obj); + r_info->linear_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - closest_B); + } + } + } + + p_closest_safe = best_safe; + p_closest_unsafe = best_unsafe; + + return true; +} + +bool PhysicsDirectSpaceState3DSW::collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + + if (p_result_max <= 0) + return 0; + + Shape3DSW *shape = static_cast(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); + + AABB aabb = p_shape_xform.xform(shape->get_aabb()); + aabb = aabb.grow(p_margin); + + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + + bool collided = false; + r_result_count = 0; + + PhysicsServer3DSW::CollCbkData cbk; + cbk.max = p_result_max; + cbk.amount = 0; + cbk.ptr = r_results; + CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk; + + PhysicsServer3DSW::CollCbkData *cbkptr = &cbk; + + for (int i = 0; i < amount; i++) { + + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) + continue; + + const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + int shape_idx = space->intersection_query_subindex_results[i]; + + if (p_exclude.has(col_obj->get_self())) { + continue; + } + + if (CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { + collided = true; + } + } + + r_result_count = cbk.amount; + + return collided; +} + +struct _RestCallbackData { + + const CollisionObject3DSW *object; + const CollisionObject3DSW *best_object; + int shape; + int best_shape; + Vector3 best_contact; + Vector3 best_normal; + real_t best_len; + real_t min_allowed_depth; +}; + +static void _rest_cbk_result(const Vector3 &p_point_A, const Vector3 &p_point_B, void *p_userdata) { + + _RestCallbackData *rd = (_RestCallbackData *)p_userdata; + + Vector3 contact_rel = p_point_B - p_point_A; + real_t len = contact_rel.length(); + if (len < rd->min_allowed_depth) + return; + if (len <= rd->best_len) + return; + + rd->best_len = len; + rd->best_contact = p_point_B; + rd->best_normal = contact_rel / len; + rd->best_object = rd->object; + rd->best_shape = rd->shape; +} +bool PhysicsDirectSpaceState3DSW::rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + + Shape3DSW *shape = static_cast(PhysicsServer3D::get_singleton())->shape_owner.getornull(p_shape); + ERR_FAIL_COND_V(!shape, 0); + + AABB aabb = p_shape_xform.xform(shape->get_aabb()); + aabb = aabb.grow(p_margin); + + int amount = space->broadphase->cull_aabb(aabb, space->intersection_query_results, Space3DSW::INTERSECTION_QUERY_MAX, space->intersection_query_subindex_results); + + _RestCallbackData rcd; + rcd.best_len = 0; + rcd.best_object = NULL; + rcd.best_shape = 0; + rcd.min_allowed_depth = space->test_motion_min_contact_depth; + + for (int i = 0; i < amount; i++) { + + if (!_can_collide_with(space->intersection_query_results[i], p_collision_mask, p_collide_with_bodies, p_collide_with_areas)) + continue; + + const CollisionObject3DSW *col_obj = space->intersection_query_results[i]; + int shape_idx = space->intersection_query_subindex_results[i]; + + if (p_exclude.has(col_obj->get_self())) + continue; + + rcd.object = col_obj; + rcd.shape = shape_idx; + bool sc = CollisionSolver3DSW::solve_static(shape, p_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, NULL, p_margin); + if (!sc) + continue; + } + + if (rcd.best_len == 0 || !rcd.best_object) + return false; + + r_info->collider_id = rcd.best_object->get_instance_id(); + r_info->shape = rcd.best_shape; + r_info->normal = rcd.best_normal; + r_info->point = rcd.best_contact; + r_info->rid = rcd.best_object->get_self(); + if (rcd.best_object->get_type() == CollisionObject3DSW::TYPE_BODY) { + + const Body3DSW *body = static_cast(rcd.best_object); + r_info->linear_velocity = body->get_linear_velocity() + + (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); + + } else { + r_info->linear_velocity = Vector3(); + } + + return true; +} + +Vector3 PhysicsDirectSpaceState3DSW::get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const { + + CollisionObject3DSW *obj = PhysicsServer3DSW::singleton->area_owner.getornull(p_object); + if (!obj) { + obj = PhysicsServer3DSW::singleton->body_owner.getornull(p_object); + } + ERR_FAIL_COND_V(!obj, Vector3()); + + ERR_FAIL_COND_V(obj->get_space() != space, Vector3()); + + float min_distance = 1e20; + Vector3 min_point; + + bool shapes_found = false; + + for (int i = 0; i < obj->get_shape_count(); i++) { + + if (obj->is_shape_set_as_disabled(i)) + continue; + + Transform shape_xform = obj->get_transform() * obj->get_shape_transform(i); + Shape3DSW *shape = obj->get_shape(i); + + Vector3 point = shape->get_closest_point_to(shape_xform.affine_inverse().xform(p_point)); + point = shape_xform.xform(point); + + float dist = point.distance_to(p_point); + if (dist < min_distance) { + min_distance = dist; + min_point = point; + } + shapes_found = true; + } + + if (!shapes_found) { + return obj->get_transform().origin; //no shapes found, use distance to origin. + } else { + return min_point; + } +} + +PhysicsDirectSpaceState3DSW::PhysicsDirectSpaceState3DSW() { + + space = NULL; +} + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +int Space3DSW::_cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb) { + + int amount = broadphase->cull_aabb(p_aabb, intersection_query_results, INTERSECTION_QUERY_MAX, intersection_query_subindex_results); + + for (int i = 0; i < amount; i++) { + + bool keep = true; + + if (intersection_query_results[i] == p_body) + keep = false; + else if (intersection_query_results[i]->get_type() == CollisionObject3DSW::TYPE_AREA) + keep = false; + else if ((static_cast(intersection_query_results[i])->test_collision_mask(p_body)) == 0) + keep = false; + else if (static_cast(intersection_query_results[i])->has_exception(p_body->get_self()) || p_body->has_exception(intersection_query_results[i]->get_self())) + keep = false; + else if (static_cast(intersection_query_results[i])->is_shape_set_as_disabled(intersection_query_subindex_results[i])) + keep = false; + + if (!keep) { + + if (i < amount - 1) { + SWAP(intersection_query_results[i], intersection_query_results[amount - 1]); + SWAP(intersection_query_subindex_results[i], intersection_query_subindex_results[amount - 1]); + } + + amount--; + i--; + } + } + + return amount; +} + +int Space3DSW::test_body_ray_separation(Body3DSW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin) { + + AABB body_aabb; + + bool shapes_found = false; + + for (int i = 0; i < p_body->get_shape_count(); i++) { + + if (p_body->is_shape_set_as_disabled(i)) + continue; + + if (!shapes_found) { + body_aabb = p_body->get_shape_aabb(i); + shapes_found = true; + } else { + body_aabb = body_aabb.merge(p_body->get_shape_aabb(i)); + } + } + + if (!shapes_found) { + return 0; + } + // Undo the currently transform the physics server is aware of and apply the provided one + body_aabb = p_transform.xform(p_body->get_inv_transform().xform(body_aabb)); + body_aabb = body_aabb.grow(p_margin); + + Transform body_transform = p_transform; + + for (int i = 0; i < p_result_max; i++) { + //reset results + r_results[i].collision_depth = 0; + } + + int rays_found = 0; + + { + // raycast AND separate + + const int max_results = 32; + int recover_attempts = 4; + Vector3 sr[max_results * 2]; + PhysicsServer3DSW::CollCbkData cbk; + cbk.max = max_results; + PhysicsServer3DSW::CollCbkData *cbkptr = &cbk; + CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk; + + do { + + Vector3 recover_motion; + + bool collided = false; + + int amount = _cull_aabb_for_body(p_body, body_aabb); + + for (int j = 0; j < p_body->get_shape_count(); j++) { + if (p_body->is_shape_set_as_disabled(j)) + continue; + + Shape3DSW *body_shape = p_body->get_shape(j); + + if (body_shape->get_type() != PhysicsServer3D::SHAPE_RAY) + continue; + + Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); + + for (int i = 0; i < amount; i++) { + + const CollisionObject3DSW *col_obj = intersection_query_results[i]; + int shape_idx = intersection_query_subindex_results[i]; + + cbk.amount = 0; + cbk.ptr = sr; + + if (CollisionObject3DSW::TYPE_BODY == col_obj->get_type()) { + const Body3DSW *b = static_cast(col_obj); + if (p_infinite_inertia && PhysicsServer3D::BODY_MODE_STATIC != b->get_mode() && PhysicsServer3D::BODY_MODE_KINEMATIC != b->get_mode()) { + continue; + } + } + + Shape3DSW *against_shape = col_obj->get_shape(shape_idx); + if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, against_shape, col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { + if (cbk.amount > 0) { + collided = true; + } + + int ray_index = -1; //reuse shape + for (int k = 0; k < rays_found; k++) { + if (r_results[k].collision_local_shape == j) { + ray_index = k; + } + } + + if (ray_index == -1 && rays_found < p_result_max) { + ray_index = rays_found; + rays_found++; + } + + if (ray_index != -1) { + PhysicsServer3D::SeparationResult &result = r_results[ray_index]; + + for (int k = 0; k < cbk.amount; k++) { + Vector3 a = sr[k * 2 + 0]; + Vector3 b = sr[k * 2 + 1]; + + recover_motion += (b - a) * 0.4; + + float depth = a.distance_to(b); + if (depth > result.collision_depth) { + + result.collision_depth = depth; + result.collision_point = b; + result.collision_normal = (b - a).normalized(); + result.collision_local_shape = j; + result.collider = col_obj->get_self(); + result.collider_id = col_obj->get_instance_id(); + result.collider_shape = shape_idx; + //result.collider_metadata = col_obj->get_shape_metadata(shape_idx); + if (col_obj->get_type() == CollisionObject3DSW::TYPE_BODY) { + Body3DSW *body = (Body3DSW *)col_obj; + + Vector3 rel_vec = b - body->get_transform().get_origin(); + //result.collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); + result.collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rel_vec); // * mPos); + } + } + } + } + } + } + } + + if (!collided || recover_motion == Vector3()) { + break; + } + + body_transform.origin += recover_motion; + body_aabb.position += recover_motion; + + recover_attempts--; + } while (recover_attempts); + } + + //optimize results (remove non colliding) + for (int i = 0; i < rays_found; i++) { + if (r_results[i].collision_depth == 0) { + rays_found--; + SWAP(r_results[i], r_results[rays_found]); + } + } + + r_recover_motion = body_transform.origin - p_transform.origin; + return rays_found; +} + +bool Space3DSW::test_body_motion(Body3DSW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes) { + + //give me back regular physics engine logic + //this is madness + //and most people using this function will think + //what it does is simpler than using physics + //this took about a week to get right.. + //but is it right? who knows at this point.. + + if (r_result) { + r_result->collider_id = ObjectID(); + r_result->collider_shape = 0; + } + AABB body_aabb; + bool shapes_found = false; + + for (int i = 0; i < p_body->get_shape_count(); i++) { + + if (p_body->is_shape_set_as_disabled(i)) + continue; + + if (!shapes_found) { + body_aabb = p_body->get_shape_aabb(i); + shapes_found = true; + } else { + body_aabb = body_aabb.merge(p_body->get_shape_aabb(i)); + } + } + + if (!shapes_found) { + if (r_result) { + *r_result = PhysicsServer3D::MotionResult(); + r_result->motion = p_motion; + } + + return false; + } + + // Undo the currently transform the physics server is aware of and apply the provided one + body_aabb = p_from.xform(p_body->get_inv_transform().xform(body_aabb)); + body_aabb = body_aabb.grow(p_margin); + + Transform body_transform = p_from; + + { + //STEP 1, FREE BODY IF STUCK + + const int max_results = 32; + int recover_attempts = 4; + Vector3 sr[max_results * 2]; + + do { + + PhysicsServer3DSW::CollCbkData cbk; + cbk.max = max_results; + cbk.amount = 0; + cbk.ptr = sr; + + PhysicsServer3DSW::CollCbkData *cbkptr = &cbk; + CollisionSolver3DSW::CallbackResult cbkres = PhysicsServer3DSW::_shape_col_cbk; + + bool collided = false; + + int amount = _cull_aabb_for_body(p_body, body_aabb); + + for (int j = 0; j < p_body->get_shape_count(); j++) { + if (p_body->is_shape_set_as_disabled(j)) + continue; + + Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); + Shape3DSW *body_shape = p_body->get_shape(j); + if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) { + continue; + } + + for (int i = 0; i < amount; i++) { + + const CollisionObject3DSW *col_obj = intersection_query_results[i]; + int shape_idx = intersection_query_subindex_results[i]; + + if (CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), cbkres, cbkptr, NULL, p_margin)) { + collided = cbk.amount > 0; + } + } + } + + if (!collided) { + break; + } + + Vector3 recover_motion; + + for (int i = 0; i < cbk.amount; i++) { + + Vector3 a = sr[i * 2 + 0]; + Vector3 b = sr[i * 2 + 1]; + recover_motion += (b - a) * 0.4; + } + + if (recover_motion == Vector3()) { + collided = false; + break; + } + + body_transform.origin += recover_motion; + body_aabb.position += recover_motion; + + recover_attempts--; + + } while (recover_attempts); + } + + real_t safe = 1.0; + real_t unsafe = 1.0; + int best_shape = -1; + + { + // STEP 2 ATTEMPT MOTION + + AABB motion_aabb = body_aabb; + motion_aabb.position += p_motion; + motion_aabb = motion_aabb.merge(body_aabb); + + int amount = _cull_aabb_for_body(p_body, motion_aabb); + + for (int j = 0; j < p_body->get_shape_count(); j++) { + + if (p_body->is_shape_set_as_disabled(j)) + continue; + + Transform body_shape_xform = body_transform * p_body->get_shape_transform(j); + Shape3DSW *body_shape = p_body->get_shape(j); + + if (p_exclude_raycast_shapes && body_shape->get_type() == PhysicsServer3D::SHAPE_RAY) { + continue; + } + + Transform body_shape_xform_inv = body_shape_xform.affine_inverse(); + MotionShape3DSW mshape; + mshape.shape = body_shape; + mshape.motion = body_shape_xform_inv.basis.xform(p_motion); + + bool stuck = false; + + real_t best_safe = 1; + real_t best_unsafe = 1; + + for (int i = 0; i < amount; i++) { + + const CollisionObject3DSW *col_obj = intersection_query_results[i]; + int shape_idx = intersection_query_subindex_results[i]; + + //test initial overlap, does it collide if going all the way? + Vector3 point_A, point_B; + Vector3 sep_axis = p_motion.normalized(); + + Transform col_obj_xform = col_obj->get_transform() * col_obj->get_shape_transform(shape_idx); + //test initial overlap, does it collide if going all the way? + if (CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { + continue; + } + sep_axis = p_motion.normalized(); + + if (!CollisionSolver3DSW::solve_distance(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, point_A, point_B, motion_aabb, &sep_axis)) { + stuck = true; + break; + } + + //just do kinematic solving + real_t low = 0; + real_t hi = 1; + Vector3 mnormal = p_motion.normalized(); + + for (int k = 0; k < 8; k++) { //steps should be customizable.. + + real_t ofs = (low + hi) * 0.5; + + Vector3 sep = mnormal; //important optimization for this to work fast enough + + mshape.motion = body_shape_xform_inv.basis.xform(p_motion * ofs); + + Vector3 lA, lB; + + bool collided = !CollisionSolver3DSW::solve_distance(&mshape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj_xform, lA, lB, motion_aabb, &sep); + + if (collided) { + + hi = ofs; + } else { + + point_A = lA; + point_B = lB; + low = ofs; + } + } + + if (low < best_safe) { + best_safe = low; + best_unsafe = hi; + } + } + + if (stuck) { + + safe = 0; + unsafe = 0; + best_shape = j; //sadly it's the best + break; + } + if (best_safe == 1.0) { + continue; + } + if (best_safe < safe) { + + safe = best_safe; + unsafe = best_unsafe; + best_shape = j; + } + } + } + + bool collided = false; + if (safe >= 1) { + //not collided + collided = false; + if (r_result) { + + r_result->motion = p_motion; + r_result->remainder = Vector3(); + r_result->motion += (body_transform.get_origin() - p_from.get_origin()); + } + + } else { + + //it collided, let's get the rest info in unsafe advance + Transform ugt = body_transform; + ugt.origin += p_motion * unsafe; + + _RestCallbackData rcd; + rcd.best_len = 0; + rcd.best_object = NULL; + rcd.best_shape = 0; + rcd.min_allowed_depth = test_motion_min_contact_depth; + + Transform body_shape_xform = ugt * p_body->get_shape_transform(best_shape); + Shape3DSW *body_shape = p_body->get_shape(best_shape); + + body_aabb.position += p_motion * unsafe; + + int amount = _cull_aabb_for_body(p_body, body_aabb); + + for (int i = 0; i < amount; i++) { + + const CollisionObject3DSW *col_obj = intersection_query_results[i]; + int shape_idx = intersection_query_subindex_results[i]; + + rcd.object = col_obj; + rcd.shape = shape_idx; + bool sc = CollisionSolver3DSW::solve_static(body_shape, body_shape_xform, col_obj->get_shape(shape_idx), col_obj->get_transform() * col_obj->get_shape_transform(shape_idx), _rest_cbk_result, &rcd, NULL, p_margin); + if (!sc) + continue; + } + + if (rcd.best_len != 0) { + + if (r_result) { + r_result->collider = rcd.best_object->get_self(); + r_result->collider_id = rcd.best_object->get_instance_id(); + r_result->collider_shape = rcd.best_shape; + r_result->collision_local_shape = best_shape; + r_result->collision_normal = rcd.best_normal; + r_result->collision_point = rcd.best_contact; + //r_result->collider_metadata = rcd.best_object->get_shape_metadata(rcd.best_shape); + + const Body3DSW *body = static_cast(rcd.best_object); + //Vector3 rel_vec = r_result->collision_point - body->get_transform().get_origin(); + // r_result->collider_velocity = Vector3(-body->get_angular_velocity() * rel_vec.y, body->get_angular_velocity() * rel_vec.x) + body->get_linear_velocity(); + r_result->collider_velocity = body->get_linear_velocity() + (body->get_angular_velocity()).cross(body->get_transform().origin - rcd.best_contact); // * mPos); + + r_result->motion = safe * p_motion; + r_result->remainder = p_motion - safe * p_motion; + r_result->motion += (body_transform.get_origin() - p_from.get_origin()); + } + + collided = true; + } else { + if (r_result) { + + r_result->motion = p_motion; + r_result->remainder = Vector3(); + r_result->motion += (body_transform.get_origin() - p_from.get_origin()); + } + + collided = false; + } + } + + return collided; +} + +void *Space3DSW::_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self) { + + CollisionObject3DSW::Type type_A = A->get_type(); + CollisionObject3DSW::Type type_B = B->get_type(); + if (type_A > type_B) { + + SWAP(A, B); + SWAP(p_subindex_A, p_subindex_B); + SWAP(type_A, type_B); + } + + Space3DSW *self = (Space3DSW *)p_self; + + self->collision_pairs++; + + if (type_A == CollisionObject3DSW::TYPE_AREA) { + + Area3DSW *area = static_cast(A); + if (type_B == CollisionObject3DSW::TYPE_AREA) { + + Area3DSW *area_b = static_cast(B); + Area2Pair3DSW *area2_pair = memnew(Area2Pair3DSW(area_b, p_subindex_B, area, p_subindex_A)); + return area2_pair; + } else { + + Body3DSW *body = static_cast(B); + AreaPair3DSW *area_pair = memnew(AreaPair3DSW(body, p_subindex_B, area, p_subindex_A)); + return area_pair; + } + } else { + + BodyPair3DSW *b = memnew(BodyPair3DSW((Body3DSW *)A, p_subindex_A, (Body3DSW *)B, p_subindex_B)); + return b; + } + + return NULL; +} + +void Space3DSW::_broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self) { + + Space3DSW *self = (Space3DSW *)p_self; + self->collision_pairs--; + Constraint3DSW *c = (Constraint3DSW *)p_data; + memdelete(c); +} + +const SelfList::List &Space3DSW::get_active_body_list() const { + + return active_list; +} +void Space3DSW::body_add_to_active_list(SelfList *p_body) { + + active_list.add(p_body); +} +void Space3DSW::body_remove_from_active_list(SelfList *p_body) { + + active_list.remove(p_body); +} + +void Space3DSW::body_add_to_inertia_update_list(SelfList *p_body) { + + inertia_update_list.add(p_body); +} + +void Space3DSW::body_remove_from_inertia_update_list(SelfList *p_body) { + + inertia_update_list.remove(p_body); +} + +BroadPhase3DSW *Space3DSW::get_broadphase() { + + return broadphase; +} + +void Space3DSW::add_object(CollisionObject3DSW *p_object) { + + ERR_FAIL_COND(objects.has(p_object)); + objects.insert(p_object); +} + +void Space3DSW::remove_object(CollisionObject3DSW *p_object) { + + ERR_FAIL_COND(!objects.has(p_object)); + objects.erase(p_object); +} + +const Set &Space3DSW::get_objects() const { + + return objects; +} + +void Space3DSW::body_add_to_state_query_list(SelfList *p_body) { + + state_query_list.add(p_body); +} +void Space3DSW::body_remove_from_state_query_list(SelfList *p_body) { + + state_query_list.remove(p_body); +} + +void Space3DSW::area_add_to_monitor_query_list(SelfList *p_area) { + + monitor_query_list.add(p_area); +} +void Space3DSW::area_remove_from_monitor_query_list(SelfList *p_area) { + + monitor_query_list.remove(p_area); +} + +void Space3DSW::area_add_to_moved_list(SelfList *p_area) { + + area_moved_list.add(p_area); +} + +void Space3DSW::area_remove_from_moved_list(SelfList *p_area) { + + area_moved_list.remove(p_area); +} + +const SelfList::List &Space3DSW::get_moved_area_list() const { + + return area_moved_list; +} + +void Space3DSW::call_queries() { + + while (state_query_list.first()) { + + Body3DSW *b = state_query_list.first()->self(); + state_query_list.remove(state_query_list.first()); + b->call_queries(); + } + + while (monitor_query_list.first()) { + + Area3DSW *a = monitor_query_list.first()->self(); + monitor_query_list.remove(monitor_query_list.first()); + a->call_queries(); + } +} + +void Space3DSW::setup() { + + contact_debug_count = 0; + while (inertia_update_list.first()) { + inertia_update_list.first()->self()->update_inertias(); + inertia_update_list.remove(inertia_update_list.first()); + } +} + +void Space3DSW::update() { + + broadphase->update(); +} + +void Space3DSW::set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value) { + + switch (p_param) { + + case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: contact_recycle_radius = p_value; break; + case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION: contact_max_separation = p_value; break; + case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: contact_max_allowed_penetration = p_value; break; + case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: body_linear_velocity_sleep_threshold = p_value; break; + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: body_angular_velocity_sleep_threshold = p_value; break; + case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP: body_time_to_sleep = p_value; break; + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: body_angular_velocity_damp_ratio = p_value; break; + case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: constraint_bias = p_value; break; + case PhysicsServer3D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: test_motion_min_contact_depth = p_value; break; + } +} + +real_t Space3DSW::get_param(PhysicsServer3D::SpaceParameter p_param) const { + + switch (p_param) { + + case PhysicsServer3D::SPACE_PARAM_CONTACT_RECYCLE_RADIUS: return contact_recycle_radius; + case PhysicsServer3D::SPACE_PARAM_CONTACT_MAX_SEPARATION: return contact_max_separation; + case PhysicsServer3D::SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION: return contact_max_allowed_penetration; + case PhysicsServer3D::SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD: return body_linear_velocity_sleep_threshold; + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD: return body_angular_velocity_sleep_threshold; + case PhysicsServer3D::SPACE_PARAM_BODY_TIME_TO_SLEEP: return body_time_to_sleep; + case PhysicsServer3D::SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO: return body_angular_velocity_damp_ratio; + case PhysicsServer3D::SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS: return constraint_bias; + case PhysicsServer3D::SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH: return test_motion_min_contact_depth; + } + return 0; +} + +void Space3DSW::lock() { + + locked = true; +} + +void Space3DSW::unlock() { + + locked = false; +} + +bool Space3DSW::is_locked() const { + + return locked; +} + +PhysicsDirectSpaceState3DSW *Space3DSW::get_direct_state() { + + return direct_access; +} + +Space3DSW::Space3DSW() { + + collision_pairs = 0; + active_objects = 0; + island_count = 0; + contact_debug_count = 0; + + locked = false; + contact_recycle_radius = 0.01; + contact_max_separation = 0.05; + contact_max_allowed_penetration = 0.01; + test_motion_min_contact_depth = 0.00001; + + constraint_bias = 0.01; + body_linear_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_linear", 0.1); + body_angular_velocity_sleep_threshold = GLOBAL_DEF("physics/3d/sleep_threshold_angular", (8.0 / 180.0 * Math_PI)); + body_time_to_sleep = GLOBAL_DEF("physics/3d/time_before_sleep", 0.5); + ProjectSettings::get_singleton()->set_custom_property_info("physics/3d/time_before_sleep", PropertyInfo(Variant::FLOAT, "physics/3d/time_before_sleep", PROPERTY_HINT_RANGE, "0,5,0.01,or_greater")); + body_angular_velocity_damp_ratio = 10; + + broadphase = BroadPhase3DSW::create_func(); + broadphase->set_pair_callback(_broadphase_pair, this); + broadphase->set_unpair_callback(_broadphase_unpair, this); + area = NULL; + + direct_access = memnew(PhysicsDirectSpaceState3DSW); + direct_access->space = this; + + for (int i = 0; i < ELAPSED_TIME_MAX; i++) + elapsed_time[i] = 0; +} + +Space3DSW::~Space3DSW() { + + memdelete(broadphase); + memdelete(direct_access); +} diff --git a/servers/physics_3d/space_3d_sw.h b/servers/physics_3d/space_3d_sw.h new file mode 100644 index 0000000000..c32af5c5d4 --- /dev/null +++ b/servers/physics_3d/space_3d_sw.h @@ -0,0 +1,208 @@ +/*************************************************************************/ +/* space_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SPACE_SW_H +#define SPACE_SW_H + +#include "area_3d_sw.h" +#include "area_pair_3d_sw.h" +#include "body_3d_sw.h" +#include "body_pair_3d_sw.h" +#include "broad_phase_3d_sw.h" +#include "collision_object_3d_sw.h" +#include "core/hash_map.h" +#include "core/project_settings.h" +#include "core/typedefs.h" + +class PhysicsDirectSpaceState3DSW : public PhysicsDirectSpaceState3D { + + GDCLASS(PhysicsDirectSpaceState3DSW, PhysicsDirectSpaceState3D); + +public: + Space3DSW *space; + + virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false); + virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, real_t p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, real_t p_margin, real_t &p_closest_safe, real_t &p_closest_unsafe, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL); + virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, real_t p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, real_t p_margin, ShapeRestInfo *r_info, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const; + + PhysicsDirectSpaceState3DSW(); +}; + +class Space3DSW { + +public: + enum ElapsedTime { + ELAPSED_TIME_INTEGRATE_FORCES, + ELAPSED_TIME_GENERATE_ISLANDS, + ELAPSED_TIME_SETUP_CONSTRAINTS, + ELAPSED_TIME_SOLVE_CONSTRAINTS, + ELAPSED_TIME_INTEGRATE_VELOCITIES, + ELAPSED_TIME_MAX + + }; + +private: + uint64_t elapsed_time[ELAPSED_TIME_MAX]; + + PhysicsDirectSpaceState3DSW *direct_access; + RID self; + + BroadPhase3DSW *broadphase; + SelfList::List active_list; + SelfList::List inertia_update_list; + SelfList::List state_query_list; + SelfList::List monitor_query_list; + SelfList::List area_moved_list; + + static void *_broadphase_pair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_self); + static void _broadphase_unpair(CollisionObject3DSW *A, int p_subindex_A, CollisionObject3DSW *B, int p_subindex_B, void *p_data, void *p_self); + + Set objects; + + Area3DSW *area; + + real_t contact_recycle_radius; + real_t contact_max_separation; + real_t contact_max_allowed_penetration; + real_t constraint_bias; + real_t test_motion_min_contact_depth; + + enum { + + INTERSECTION_QUERY_MAX = 2048 + }; + + CollisionObject3DSW *intersection_query_results[INTERSECTION_QUERY_MAX]; + int intersection_query_subindex_results[INTERSECTION_QUERY_MAX]; + + real_t body_linear_velocity_sleep_threshold; + real_t body_angular_velocity_sleep_threshold; + real_t body_time_to_sleep; + real_t body_angular_velocity_damp_ratio; + + bool locked; + + int island_count; + int active_objects; + int collision_pairs; + + RID static_global_body; + + Vector contact_debug; + int contact_debug_count; + + friend class PhysicsDirectSpaceState3DSW; + + int _cull_aabb_for_body(Body3DSW *p_body, const AABB &p_aabb); + +public: + _FORCE_INLINE_ void set_self(const RID &p_self) { self = p_self; } + _FORCE_INLINE_ RID get_self() const { return self; } + + void set_default_area(Area3DSW *p_area) { area = p_area; } + Area3DSW *get_default_area() const { return area; } + + const SelfList::List &get_active_body_list() const; + void body_add_to_active_list(SelfList *p_body); + void body_remove_from_active_list(SelfList *p_body); + void body_add_to_inertia_update_list(SelfList *p_body); + void body_remove_from_inertia_update_list(SelfList *p_body); + + void body_add_to_state_query_list(SelfList *p_body); + void body_remove_from_state_query_list(SelfList *p_body); + + void area_add_to_monitor_query_list(SelfList *p_area); + void area_remove_from_monitor_query_list(SelfList *p_area); + void area_add_to_moved_list(SelfList *p_area); + void area_remove_from_moved_list(SelfList *p_area); + const SelfList::List &get_moved_area_list() const; + + BroadPhase3DSW *get_broadphase(); + + void add_object(CollisionObject3DSW *p_object); + void remove_object(CollisionObject3DSW *p_object); + const Set &get_objects() const; + + _FORCE_INLINE_ real_t get_contact_recycle_radius() const { return contact_recycle_radius; } + _FORCE_INLINE_ real_t get_contact_max_separation() const { return contact_max_separation; } + _FORCE_INLINE_ real_t get_contact_max_allowed_penetration() const { return contact_max_allowed_penetration; } + _FORCE_INLINE_ real_t get_constraint_bias() const { return constraint_bias; } + _FORCE_INLINE_ real_t get_body_linear_velocity_sleep_threshold() const { return body_linear_velocity_sleep_threshold; } + _FORCE_INLINE_ real_t get_body_angular_velocity_sleep_threshold() const { return body_angular_velocity_sleep_threshold; } + _FORCE_INLINE_ real_t get_body_time_to_sleep() const { return body_time_to_sleep; } + _FORCE_INLINE_ real_t get_body_angular_velocity_damp_ratio() const { return body_angular_velocity_damp_ratio; } + + void update(); + void setup(); + void call_queries(); + + bool is_locked() const; + void lock(); + void unlock(); + + void set_param(PhysicsServer3D::SpaceParameter p_param, real_t p_value); + real_t get_param(PhysicsServer3D::SpaceParameter p_param) const; + + void set_island_count(int p_island_count) { island_count = p_island_count; } + int get_island_count() const { return island_count; } + + void set_active_objects(int p_active_objects) { active_objects = p_active_objects; } + int get_active_objects() const { return active_objects; } + + int get_collision_pairs() const { return collision_pairs; } + + PhysicsDirectSpaceState3DSW *get_direct_state(); + + void set_debug_contacts(int p_amount) { contact_debug.resize(p_amount); } + _FORCE_INLINE_ bool is_debugging_contacts() const { return !contact_debug.empty(); } + _FORCE_INLINE_ void add_debug_contact(const Vector3 &p_contact) { + if (contact_debug_count < contact_debug.size()) contact_debug.write[contact_debug_count++] = p_contact; + } + _FORCE_INLINE_ Vector get_debug_contacts() { return contact_debug; } + _FORCE_INLINE_ int get_debug_contact_count() { return contact_debug_count; } + + void set_static_global_body(RID p_body) { static_global_body = p_body; } + RID get_static_global_body() { return static_global_body; } + + void set_elapsed_time(ElapsedTime p_time, uint64_t p_msec) { elapsed_time[p_time] = p_msec; } + uint64_t get_elapsed_time(ElapsedTime p_time) const { return elapsed_time[p_time]; } + + int test_body_ray_separation(Body3DSW *p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, PhysicsServer3D::SeparationResult *r_results, int p_result_max, real_t p_margin); + bool test_body_motion(Body3DSW *p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, real_t p_margin, PhysicsServer3D::MotionResult *r_result, bool p_exclude_raycast_shapes); + + Space3DSW(); + ~Space3DSW(); +}; + +#endif // SPACE__SW_H diff --git a/servers/physics_3d/step_3d_sw.cpp b/servers/physics_3d/step_3d_sw.cpp new file mode 100644 index 0000000000..ef9015a61c --- /dev/null +++ b/servers/physics_3d/step_3d_sw.cpp @@ -0,0 +1,299 @@ +/*************************************************************************/ +/* step_sw.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "step_3d_sw.h" +#include "joints_3d_sw.h" + +#include "core/os/os.h" + +void Step3DSW::_populate_island(Body3DSW *p_body, Body3DSW **p_island, Constraint3DSW **p_constraint_island) { + + p_body->set_island_step(_step); + p_body->set_island_next(*p_island); + *p_island = p_body; + + for (Map::Element *E = p_body->get_constraint_map().front(); E; E = E->next()) { + + Constraint3DSW *c = (Constraint3DSW *)E->key(); + if (c->get_island_step() == _step) + continue; //already processed + c->set_island_step(_step); + c->set_island_next(*p_constraint_island); + *p_constraint_island = c; + + for (int i = 0; i < c->get_body_count(); i++) { + if (i == E->get()) + continue; + Body3DSW *b = c->get_body_ptr()[i]; + if (b->get_island_step() == _step || b->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) + continue; //no go + _populate_island(c->get_body_ptr()[i], p_island, p_constraint_island); + } + } +} + +void Step3DSW::_setup_island(Constraint3DSW *p_island, real_t p_delta) { + + Constraint3DSW *ci = p_island; + while (ci) { + ci->setup(p_delta); + //todo remove from island if process fails + ci = ci->get_island_next(); + } +} + +void Step3DSW::_solve_island(Constraint3DSW *p_island, int p_iterations, real_t p_delta) { + + int at_priority = 1; + + while (p_island) { + + for (int i = 0; i < p_iterations; i++) { + + Constraint3DSW *ci = p_island; + while (ci) { + ci->solve(p_delta); + ci = ci->get_island_next(); + } + } + + at_priority++; + + { + Constraint3DSW *ci = p_island; + Constraint3DSW *prev = NULL; + while (ci) { + if (ci->get_priority() < at_priority) { + if (prev) { + prev->set_island_next(ci->get_island_next()); //remove + } else { + p_island = ci->get_island_next(); + } + } else { + + prev = ci; + } + + ci = ci->get_island_next(); + } + } + } +} + +void Step3DSW::_check_suspend(Body3DSW *p_island, real_t p_delta) { + + bool can_sleep = true; + + Body3DSW *b = p_island; + while (b) { + + if (b->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { + b = b->get_island_next(); + continue; //ignore for static + } + + if (!b->sleep_test(p_delta)) + can_sleep = false; + + b = b->get_island_next(); + } + + //put all to sleep or wake up everyoen + + b = p_island; + while (b) { + + if (b->get_mode() == PhysicsServer3D::BODY_MODE_STATIC || b->get_mode() == PhysicsServer3D::BODY_MODE_KINEMATIC) { + b = b->get_island_next(); + continue; //ignore for static + } + + bool active = b->is_active(); + + if (active == can_sleep) + b->set_active(!can_sleep); + + b = b->get_island_next(); + } +} + +void Step3DSW::step(Space3DSW *p_space, real_t p_delta, int p_iterations) { + + p_space->lock(); // can't access space during this + + p_space->setup(); //update inertias, etc + + const SelfList::List *body_list = &p_space->get_active_body_list(); + + /* INTEGRATE FORCES */ + + uint64_t profile_begtime = OS::get_singleton()->get_ticks_usec(); + uint64_t profile_endtime = 0; + + int active_count = 0; + + const SelfList *b = body_list->first(); + while (b) { + + b->self()->integrate_forces(p_delta); + b = b->next(); + active_count++; + } + + p_space->set_active_objects(active_count); + + { //profile + profile_endtime = OS::get_singleton()->get_ticks_usec(); + p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_FORCES, profile_endtime - profile_begtime); + profile_begtime = profile_endtime; + } + + /* GENERATE CONSTRAINT ISLANDS */ + + Body3DSW *island_list = NULL; + Constraint3DSW *constraint_island_list = NULL; + b = body_list->first(); + + int island_count = 0; + + while (b) { + Body3DSW *body = b->self(); + + if (body->get_island_step() != _step) { + + Body3DSW *island = NULL; + Constraint3DSW *constraint_island = NULL; + _populate_island(body, &island, &constraint_island); + + island->set_island_list_next(island_list); + island_list = island; + + if (constraint_island) { + constraint_island->set_island_list_next(constraint_island_list); + constraint_island_list = constraint_island; + island_count++; + } + } + b = b->next(); + } + + p_space->set_island_count(island_count); + + const SelfList::List &aml = p_space->get_moved_area_list(); + + while (aml.first()) { + for (const Set::Element *E = aml.first()->self()->get_constraints().front(); E; E = E->next()) { + + Constraint3DSW *c = E->get(); + if (c->get_island_step() == _step) + continue; + c->set_island_step(_step); + c->set_island_next(NULL); + c->set_island_list_next(constraint_island_list); + constraint_island_list = c; + } + p_space->area_remove_from_moved_list((SelfList *)aml.first()); //faster to remove here + } + + { //profile + profile_endtime = OS::get_singleton()->get_ticks_usec(); + p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_GENERATE_ISLANDS, profile_endtime - profile_begtime); + profile_begtime = profile_endtime; + } + + /* SETUP CONSTRAINT ISLANDS */ + + { + Constraint3DSW *ci = constraint_island_list; + while (ci) { + + _setup_island(ci, p_delta); + ci = ci->get_island_list_next(); + } + } + + { //profile + profile_endtime = OS::get_singleton()->get_ticks_usec(); + p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_SETUP_CONSTRAINTS, profile_endtime - profile_begtime); + profile_begtime = profile_endtime; + } + + /* SOLVE CONSTRAINT ISLANDS */ + + { + Constraint3DSW *ci = constraint_island_list; + while (ci) { + //iterating each island separatedly improves cache efficiency + _solve_island(ci, p_iterations, p_delta); + ci = ci->get_island_list_next(); + } + } + + { //profile + profile_endtime = OS::get_singleton()->get_ticks_usec(); + p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_SOLVE_CONSTRAINTS, profile_endtime - profile_begtime); + profile_begtime = profile_endtime; + } + + /* INTEGRATE VELOCITIES */ + + b = body_list->first(); + while (b) { + const SelfList *n = b->next(); + b->self()->integrate_velocities(p_delta); + b = n; + } + + /* SLEEP / WAKE UP ISLANDS */ + + { + Body3DSW *bi = island_list; + while (bi) { + + _check_suspend(bi, p_delta); + bi = bi->get_island_list_next(); + } + } + + { //profile + profile_endtime = OS::get_singleton()->get_ticks_usec(); + p_space->set_elapsed_time(Space3DSW::ELAPSED_TIME_INTEGRATE_VELOCITIES, profile_endtime - profile_begtime); + profile_begtime = profile_endtime; + } + + p_space->update(); + p_space->unlock(); + _step++; +} + +Step3DSW::Step3DSW() { + + _step = 1; +} diff --git a/servers/physics_3d/step_3d_sw.h b/servers/physics_3d/step_3d_sw.h new file mode 100644 index 0000000000..dcd67fa122 --- /dev/null +++ b/servers/physics_3d/step_3d_sw.h @@ -0,0 +1,50 @@ +/*************************************************************************/ +/* step_sw.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef STEP_SW_H +#define STEP_SW_H + +#include "space_3d_sw.h" + +class Step3DSW { + + uint64_t _step; + + void _populate_island(Body3DSW *p_body, Body3DSW **p_island, Constraint3DSW **p_constraint_island); + void _setup_island(Constraint3DSW *p_island, real_t p_delta); + void _solve_island(Constraint3DSW *p_island, int p_iterations, real_t p_delta); + void _check_suspend(Body3DSW *p_island, real_t p_delta); + +public: + void step(Space3DSW *p_space, real_t p_delta, int p_iterations); + Step3DSW(); +}; + +#endif // STEP__SW_H diff --git a/servers/physics_server.cpp b/servers/physics_server.cpp deleted file mode 100644 index 57f3a7979e..0000000000 --- a/servers/physics_server.cpp +++ /dev/null @@ -1,800 +0,0 @@ -/*************************************************************************/ -/* physics_server.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "physics_server.h" - -#include "core/method_bind_ext.gen.inc" -#include "core/print_string.h" -#include "core/project_settings.h" - -PhysicsServer *PhysicsServer::singleton = NULL; - -void PhysicsDirectBodyState::integrate_forces() { - - real_t step = get_step(); - Vector3 lv = get_linear_velocity(); - lv += get_total_gravity() * step; - - Vector3 av = get_angular_velocity(); - - float linear_damp = 1.0 - step * get_total_linear_damp(); - - if (linear_damp < 0) // reached zero in the given time - linear_damp = 0; - - float angular_damp = 1.0 - step * get_total_angular_damp(); - - if (angular_damp < 0) // reached zero in the given time - angular_damp = 0; - - lv *= linear_damp; - av *= angular_damp; - - set_linear_velocity(lv); - set_angular_velocity(av); -} - -Object *PhysicsDirectBodyState::get_contact_collider_object(int p_contact_idx) const { - - ObjectID objid = get_contact_collider_id(p_contact_idx); - Object *obj = ObjectDB::get_instance(objid); - return obj; -} - -PhysicsServer *PhysicsServer::get_singleton() { - - return singleton; -} - -void PhysicsDirectBodyState::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_total_gravity"), &PhysicsDirectBodyState::get_total_gravity); - ClassDB::bind_method(D_METHOD("get_total_linear_damp"), &PhysicsDirectBodyState::get_total_linear_damp); - ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState::get_total_angular_damp); - - ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState::get_center_of_mass); - ClassDB::bind_method(D_METHOD("get_principal_inertia_axes"), &PhysicsDirectBodyState::get_principal_inertia_axes); - - ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState::get_inverse_mass); - ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState::get_inverse_inertia); - - ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &PhysicsDirectBodyState::set_linear_velocity); - ClassDB::bind_method(D_METHOD("get_linear_velocity"), &PhysicsDirectBodyState::get_linear_velocity); - - ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &PhysicsDirectBodyState::set_angular_velocity); - ClassDB::bind_method(D_METHOD("get_angular_velocity"), &PhysicsDirectBodyState::get_angular_velocity); - - ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState::set_transform); - ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState::get_transform); - - ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState::add_central_force); - ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState::add_force); - ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState::add_torque); - ClassDB::bind_method(D_METHOD("apply_central_impulse", "j"), &PhysicsDirectBodyState::apply_central_impulse); - ClassDB::bind_method(D_METHOD("apply_impulse", "position", "j"), &PhysicsDirectBodyState::apply_impulse); - ClassDB::bind_method(D_METHOD("apply_torque_impulse", "j"), &PhysicsDirectBodyState::apply_torque_impulse); - - ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState::set_sleep_state); - ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState::is_sleeping); - - ClassDB::bind_method(D_METHOD("get_contact_count"), &PhysicsDirectBodyState::get_contact_count); - - ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_position); - ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_normal); - ClassDB::bind_method(D_METHOD("get_contact_impulse", "contact_idx"), &PhysicsDirectBodyState::get_contact_impulse); - ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &PhysicsDirectBodyState::get_contact_local_shape); - ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider); - ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_position); - ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_id); - ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_object); - ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_shape); - ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState::get_contact_collider_velocity_at_position); - ClassDB::bind_method(D_METHOD("get_step"), &PhysicsDirectBodyState::get_step); - ClassDB::bind_method(D_METHOD("integrate_forces"), &PhysicsDirectBodyState::integrate_forces); - ClassDB::bind_method(D_METHOD("get_space_state"), &PhysicsDirectBodyState::get_space_state); - - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step"), "", "get_step"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inverse_mass"), "", "get_inverse_mass"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_angular_damp"), "", "get_total_angular_damp"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inverse_inertia"), "", "get_inverse_inertia"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "total_gravity"), "", "get_total_gravity"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass"), "", "get_center_of_mass"); - ADD_PROPERTY(PropertyInfo(Variant::BASIS, "principal_inertia_axes"), "", "get_principal_inertia_axes"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); -} - -PhysicsDirectBodyState::PhysicsDirectBodyState() {} - -/////////////////////////////////////////////////////// - -void PhysicsShapeQueryParameters::set_shape(const RES &p_shape) { - - ERR_FAIL_COND(p_shape.is_null()); - shape = p_shape->get_rid(); -} - -void PhysicsShapeQueryParameters::set_shape_rid(const RID &p_shape) { - - shape = p_shape; -} - -RID PhysicsShapeQueryParameters::get_shape_rid() const { - - return shape; -} - -void PhysicsShapeQueryParameters::set_transform(const Transform &p_transform) { - - transform = p_transform; -} -Transform PhysicsShapeQueryParameters::get_transform() const { - - return transform; -} - -void PhysicsShapeQueryParameters::set_margin(float p_margin) { - - margin = p_margin; -} - -float PhysicsShapeQueryParameters::get_margin() const { - - return margin; -} - -void PhysicsShapeQueryParameters::set_collision_mask(int p_collision_mask) { - - collision_mask = p_collision_mask; -} -int PhysicsShapeQueryParameters::get_collision_mask() const { - - return collision_mask; -} - -void PhysicsShapeQueryParameters::set_exclude(const Vector &p_exclude) { - - exclude.clear(); - for (int i = 0; i < p_exclude.size(); i++) - exclude.insert(p_exclude[i]); -} - -Vector PhysicsShapeQueryParameters::get_exclude() const { - - Vector ret; - ret.resize(exclude.size()); - int idx = 0; - for (Set::Element *E = exclude.front(); E; E = E->next()) { - ret.write[idx] = E->get(); - } - return ret; -} - -void PhysicsShapeQueryParameters::set_collide_with_bodies(bool p_enable) { - collide_with_bodies = p_enable; -} - -bool PhysicsShapeQueryParameters::is_collide_with_bodies_enabled() const { - return collide_with_bodies; -} - -void PhysicsShapeQueryParameters::set_collide_with_areas(bool p_enable) { - collide_with_areas = p_enable; -} - -bool PhysicsShapeQueryParameters::is_collide_with_areas_enabled() const { - return collide_with_areas; -} - -void PhysicsShapeQueryParameters::_bind_methods() { - - ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters::set_shape); - ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters::set_shape_rid); - ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters::get_shape_rid); - - ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsShapeQueryParameters::set_transform); - ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsShapeQueryParameters::get_transform); - - ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters::set_margin); - ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters::get_margin); - - ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsShapeQueryParameters::set_collision_mask); - ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsShapeQueryParameters::get_collision_mask); - - ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsShapeQueryParameters::set_exclude); - ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsShapeQueryParameters::get_exclude); - - ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsShapeQueryParameters::set_collide_with_bodies); - ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsShapeQueryParameters::is_collide_with_bodies_enabled); - - ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsShapeQueryParameters::set_collide_with_areas); - ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters::is_collide_with_areas_enabled); - - ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); - ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); - ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); - //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter - ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); - ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); - ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); -} - -PhysicsShapeQueryParameters::PhysicsShapeQueryParameters() { - - margin = 0; - collision_mask = 0x7FFFFFFF; - collide_with_bodies = true; - collide_with_areas = false; -} - -///////////////////////////////////// - -Dictionary PhysicsDirectSpaceState::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { - - RayResult inters; - Set exclude; - for (int i = 0; i < p_exclude.size(); i++) - exclude.insert(p_exclude[i]); - - bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas); - - if (!res) - return Dictionary(); - - Dictionary d; - d["position"] = inters.position; - d["normal"] = inters.normal; - d["collider_id"] = inters.collider_id; - d["collider"] = inters.collider; - d["shape"] = inters.shape; - d["rid"] = inters.rid; - - return d; -} - -Array PhysicsDirectSpaceState::_intersect_shape(const Ref &p_shape_query, int p_max_results) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - - Vector sr; - sr.resize(p_max_results); - int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - Array ret; - ret.resize(rc); - for (int i = 0; i < rc; i++) { - - Dictionary d; - d["rid"] = sr[i].rid; - d["collider_id"] = sr[i].collider_id; - d["collider"] = sr[i].collider; - d["shape"] = sr[i].shape; - ret[i] = d; - } - - return ret; -} - -Array PhysicsDirectSpaceState::_cast_motion(const Ref &p_shape_query, const Vector3 &p_motion) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - - float closest_safe, closest_unsafe; - bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - if (!res) - return Array(); - Array ret; - ret.resize(2); - ret[0] = closest_safe; - ret[1] = closest_unsafe; - return ret; -} -Array PhysicsDirectSpaceState::_collide_shape(const Ref &p_shape_query, int p_max_results) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); - - Vector ret; - ret.resize(p_max_results * 2); - int rc = 0; - bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - if (!res) - return Array(); - Array r; - r.resize(rc * 2); - for (int i = 0; i < rc * 2; i++) - r[i] = ret[i]; - return r; -} -Dictionary PhysicsDirectSpaceState::_get_rest_info(const Ref &p_shape_query) { - - ERR_FAIL_COND_V(!p_shape_query.is_valid(), Dictionary()); - - ShapeRestInfo sri; - - bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); - Dictionary r; - if (!res) - return r; - - r["point"] = sri.point; - r["normal"] = sri.normal; - r["rid"] = sri.rid; - r["collider_id"] = sri.collider_id; - r["shape"] = sri.shape; - r["linear_velocity"] = sri.linear_velocity; - - return r; -} - -PhysicsDirectSpaceState::PhysicsDirectSpaceState() { -} - -void PhysicsDirectSpaceState::_bind_methods() { - - ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState::_intersect_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState::_cast_motion); - ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState::_collide_shape, DEFVAL(32)); - ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState::_get_rest_info); -} - -int PhysicsShapeQueryResult::get_result_count() const { - - return result.size(); -} -RID PhysicsShapeQueryResult::get_result_rid(int p_idx) const { - - return result[p_idx].rid; -} -ObjectID PhysicsShapeQueryResult::get_result_object_id(int p_idx) const { - - return result[p_idx].collider_id; -} -Object *PhysicsShapeQueryResult::get_result_object(int p_idx) const { - - return result[p_idx].collider; -} -int PhysicsShapeQueryResult::get_result_object_shape(int p_idx) const { - - return result[p_idx].shape; -} - -PhysicsShapeQueryResult::PhysicsShapeQueryResult() { -} - -void PhysicsShapeQueryResult::_bind_methods() { - - ClassDB::bind_method(D_METHOD("get_result_count"), &PhysicsShapeQueryResult::get_result_count); - ClassDB::bind_method(D_METHOD("get_result_rid", "idx"), &PhysicsShapeQueryResult::get_result_rid); - ClassDB::bind_method(D_METHOD("get_result_object_id", "idx"), &PhysicsShapeQueryResult::get_result_object_id); - ClassDB::bind_method(D_METHOD("get_result_object", "idx"), &PhysicsShapeQueryResult::get_result_object); - ClassDB::bind_method(D_METHOD("get_result_object_shape", "idx"), &PhysicsShapeQueryResult::get_result_object_shape); -} - -/////////////////////////////////////// - -void PhysicsServer::_bind_methods() { - -#ifndef _3D_DISABLED - - ClassDB::bind_method(D_METHOD("shape_create", "type"), &PhysicsServer::shape_create); - ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &PhysicsServer::shape_set_data); - - ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &PhysicsServer::shape_get_type); - ClassDB::bind_method(D_METHOD("shape_get_data", "shape"), &PhysicsServer::shape_get_data); - - ClassDB::bind_method(D_METHOD("space_create"), &PhysicsServer::space_create); - ClassDB::bind_method(D_METHOD("space_set_active", "space", "active"), &PhysicsServer::space_set_active); - ClassDB::bind_method(D_METHOD("space_is_active", "space"), &PhysicsServer::space_is_active); - ClassDB::bind_method(D_METHOD("space_set_param", "space", "param", "value"), &PhysicsServer::space_set_param); - ClassDB::bind_method(D_METHOD("space_get_param", "space", "param"), &PhysicsServer::space_get_param); - ClassDB::bind_method(D_METHOD("space_get_direct_state", "space"), &PhysicsServer::space_get_direct_state); - - ClassDB::bind_method(D_METHOD("area_create"), &PhysicsServer::area_create); - ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer::area_set_space); - ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer::area_get_space); - - ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer::area_set_space_override_mode); - ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer::area_get_space_override_mode); - - ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer::area_add_shape, DEFVAL(Transform()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer::area_set_shape); - ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer::area_set_shape_transform); - ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &PhysicsServer::area_set_shape_disabled); - - ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &PhysicsServer::area_get_shape_count); - ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &PhysicsServer::area_get_shape); - ClassDB::bind_method(D_METHOD("area_get_shape_transform", "area", "shape_idx"), &PhysicsServer::area_get_shape_transform); - - ClassDB::bind_method(D_METHOD("area_remove_shape", "area", "shape_idx"), &PhysicsServer::area_remove_shape); - ClassDB::bind_method(D_METHOD("area_clear_shapes", "area"), &PhysicsServer::area_clear_shapes); - - ClassDB::bind_method(D_METHOD("area_set_collision_layer", "area", "layer"), &PhysicsServer::area_set_collision_layer); - ClassDB::bind_method(D_METHOD("area_set_collision_mask", "area", "mask"), &PhysicsServer::area_set_collision_mask); - - ClassDB::bind_method(D_METHOD("area_set_param", "area", "param", "value"), &PhysicsServer::area_set_param); - ClassDB::bind_method(D_METHOD("area_set_transform", "area", "transform"), &PhysicsServer::area_set_transform); - - ClassDB::bind_method(D_METHOD("area_get_param", "area", "param"), &PhysicsServer::area_get_param); - ClassDB::bind_method(D_METHOD("area_get_transform", "area"), &PhysicsServer::area_get_transform); - - ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &PhysicsServer::area_attach_object_instance_id); - ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &PhysicsServer::area_get_object_instance_id); - - ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer::area_set_monitor_callback); - ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer::area_set_area_monitor_callback); - ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer::area_set_monitorable); - - ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer::area_set_ray_pickable); - ClassDB::bind_method(D_METHOD("area_is_ray_pickable", "area"), &PhysicsServer::area_is_ray_pickable); - - ClassDB::bind_method(D_METHOD("body_create", "mode", "init_sleeping"), &PhysicsServer::body_create, DEFVAL(BODY_MODE_RIGID), DEFVAL(false)); - - ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &PhysicsServer::body_set_space); - ClassDB::bind_method(D_METHOD("body_get_space", "body"), &PhysicsServer::body_get_space); - - ClassDB::bind_method(D_METHOD("body_set_mode", "body", "mode"), &PhysicsServer::body_set_mode); - ClassDB::bind_method(D_METHOD("body_get_mode", "body"), &PhysicsServer::body_get_mode); - - ClassDB::bind_method(D_METHOD("body_set_collision_layer", "body", "layer"), &PhysicsServer::body_set_collision_layer); - ClassDB::bind_method(D_METHOD("body_get_collision_layer", "body"), &PhysicsServer::body_get_collision_layer); - - ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer::body_set_collision_mask); - ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer::body_get_collision_mask); - - ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer::body_add_shape, DEFVAL(Transform()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer::body_set_shape); - ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer::body_set_shape_transform); - ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer::body_set_shape_disabled); - - ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &PhysicsServer::body_get_shape_count); - ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &PhysicsServer::body_get_shape); - ClassDB::bind_method(D_METHOD("body_get_shape_transform", "body", "shape_idx"), &PhysicsServer::body_get_shape_transform); - - ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &PhysicsServer::body_remove_shape); - ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &PhysicsServer::body_clear_shapes); - - ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &PhysicsServer::body_attach_object_instance_id); - ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &PhysicsServer::body_get_object_instance_id); - - ClassDB::bind_method(D_METHOD("body_set_enable_continuous_collision_detection", "body", "enable"), &PhysicsServer::body_set_enable_continuous_collision_detection); - ClassDB::bind_method(D_METHOD("body_is_continuous_collision_detection_enabled", "body"), &PhysicsServer::body_is_continuous_collision_detection_enabled); - - ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer::body_set_param); - ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer::body_get_param); - - ClassDB::bind_method(D_METHOD("body_set_kinematic_safe_margin", "body", "margin"), &PhysicsServer::body_set_kinematic_safe_margin); - ClassDB::bind_method(D_METHOD("body_get_kinematic_safe_margin", "body"), &PhysicsServer::body_get_kinematic_safe_margin); - - ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer::body_set_state); - ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer::body_get_state); - - ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer::body_add_central_force); - ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer::body_add_force); - ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer::body_add_torque); - - ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer::body_apply_central_impulse); - ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &PhysicsServer::body_apply_impulse); - ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer::body_apply_torque_impulse); - ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer::body_set_axis_velocity); - - ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis", "lock"), &PhysicsServer::body_set_axis_lock); - ClassDB::bind_method(D_METHOD("body_is_axis_locked", "body", "axis"), &PhysicsServer::body_is_axis_locked); - - ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer::body_add_collision_exception); - ClassDB::bind_method(D_METHOD("body_remove_collision_exception", "body", "excepted_body"), &PhysicsServer::body_remove_collision_exception); - - ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported", "body", "amount"), &PhysicsServer::body_set_max_contacts_reported); - ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported", "body"), &PhysicsServer::body_get_max_contacts_reported); - - ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer::body_set_omit_force_integration); - ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer::body_is_omitting_force_integration); - - ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer::body_set_force_integration_callback, DEFVAL(Variant())); - - ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer::body_set_ray_pickable); - ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer::body_is_ray_pickable); - - ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer::body_get_direct_state); - - /* JOINT API */ - - BIND_ENUM_CONSTANT(JOINT_PIN); - BIND_ENUM_CONSTANT(JOINT_HINGE); - BIND_ENUM_CONSTANT(JOINT_SLIDER); - BIND_ENUM_CONSTANT(JOINT_CONE_TWIST); - BIND_ENUM_CONSTANT(JOINT_6DOF); - - ClassDB::bind_method(D_METHOD("joint_create_pin", "body_A", "local_A", "body_B", "local_B"), &PhysicsServer::joint_create_pin); - ClassDB::bind_method(D_METHOD("pin_joint_set_param", "joint", "param", "value"), &PhysicsServer::pin_joint_set_param); - ClassDB::bind_method(D_METHOD("pin_joint_get_param", "joint", "param"), &PhysicsServer::pin_joint_get_param); - - ClassDB::bind_method(D_METHOD("pin_joint_set_local_a", "joint", "local_A"), &PhysicsServer::pin_joint_set_local_a); - ClassDB::bind_method(D_METHOD("pin_joint_get_local_a", "joint"), &PhysicsServer::pin_joint_get_local_a); - - ClassDB::bind_method(D_METHOD("pin_joint_set_local_b", "joint", "local_B"), &PhysicsServer::pin_joint_set_local_b); - ClassDB::bind_method(D_METHOD("pin_joint_get_local_b", "joint"), &PhysicsServer::pin_joint_get_local_b); - - BIND_ENUM_CONSTANT(PIN_JOINT_BIAS); - BIND_ENUM_CONSTANT(PIN_JOINT_DAMPING); - BIND_ENUM_CONSTANT(PIN_JOINT_IMPULSE_CLAMP); - - BIND_ENUM_CONSTANT(HINGE_JOINT_BIAS); - BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_UPPER); - BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_LOWER); - BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_BIAS); - BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_RELAXATION); - BIND_ENUM_CONSTANT(HINGE_JOINT_MOTOR_TARGET_VELOCITY); - BIND_ENUM_CONSTANT(HINGE_JOINT_MOTOR_MAX_IMPULSE); - - BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT); - BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR); - - ClassDB::bind_method(D_METHOD("joint_create_hinge", "body_A", "hinge_A", "body_B", "hinge_B"), &PhysicsServer::joint_create_hinge); - - ClassDB::bind_method(D_METHOD("hinge_joint_set_param", "joint", "param", "value"), &PhysicsServer::hinge_joint_set_param); - ClassDB::bind_method(D_METHOD("hinge_joint_get_param", "joint", "param"), &PhysicsServer::hinge_joint_get_param); - - ClassDB::bind_method(D_METHOD("hinge_joint_set_flag", "joint", "flag", "enabled"), &PhysicsServer::hinge_joint_set_flag); - ClassDB::bind_method(D_METHOD("hinge_joint_get_flag", "joint", "flag"), &PhysicsServer::hinge_joint_get_flag); - - ClassDB::bind_method(D_METHOD("joint_create_slider", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer::joint_create_slider); - - ClassDB::bind_method(D_METHOD("slider_joint_set_param", "joint", "param", "value"), &PhysicsServer::slider_joint_set_param); - ClassDB::bind_method(D_METHOD("slider_joint_get_param", "joint", "param"), &PhysicsServer::slider_joint_get_param); - - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_UPPER); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_LOWER); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_DAMPING); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_MOTION_SOFTNESS); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_MOTION_RESTITUTION); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_MOTION_DAMPING); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION); - BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING); - - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_UPPER); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_LOWER); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_DAMPING); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_MOTION_DAMPING); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION); - BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING); - BIND_ENUM_CONSTANT(SLIDER_JOINT_MAX); - - ClassDB::bind_method(D_METHOD("joint_create_cone_twist", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer::joint_create_cone_twist); - - ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param", "joint", "param", "value"), &PhysicsServer::cone_twist_joint_set_param); - ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param", "joint", "param"), &PhysicsServer::cone_twist_joint_get_param); - - BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_SWING_SPAN); - BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_TWIST_SPAN); - BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_BIAS); - BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_SOFTNESS); - BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_RELAXATION); - - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_LOWER_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_UPPER_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_RESTITUTION); - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_DAMPING); - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY); - BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LOWER_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_UPPER_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_DAMPING); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_RESTITUTION); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_FORCE_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_ERP); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY); - BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT); - - BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT); - BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_MOTOR); - BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR); - - ClassDB::bind_method(D_METHOD("joint_get_type", "joint"), &PhysicsServer::joint_get_type); - - ClassDB::bind_method(D_METHOD("joint_set_solver_priority", "joint", "priority"), &PhysicsServer::joint_set_solver_priority); - ClassDB::bind_method(D_METHOD("joint_get_solver_priority", "joint"), &PhysicsServer::joint_get_solver_priority); - - ClassDB::bind_method(D_METHOD("joint_create_generic_6dof", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer::joint_create_generic_6dof); - - ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param", "joint", "axis", "param", "value"), &PhysicsServer::generic_6dof_joint_set_param); - ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param", "joint", "axis", "param"), &PhysicsServer::generic_6dof_joint_get_param); - - ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_flag", "joint", "axis", "flag", "enable"), &PhysicsServer::generic_6dof_joint_set_flag); - ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_flag", "joint", "axis", "flag"), &PhysicsServer::generic_6dof_joint_get_flag); - - ClassDB::bind_method(D_METHOD("free_rid", "rid"), &PhysicsServer::free); - - ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer::set_active); - - ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer::get_process_info); - - BIND_ENUM_CONSTANT(SHAPE_PLANE); - BIND_ENUM_CONSTANT(SHAPE_RAY); - BIND_ENUM_CONSTANT(SHAPE_SPHERE); - BIND_ENUM_CONSTANT(SHAPE_BOX); - BIND_ENUM_CONSTANT(SHAPE_CAPSULE); - BIND_ENUM_CONSTANT(SHAPE_CYLINDER); - BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON); - BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); - BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP); - BIND_ENUM_CONSTANT(SHAPE_CUSTOM); - - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); - BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); - BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); - BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); - BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); - - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE_REPLACE); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE); - BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE_COMBINE); - - BIND_ENUM_CONSTANT(BODY_MODE_STATIC); - BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); - BIND_ENUM_CONSTANT(BODY_MODE_RIGID); - BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER); - - BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); - BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); - BIND_ENUM_CONSTANT(BODY_PARAM_MASS); - BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE); - BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP); - BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP); - BIND_ENUM_CONSTANT(BODY_PARAM_MAX); - - BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM); - BIND_ENUM_CONSTANT(BODY_STATE_LINEAR_VELOCITY); - BIND_ENUM_CONSTANT(BODY_STATE_ANGULAR_VELOCITY); - BIND_ENUM_CONSTANT(BODY_STATE_SLEEPING); - BIND_ENUM_CONSTANT(BODY_STATE_CAN_SLEEP); - - BIND_ENUM_CONSTANT(AREA_BODY_ADDED); - BIND_ENUM_CONSTANT(AREA_BODY_REMOVED); - - BIND_ENUM_CONSTANT(INFO_ACTIVE_OBJECTS); - BIND_ENUM_CONSTANT(INFO_COLLISION_PAIRS); - BIND_ENUM_CONSTANT(INFO_ISLAND_COUNT); - - BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); - BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); - BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO); - BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); - BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); - - BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X); - BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y); - BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Z); - BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_X); - BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Y); - BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Z); - -#endif -} - -PhysicsServer::PhysicsServer() { - - ERR_FAIL_COND(singleton != NULL); - singleton = this; -} - -PhysicsServer::~PhysicsServer() { - - singleton = NULL; -} - -Vector PhysicsServerManager::physics_servers; -int PhysicsServerManager::default_server_id = -1; -int PhysicsServerManager::default_server_priority = -1; -const String PhysicsServerManager::setting_property_name("physics/3d/physics_engine"); - -void PhysicsServerManager::on_servers_changed() { - - String physics_servers2("DEFAULT"); - for (int i = get_servers_count() - 1; 0 <= i; --i) { - physics_servers2 += "," + get_server_name(i); - } - ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2)); -} - -void PhysicsServerManager::register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback) { - - ERR_FAIL_COND(!p_creat_callback); - ERR_FAIL_COND(find_server_id(p_name) != -1); - physics_servers.push_back(ClassInfo(p_name, p_creat_callback)); - on_servers_changed(); -} - -void PhysicsServerManager::set_default_server(const String &p_name, int p_priority) { - - const int id = find_server_id(p_name); - ERR_FAIL_COND(id == -1); // Not found - if (default_server_priority < p_priority) { - default_server_id = id; - default_server_priority = p_priority; - } -} - -int PhysicsServerManager::find_server_id(const String &p_name) { - - for (int i = physics_servers.size() - 1; 0 <= i; --i) { - if (p_name == physics_servers[i].name) { - return i; - } - } - return -1; -} - -int PhysicsServerManager::get_servers_count() { - return physics_servers.size(); -} - -String PhysicsServerManager::get_server_name(int p_id) { - ERR_FAIL_INDEX_V(p_id, get_servers_count(), ""); - return physics_servers[p_id].name; -} - -PhysicsServer *PhysicsServerManager::new_default_server() { - ERR_FAIL_COND_V(default_server_id == -1, NULL); - return physics_servers[default_server_id].create_callback(); -} - -PhysicsServer *PhysicsServerManager::new_server(const String &p_name) { - int id = find_server_id(p_name); - if (id == -1) { - return NULL; - } else { - return physics_servers[id].create_callback(); - } -} diff --git a/servers/physics_server.h b/servers/physics_server.h deleted file mode 100644 index f1388c8758..0000000000 --- a/servers/physics_server.h +++ /dev/null @@ -1,844 +0,0 @@ -/*************************************************************************/ -/* physics_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef PHYSICS_SERVER_H -#define PHYSICS_SERVER_H - -#include "core/object.h" -#include "core/resource.h" - -class PhysicsDirectSpaceState; - -class PhysicsDirectBodyState : public Object { - - GDCLASS(PhysicsDirectBodyState, Object); - -protected: - static void _bind_methods(); - -public: - virtual Vector3 get_total_gravity() const = 0; - virtual float get_total_angular_damp() const = 0; - virtual float get_total_linear_damp() const = 0; - - virtual Vector3 get_center_of_mass() const = 0; - virtual Basis get_principal_inertia_axes() const = 0; - virtual float get_inverse_mass() const = 0; // get the mass - virtual Vector3 get_inverse_inertia() const = 0; // get density of this body space - virtual Basis get_inverse_inertia_tensor() const = 0; // get density of this body space - - virtual void set_linear_velocity(const Vector3 &p_velocity) = 0; - virtual Vector3 get_linear_velocity() const = 0; - - virtual void set_angular_velocity(const Vector3 &p_velocity) = 0; - virtual Vector3 get_angular_velocity() const = 0; - - virtual void set_transform(const Transform &p_transform) = 0; - virtual Transform get_transform() const = 0; - - virtual void add_central_force(const Vector3 &p_force) = 0; - virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) = 0; - virtual void add_torque(const Vector3 &p_torque) = 0; - virtual void apply_central_impulse(const Vector3 &p_j) = 0; - virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) = 0; - virtual void apply_torque_impulse(const Vector3 &p_j) = 0; - - virtual void set_sleep_state(bool p_enable) = 0; - virtual bool is_sleeping() const = 0; - - virtual int get_contact_count() const = 0; - - virtual Vector3 get_contact_local_position(int p_contact_idx) const = 0; - virtual Vector3 get_contact_local_normal(int p_contact_idx) const = 0; - virtual float get_contact_impulse(int p_contact_idx) const = 0; - virtual int get_contact_local_shape(int p_contact_idx) const = 0; - - virtual RID get_contact_collider(int p_contact_idx) const = 0; - virtual Vector3 get_contact_collider_position(int p_contact_idx) const = 0; - virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0; - virtual Object *get_contact_collider_object(int p_contact_idx) const; - virtual int get_contact_collider_shape(int p_contact_idx) const = 0; - virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0; - - virtual real_t get_step() const = 0; - virtual void integrate_forces(); - - virtual PhysicsDirectSpaceState *get_space_state() = 0; - - PhysicsDirectBodyState(); -}; - -class PhysicsShapeQueryResult; - -class PhysicsShapeQueryParameters : public Reference { - - GDCLASS(PhysicsShapeQueryParameters, Reference); - friend class PhysicsDirectSpaceState; - - RID shape; - Transform transform; - float margin; - Set exclude; - uint32_t collision_mask; - - bool collide_with_bodies; - bool collide_with_areas; - -protected: - static void _bind_methods(); - -public: - void set_shape(const RES &p_shape); - void set_shape_rid(const RID &p_shape); - RID get_shape_rid() const; - - void set_transform(const Transform &p_transform); - Transform get_transform() const; - - void set_margin(float p_margin); - float get_margin() const; - - void set_collision_mask(int p_collision_mask); - int get_collision_mask() const; - - void set_exclude(const Vector &p_exclude); - Vector get_exclude() const; - - void set_collide_with_bodies(bool p_enable); - bool is_collide_with_bodies_enabled() const; - - void set_collide_with_areas(bool p_enable); - bool is_collide_with_areas_enabled() const; - - PhysicsShapeQueryParameters(); -}; - -class PhysicsDirectSpaceState : public Object { - - GDCLASS(PhysicsDirectSpaceState, Object); - -private: - Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector &p_exclude = Vector(), uint32_t p_collision_mask = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); - Array _intersect_shape(const Ref &p_shape_query, int p_max_results = 32); - Array _cast_motion(const Ref &p_shape_query, const Vector3 &p_motion); - Array _collide_shape(const Ref &p_shape_query, int p_max_results = 32); - Dictionary _get_rest_info(const Ref &p_shape_query); - -protected: - static void _bind_methods(); - -public: - struct ShapeResult { - - RID rid; - ObjectID collider_id; - Object *collider; - int shape; - }; - - virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - struct RayResult { - - Vector3 position; - Vector3 normal; - RID rid; - ObjectID collider_id; - Object *collider; - int shape; - }; - - virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0; - - virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - struct ShapeRestInfo { - - Vector3 point; - Vector3 normal; - RID rid; - ObjectID collider_id; - int shape; - Vector3 linear_velocity; //velocity at contact point - }; - - virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL) = 0; - - virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; - - virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0; - - PhysicsDirectSpaceState(); -}; - -class PhysicsShapeQueryResult : public Reference { - - GDCLASS(PhysicsShapeQueryResult, Reference); - - Vector result; - - friend class PhysicsDirectSpaceState; - -protected: - static void _bind_methods(); - -public: - int get_result_count() const; - RID get_result_rid(int p_idx) const; - ObjectID get_result_object_id(int p_idx) const; - Object *get_result_object(int p_idx) const; - int get_result_object_shape(int p_idx) const; - - PhysicsShapeQueryResult(); -}; - -class PhysicsServer : public Object { - - GDCLASS(PhysicsServer, Object); - - static PhysicsServer *singleton; - -protected: - static void _bind_methods(); - -public: - static PhysicsServer *get_singleton(); - - enum ShapeType { - SHAPE_PLANE, ///< plane:"plane" - SHAPE_RAY, ///< float:"length" - SHAPE_SPHERE, ///< float:"radius" - SHAPE_BOX, ///< vec3:"extents" - SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule - SHAPE_CYLINDER, ///< dict( float:"radius", float:"height"):cylinder - SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" - SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) - SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights" - SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error - }; - - virtual RID shape_create(ShapeType p_shape) = 0; - virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0; - virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0; - - virtual ShapeType shape_get_type(RID p_shape) const = 0; - virtual Variant shape_get_data(RID p_shape) const = 0; - - virtual void shape_set_margin(RID p_shape, real_t p_margin) = 0; - virtual real_t shape_get_margin(RID p_shape) const = 0; - - virtual real_t shape_get_custom_solver_bias(RID p_shape) const = 0; - - /* SPACE API */ - - virtual RID space_create() = 0; - virtual void space_set_active(RID p_space, bool p_active) = 0; - virtual bool space_is_active(RID p_space) const = 0; - - enum SpaceParameter { - - SPACE_PARAM_CONTACT_RECYCLE_RADIUS, - SPACE_PARAM_CONTACT_MAX_SEPARATION, - SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION, - SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD, - SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD, - SPACE_PARAM_BODY_TIME_TO_SLEEP, - SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO, - SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, - SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH - }; - - virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; - virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0; - - // this function only works on physics process, errors and returns null otherwise - virtual PhysicsDirectSpaceState *space_get_direct_state(RID p_space) = 0; - - virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0; - virtual Vector space_get_contacts(RID p_space) const = 0; - virtual int space_get_contact_count(RID p_space) const = 0; - - //missing space parameters - - /* AREA API */ - - //missing attenuation? missing better override? - - enum AreaParameter { - AREA_PARAM_GRAVITY, - AREA_PARAM_GRAVITY_VECTOR, - AREA_PARAM_GRAVITY_IS_POINT, - AREA_PARAM_GRAVITY_DISTANCE_SCALE, - AREA_PARAM_GRAVITY_POINT_ATTENUATION, - AREA_PARAM_LINEAR_DAMP, - AREA_PARAM_ANGULAR_DAMP, - AREA_PARAM_PRIORITY - }; - - virtual RID area_create() = 0; - - virtual void area_set_space(RID p_area, RID p_space) = 0; - virtual RID area_get_space(RID p_area) const = 0; - - enum AreaSpaceOverrideMode { - AREA_SPACE_OVERRIDE_DISABLED, - AREA_SPACE_OVERRIDE_COMBINE, - AREA_SPACE_OVERRIDE_COMBINE_REPLACE, - AREA_SPACE_OVERRIDE_REPLACE, - AREA_SPACE_OVERRIDE_REPLACE_COMBINE - }; - - virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; - virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; - - virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; - virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; - virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) = 0; - - virtual int area_get_shape_count(RID p_area) const = 0; - virtual RID area_get_shape(RID p_area, int p_shape_idx) const = 0; - virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const = 0; - - virtual void area_remove_shape(RID p_area, int p_shape_idx) = 0; - virtual void area_clear_shapes(RID p_area) = 0; - - virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) = 0; - - virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0; - virtual ObjectID area_get_object_instance_id(RID p_area) const = 0; - - virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0; - virtual void area_set_transform(RID p_area, const Transform &p_transform) = 0; - - virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0; - virtual Transform area_get_transform(RID p_area) const = 0; - - virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0; - virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0; - - virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0; - - virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; - virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; - - virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0; - virtual bool area_is_ray_pickable(RID p_area) const = 0; - - /* BODY API */ - - //missing ccd? - - enum BodyMode { - BODY_MODE_STATIC, - BODY_MODE_KINEMATIC, - BODY_MODE_RIGID, - BODY_MODE_CHARACTER - }; - - virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) = 0; - - virtual void body_set_space(RID p_body, RID p_space) = 0; - virtual RID body_get_space(RID p_body) const = 0; - - virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0; - virtual BodyMode body_get_mode(RID p_body) const = 0; - - virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; - virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; - virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) = 0; - - virtual int body_get_shape_count(RID p_body) const = 0; - virtual RID body_get_shape(RID p_body, int p_shape_idx) const = 0; - virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const = 0; - - virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0; - virtual void body_clear_shapes(RID p_body) = 0; - - virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) = 0; - - virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) = 0; - virtual ObjectID body_get_object_instance_id(RID p_body) const = 0; - - virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) = 0; - virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const = 0; - - virtual void body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; - virtual uint32_t body_get_collision_layer(RID p_body) const = 0; - - virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; - virtual uint32_t body_get_collision_mask(RID p_body) const = 0; - - virtual void body_set_user_flags(RID p_body, uint32_t p_flags) = 0; - virtual uint32_t body_get_user_flags(RID p_body) const = 0; - - // common body variables - enum BodyParameter { - BODY_PARAM_BOUNCE, - BODY_PARAM_FRICTION, - BODY_PARAM_MASS, ///< unused for static, always infinite - BODY_PARAM_GRAVITY_SCALE, - BODY_PARAM_LINEAR_DAMP, - BODY_PARAM_ANGULAR_DAMP, - BODY_PARAM_MAX, - }; - - virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; - virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0; - - virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0; - virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0; - - //state - enum BodyState { - BODY_STATE_TRANSFORM, - BODY_STATE_LINEAR_VELOCITY, - BODY_STATE_ANGULAR_VELOCITY, - BODY_STATE_SLEEPING, - BODY_STATE_CAN_SLEEP - }; - - virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; - virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0; - - //do something about it - virtual void body_set_applied_force(RID p_body, const Vector3 &p_force) = 0; - virtual Vector3 body_get_applied_force(RID p_body) const = 0; - - virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque) = 0; - virtual Vector3 body_get_applied_torque(RID p_body) const = 0; - - virtual void body_add_central_force(RID p_body, const Vector3 &p_force) = 0; - virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) = 0; - virtual void body_add_torque(RID p_body, const Vector3 &p_torque) = 0; - - virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) = 0; - virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) = 0; - virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0; - virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0; - - enum BodyAxis { - BODY_AXIS_LINEAR_X = 1 << 0, - BODY_AXIS_LINEAR_Y = 1 << 1, - BODY_AXIS_LINEAR_Z = 1 << 2, - BODY_AXIS_ANGULAR_X = 1 << 3, - BODY_AXIS_ANGULAR_Y = 1 << 4, - BODY_AXIS_ANGULAR_Z = 1 << 5 - }; - - virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) = 0; - virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const = 0; - - //fix - virtual void body_add_collision_exception(RID p_body, RID p_body_b) = 0; - virtual void body_remove_collision_exception(RID p_body, RID p_body_b) = 0; - virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; - - virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) = 0; - virtual int body_get_max_contacts_reported(RID p_body) const = 0; - - //missing remove - virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) = 0; - virtual float body_get_contacts_reported_depth_threshold(RID p_body) const = 0; - - virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0; - virtual bool body_is_omitting_force_integration(RID p_body) const = 0; - - virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; - - virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0; - virtual bool body_is_ray_pickable(RID p_body) const = 0; - - // this function only works on physics process, errors and returns null otherwise - virtual PhysicsDirectBodyState *body_get_direct_state(RID p_body) = 0; - - struct MotionResult { - - Vector3 motion; - Vector3 remainder; - - Vector3 collision_point; - Vector3 collision_normal; - Vector3 collider_velocity; - int collision_local_shape; - ObjectID collider_id; - RID collider; - int collider_shape; - Variant collider_metadata; - MotionResult() { - collision_local_shape = 0; - collider_id = ObjectID(); - collider_shape = 0; - } - }; - - virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; - - struct SeparationResult { - - float collision_depth; - Vector3 collision_point; - Vector3 collision_normal; - Vector3 collider_velocity; - int collision_local_shape; - ObjectID collider_id; - RID collider; - int collider_shape; - Variant collider_metadata; - }; - - virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0; - - /* SOFT BODY */ - - virtual RID soft_body_create(bool p_init_sleeping = false) = 0; - - virtual void soft_body_update_visual_server(RID p_body, class SoftBodyVisualServerHandler *p_visual_server_handler) = 0; - - virtual void soft_body_set_space(RID p_body, RID p_space) = 0; - virtual RID soft_body_get_space(RID p_body) const = 0; - - virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) = 0; - - virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; - virtual uint32_t soft_body_get_collision_layer(RID p_body) const = 0; - - virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; - virtual uint32_t soft_body_get_collision_mask(RID p_body) const = 0; - - virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) = 0; - virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) = 0; - virtual void soft_body_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; - - virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; - virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const = 0; - - virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) = 0; - virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const = 0; - - virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0; - virtual bool soft_body_is_ray_pickable(RID p_body) const = 0; - - virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) = 0; - virtual int soft_body_get_simulation_precision(RID p_body) = 0; - - virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) = 0; - virtual real_t soft_body_get_total_mass(RID p_body) = 0; - - virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) = 0; - virtual real_t soft_body_get_linear_stiffness(RID p_body) = 0; - - virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) = 0; - virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) = 0; - - virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) = 0; - virtual real_t soft_body_get_volume_stiffness(RID p_body) = 0; - - virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) = 0; - virtual real_t soft_body_get_pressure_coefficient(RID p_body) = 0; - - virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) = 0; - virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) = 0; - - virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) = 0; - virtual real_t soft_body_get_damping_coefficient(RID p_body) = 0; - - virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) = 0; - virtual real_t soft_body_get_drag_coefficient(RID p_body) = 0; - - virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) = 0; - virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) = 0; - - virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const = 0; - - virtual void soft_body_remove_all_pinned_points(RID p_body) = 0; - virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) = 0; - virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) = 0; - - /* JOINT API */ - - enum JointType { - - JOINT_PIN, - JOINT_HINGE, - JOINT_SLIDER, - JOINT_CONE_TWIST, - JOINT_6DOF - - }; - - virtual JointType joint_get_type(RID p_joint) const = 0; - - virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0; - virtual int joint_get_solver_priority(RID p_joint) const = 0; - - virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; - virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; - - virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0; - - enum PinJointParam { - PIN_JOINT_BIAS, - PIN_JOINT_DAMPING, - PIN_JOINT_IMPULSE_CLAMP - }; - - virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) = 0; - virtual float pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0; - - virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) = 0; - virtual Vector3 pin_joint_get_local_a(RID p_joint) const = 0; - - virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) = 0; - virtual Vector3 pin_joint_get_local_b(RID p_joint) const = 0; - - enum HingeJointParam { - - HINGE_JOINT_BIAS, - HINGE_JOINT_LIMIT_UPPER, - HINGE_JOINT_LIMIT_LOWER, - HINGE_JOINT_LIMIT_BIAS, - HINGE_JOINT_LIMIT_SOFTNESS, - HINGE_JOINT_LIMIT_RELAXATION, - HINGE_JOINT_MOTOR_TARGET_VELOCITY, - HINGE_JOINT_MOTOR_MAX_IMPULSE, - HINGE_JOINT_MAX - }; - - enum HingeJointFlag { - HINGE_JOINT_FLAG_USE_LIMIT, - HINGE_JOINT_FLAG_ENABLE_MOTOR, - HINGE_JOINT_FLAG_MAX - }; - - virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0; - virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0; - - virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) = 0; - virtual float hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0; - - virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) = 0; - virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const = 0; - - enum SliderJointParam { - SLIDER_JOINT_LINEAR_LIMIT_UPPER, - SLIDER_JOINT_LINEAR_LIMIT_LOWER, - SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, - SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, - SLIDER_JOINT_LINEAR_LIMIT_DAMPING, - SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, - SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, - SLIDER_JOINT_LINEAR_MOTION_DAMPING, - SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, - SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, - SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, - - SLIDER_JOINT_ANGULAR_LIMIT_UPPER, - SLIDER_JOINT_ANGULAR_LIMIT_LOWER, - SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, - SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, - SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, - SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, - SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, - SLIDER_JOINT_ANGULAR_MOTION_DAMPING, - SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, - SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, - SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, - SLIDER_JOINT_MAX - - }; - - virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A - - virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) = 0; - virtual float slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0; - - enum ConeTwistJointParam { - CONE_TWIST_JOINT_SWING_SPAN, - CONE_TWIST_JOINT_TWIST_SPAN, - CONE_TWIST_JOINT_BIAS, - CONE_TWIST_JOINT_SOFTNESS, - CONE_TWIST_JOINT_RELAXATION, - CONE_TWIST_MAX - }; - - virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A - - virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) = 0; - virtual float cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0; - - enum G6DOFJointAxisParam { - G6DOF_JOINT_LINEAR_LOWER_LIMIT, - G6DOF_JOINT_LINEAR_UPPER_LIMIT, - G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, - G6DOF_JOINT_LINEAR_RESTITUTION, - G6DOF_JOINT_LINEAR_DAMPING, - G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, - G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, - G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, - G6DOF_JOINT_LINEAR_SPRING_DAMPING, - G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, - G6DOF_JOINT_ANGULAR_LOWER_LIMIT, - G6DOF_JOINT_ANGULAR_UPPER_LIMIT, - G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, - G6DOF_JOINT_ANGULAR_DAMPING, - G6DOF_JOINT_ANGULAR_RESTITUTION, - G6DOF_JOINT_ANGULAR_FORCE_LIMIT, - G6DOF_JOINT_ANGULAR_ERP, - G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, - G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, - G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, - G6DOF_JOINT_ANGULAR_SPRING_DAMPING, - G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, - G6DOF_JOINT_MAX - }; - - enum G6DOFJointAxisFlag { - - G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, - G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, - G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, - G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, - G6DOF_JOINT_FLAG_ENABLE_MOTOR, - G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, - G6DOF_JOINT_FLAG_MAX - }; - - virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A - - virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, float p_value) = 0; - virtual float generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) = 0; - - virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) = 0; - virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) = 0; - - virtual void generic_6dof_joint_set_precision(RID p_joint, int precision) = 0; - virtual int generic_6dof_joint_get_precision(RID p_joint) = 0; - - /* QUERY API */ - - enum AreaBodyStatus { - AREA_BODY_ADDED, - AREA_BODY_REMOVED - }; - - /* MISC */ - - virtual void free(RID p_rid) = 0; - - virtual void set_active(bool p_active) = 0; - virtual void init() = 0; - virtual void step(float p_step) = 0; - virtual void sync() = 0; - virtual void flush_queries() = 0; - virtual void finish() = 0; - - virtual bool is_flushing_queries() const = 0; - - enum ProcessInfo { - - INFO_ACTIVE_OBJECTS, - INFO_COLLISION_PAIRS, - INFO_ISLAND_COUNT - }; - - virtual int get_process_info(ProcessInfo p_info) = 0; - - PhysicsServer(); - ~PhysicsServer(); -}; - -typedef PhysicsServer *(*CreatePhysicsServerCallback)(); - -class PhysicsServerManager { - struct ClassInfo { - String name; - CreatePhysicsServerCallback create_callback; - - ClassInfo() : - name(""), - create_callback(NULL) {} - - ClassInfo(String p_name, CreatePhysicsServerCallback p_create_callback) : - name(p_name), - create_callback(p_create_callback) {} - - ClassInfo(const ClassInfo &p_ci) : - name(p_ci.name), - create_callback(p_ci.create_callback) {} - - ClassInfo operator=(const ClassInfo &p_ci) { - name = p_ci.name; - create_callback = p_ci.create_callback; - return *this; - } - }; - - static Vector physics_servers; - static int default_server_id; - static int default_server_priority; - -public: - static const String setting_property_name; - -private: - static void on_servers_changed(); - -public: - static void register_server(const String &p_name, CreatePhysicsServerCallback p_creat_callback); - static void set_default_server(const String &p_name, int p_priority = 0); - static int find_server_id(const String &p_name); - static int get_servers_count(); - static String get_server_name(int p_id); - static PhysicsServer *new_default_server(); - static PhysicsServer *new_server(const String &p_name); -}; - -VARIANT_ENUM_CAST(PhysicsServer::ShapeType); -VARIANT_ENUM_CAST(PhysicsServer::SpaceParameter); -VARIANT_ENUM_CAST(PhysicsServer::AreaParameter); -VARIANT_ENUM_CAST(PhysicsServer::AreaSpaceOverrideMode); -VARIANT_ENUM_CAST(PhysicsServer::BodyMode); -VARIANT_ENUM_CAST(PhysicsServer::BodyParameter); -VARIANT_ENUM_CAST(PhysicsServer::BodyState); -VARIANT_ENUM_CAST(PhysicsServer::BodyAxis); -VARIANT_ENUM_CAST(PhysicsServer::PinJointParam); -VARIANT_ENUM_CAST(PhysicsServer::JointType); -VARIANT_ENUM_CAST(PhysicsServer::HingeJointParam); -VARIANT_ENUM_CAST(PhysicsServer::HingeJointFlag); -VARIANT_ENUM_CAST(PhysicsServer::SliderJointParam); -VARIANT_ENUM_CAST(PhysicsServer::ConeTwistJointParam); -VARIANT_ENUM_CAST(PhysicsServer::G6DOFJointAxisParam); -VARIANT_ENUM_CAST(PhysicsServer::G6DOFJointAxisFlag); -VARIANT_ENUM_CAST(PhysicsServer::AreaBodyStatus); -VARIANT_ENUM_CAST(PhysicsServer::ProcessInfo); - -#endif diff --git a/servers/physics_server_2d.cpp b/servers/physics_server_2d.cpp new file mode 100644 index 0000000000..d80a51ca36 --- /dev/null +++ b/servers/physics_server_2d.cpp @@ -0,0 +1,840 @@ +/*************************************************************************/ +/* physics_2d_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_2d.h" + +#include "core/method_bind_ext.gen.inc" +#include "core/print_string.h" +#include "core/project_settings.h" + +PhysicsServer2D *PhysicsServer2D::singleton = NULL; + +void PhysicsDirectBodyState2D::integrate_forces() { + + real_t step = get_step(); + Vector2 lv = get_linear_velocity(); + lv += get_total_gravity() * step; + + real_t av = get_angular_velocity(); + + float damp = 1.0 - step * get_total_linear_damp(); + + if (damp < 0) // reached zero in the given time + damp = 0; + + lv *= damp; + + damp = 1.0 - step * get_total_angular_damp(); + + if (damp < 0) // reached zero in the given time + damp = 0; + + av *= damp; + + set_linear_velocity(lv); + set_angular_velocity(av); +} + +Object *PhysicsDirectBodyState2D::get_contact_collider_object(int p_contact_idx) const { + + ObjectID objid = get_contact_collider_id(p_contact_idx); + Object *obj = ObjectDB::get_instance(objid); + return obj; +} + +PhysicsServer2D *PhysicsServer2D::get_singleton() { + + return singleton; +} + +void PhysicsDirectBodyState2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_total_gravity"), &PhysicsDirectBodyState2D::get_total_gravity); + ClassDB::bind_method(D_METHOD("get_total_linear_damp"), &PhysicsDirectBodyState2D::get_total_linear_damp); + ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState2D::get_total_angular_damp); + + ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState2D::get_inverse_mass); + ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState2D::get_inverse_inertia); + + ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &PhysicsDirectBodyState2D::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &PhysicsDirectBodyState2D::get_linear_velocity); + + ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &PhysicsDirectBodyState2D::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &PhysicsDirectBodyState2D::get_angular_velocity); + + ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState2D::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState2D::get_transform); + + ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState2D::add_central_force); + ClassDB::bind_method(D_METHOD("add_force", "offset", "force"), &PhysicsDirectBodyState2D::add_force); + ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState2D::add_torque); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_central_impulse); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "impulse"), &PhysicsDirectBodyState2D::apply_torque_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "offset", "impulse"), &PhysicsDirectBodyState2D::apply_impulse); + + ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState2D::set_sleep_state); + ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState2D::is_sleeping); + + ClassDB::bind_method(D_METHOD("get_contact_count"), &PhysicsDirectBodyState2D::get_contact_count); + + ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_local_position); + ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_local_normal); + ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_local_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider); + ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_position); + ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_id); + ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_object); + ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider_shape_metadata", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_shape_metadata); + ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState2D::get_contact_collider_velocity_at_position); + ClassDB::bind_method(D_METHOD("get_step"), &PhysicsDirectBodyState2D::get_step); + ClassDB::bind_method(D_METHOD("integrate_forces"), &PhysicsDirectBodyState2D::integrate_forces); + ClassDB::bind_method(D_METHOD("get_space_state"), &PhysicsDirectBodyState2D::get_space_state); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step"), "", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inverse_mass"), "", "get_inverse_mass"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inverse_inertia"), "", "get_inverse_inertia"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_angular_damp"), "", "get_total_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "total_gravity"), "", "get_total_gravity"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); +} + +PhysicsDirectBodyState2D::PhysicsDirectBodyState2D() {} + +/////////////////////////////////////////////////////// + +void PhysicsShapeQueryParameters2D::set_shape(const RES &p_shape) { + + ERR_FAIL_COND(p_shape.is_null()); + shape = p_shape->get_rid(); +} + +void PhysicsShapeQueryParameters2D::set_shape_rid(const RID &p_shape) { + + shape = p_shape; +} + +RID PhysicsShapeQueryParameters2D::get_shape_rid() const { + + return shape; +} + +void PhysicsShapeQueryParameters2D::set_transform(const Transform2D &p_transform) { + + transform = p_transform; +} +Transform2D PhysicsShapeQueryParameters2D::get_transform() const { + + return transform; +} + +void PhysicsShapeQueryParameters2D::set_motion(const Vector2 &p_motion) { + + motion = p_motion; +} +Vector2 PhysicsShapeQueryParameters2D::get_motion() const { + + return motion; +} + +void PhysicsShapeQueryParameters2D::set_margin(float p_margin) { + + margin = p_margin; +} +float PhysicsShapeQueryParameters2D::get_margin() const { + + return margin; +} + +void PhysicsShapeQueryParameters2D::set_collision_mask(int p_collision_mask) { + + collision_mask = p_collision_mask; +} +int PhysicsShapeQueryParameters2D::get_collision_mask() const { + + return collision_mask; +} + +void PhysicsShapeQueryParameters2D::set_exclude(const Vector &p_exclude) { + + exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) + exclude.insert(p_exclude[i]); +} + +Vector PhysicsShapeQueryParameters2D::get_exclude() const { + + Vector ret; + ret.resize(exclude.size()); + int idx = 0; + for (Set::Element *E = exclude.front(); E; E = E->next()) { + ret.write[idx] = E->get(); + } + return ret; +} + +void PhysicsShapeQueryParameters2D::set_collide_with_bodies(bool p_enable) { + collide_with_bodies = p_enable; +} + +bool PhysicsShapeQueryParameters2D::is_collide_with_bodies_enabled() const { + return collide_with_bodies; +} + +void PhysicsShapeQueryParameters2D::set_collide_with_areas(bool p_enable) { + collide_with_areas = p_enable; +} + +bool PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled() const { + return collide_with_areas; +} + +void PhysicsShapeQueryParameters2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters2D::set_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters2D::set_shape_rid); + ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters2D::get_shape_rid); + + ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsShapeQueryParameters2D::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsShapeQueryParameters2D::get_transform); + + ClassDB::bind_method(D_METHOD("set_motion", "motion"), &PhysicsShapeQueryParameters2D::set_motion); + ClassDB::bind_method(D_METHOD("get_motion"), &PhysicsShapeQueryParameters2D::get_motion); + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters2D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters2D::get_margin); + + ClassDB::bind_method(D_METHOD("set_collision_layer", "collision_layer"), &PhysicsShapeQueryParameters2D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_layer"), &PhysicsShapeQueryParameters2D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsShapeQueryParameters2D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsShapeQueryParameters2D::get_exclude); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsShapeQueryParameters2D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsShapeQueryParameters2D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsShapeQueryParameters2D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters2D::is_collide_with_areas_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_layer", PROPERTY_HINT_LAYERS_2D_PHYSICS), "set_collision_layer", "get_collision_layer"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "set_motion", "get_motion"); + //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter + ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); +} + +PhysicsShapeQueryParameters2D::PhysicsShapeQueryParameters2D() { + + margin = 0; + collision_mask = 0x7FFFFFFF; + collide_with_bodies = true; + collide_with_areas = false; +} + +Dictionary PhysicsDirectSpaceState2D::_intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { + + RayResult inters; + Set exclude; + for (int i = 0; i < p_exclude.size(); i++) + exclude.insert(p_exclude[i]); + + bool res = intersect_ray(p_from, p_to, inters, exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); + + if (!res) + return Dictionary(); + + Dictionary d; + d["position"] = inters.position; + d["normal"] = inters.normal; + d["collider_id"] = inters.collider_id; + d["collider"] = inters.collider; + d["shape"] = inters.shape; + d["rid"] = inters.rid; + d["metadata"] = inters.metadata; + + return d; +} + +Array PhysicsDirectSpaceState2D::_intersect_shape(const Ref &p_shape_query, int p_max_results) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); + + Vector sr; + sr.resize(p_max_results); + int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + Array ret; + ret.resize(rc); + for (int i = 0; i < rc; i++) { + + Dictionary d; + d["rid"] = sr[i].rid; + d["collider_id"] = sr[i].collider_id; + d["collider"] = sr[i].collider; + d["shape"] = sr[i].shape; + d["metadata"] = sr[i].metadata; + ret[i] = d; + } + + return ret; +} + +Array PhysicsDirectSpaceState2D::_cast_motion(const Ref &p_shape_query) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); + + float closest_safe, closest_unsafe; + bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + if (!res) + return Array(); + Array ret; + ret.resize(2); + ret[0] = closest_safe; + ret[1] = closest_unsafe; + return ret; +} + +Array PhysicsDirectSpaceState2D::_intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas, ObjectID p_canvas_instance_id) { + + Set exclude; + for (int i = 0; i < p_exclude.size(); i++) + exclude.insert(p_exclude[i]); + + Vector ret; + ret.resize(p_max_results); + + int rc; + if (p_filter_by_canvas) + rc = intersect_point(p_point, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); + else + rc = intersect_point_on_canvas(p_point, p_canvas_instance_id, ret.ptrw(), ret.size(), exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); + + if (rc == 0) + return Array(); + + Array r; + r.resize(rc); + for (int i = 0; i < rc; i++) { + + Dictionary d; + d["rid"] = ret[i].rid; + d["collider_id"] = ret[i].collider_id; + d["collider"] = ret[i].collider; + d["shape"] = ret[i].shape; + d["metadata"] = ret[i].metadata; + r[i] = d; + } + return r; +} + +Array PhysicsDirectSpaceState2D::_intersect_point(const Vector2 &p_point, int p_max_results, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { + + return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas); +} + +Array PhysicsDirectSpaceState2D::_intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results, const Vector &p_exclude, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas) { + + return _intersect_point_impl(p_point, p_max_results, p_exclude, p_layers, p_collide_with_bodies, p_collide_with_areas, true, p_canvas_intance_id); +} + +Array PhysicsDirectSpaceState2D::_collide_shape(const Ref &p_shape_query, int p_max_results) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); + + Vector ret; + ret.resize(p_max_results * 2); + int rc = 0; + bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + if (!res) + return Array(); + Array r; + r.resize(rc * 2); + for (int i = 0; i < rc * 2; i++) + r[i] = ret[i]; + return r; +} +Dictionary PhysicsDirectSpaceState2D::_get_rest_info(const Ref &p_shape_query) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Dictionary()); + + ShapeRestInfo sri; + + bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->motion, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + Dictionary r; + if (!res) + return r; + + r["point"] = sri.point; + r["normal"] = sri.normal; + r["rid"] = sri.rid; + r["collider_id"] = sri.collider_id; + r["shape"] = sri.shape; + r["linear_velocity"] = sri.linear_velocity; + r["metadata"] = sri.metadata; + + return r; +} + +PhysicsDirectSpaceState2D::PhysicsDirectSpaceState2D() { +} + +void PhysicsDirectSpaceState2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("intersect_point", "point", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("intersect_point_on_canvas", "point", "canvas_instance_id", "max_results", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_point_on_canvas, DEFVAL(32), DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_layer", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState2D::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_intersect_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion", "shape"), &PhysicsDirectSpaceState2D::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState2D::_collide_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState2D::_get_rest_info); +} + +int PhysicsShapeQueryResult2D::get_result_count() const { + + return result.size(); +} +RID PhysicsShapeQueryResult2D::get_result_rid(int p_idx) const { + + return result[p_idx].rid; +} +ObjectID PhysicsShapeQueryResult2D::get_result_object_id(int p_idx) const { + + return result[p_idx].collider_id; +} +Object *PhysicsShapeQueryResult2D::get_result_object(int p_idx) const { + + return result[p_idx].collider; +} +int PhysicsShapeQueryResult2D::get_result_object_shape(int p_idx) const { + + return result[p_idx].shape; +} + +PhysicsShapeQueryResult2D::PhysicsShapeQueryResult2D() { +} + +void PhysicsShapeQueryResult2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_result_count"), &PhysicsShapeQueryResult2D::get_result_count); + ClassDB::bind_method(D_METHOD("get_result_rid", "idx"), &PhysicsShapeQueryResult2D::get_result_rid); + ClassDB::bind_method(D_METHOD("get_result_object_id", "idx"), &PhysicsShapeQueryResult2D::get_result_object_id); + ClassDB::bind_method(D_METHOD("get_result_object", "idx"), &PhysicsShapeQueryResult2D::get_result_object); + ClassDB::bind_method(D_METHOD("get_result_object_shape", "idx"), &PhysicsShapeQueryResult2D::get_result_object_shape); +} + +/////////////////////////////// + +Vector2 Physics2DTestMotionResult::get_motion() const { + + return result.motion; +} +Vector2 Physics2DTestMotionResult::get_motion_remainder() const { + + return result.remainder; +} + +Vector2 Physics2DTestMotionResult::get_collision_point() const { + + return result.collision_point; +} +Vector2 Physics2DTestMotionResult::get_collision_normal() const { + + return result.collision_normal; +} +Vector2 Physics2DTestMotionResult::get_collider_velocity() const { + + return result.collider_velocity; +} +ObjectID Physics2DTestMotionResult::get_collider_id() const { + + return result.collider_id; +} +RID Physics2DTestMotionResult::get_collider_rid() const { + + return result.collider; +} + +Object *Physics2DTestMotionResult::get_collider() const { + return ObjectDB::get_instance(result.collider_id); +} + +int Physics2DTestMotionResult::get_collider_shape() const { + + return result.collider_shape; +} + +void Physics2DTestMotionResult::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_motion"), &Physics2DTestMotionResult::get_motion); + ClassDB::bind_method(D_METHOD("get_motion_remainder"), &Physics2DTestMotionResult::get_motion_remainder); + ClassDB::bind_method(D_METHOD("get_collision_point"), &Physics2DTestMotionResult::get_collision_point); + ClassDB::bind_method(D_METHOD("get_collision_normal"), &Physics2DTestMotionResult::get_collision_normal); + ClassDB::bind_method(D_METHOD("get_collider_velocity"), &Physics2DTestMotionResult::get_collider_velocity); + ClassDB::bind_method(D_METHOD("get_collider_id"), &Physics2DTestMotionResult::get_collider_id); + ClassDB::bind_method(D_METHOD("get_collider_rid"), &Physics2DTestMotionResult::get_collider_rid); + ClassDB::bind_method(D_METHOD("get_collider"), &Physics2DTestMotionResult::get_collider); + ClassDB::bind_method(D_METHOD("get_collider_shape"), &Physics2DTestMotionResult::get_collider_shape); + + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion"), "", "get_motion"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "motion_remainder"), "", "get_motion_remainder"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_point"), "", "get_collision_point"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collision_normal"), "", "get_collision_normal"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "collider_velocity"), "", "get_collider_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_id", PROPERTY_HINT_OBJECT_ID), "", "get_collider_id"); + ADD_PROPERTY(PropertyInfo(Variant::_RID, "collider_rid"), "", "get_collider_rid"); + ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "collider"), "", "get_collider"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "collider_shape"), "", "get_collider_shape"); +} + +Physics2DTestMotionResult::Physics2DTestMotionResult() { + + colliding = false; + + result.collider_shape = 0; +} + +/////////////////////////////////////// + +bool PhysicsServer2D::_body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin, const Ref &p_result) { + + MotionResult *r = NULL; + if (p_result.is_valid()) + r = p_result->get_result_ptr(); + return body_test_motion(p_body, p_from, p_motion, p_infinite_inertia, p_margin, r); +} + +void PhysicsServer2D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("line_shape_create"), &PhysicsServer2D::line_shape_create); + ClassDB::bind_method(D_METHOD("ray_shape_create"), &PhysicsServer2D::ray_shape_create); + ClassDB::bind_method(D_METHOD("segment_shape_create"), &PhysicsServer2D::segment_shape_create); + ClassDB::bind_method(D_METHOD("circle_shape_create"), &PhysicsServer2D::circle_shape_create); + ClassDB::bind_method(D_METHOD("rectangle_shape_create"), &PhysicsServer2D::rectangle_shape_create); + ClassDB::bind_method(D_METHOD("capsule_shape_create"), &PhysicsServer2D::capsule_shape_create); + ClassDB::bind_method(D_METHOD("convex_polygon_shape_create"), &PhysicsServer2D::convex_polygon_shape_create); + ClassDB::bind_method(D_METHOD("concave_polygon_shape_create"), &PhysicsServer2D::concave_polygon_shape_create); + + ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &PhysicsServer2D::shape_set_data); + + ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &PhysicsServer2D::shape_get_type); + ClassDB::bind_method(D_METHOD("shape_get_data", "shape"), &PhysicsServer2D::shape_get_data); + + ClassDB::bind_method(D_METHOD("space_create"), &PhysicsServer2D::space_create); + ClassDB::bind_method(D_METHOD("space_set_active", "space", "active"), &PhysicsServer2D::space_set_active); + ClassDB::bind_method(D_METHOD("space_is_active", "space"), &PhysicsServer2D::space_is_active); + ClassDB::bind_method(D_METHOD("space_set_param", "space", "param", "value"), &PhysicsServer2D::space_set_param); + ClassDB::bind_method(D_METHOD("space_get_param", "space", "param"), &PhysicsServer2D::space_get_param); + ClassDB::bind_method(D_METHOD("space_get_direct_state", "space"), &PhysicsServer2D::space_get_direct_state); + + ClassDB::bind_method(D_METHOD("area_create"), &PhysicsServer2D::area_create); + ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer2D::area_set_space); + ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer2D::area_get_space); + + ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer2D::area_set_space_override_mode); + ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer2D::area_get_space_override_mode); + + ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer2D::area_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer2D::area_set_shape); + ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer2D::area_set_shape_transform); + ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &PhysicsServer2D::area_set_shape_disabled); + + ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &PhysicsServer2D::area_get_shape_count); + ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &PhysicsServer2D::area_get_shape); + ClassDB::bind_method(D_METHOD("area_get_shape_transform", "area", "shape_idx"), &PhysicsServer2D::area_get_shape_transform); + + ClassDB::bind_method(D_METHOD("area_remove_shape", "area", "shape_idx"), &PhysicsServer2D::area_remove_shape); + ClassDB::bind_method(D_METHOD("area_clear_shapes", "area"), &PhysicsServer2D::area_clear_shapes); + + ClassDB::bind_method(D_METHOD("area_set_collision_layer", "area", "layer"), &PhysicsServer2D::area_set_collision_layer); + ClassDB::bind_method(D_METHOD("area_set_collision_mask", "area", "mask"), &PhysicsServer2D::area_set_collision_mask); + + ClassDB::bind_method(D_METHOD("area_set_param", "area", "param", "value"), &PhysicsServer2D::area_set_param); + ClassDB::bind_method(D_METHOD("area_set_transform", "area", "transform"), &PhysicsServer2D::area_set_transform); + + ClassDB::bind_method(D_METHOD("area_get_param", "area", "param"), &PhysicsServer2D::area_get_param); + ClassDB::bind_method(D_METHOD("area_get_transform", "area"), &PhysicsServer2D::area_get_transform); + + ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &PhysicsServer2D::area_attach_object_instance_id); + ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &PhysicsServer2D::area_get_object_instance_id); + + ClassDB::bind_method(D_METHOD("area_attach_canvas_instance_id", "area", "id"), &PhysicsServer2D::area_attach_canvas_instance_id); + ClassDB::bind_method(D_METHOD("area_get_canvas_instance_id", "area"), &PhysicsServer2D::area_get_canvas_instance_id); + + ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer2D::area_set_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer2D::area_set_area_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer2D::area_set_monitorable); + + ClassDB::bind_method(D_METHOD("body_create"), &PhysicsServer2D::body_create); + + ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &PhysicsServer2D::body_set_space); + ClassDB::bind_method(D_METHOD("body_get_space", "body"), &PhysicsServer2D::body_get_space); + + ClassDB::bind_method(D_METHOD("body_set_mode", "body", "mode"), &PhysicsServer2D::body_set_mode); + ClassDB::bind_method(D_METHOD("body_get_mode", "body"), &PhysicsServer2D::body_get_mode); + + ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer2D::body_add_shape, DEFVAL(Transform2D()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer2D::body_set_shape); + ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer2D::body_set_shape_transform); + ClassDB::bind_method(D_METHOD("body_set_shape_metadata", "body", "shape_idx", "metadata"), &PhysicsServer2D::body_set_shape_metadata); + + ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &PhysicsServer2D::body_get_shape_count); + ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &PhysicsServer2D::body_get_shape); + ClassDB::bind_method(D_METHOD("body_get_shape_transform", "body", "shape_idx"), &PhysicsServer2D::body_get_shape_transform); + ClassDB::bind_method(D_METHOD("body_get_shape_metadata", "body", "shape_idx"), &PhysicsServer2D::body_get_shape_metadata); + + ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &PhysicsServer2D::body_remove_shape); + ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &PhysicsServer2D::body_clear_shapes); + + ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer2D::body_set_shape_disabled); + ClassDB::bind_method(D_METHOD("body_set_shape_as_one_way_collision", "body", "shape_idx", "enable", "margin"), &PhysicsServer2D::body_set_shape_as_one_way_collision); + + ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &PhysicsServer2D::body_attach_object_instance_id); + ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &PhysicsServer2D::body_get_object_instance_id); + + ClassDB::bind_method(D_METHOD("body_attach_canvas_instance_id", "body", "id"), &PhysicsServer2D::body_attach_canvas_instance_id); + ClassDB::bind_method(D_METHOD("body_get_canvas_instance_id", "body"), &PhysicsServer2D::body_get_canvas_instance_id); + + ClassDB::bind_method(D_METHOD("body_set_continuous_collision_detection_mode", "body", "mode"), &PhysicsServer2D::body_set_continuous_collision_detection_mode); + ClassDB::bind_method(D_METHOD("body_get_continuous_collision_detection_mode", "body"), &PhysicsServer2D::body_get_continuous_collision_detection_mode); + + ClassDB::bind_method(D_METHOD("body_set_collision_layer", "body", "layer"), &PhysicsServer2D::body_set_collision_layer); + ClassDB::bind_method(D_METHOD("body_get_collision_layer", "body"), &PhysicsServer2D::body_get_collision_layer); + + ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer2D::body_set_collision_mask); + ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer2D::body_get_collision_mask); + + ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer2D::body_set_param); + ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer2D::body_get_param); + + ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer2D::body_set_state); + ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer2D::body_get_state); + + ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_central_impulse); + ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer2D::body_apply_torque_impulse); + ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &PhysicsServer2D::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer2D::body_add_central_force); + ClassDB::bind_method(D_METHOD("body_add_force", "body", "offset", "force"), &PhysicsServer2D::body_add_force); + ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer2D::body_add_torque); + ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer2D::body_set_axis_velocity); + + ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer2D::body_add_collision_exception); + ClassDB::bind_method(D_METHOD("body_remove_collision_exception", "body", "excepted_body"), &PhysicsServer2D::body_remove_collision_exception); + + ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported", "body", "amount"), &PhysicsServer2D::body_set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported", "body"), &PhysicsServer2D::body_get_max_contacts_reported); + + ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer2D::body_set_omit_force_integration); + ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer2D::body_is_omitting_force_integration); + + ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer2D::body_set_force_integration_callback, DEFVAL(Variant())); + + ClassDB::bind_method(D_METHOD("body_test_motion", "body", "from", "motion", "infinite_inertia", "margin", "result"), &PhysicsServer2D::_body_test_motion, DEFVAL(0.08), DEFVAL(Variant())); + + ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer2D::body_get_direct_state); + + /* JOINT API */ + + ClassDB::bind_method(D_METHOD("joint_set_param", "joint", "param", "value"), &PhysicsServer2D::joint_set_param); + ClassDB::bind_method(D_METHOD("joint_get_param", "joint", "param"), &PhysicsServer2D::joint_get_param); + + ClassDB::bind_method(D_METHOD("pin_joint_create", "anchor", "body_a", "body_b"), &PhysicsServer2D::pin_joint_create, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("groove_joint_create", "groove1_a", "groove2_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::groove_joint_create, DEFVAL(RID()), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("damped_spring_joint_create", "anchor_a", "anchor_b", "body_a", "body_b"), &PhysicsServer2D::damped_spring_joint_create, DEFVAL(RID())); + + ClassDB::bind_method(D_METHOD("damped_string_joint_set_param", "joint", "param", "value"), &PhysicsServer2D::damped_string_joint_set_param); + ClassDB::bind_method(D_METHOD("damped_string_joint_get_param", "joint", "param"), &PhysicsServer2D::damped_string_joint_get_param); + + ClassDB::bind_method(D_METHOD("joint_get_type", "joint"), &PhysicsServer2D::joint_get_type); + + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &PhysicsServer2D::free); + + ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer2D::set_active); + + ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer2D::get_process_info); + + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); + BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); + + BIND_ENUM_CONSTANT(SHAPE_LINE); + BIND_ENUM_CONSTANT(SHAPE_RAY); + BIND_ENUM_CONSTANT(SHAPE_SEGMENT); + BIND_ENUM_CONSTANT(SHAPE_CIRCLE); + BIND_ENUM_CONSTANT(SHAPE_RECTANGLE); + BIND_ENUM_CONSTANT(SHAPE_CAPSULE); + BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON); + BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); + BIND_ENUM_CONSTANT(SHAPE_CUSTOM); + + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); + + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE_REPLACE); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE_COMBINE); + + BIND_ENUM_CONSTANT(BODY_MODE_STATIC); + BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID); + BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER); + + BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); + BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); + BIND_ENUM_CONSTANT(BODY_PARAM_MASS); + BIND_ENUM_CONSTANT(BODY_PARAM_INERTIA); + BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE); + BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP); + BIND_ENUM_CONSTANT(BODY_PARAM_MAX); + + BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM); + BIND_ENUM_CONSTANT(BODY_STATE_LINEAR_VELOCITY); + BIND_ENUM_CONSTANT(BODY_STATE_ANGULAR_VELOCITY); + BIND_ENUM_CONSTANT(BODY_STATE_SLEEPING); + BIND_ENUM_CONSTANT(BODY_STATE_CAN_SLEEP); + + BIND_ENUM_CONSTANT(JOINT_PIN); + BIND_ENUM_CONSTANT(JOINT_GROOVE); + BIND_ENUM_CONSTANT(JOINT_DAMPED_SPRING); + + BIND_ENUM_CONSTANT(JOINT_PARAM_BIAS); + BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_BIAS); + BIND_ENUM_CONSTANT(JOINT_PARAM_MAX_FORCE); + + BIND_ENUM_CONSTANT(DAMPED_STRING_REST_LENGTH); + BIND_ENUM_CONSTANT(DAMPED_STRING_STIFFNESS); + BIND_ENUM_CONSTANT(DAMPED_STRING_DAMPING); + + BIND_ENUM_CONSTANT(CCD_MODE_DISABLED); + BIND_ENUM_CONSTANT(CCD_MODE_CAST_RAY); + BIND_ENUM_CONSTANT(CCD_MODE_CAST_SHAPE); + + BIND_ENUM_CONSTANT(AREA_BODY_ADDED); + BIND_ENUM_CONSTANT(AREA_BODY_REMOVED); + + BIND_ENUM_CONSTANT(INFO_ACTIVE_OBJECTS); + BIND_ENUM_CONSTANT(INFO_COLLISION_PAIRS); + BIND_ENUM_CONSTANT(INFO_ISLAND_COUNT); +} + +PhysicsServer2D::PhysicsServer2D() { + + singleton = this; +} + +PhysicsServer2D::~PhysicsServer2D() { + + singleton = NULL; +} + +Vector PhysicsServer2DManager::physics_2d_servers; +int PhysicsServer2DManager::default_server_id = -1; +int PhysicsServer2DManager::default_server_priority = -1; +const String PhysicsServer2DManager::setting_property_name("physics/2d/physics_engine"); + +void PhysicsServer2DManager::on_servers_changed() { + + String physics_servers("DEFAULT"); + for (int i = get_servers_count() - 1; 0 <= i; --i) { + physics_servers += "," + get_server_name(i); + } + ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers)); +} + +void PhysicsServer2DManager::register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback) { + + ERR_FAIL_COND(!p_creat_callback); + ERR_FAIL_COND(find_server_id(p_name) != -1); + physics_2d_servers.push_back(ClassInfo(p_name, p_creat_callback)); + on_servers_changed(); +} + +void PhysicsServer2DManager::set_default_server(const String &p_name, int p_priority) { + + const int id = find_server_id(p_name); + ERR_FAIL_COND(id == -1); // Not found + if (default_server_priority < p_priority) { + default_server_id = id; + default_server_priority = p_priority; + } +} + +int PhysicsServer2DManager::find_server_id(const String &p_name) { + + for (int i = physics_2d_servers.size() - 1; 0 <= i; --i) { + if (p_name == physics_2d_servers[i].name) { + return i; + } + } + return -1; +} + +int PhysicsServer2DManager::get_servers_count() { + return physics_2d_servers.size(); +} + +String PhysicsServer2DManager::get_server_name(int p_id) { + ERR_FAIL_INDEX_V(p_id, get_servers_count(), ""); + return physics_2d_servers[p_id].name; +} + +PhysicsServer2D *PhysicsServer2DManager::new_default_server() { + ERR_FAIL_COND_V(default_server_id == -1, NULL); + return physics_2d_servers[default_server_id].create_callback(); +} + +PhysicsServer2D *PhysicsServer2DManager::new_server(const String &p_name) { + int id = find_server_id(p_name); + if (id == -1) { + return NULL; + } else { + return physics_2d_servers[id].create_callback(); + } +} diff --git a/servers/physics_server_2d.h b/servers/physics_server_2d.h new file mode 100644 index 0000000000..9fa3a7b71a --- /dev/null +++ b/servers/physics_server_2d.h @@ -0,0 +1,699 @@ +/*************************************************************************/ +/* physics_2d_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_2D_SERVER_H +#define PHYSICS_2D_SERVER_H + +#include "core/object.h" +#include "core/reference.h" +#include "core/resource.h" + +class PhysicsDirectSpaceState2D; + +class PhysicsDirectBodyState2D : public Object { + + GDCLASS(PhysicsDirectBodyState2D, Object); + +protected: + static void _bind_methods(); + +public: + virtual Vector2 get_total_gravity() const = 0; // get gravity vector working on this body space/area + virtual float get_total_linear_damp() const = 0; // get density of this body space/area + virtual float get_total_angular_damp() const = 0; // get density of this body space/area + + virtual float get_inverse_mass() const = 0; // get the mass + virtual real_t get_inverse_inertia() const = 0; // get density of this body space + + virtual void set_linear_velocity(const Vector2 &p_velocity) = 0; + virtual Vector2 get_linear_velocity() const = 0; + + virtual void set_angular_velocity(real_t p_velocity) = 0; + virtual real_t get_angular_velocity() const = 0; + + virtual void set_transform(const Transform2D &p_transform) = 0; + virtual Transform2D get_transform() const = 0; + + virtual void add_central_force(const Vector2 &p_force) = 0; + virtual void add_force(const Vector2 &p_offset, const Vector2 &p_force) = 0; + virtual void add_torque(real_t p_torque) = 0; + virtual void apply_central_impulse(const Vector2 &p_impulse) = 0; + virtual void apply_torque_impulse(real_t p_torque) = 0; + virtual void apply_impulse(const Vector2 &p_offset, const Vector2 &p_impulse) = 0; + + virtual void set_sleep_state(bool p_enable) = 0; + virtual bool is_sleeping() const = 0; + + virtual int get_contact_count() const = 0; + + virtual Vector2 get_contact_local_position(int p_contact_idx) const = 0; + virtual Vector2 get_contact_local_normal(int p_contact_idx) const = 0; + virtual int get_contact_local_shape(int p_contact_idx) const = 0; + + virtual RID get_contact_collider(int p_contact_idx) const = 0; + virtual Vector2 get_contact_collider_position(int p_contact_idx) const = 0; + virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0; + virtual Object *get_contact_collider_object(int p_contact_idx) const; + virtual int get_contact_collider_shape(int p_contact_idx) const = 0; + virtual Variant get_contact_collider_shape_metadata(int p_contact_idx) const = 0; + virtual Vector2 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0; + + virtual real_t get_step() const = 0; + virtual void integrate_forces(); + + virtual PhysicsDirectSpaceState2D *get_space_state() = 0; + + PhysicsDirectBodyState2D(); +}; + +class PhysicsShapeQueryResult2D; + +//used for script +class PhysicsShapeQueryParameters2D : public Reference { + + GDCLASS(PhysicsShapeQueryParameters2D, Reference); + friend class PhysicsDirectSpaceState2D; + RID shape; + Transform2D transform; + Vector2 motion; + float margin; + Set exclude; + uint32_t collision_mask; + + bool collide_with_bodies; + bool collide_with_areas; + +protected: + static void _bind_methods(); + +public: + void set_shape(const RES &p_shape); + void set_shape_rid(const RID &p_shape); + RID get_shape_rid() const; + + void set_transform(const Transform2D &p_transform); + Transform2D get_transform() const; + + void set_motion(const Vector2 &p_motion); + Vector2 get_motion() const; + + void set_margin(float p_margin); + float get_margin() const; + + void set_collision_mask(int p_collision_mask); + int get_collision_mask() const; + + void set_collide_with_bodies(bool p_enable); + bool is_collide_with_bodies_enabled() const; + + void set_collide_with_areas(bool p_enable); + bool is_collide_with_areas_enabled() const; + + void set_exclude(const Vector &p_exclude); + Vector get_exclude() const; + + PhysicsShapeQueryParameters2D(); +}; + +class PhysicsDirectSpaceState2D : public Object { + + GDCLASS(PhysicsDirectSpaceState2D, Object); + + Dictionary _intersect_ray(const Vector2 &p_from, const Vector2 &p_to, const Vector &p_exclude = Vector(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + Array _intersect_point(const Vector2 &p_point, int p_max_results = 32, const Vector &p_exclude = Vector(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + Array _intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_intance_id, int p_max_results = 32, const Vector &p_exclude = Vector(), uint32_t p_layers = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + Array _intersect_point_impl(const Vector2 &p_point, int p_max_results, const Vector &p_exclud, uint32_t p_layers, bool p_collide_with_bodies, bool p_collide_with_areas, bool p_filter_by_canvas = false, ObjectID p_canvas_instance_id = ObjectID()); + Array _intersect_shape(const Ref &p_shape_query, int p_max_results = 32); + Array _cast_motion(const Ref &p_shape_query); + Array _collide_shape(const Ref &p_shape_query, int p_max_results = 32); + Dictionary _get_rest_info(const Ref &p_shape_query); + +protected: + static void _bind_methods(); + +public: + struct RayResult { + + Vector2 position; + Vector2 normal; + RID rid; + ObjectID collider_id; + Object *collider; + int shape; + Variant metadata; + }; + + virtual bool intersect_ray(const Vector2 &p_from, const Vector2 &p_to, RayResult &r_result, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + struct ShapeResult { + + RID rid; + ObjectID collider_id; + Object *collider; + int shape; + Variant metadata; + }; + + virtual int intersect_point(const Vector2 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; + virtual int intersect_point_on_canvas(const Vector2 &p_point, ObjectID p_canvas_instance_id, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_point = false) = 0; + + virtual int intersect_shape(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + virtual bool cast_motion(const RID &p_shape, const Transform2D &p_xform, const Vector2 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + virtual bool collide_shape(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, Vector2 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + struct ShapeRestInfo { + + Vector2 point; + Vector2 normal; + RID rid; + ObjectID collider_id; + int shape; + Vector2 linear_velocity; //velocity at contact point + Variant metadata; + }; + + virtual bool rest_info(RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, float p_margin, ShapeRestInfo *r_info, const Set &p_exclude = Set(), uint32_t p_collision_layer = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + PhysicsDirectSpaceState2D(); +}; + +class PhysicsShapeQueryResult2D : public Reference { + + GDCLASS(PhysicsShapeQueryResult2D, Reference); + + Vector result; + + friend class PhysicsDirectSpaceState2D; + +protected: + static void _bind_methods(); + +public: + int get_result_count() const; + RID get_result_rid(int p_idx) const; + ObjectID get_result_object_id(int p_idx) const; + Object *get_result_object(int p_idx) const; + int get_result_object_shape(int p_idx) const; + + PhysicsShapeQueryResult2D(); +}; + +class Physics2DTestMotionResult; + +class PhysicsServer2D : public Object { + + GDCLASS(PhysicsServer2D, Object); + + static PhysicsServer2D *singleton; + + virtual bool _body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.08, const Ref &p_result = Ref()); + +protected: + static void _bind_methods(); + +public: + static PhysicsServer2D *get_singleton(); + + enum ShapeType { + SHAPE_LINE, ///< plane:"plane" + SHAPE_RAY, ///< float:"length" + SHAPE_SEGMENT, ///< float:"length" + SHAPE_CIRCLE, ///< float:"radius" + SHAPE_RECTANGLE, ///< vec3:"extents" + SHAPE_CAPSULE, + SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" + SHAPE_CONCAVE_POLYGON, ///< Vector2 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector2 array) + SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error + }; + + virtual RID line_shape_create() = 0; + virtual RID ray_shape_create() = 0; + virtual RID segment_shape_create() = 0; + virtual RID circle_shape_create() = 0; + virtual RID rectangle_shape_create() = 0; + virtual RID capsule_shape_create() = 0; + virtual RID convex_polygon_shape_create() = 0; + virtual RID concave_polygon_shape_create() = 0; + + virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0; + virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0; + + virtual ShapeType shape_get_type(RID p_shape) const = 0; + virtual Variant shape_get_data(RID p_shape) const = 0; + virtual real_t shape_get_custom_solver_bias(RID p_shape) const = 0; + + //these work well, but should be used from the main thread only + virtual bool shape_collide(RID p_shape_A, const Transform2D &p_xform_A, const Vector2 &p_motion_A, RID p_shape_B, const Transform2D &p_xform_B, const Vector2 &p_motion_B, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; + + /* SPACE API */ + + virtual RID space_create() = 0; + virtual void space_set_active(RID p_space, bool p_active) = 0; + virtual bool space_is_active(RID p_space) const = 0; + + enum SpaceParameter { + + SPACE_PARAM_CONTACT_RECYCLE_RADIUS, + SPACE_PARAM_CONTACT_MAX_SEPARATION, + SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION, + SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD, + SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD, + SPACE_PARAM_BODY_TIME_TO_SLEEP, + SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, + SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH, + }; + + virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; + virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0; + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectSpaceState2D *space_get_direct_state(RID p_space) = 0; + + virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0; + virtual Vector space_get_contacts(RID p_space) const = 0; + virtual int space_get_contact_count(RID p_space) const = 0; + + //missing space parameters + + /* AREA API */ + + //missing attenuation? missing better override? + + enum AreaParameter { + AREA_PARAM_GRAVITY, + AREA_PARAM_GRAVITY_VECTOR, + AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_DISTANCE_SCALE, + AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP, + AREA_PARAM_PRIORITY + }; + + virtual RID area_create() = 0; + + virtual void area_set_space(RID p_area, RID p_space) = 0; + virtual RID area_get_space(RID p_area) const = 0; + + enum AreaSpaceOverrideMode { + AREA_SPACE_OVERRIDE_DISABLED, + AREA_SPACE_OVERRIDE_COMBINE, + AREA_SPACE_OVERRIDE_COMBINE_REPLACE, // Combines, then discards all subsequent calculations + AREA_SPACE_OVERRIDE_REPLACE, + AREA_SPACE_OVERRIDE_REPLACE_COMBINE // Discards all previous calculations, then keeps combining + }; + + virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; + virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; + + virtual void area_add_shape(RID p_area, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; + virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; + virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform2D &p_transform) = 0; + + virtual int area_get_shape_count(RID p_area) const = 0; + virtual RID area_get_shape(RID p_area, int p_shape_idx) const = 0; + virtual Transform2D area_get_shape_transform(RID p_area, int p_shape_idx) const = 0; + + virtual void area_remove_shape(RID p_area, int p_shape_idx) = 0; + virtual void area_clear_shapes(RID p_area) = 0; + + virtual void area_set_shape_disabled(RID p_area, int p_shape, bool p_disabled) = 0; + + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0; + virtual ObjectID area_get_object_instance_id(RID p_area) const = 0; + + virtual void area_attach_canvas_instance_id(RID p_area, ObjectID p_id) = 0; + virtual ObjectID area_get_canvas_instance_id(RID p_area) const = 0; + + virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0; + virtual void area_set_transform(RID p_area, const Transform2D &p_transform) = 0; + + virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0; + virtual Transform2D area_get_transform(RID p_area) const = 0; + + virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0; + virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0; + + virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0; + virtual void area_set_pickable(RID p_area, bool p_pickable) = 0; + + virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; + virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; + + /* BODY API */ + + //missing ccd? + + enum BodyMode { + BODY_MODE_STATIC, + BODY_MODE_KINEMATIC, + BODY_MODE_RIGID, + BODY_MODE_CHARACTER + }; + + virtual RID body_create() = 0; + + virtual void body_set_space(RID p_body, RID p_space) = 0; + virtual RID body_get_space(RID p_body) const = 0; + + virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0; + virtual BodyMode body_get_mode(RID p_body) const = 0; + + virtual void body_add_shape(RID p_body, RID p_shape, const Transform2D &p_transform = Transform2D(), bool p_disabled = false) = 0; + virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; + virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform2D &p_transform) = 0; + virtual void body_set_shape_metadata(RID p_body, int p_shape_idx, const Variant &p_metadata) = 0; + + virtual int body_get_shape_count(RID p_body) const = 0; + virtual RID body_get_shape(RID p_body, int p_shape_idx) const = 0; + virtual Transform2D body_get_shape_transform(RID p_body, int p_shape_idx) const = 0; + virtual Variant body_get_shape_metadata(RID p_body, int p_shape_idx) const = 0; + + virtual void body_set_shape_disabled(RID p_body, int p_shape, bool p_disabled) = 0; + virtual void body_set_shape_as_one_way_collision(RID p_body, int p_shape, bool p_enabled, float p_margin = 0) = 0; + + virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0; + virtual void body_clear_shapes(RID p_body) = 0; + + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) = 0; + virtual ObjectID body_get_object_instance_id(RID p_body) const = 0; + + virtual void body_attach_canvas_instance_id(RID p_body, ObjectID p_id) = 0; + virtual ObjectID body_get_canvas_instance_id(RID p_body) const = 0; + + enum CCDMode { + CCD_MODE_DISABLED, + CCD_MODE_CAST_RAY, + CCD_MODE_CAST_SHAPE, + }; + + virtual void body_set_continuous_collision_detection_mode(RID p_body, CCDMode p_mode) = 0; + virtual CCDMode body_get_continuous_collision_detection_mode(RID p_body) const = 0; + + virtual void body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; + virtual uint32_t body_get_collision_layer(RID p_body) const = 0; + + virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; + virtual uint32_t body_get_collision_mask(RID p_body) const = 0; + + // common body variables + enum BodyParameter { + BODY_PARAM_BOUNCE, + BODY_PARAM_FRICTION, + BODY_PARAM_MASS, ///< unused for static, always infinite + BODY_PARAM_INERTIA, // read-only: computed from mass & shapes + BODY_PARAM_GRAVITY_SCALE, + BODY_PARAM_LINEAR_DAMP, + BODY_PARAM_ANGULAR_DAMP, + BODY_PARAM_MAX, + }; + + virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; + virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0; + + //state + enum BodyState { + BODY_STATE_TRANSFORM, + BODY_STATE_LINEAR_VELOCITY, + BODY_STATE_ANGULAR_VELOCITY, + BODY_STATE_SLEEPING, + BODY_STATE_CAN_SLEEP, + }; + + virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; + virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0; + + //do something about it + virtual void body_set_applied_force(RID p_body, const Vector2 &p_force) = 0; + virtual Vector2 body_get_applied_force(RID p_body) const = 0; + + virtual void body_set_applied_torque(RID p_body, float p_torque) = 0; + virtual float body_get_applied_torque(RID p_body) const = 0; + + virtual void body_add_central_force(RID p_body, const Vector2 &p_force) = 0; + virtual void body_add_force(RID p_body, const Vector2 &p_offset, const Vector2 &p_force) = 0; + virtual void body_add_torque(RID p_body, float p_torque) = 0; + + virtual void body_apply_central_impulse(RID p_body, const Vector2 &p_impulse) = 0; + virtual void body_apply_torque_impulse(RID p_body, float p_torque) = 0; + virtual void body_apply_impulse(RID p_body, const Vector2 &p_offset, const Vector2 &p_impulse) = 0; + virtual void body_set_axis_velocity(RID p_body, const Vector2 &p_axis_velocity) = 0; + + //fix + virtual void body_add_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void body_remove_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; + + virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) = 0; + virtual int body_get_max_contacts_reported(RID p_body) const = 0; + + //missing remove + virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) = 0; + virtual float body_get_contacts_reported_depth_threshold(RID p_body) const = 0; + + virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0; + virtual bool body_is_omitting_force_integration(RID p_body) const = 0; + + virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; + + virtual bool body_collide_shape(RID p_body, int p_body_shape, RID p_shape, const Transform2D &p_shape_xform, const Vector2 &p_motion, Vector2 *r_results, int p_result_max, int &r_result_count) = 0; + + virtual void body_set_pickable(RID p_body, bool p_pickable) = 0; + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectBodyState2D *body_get_direct_state(RID p_body) = 0; + + struct MotionResult { + + Vector2 motion; + Vector2 remainder; + + Vector2 collision_point; + Vector2 collision_normal; + Vector2 collider_velocity; + int collision_local_shape; + ObjectID collider_id; + RID collider; + int collider_shape; + Variant collider_metadata; + + MotionResult() { + collision_local_shape = 0; + collider_shape = 0; + collider_id = ObjectID(); + } + }; + + virtual bool body_test_motion(RID p_body, const Transform2D &p_from, const Vector2 &p_motion, bool p_infinite_inertia, float p_margin = 0.001, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; + + struct SeparationResult { + + float collision_depth; + Vector2 collision_point; + Vector2 collision_normal; + Vector2 collider_velocity; + int collision_local_shape; + ObjectID collider_id; + RID collider; + int collider_shape; + Variant collider_metadata; + }; + + virtual int body_test_ray_separation(RID p_body, const Transform2D &p_transform, bool p_infinite_inertia, Vector2 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0; + + /* JOINT API */ + + enum JointType { + + JOINT_PIN, + JOINT_GROOVE, + JOINT_DAMPED_SPRING + }; + + enum JointParam { + JOINT_PARAM_BIAS, + JOINT_PARAM_MAX_BIAS, + JOINT_PARAM_MAX_FORCE, + }; + + virtual void joint_set_param(RID p_joint, JointParam p_param, real_t p_value) = 0; + virtual real_t joint_get_param(RID p_joint, JointParam p_param) const = 0; + + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; + + virtual RID pin_joint_create(const Vector2 &p_anchor, RID p_body_a, RID p_body_b = RID()) = 0; + virtual RID groove_joint_create(const Vector2 &p_a_groove1, const Vector2 &p_a_groove2, const Vector2 &p_b_anchor, RID p_body_a, RID p_body_b) = 0; + virtual RID damped_spring_joint_create(const Vector2 &p_anchor_a, const Vector2 &p_anchor_b, RID p_body_a, RID p_body_b = RID()) = 0; + + enum PinJointParam { + PIN_JOINT_SOFTNESS + }; + + virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, real_t p_value) = 0; + virtual real_t pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0; + + enum DampedStringParam { + DAMPED_STRING_REST_LENGTH, + DAMPED_STRING_STIFFNESS, + DAMPED_STRING_DAMPING + }; + virtual void damped_string_joint_set_param(RID p_joint, DampedStringParam p_param, real_t p_value) = 0; + virtual real_t damped_string_joint_get_param(RID p_joint, DampedStringParam p_param) const = 0; + + virtual JointType joint_get_type(RID p_joint) const = 0; + + /* QUERY API */ + + enum AreaBodyStatus { + AREA_BODY_ADDED, + AREA_BODY_REMOVED + }; + + /* MISC */ + + virtual void free(RID p_rid) = 0; + + virtual void set_active(bool p_active) = 0; + virtual void init() = 0; + virtual void step(float p_step) = 0; + virtual void sync() = 0; + virtual void flush_queries() = 0; + virtual void end_sync() = 0; + virtual void finish() = 0; + + virtual bool is_flushing_queries() const = 0; + + enum ProcessInfo { + + INFO_ACTIVE_OBJECTS, + INFO_COLLISION_PAIRS, + INFO_ISLAND_COUNT + }; + + virtual int get_process_info(ProcessInfo p_info) = 0; + + PhysicsServer2D(); + ~PhysicsServer2D(); +}; + +class Physics2DTestMotionResult : public Reference { + + GDCLASS(Physics2DTestMotionResult, Reference); + + PhysicsServer2D::MotionResult result; + bool colliding; + friend class PhysicsServer2D; + +protected: + static void _bind_methods(); + +public: + PhysicsServer2D::MotionResult *get_result_ptr() const { return const_cast(&result); } + + //bool is_colliding() const; + Vector2 get_motion() const; + Vector2 get_motion_remainder() const; + + Vector2 get_collision_point() const; + Vector2 get_collision_normal() const; + Vector2 get_collider_velocity() const; + ObjectID get_collider_id() const; + RID get_collider_rid() const; + Object *get_collider() const; + int get_collider_shape() const; + + Physics2DTestMotionResult(); +}; + +typedef PhysicsServer2D *(*CreatePhysicsServer2DCallback)(); + +class PhysicsServer2DManager { + struct ClassInfo { + String name; + CreatePhysicsServer2DCallback create_callback; + + ClassInfo() : + name(""), + create_callback(NULL) {} + + ClassInfo(String p_name, CreatePhysicsServer2DCallback p_create_callback) : + name(p_name), + create_callback(p_create_callback) {} + + ClassInfo(const ClassInfo &p_ci) : + name(p_ci.name), + create_callback(p_ci.create_callback) {} + + ClassInfo operator=(const ClassInfo &p_ci) { + name = p_ci.name; + create_callback = p_ci.create_callback; + return *this; + } + }; + + static Vector physics_2d_servers; + static int default_server_id; + static int default_server_priority; + +public: + static const String setting_property_name; + +private: + static void on_servers_changed(); + +public: + static void register_server(const String &p_name, CreatePhysicsServer2DCallback p_creat_callback); + static void set_default_server(const String &p_name, int p_priority = 0); + static int find_server_id(const String &p_name); + static int get_servers_count(); + static String get_server_name(int p_id); + static PhysicsServer2D *new_default_server(); + static PhysicsServer2D *new_server(const String &p_name); +}; + +VARIANT_ENUM_CAST(PhysicsServer2D::ShapeType); +VARIANT_ENUM_CAST(PhysicsServer2D::SpaceParameter); +VARIANT_ENUM_CAST(PhysicsServer2D::AreaParameter); +VARIANT_ENUM_CAST(PhysicsServer2D::AreaSpaceOverrideMode); +VARIANT_ENUM_CAST(PhysicsServer2D::BodyMode); +VARIANT_ENUM_CAST(PhysicsServer2D::BodyParameter); +VARIANT_ENUM_CAST(PhysicsServer2D::BodyState); +VARIANT_ENUM_CAST(PhysicsServer2D::CCDMode); +VARIANT_ENUM_CAST(PhysicsServer2D::JointParam); +VARIANT_ENUM_CAST(PhysicsServer2D::JointType); +VARIANT_ENUM_CAST(PhysicsServer2D::DampedStringParam); +//VARIANT_ENUM_CAST( PhysicsServer2D::ObjectType ); +VARIANT_ENUM_CAST(PhysicsServer2D::AreaBodyStatus); +VARIANT_ENUM_CAST(PhysicsServer2D::ProcessInfo); + +#endif diff --git a/servers/physics_server_3d.cpp b/servers/physics_server_3d.cpp new file mode 100644 index 0000000000..ddc96d2722 --- /dev/null +++ b/servers/physics_server_3d.cpp @@ -0,0 +1,800 @@ +/*************************************************************************/ +/* physics_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "physics_server_3d.h" + +#include "core/method_bind_ext.gen.inc" +#include "core/print_string.h" +#include "core/project_settings.h" + +PhysicsServer3D *PhysicsServer3D::singleton = NULL; + +void PhysicsDirectBodyState3D::integrate_forces() { + + real_t step = get_step(); + Vector3 lv = get_linear_velocity(); + lv += get_total_gravity() * step; + + Vector3 av = get_angular_velocity(); + + float linear_damp = 1.0 - step * get_total_linear_damp(); + + if (linear_damp < 0) // reached zero in the given time + linear_damp = 0; + + float angular_damp = 1.0 - step * get_total_angular_damp(); + + if (angular_damp < 0) // reached zero in the given time + angular_damp = 0; + + lv *= linear_damp; + av *= angular_damp; + + set_linear_velocity(lv); + set_angular_velocity(av); +} + +Object *PhysicsDirectBodyState3D::get_contact_collider_object(int p_contact_idx) const { + + ObjectID objid = get_contact_collider_id(p_contact_idx); + Object *obj = ObjectDB::get_instance(objid); + return obj; +} + +PhysicsServer3D *PhysicsServer3D::get_singleton() { + + return singleton; +} + +void PhysicsDirectBodyState3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_total_gravity"), &PhysicsDirectBodyState3D::get_total_gravity); + ClassDB::bind_method(D_METHOD("get_total_linear_damp"), &PhysicsDirectBodyState3D::get_total_linear_damp); + ClassDB::bind_method(D_METHOD("get_total_angular_damp"), &PhysicsDirectBodyState3D::get_total_angular_damp); + + ClassDB::bind_method(D_METHOD("get_center_of_mass"), &PhysicsDirectBodyState3D::get_center_of_mass); + ClassDB::bind_method(D_METHOD("get_principal_inertia_axes"), &PhysicsDirectBodyState3D::get_principal_inertia_axes); + + ClassDB::bind_method(D_METHOD("get_inverse_mass"), &PhysicsDirectBodyState3D::get_inverse_mass); + ClassDB::bind_method(D_METHOD("get_inverse_inertia"), &PhysicsDirectBodyState3D::get_inverse_inertia); + + ClassDB::bind_method(D_METHOD("set_linear_velocity", "velocity"), &PhysicsDirectBodyState3D::set_linear_velocity); + ClassDB::bind_method(D_METHOD("get_linear_velocity"), &PhysicsDirectBodyState3D::get_linear_velocity); + + ClassDB::bind_method(D_METHOD("set_angular_velocity", "velocity"), &PhysicsDirectBodyState3D::set_angular_velocity); + ClassDB::bind_method(D_METHOD("get_angular_velocity"), &PhysicsDirectBodyState3D::get_angular_velocity); + + ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsDirectBodyState3D::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsDirectBodyState3D::get_transform); + + ClassDB::bind_method(D_METHOD("add_central_force", "force"), &PhysicsDirectBodyState3D::add_central_force); + ClassDB::bind_method(D_METHOD("add_force", "force", "position"), &PhysicsDirectBodyState3D::add_force); + ClassDB::bind_method(D_METHOD("add_torque", "torque"), &PhysicsDirectBodyState3D::add_torque); + ClassDB::bind_method(D_METHOD("apply_central_impulse", "j"), &PhysicsDirectBodyState3D::apply_central_impulse); + ClassDB::bind_method(D_METHOD("apply_impulse", "position", "j"), &PhysicsDirectBodyState3D::apply_impulse); + ClassDB::bind_method(D_METHOD("apply_torque_impulse", "j"), &PhysicsDirectBodyState3D::apply_torque_impulse); + + ClassDB::bind_method(D_METHOD("set_sleep_state", "enabled"), &PhysicsDirectBodyState3D::set_sleep_state); + ClassDB::bind_method(D_METHOD("is_sleeping"), &PhysicsDirectBodyState3D::is_sleeping); + + ClassDB::bind_method(D_METHOD("get_contact_count"), &PhysicsDirectBodyState3D::get_contact_count); + + ClassDB::bind_method(D_METHOD("get_contact_local_position", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_local_position); + ClassDB::bind_method(D_METHOD("get_contact_local_normal", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_local_normal); + ClassDB::bind_method(D_METHOD("get_contact_impulse", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_impulse); + ClassDB::bind_method(D_METHOD("get_contact_local_shape", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_local_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_collider); + ClassDB::bind_method(D_METHOD("get_contact_collider_position", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_collider_position); + ClassDB::bind_method(D_METHOD("get_contact_collider_id", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_collider_id); + ClassDB::bind_method(D_METHOD("get_contact_collider_object", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_collider_object); + ClassDB::bind_method(D_METHOD("get_contact_collider_shape", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_collider_shape); + ClassDB::bind_method(D_METHOD("get_contact_collider_velocity_at_position", "contact_idx"), &PhysicsDirectBodyState3D::get_contact_collider_velocity_at_position); + ClassDB::bind_method(D_METHOD("get_step"), &PhysicsDirectBodyState3D::get_step); + ClassDB::bind_method(D_METHOD("integrate_forces"), &PhysicsDirectBodyState3D::integrate_forces); + ClassDB::bind_method(D_METHOD("get_space_state"), &PhysicsDirectBodyState3D::get_space_state); + + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "step"), "", "get_step"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "inverse_mass"), "", "get_inverse_mass"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_angular_damp"), "", "get_total_angular_damp"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "total_linear_damp"), "", "get_total_linear_damp"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "inverse_inertia"), "", "get_inverse_inertia"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "total_gravity"), "", "get_total_gravity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "center_of_mass"), "", "get_center_of_mass"); + ADD_PROPERTY(PropertyInfo(Variant::BASIS, "principal_inertia_axes"), "", "get_principal_inertia_axes"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "angular_velocity"), "set_angular_velocity", "get_angular_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::VECTOR3, "linear_velocity"), "set_linear_velocity", "get_linear_velocity"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "sleeping"), "set_sleep_state", "is_sleeping"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM2D, "transform"), "set_transform", "get_transform"); +} + +PhysicsDirectBodyState3D::PhysicsDirectBodyState3D() {} + +/////////////////////////////////////////////////////// + +void PhysicsShapeQueryParameters3D::set_shape(const RES &p_shape) { + + ERR_FAIL_COND(p_shape.is_null()); + shape = p_shape->get_rid(); +} + +void PhysicsShapeQueryParameters3D::set_shape_rid(const RID &p_shape) { + + shape = p_shape; +} + +RID PhysicsShapeQueryParameters3D::get_shape_rid() const { + + return shape; +} + +void PhysicsShapeQueryParameters3D::set_transform(const Transform &p_transform) { + + transform = p_transform; +} +Transform PhysicsShapeQueryParameters3D::get_transform() const { + + return transform; +} + +void PhysicsShapeQueryParameters3D::set_margin(float p_margin) { + + margin = p_margin; +} + +float PhysicsShapeQueryParameters3D::get_margin() const { + + return margin; +} + +void PhysicsShapeQueryParameters3D::set_collision_mask(int p_collision_mask) { + + collision_mask = p_collision_mask; +} +int PhysicsShapeQueryParameters3D::get_collision_mask() const { + + return collision_mask; +} + +void PhysicsShapeQueryParameters3D::set_exclude(const Vector &p_exclude) { + + exclude.clear(); + for (int i = 0; i < p_exclude.size(); i++) + exclude.insert(p_exclude[i]); +} + +Vector PhysicsShapeQueryParameters3D::get_exclude() const { + + Vector ret; + ret.resize(exclude.size()); + int idx = 0; + for (Set::Element *E = exclude.front(); E; E = E->next()) { + ret.write[idx] = E->get(); + } + return ret; +} + +void PhysicsShapeQueryParameters3D::set_collide_with_bodies(bool p_enable) { + collide_with_bodies = p_enable; +} + +bool PhysicsShapeQueryParameters3D::is_collide_with_bodies_enabled() const { + return collide_with_bodies; +} + +void PhysicsShapeQueryParameters3D::set_collide_with_areas(bool p_enable) { + collide_with_areas = p_enable; +} + +bool PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled() const { + return collide_with_areas; +} + +void PhysicsShapeQueryParameters3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("set_shape", "shape"), &PhysicsShapeQueryParameters3D::set_shape); + ClassDB::bind_method(D_METHOD("set_shape_rid", "shape"), &PhysicsShapeQueryParameters3D::set_shape_rid); + ClassDB::bind_method(D_METHOD("get_shape_rid"), &PhysicsShapeQueryParameters3D::get_shape_rid); + + ClassDB::bind_method(D_METHOD("set_transform", "transform"), &PhysicsShapeQueryParameters3D::set_transform); + ClassDB::bind_method(D_METHOD("get_transform"), &PhysicsShapeQueryParameters3D::get_transform); + + ClassDB::bind_method(D_METHOD("set_margin", "margin"), &PhysicsShapeQueryParameters3D::set_margin); + ClassDB::bind_method(D_METHOD("get_margin"), &PhysicsShapeQueryParameters3D::get_margin); + + ClassDB::bind_method(D_METHOD("set_collision_mask", "collision_mask"), &PhysicsShapeQueryParameters3D::set_collision_mask); + ClassDB::bind_method(D_METHOD("get_collision_mask"), &PhysicsShapeQueryParameters3D::get_collision_mask); + + ClassDB::bind_method(D_METHOD("set_exclude", "exclude"), &PhysicsShapeQueryParameters3D::set_exclude); + ClassDB::bind_method(D_METHOD("get_exclude"), &PhysicsShapeQueryParameters3D::get_exclude); + + ClassDB::bind_method(D_METHOD("set_collide_with_bodies", "enable"), &PhysicsShapeQueryParameters3D::set_collide_with_bodies); + ClassDB::bind_method(D_METHOD("is_collide_with_bodies_enabled"), &PhysicsShapeQueryParameters3D::is_collide_with_bodies_enabled); + + ClassDB::bind_method(D_METHOD("set_collide_with_areas", "enable"), &PhysicsShapeQueryParameters3D::set_collide_with_areas); + ClassDB::bind_method(D_METHOD("is_collide_with_areas_enabled"), &PhysicsShapeQueryParameters3D::is_collide_with_areas_enabled); + + ADD_PROPERTY(PropertyInfo(Variant::INT, "collision_mask", PROPERTY_HINT_LAYERS_3D_PHYSICS), "set_collision_mask", "get_collision_mask"); + ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "exclude", PROPERTY_HINT_NONE, itos(Variant::_RID) + ":"), "set_exclude", "get_exclude"); + ADD_PROPERTY(PropertyInfo(Variant::FLOAT, "margin", PROPERTY_HINT_RANGE, "0,100,0.01"), "set_margin", "get_margin"); + //ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "shape", PROPERTY_HINT_RESOURCE_TYPE, "Shape2D"), "set_shape", ""); // FIXME: Lacks a getter + ADD_PROPERTY(PropertyInfo(Variant::_RID, "shape_rid"), "set_shape_rid", "get_shape_rid"); + ADD_PROPERTY(PropertyInfo(Variant::TRANSFORM, "transform"), "set_transform", "get_transform"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_bodies"), "set_collide_with_bodies", "is_collide_with_bodies_enabled"); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "collide_with_areas"), "set_collide_with_areas", "is_collide_with_areas_enabled"); +} + +PhysicsShapeQueryParameters3D::PhysicsShapeQueryParameters3D() { + + margin = 0; + collision_mask = 0x7FFFFFFF; + collide_with_bodies = true; + collide_with_areas = false; +} + +///////////////////////////////////// + +Dictionary PhysicsDirectSpaceState3D::_intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector &p_exclude, uint32_t p_collision_mask, bool p_collide_with_bodies, bool p_collide_with_areas) { + + RayResult inters; + Set exclude; + for (int i = 0; i < p_exclude.size(); i++) + exclude.insert(p_exclude[i]); + + bool res = intersect_ray(p_from, p_to, inters, exclude, p_collision_mask, p_collide_with_bodies, p_collide_with_areas); + + if (!res) + return Dictionary(); + + Dictionary d; + d["position"] = inters.position; + d["normal"] = inters.normal; + d["collider_id"] = inters.collider_id; + d["collider"] = inters.collider; + d["shape"] = inters.shape; + d["rid"] = inters.rid; + + return d; +} + +Array PhysicsDirectSpaceState3D::_intersect_shape(const Ref &p_shape_query, int p_max_results) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); + + Vector sr; + sr.resize(p_max_results); + int rc = intersect_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, sr.ptrw(), sr.size(), p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + Array ret; + ret.resize(rc); + for (int i = 0; i < rc; i++) { + + Dictionary d; + d["rid"] = sr[i].rid; + d["collider_id"] = sr[i].collider_id; + d["collider"] = sr[i].collider; + d["shape"] = sr[i].shape; + ret[i] = d; + } + + return ret; +} + +Array PhysicsDirectSpaceState3D::_cast_motion(const Ref &p_shape_query, const Vector3 &p_motion) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); + + float closest_safe, closest_unsafe; + bool res = cast_motion(p_shape_query->shape, p_shape_query->transform, p_motion, p_shape_query->margin, closest_safe, closest_unsafe, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + if (!res) + return Array(); + Array ret; + ret.resize(2); + ret[0] = closest_safe; + ret[1] = closest_unsafe; + return ret; +} +Array PhysicsDirectSpaceState3D::_collide_shape(const Ref &p_shape_query, int p_max_results) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Array()); + + Vector ret; + ret.resize(p_max_results * 2); + int rc = 0; + bool res = collide_shape(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, ret.ptrw(), p_max_results, rc, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + if (!res) + return Array(); + Array r; + r.resize(rc * 2); + for (int i = 0; i < rc * 2; i++) + r[i] = ret[i]; + return r; +} +Dictionary PhysicsDirectSpaceState3D::_get_rest_info(const Ref &p_shape_query) { + + ERR_FAIL_COND_V(!p_shape_query.is_valid(), Dictionary()); + + ShapeRestInfo sri; + + bool res = rest_info(p_shape_query->shape, p_shape_query->transform, p_shape_query->margin, &sri, p_shape_query->exclude, p_shape_query->collision_mask, p_shape_query->collide_with_bodies, p_shape_query->collide_with_areas); + Dictionary r; + if (!res) + return r; + + r["point"] = sri.point; + r["normal"] = sri.normal; + r["rid"] = sri.rid; + r["collider_id"] = sri.collider_id; + r["shape"] = sri.shape; + r["linear_velocity"] = sri.linear_velocity; + + return r; +} + +PhysicsDirectSpaceState3D::PhysicsDirectSpaceState3D() { +} + +void PhysicsDirectSpaceState3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("intersect_ray", "from", "to", "exclude", "collision_mask", "collide_with_bodies", "collide_with_areas"), &PhysicsDirectSpaceState3D::_intersect_ray, DEFVAL(Array()), DEFVAL(0x7FFFFFFF), DEFVAL(true), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("intersect_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_intersect_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("cast_motion", "shape", "motion"), &PhysicsDirectSpaceState3D::_cast_motion); + ClassDB::bind_method(D_METHOD("collide_shape", "shape", "max_results"), &PhysicsDirectSpaceState3D::_collide_shape, DEFVAL(32)); + ClassDB::bind_method(D_METHOD("get_rest_info", "shape"), &PhysicsDirectSpaceState3D::_get_rest_info); +} + +int PhysicsShapeQueryResult3D::get_result_count() const { + + return result.size(); +} +RID PhysicsShapeQueryResult3D::get_result_rid(int p_idx) const { + + return result[p_idx].rid; +} +ObjectID PhysicsShapeQueryResult3D::get_result_object_id(int p_idx) const { + + return result[p_idx].collider_id; +} +Object *PhysicsShapeQueryResult3D::get_result_object(int p_idx) const { + + return result[p_idx].collider; +} +int PhysicsShapeQueryResult3D::get_result_object_shape(int p_idx) const { + + return result[p_idx].shape; +} + +PhysicsShapeQueryResult3D::PhysicsShapeQueryResult3D() { +} + +void PhysicsShapeQueryResult3D::_bind_methods() { + + ClassDB::bind_method(D_METHOD("get_result_count"), &PhysicsShapeQueryResult3D::get_result_count); + ClassDB::bind_method(D_METHOD("get_result_rid", "idx"), &PhysicsShapeQueryResult3D::get_result_rid); + ClassDB::bind_method(D_METHOD("get_result_object_id", "idx"), &PhysicsShapeQueryResult3D::get_result_object_id); + ClassDB::bind_method(D_METHOD("get_result_object", "idx"), &PhysicsShapeQueryResult3D::get_result_object); + ClassDB::bind_method(D_METHOD("get_result_object_shape", "idx"), &PhysicsShapeQueryResult3D::get_result_object_shape); +} + +/////////////////////////////////////// + +void PhysicsServer3D::_bind_methods() { + +#ifndef _3D_DISABLED + + ClassDB::bind_method(D_METHOD("shape_create", "type"), &PhysicsServer3D::shape_create); + ClassDB::bind_method(D_METHOD("shape_set_data", "shape", "data"), &PhysicsServer3D::shape_set_data); + + ClassDB::bind_method(D_METHOD("shape_get_type", "shape"), &PhysicsServer3D::shape_get_type); + ClassDB::bind_method(D_METHOD("shape_get_data", "shape"), &PhysicsServer3D::shape_get_data); + + ClassDB::bind_method(D_METHOD("space_create"), &PhysicsServer3D::space_create); + ClassDB::bind_method(D_METHOD("space_set_active", "space", "active"), &PhysicsServer3D::space_set_active); + ClassDB::bind_method(D_METHOD("space_is_active", "space"), &PhysicsServer3D::space_is_active); + ClassDB::bind_method(D_METHOD("space_set_param", "space", "param", "value"), &PhysicsServer3D::space_set_param); + ClassDB::bind_method(D_METHOD("space_get_param", "space", "param"), &PhysicsServer3D::space_get_param); + ClassDB::bind_method(D_METHOD("space_get_direct_state", "space"), &PhysicsServer3D::space_get_direct_state); + + ClassDB::bind_method(D_METHOD("area_create"), &PhysicsServer3D::area_create); + ClassDB::bind_method(D_METHOD("area_set_space", "area", "space"), &PhysicsServer3D::area_set_space); + ClassDB::bind_method(D_METHOD("area_get_space", "area"), &PhysicsServer3D::area_get_space); + + ClassDB::bind_method(D_METHOD("area_set_space_override_mode", "area", "mode"), &PhysicsServer3D::area_set_space_override_mode); + ClassDB::bind_method(D_METHOD("area_get_space_override_mode", "area"), &PhysicsServer3D::area_get_space_override_mode); + + ClassDB::bind_method(D_METHOD("area_add_shape", "area", "shape", "transform", "disabled"), &PhysicsServer3D::area_add_shape, DEFVAL(Transform()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("area_set_shape", "area", "shape_idx", "shape"), &PhysicsServer3D::area_set_shape); + ClassDB::bind_method(D_METHOD("area_set_shape_transform", "area", "shape_idx", "transform"), &PhysicsServer3D::area_set_shape_transform); + ClassDB::bind_method(D_METHOD("area_set_shape_disabled", "area", "shape_idx", "disabled"), &PhysicsServer3D::area_set_shape_disabled); + + ClassDB::bind_method(D_METHOD("area_get_shape_count", "area"), &PhysicsServer3D::area_get_shape_count); + ClassDB::bind_method(D_METHOD("area_get_shape", "area", "shape_idx"), &PhysicsServer3D::area_get_shape); + ClassDB::bind_method(D_METHOD("area_get_shape_transform", "area", "shape_idx"), &PhysicsServer3D::area_get_shape_transform); + + ClassDB::bind_method(D_METHOD("area_remove_shape", "area", "shape_idx"), &PhysicsServer3D::area_remove_shape); + ClassDB::bind_method(D_METHOD("area_clear_shapes", "area"), &PhysicsServer3D::area_clear_shapes); + + ClassDB::bind_method(D_METHOD("area_set_collision_layer", "area", "layer"), &PhysicsServer3D::area_set_collision_layer); + ClassDB::bind_method(D_METHOD("area_set_collision_mask", "area", "mask"), &PhysicsServer3D::area_set_collision_mask); + + ClassDB::bind_method(D_METHOD("area_set_param", "area", "param", "value"), &PhysicsServer3D::area_set_param); + ClassDB::bind_method(D_METHOD("area_set_transform", "area", "transform"), &PhysicsServer3D::area_set_transform); + + ClassDB::bind_method(D_METHOD("area_get_param", "area", "param"), &PhysicsServer3D::area_get_param); + ClassDB::bind_method(D_METHOD("area_get_transform", "area"), &PhysicsServer3D::area_get_transform); + + ClassDB::bind_method(D_METHOD("area_attach_object_instance_id", "area", "id"), &PhysicsServer3D::area_attach_object_instance_id); + ClassDB::bind_method(D_METHOD("area_get_object_instance_id", "area"), &PhysicsServer3D::area_get_object_instance_id); + + ClassDB::bind_method(D_METHOD("area_set_monitor_callback", "area", "receiver", "method"), &PhysicsServer3D::area_set_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_area_monitor_callback", "area", "receiver", "method"), &PhysicsServer3D::area_set_area_monitor_callback); + ClassDB::bind_method(D_METHOD("area_set_monitorable", "area", "monitorable"), &PhysicsServer3D::area_set_monitorable); + + ClassDB::bind_method(D_METHOD("area_set_ray_pickable", "area", "enable"), &PhysicsServer3D::area_set_ray_pickable); + ClassDB::bind_method(D_METHOD("area_is_ray_pickable", "area"), &PhysicsServer3D::area_is_ray_pickable); + + ClassDB::bind_method(D_METHOD("body_create", "mode", "init_sleeping"), &PhysicsServer3D::body_create, DEFVAL(BODY_MODE_RIGID), DEFVAL(false)); + + ClassDB::bind_method(D_METHOD("body_set_space", "body", "space"), &PhysicsServer3D::body_set_space); + ClassDB::bind_method(D_METHOD("body_get_space", "body"), &PhysicsServer3D::body_get_space); + + ClassDB::bind_method(D_METHOD("body_set_mode", "body", "mode"), &PhysicsServer3D::body_set_mode); + ClassDB::bind_method(D_METHOD("body_get_mode", "body"), &PhysicsServer3D::body_get_mode); + + ClassDB::bind_method(D_METHOD("body_set_collision_layer", "body", "layer"), &PhysicsServer3D::body_set_collision_layer); + ClassDB::bind_method(D_METHOD("body_get_collision_layer", "body"), &PhysicsServer3D::body_get_collision_layer); + + ClassDB::bind_method(D_METHOD("body_set_collision_mask", "body", "mask"), &PhysicsServer3D::body_set_collision_mask); + ClassDB::bind_method(D_METHOD("body_get_collision_mask", "body"), &PhysicsServer3D::body_get_collision_mask); + + ClassDB::bind_method(D_METHOD("body_add_shape", "body", "shape", "transform", "disabled"), &PhysicsServer3D::body_add_shape, DEFVAL(Transform()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("body_set_shape", "body", "shape_idx", "shape"), &PhysicsServer3D::body_set_shape); + ClassDB::bind_method(D_METHOD("body_set_shape_transform", "body", "shape_idx", "transform"), &PhysicsServer3D::body_set_shape_transform); + ClassDB::bind_method(D_METHOD("body_set_shape_disabled", "body", "shape_idx", "disabled"), &PhysicsServer3D::body_set_shape_disabled); + + ClassDB::bind_method(D_METHOD("body_get_shape_count", "body"), &PhysicsServer3D::body_get_shape_count); + ClassDB::bind_method(D_METHOD("body_get_shape", "body", "shape_idx"), &PhysicsServer3D::body_get_shape); + ClassDB::bind_method(D_METHOD("body_get_shape_transform", "body", "shape_idx"), &PhysicsServer3D::body_get_shape_transform); + + ClassDB::bind_method(D_METHOD("body_remove_shape", "body", "shape_idx"), &PhysicsServer3D::body_remove_shape); + ClassDB::bind_method(D_METHOD("body_clear_shapes", "body"), &PhysicsServer3D::body_clear_shapes); + + ClassDB::bind_method(D_METHOD("body_attach_object_instance_id", "body", "id"), &PhysicsServer3D::body_attach_object_instance_id); + ClassDB::bind_method(D_METHOD("body_get_object_instance_id", "body"), &PhysicsServer3D::body_get_object_instance_id); + + ClassDB::bind_method(D_METHOD("body_set_enable_continuous_collision_detection", "body", "enable"), &PhysicsServer3D::body_set_enable_continuous_collision_detection); + ClassDB::bind_method(D_METHOD("body_is_continuous_collision_detection_enabled", "body"), &PhysicsServer3D::body_is_continuous_collision_detection_enabled); + + ClassDB::bind_method(D_METHOD("body_set_param", "body", "param", "value"), &PhysicsServer3D::body_set_param); + ClassDB::bind_method(D_METHOD("body_get_param", "body", "param"), &PhysicsServer3D::body_get_param); + + ClassDB::bind_method(D_METHOD("body_set_kinematic_safe_margin", "body", "margin"), &PhysicsServer3D::body_set_kinematic_safe_margin); + ClassDB::bind_method(D_METHOD("body_get_kinematic_safe_margin", "body"), &PhysicsServer3D::body_get_kinematic_safe_margin); + + ClassDB::bind_method(D_METHOD("body_set_state", "body", "state", "value"), &PhysicsServer3D::body_set_state); + ClassDB::bind_method(D_METHOD("body_get_state", "body", "state"), &PhysicsServer3D::body_get_state); + + ClassDB::bind_method(D_METHOD("body_add_central_force", "body", "force"), &PhysicsServer3D::body_add_central_force); + ClassDB::bind_method(D_METHOD("body_add_force", "body", "force", "position"), &PhysicsServer3D::body_add_force); + ClassDB::bind_method(D_METHOD("body_add_torque", "body", "torque"), &PhysicsServer3D::body_add_torque); + + ClassDB::bind_method(D_METHOD("body_apply_central_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_central_impulse); + ClassDB::bind_method(D_METHOD("body_apply_impulse", "body", "position", "impulse"), &PhysicsServer3D::body_apply_impulse); + ClassDB::bind_method(D_METHOD("body_apply_torque_impulse", "body", "impulse"), &PhysicsServer3D::body_apply_torque_impulse); + ClassDB::bind_method(D_METHOD("body_set_axis_velocity", "body", "axis_velocity"), &PhysicsServer3D::body_set_axis_velocity); + + ClassDB::bind_method(D_METHOD("body_set_axis_lock", "body", "axis", "lock"), &PhysicsServer3D::body_set_axis_lock); + ClassDB::bind_method(D_METHOD("body_is_axis_locked", "body", "axis"), &PhysicsServer3D::body_is_axis_locked); + + ClassDB::bind_method(D_METHOD("body_add_collision_exception", "body", "excepted_body"), &PhysicsServer3D::body_add_collision_exception); + ClassDB::bind_method(D_METHOD("body_remove_collision_exception", "body", "excepted_body"), &PhysicsServer3D::body_remove_collision_exception); + + ClassDB::bind_method(D_METHOD("body_set_max_contacts_reported", "body", "amount"), &PhysicsServer3D::body_set_max_contacts_reported); + ClassDB::bind_method(D_METHOD("body_get_max_contacts_reported", "body"), &PhysicsServer3D::body_get_max_contacts_reported); + + ClassDB::bind_method(D_METHOD("body_set_omit_force_integration", "body", "enable"), &PhysicsServer3D::body_set_omit_force_integration); + ClassDB::bind_method(D_METHOD("body_is_omitting_force_integration", "body"), &PhysicsServer3D::body_is_omitting_force_integration); + + ClassDB::bind_method(D_METHOD("body_set_force_integration_callback", "body", "receiver", "method", "userdata"), &PhysicsServer3D::body_set_force_integration_callback, DEFVAL(Variant())); + + ClassDB::bind_method(D_METHOD("body_set_ray_pickable", "body", "enable"), &PhysicsServer3D::body_set_ray_pickable); + ClassDB::bind_method(D_METHOD("body_is_ray_pickable", "body"), &PhysicsServer3D::body_is_ray_pickable); + + ClassDB::bind_method(D_METHOD("body_get_direct_state", "body"), &PhysicsServer3D::body_get_direct_state); + + /* JOINT API */ + + BIND_ENUM_CONSTANT(JOINT_PIN); + BIND_ENUM_CONSTANT(JOINT_HINGE); + BIND_ENUM_CONSTANT(JOINT_SLIDER); + BIND_ENUM_CONSTANT(JOINT_CONE_TWIST); + BIND_ENUM_CONSTANT(JOINT_6DOF); + + ClassDB::bind_method(D_METHOD("joint_create_pin", "body_A", "local_A", "body_B", "local_B"), &PhysicsServer3D::joint_create_pin); + ClassDB::bind_method(D_METHOD("pin_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::pin_joint_set_param); + ClassDB::bind_method(D_METHOD("pin_joint_get_param", "joint", "param"), &PhysicsServer3D::pin_joint_get_param); + + ClassDB::bind_method(D_METHOD("pin_joint_set_local_a", "joint", "local_A"), &PhysicsServer3D::pin_joint_set_local_a); + ClassDB::bind_method(D_METHOD("pin_joint_get_local_a", "joint"), &PhysicsServer3D::pin_joint_get_local_a); + + ClassDB::bind_method(D_METHOD("pin_joint_set_local_b", "joint", "local_B"), &PhysicsServer3D::pin_joint_set_local_b); + ClassDB::bind_method(D_METHOD("pin_joint_get_local_b", "joint"), &PhysicsServer3D::pin_joint_get_local_b); + + BIND_ENUM_CONSTANT(PIN_JOINT_BIAS); + BIND_ENUM_CONSTANT(PIN_JOINT_DAMPING); + BIND_ENUM_CONSTANT(PIN_JOINT_IMPULSE_CLAMP); + + BIND_ENUM_CONSTANT(HINGE_JOINT_BIAS); + BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_UPPER); + BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_LOWER); + BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_BIAS); + BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(HINGE_JOINT_LIMIT_RELAXATION); + BIND_ENUM_CONSTANT(HINGE_JOINT_MOTOR_TARGET_VELOCITY); + BIND_ENUM_CONSTANT(HINGE_JOINT_MOTOR_MAX_IMPULSE); + + BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_USE_LIMIT); + BIND_ENUM_CONSTANT(HINGE_JOINT_FLAG_ENABLE_MOTOR); + + ClassDB::bind_method(D_METHOD("joint_create_hinge", "body_A", "hinge_A", "body_B", "hinge_B"), &PhysicsServer3D::joint_create_hinge); + + ClassDB::bind_method(D_METHOD("hinge_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::hinge_joint_set_param); + ClassDB::bind_method(D_METHOD("hinge_joint_get_param", "joint", "param"), &PhysicsServer3D::hinge_joint_get_param); + + ClassDB::bind_method(D_METHOD("hinge_joint_set_flag", "joint", "flag", "enabled"), &PhysicsServer3D::hinge_joint_set_flag); + ClassDB::bind_method(D_METHOD("hinge_joint_get_flag", "joint", "flag"), &PhysicsServer3D::hinge_joint_get_flag); + + ClassDB::bind_method(D_METHOD("joint_create_slider", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_slider); + + ClassDB::bind_method(D_METHOD("slider_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::slider_joint_set_param); + ClassDB::bind_method(D_METHOD("slider_joint_get_param", "joint", "param"), &PhysicsServer3D::slider_joint_get_param); + + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_UPPER); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_LOWER); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_LIMIT_DAMPING); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_MOTION_SOFTNESS); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_MOTION_RESTITUTION); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_MOTION_DAMPING); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION); + BIND_ENUM_CONSTANT(SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING); + + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_UPPER); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_LOWER); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_LIMIT_DAMPING); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_MOTION_DAMPING); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION); + BIND_ENUM_CONSTANT(SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING); + BIND_ENUM_CONSTANT(SLIDER_JOINT_MAX); + + ClassDB::bind_method(D_METHOD("joint_create_cone_twist", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_cone_twist); + + ClassDB::bind_method(D_METHOD("cone_twist_joint_set_param", "joint", "param", "value"), &PhysicsServer3D::cone_twist_joint_set_param); + ClassDB::bind_method(D_METHOD("cone_twist_joint_get_param", "joint", "param"), &PhysicsServer3D::cone_twist_joint_get_param); + + BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_SWING_SPAN); + BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_TWIST_SPAN); + BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_BIAS); + BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_SOFTNESS); + BIND_ENUM_CONSTANT(CONE_TWIST_JOINT_RELAXATION); + + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_LOWER_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_UPPER_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_RESTITUTION); + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_DAMPING); + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY); + BIND_ENUM_CONSTANT(G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LOWER_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_UPPER_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_DAMPING); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_RESTITUTION); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_FORCE_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_ERP); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY); + BIND_ENUM_CONSTANT(G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT); + + BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT); + BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_MOTOR); + BIND_ENUM_CONSTANT(G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR); + + ClassDB::bind_method(D_METHOD("joint_get_type", "joint"), &PhysicsServer3D::joint_get_type); + + ClassDB::bind_method(D_METHOD("joint_set_solver_priority", "joint", "priority"), &PhysicsServer3D::joint_set_solver_priority); + ClassDB::bind_method(D_METHOD("joint_get_solver_priority", "joint"), &PhysicsServer3D::joint_get_solver_priority); + + ClassDB::bind_method(D_METHOD("joint_create_generic_6dof", "body_A", "local_ref_A", "body_B", "local_ref_B"), &PhysicsServer3D::joint_create_generic_6dof); + + ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_param", "joint", "axis", "param", "value"), &PhysicsServer3D::generic_6dof_joint_set_param); + ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_param", "joint", "axis", "param"), &PhysicsServer3D::generic_6dof_joint_get_param); + + ClassDB::bind_method(D_METHOD("generic_6dof_joint_set_flag", "joint", "axis", "flag", "enable"), &PhysicsServer3D::generic_6dof_joint_set_flag); + ClassDB::bind_method(D_METHOD("generic_6dof_joint_get_flag", "joint", "axis", "flag"), &PhysicsServer3D::generic_6dof_joint_get_flag); + + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &PhysicsServer3D::free); + + ClassDB::bind_method(D_METHOD("set_active", "active"), &PhysicsServer3D::set_active); + + ClassDB::bind_method(D_METHOD("get_process_info", "process_info"), &PhysicsServer3D::get_process_info); + + BIND_ENUM_CONSTANT(SHAPE_PLANE); + BIND_ENUM_CONSTANT(SHAPE_RAY); + BIND_ENUM_CONSTANT(SHAPE_SPHERE); + BIND_ENUM_CONSTANT(SHAPE_BOX); + BIND_ENUM_CONSTANT(SHAPE_CAPSULE); + BIND_ENUM_CONSTANT(SHAPE_CYLINDER); + BIND_ENUM_CONSTANT(SHAPE_CONVEX_POLYGON); + BIND_ENUM_CONSTANT(SHAPE_CONCAVE_POLYGON); + BIND_ENUM_CONSTANT(SHAPE_HEIGHTMAP); + BIND_ENUM_CONSTANT(SHAPE_CUSTOM); + + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_VECTOR); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_IS_POINT); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_DISTANCE_SCALE); + BIND_ENUM_CONSTANT(AREA_PARAM_GRAVITY_POINT_ATTENUATION); + BIND_ENUM_CONSTANT(AREA_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_ANGULAR_DAMP); + BIND_ENUM_CONSTANT(AREA_PARAM_PRIORITY); + + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_DISABLED); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_COMBINE_REPLACE); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE); + BIND_ENUM_CONSTANT(AREA_SPACE_OVERRIDE_REPLACE_COMBINE); + + BIND_ENUM_CONSTANT(BODY_MODE_STATIC); + BIND_ENUM_CONSTANT(BODY_MODE_KINEMATIC); + BIND_ENUM_CONSTANT(BODY_MODE_RIGID); + BIND_ENUM_CONSTANT(BODY_MODE_CHARACTER); + + BIND_ENUM_CONSTANT(BODY_PARAM_BOUNCE); + BIND_ENUM_CONSTANT(BODY_PARAM_FRICTION); + BIND_ENUM_CONSTANT(BODY_PARAM_MASS); + BIND_ENUM_CONSTANT(BODY_PARAM_GRAVITY_SCALE); + BIND_ENUM_CONSTANT(BODY_PARAM_LINEAR_DAMP); + BIND_ENUM_CONSTANT(BODY_PARAM_ANGULAR_DAMP); + BIND_ENUM_CONSTANT(BODY_PARAM_MAX); + + BIND_ENUM_CONSTANT(BODY_STATE_TRANSFORM); + BIND_ENUM_CONSTANT(BODY_STATE_LINEAR_VELOCITY); + BIND_ENUM_CONSTANT(BODY_STATE_ANGULAR_VELOCITY); + BIND_ENUM_CONSTANT(BODY_STATE_SLEEPING); + BIND_ENUM_CONSTANT(BODY_STATE_CAN_SLEEP); + + BIND_ENUM_CONSTANT(AREA_BODY_ADDED); + BIND_ENUM_CONSTANT(AREA_BODY_REMOVED); + + BIND_ENUM_CONSTANT(INFO_ACTIVE_OBJECTS); + BIND_ENUM_CONSTANT(INFO_COLLISION_PAIRS); + BIND_ENUM_CONSTANT(INFO_ISLAND_COUNT); + + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_RECYCLE_RADIUS); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONTACT_MAX_SEPARATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_TIME_TO_SLEEP); + BIND_ENUM_CONSTANT(SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO); + BIND_ENUM_CONSTANT(SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS); + BIND_ENUM_CONSTANT(SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH); + + BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_X); + BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Y); + BIND_ENUM_CONSTANT(BODY_AXIS_LINEAR_Z); + BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_X); + BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Y); + BIND_ENUM_CONSTANT(BODY_AXIS_ANGULAR_Z); + +#endif +} + +PhysicsServer3D::PhysicsServer3D() { + + ERR_FAIL_COND(singleton != NULL); + singleton = this; +} + +PhysicsServer3D::~PhysicsServer3D() { + + singleton = NULL; +} + +Vector PhysicsServer3DManager::physics_servers; +int PhysicsServer3DManager::default_server_id = -1; +int PhysicsServer3DManager::default_server_priority = -1; +const String PhysicsServer3DManager::setting_property_name("physics/3d/physics_engine"); + +void PhysicsServer3DManager::on_servers_changed() { + + String physics_servers2("DEFAULT"); + for (int i = get_servers_count() - 1; 0 <= i; --i) { + physics_servers2 += "," + get_server_name(i); + } + ProjectSettings::get_singleton()->set_custom_property_info(setting_property_name, PropertyInfo(Variant::STRING, setting_property_name, PROPERTY_HINT_ENUM, physics_servers2)); +} + +void PhysicsServer3DManager::register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback) { + + ERR_FAIL_COND(!p_creat_callback); + ERR_FAIL_COND(find_server_id(p_name) != -1); + physics_servers.push_back(ClassInfo(p_name, p_creat_callback)); + on_servers_changed(); +} + +void PhysicsServer3DManager::set_default_server(const String &p_name, int p_priority) { + + const int id = find_server_id(p_name); + ERR_FAIL_COND(id == -1); // Not found + if (default_server_priority < p_priority) { + default_server_id = id; + default_server_priority = p_priority; + } +} + +int PhysicsServer3DManager::find_server_id(const String &p_name) { + + for (int i = physics_servers.size() - 1; 0 <= i; --i) { + if (p_name == physics_servers[i].name) { + return i; + } + } + return -1; +} + +int PhysicsServer3DManager::get_servers_count() { + return physics_servers.size(); +} + +String PhysicsServer3DManager::get_server_name(int p_id) { + ERR_FAIL_INDEX_V(p_id, get_servers_count(), ""); + return physics_servers[p_id].name; +} + +PhysicsServer3D *PhysicsServer3DManager::new_default_server() { + ERR_FAIL_COND_V(default_server_id == -1, NULL); + return physics_servers[default_server_id].create_callback(); +} + +PhysicsServer3D *PhysicsServer3DManager::new_server(const String &p_name) { + int id = find_server_id(p_name); + if (id == -1) { + return NULL; + } else { + return physics_servers[id].create_callback(); + } +} diff --git a/servers/physics_server_3d.h b/servers/physics_server_3d.h new file mode 100644 index 0000000000..9bb7bfe3f4 --- /dev/null +++ b/servers/physics_server_3d.h @@ -0,0 +1,844 @@ +/*************************************************************************/ +/* physics_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef PHYSICS_SERVER_H +#define PHYSICS_SERVER_H + +#include "core/object.h" +#include "core/resource.h" + +class PhysicsDirectSpaceState3D; + +class PhysicsDirectBodyState3D : public Object { + + GDCLASS(PhysicsDirectBodyState3D, Object); + +protected: + static void _bind_methods(); + +public: + virtual Vector3 get_total_gravity() const = 0; + virtual float get_total_angular_damp() const = 0; + virtual float get_total_linear_damp() const = 0; + + virtual Vector3 get_center_of_mass() const = 0; + virtual Basis get_principal_inertia_axes() const = 0; + virtual float get_inverse_mass() const = 0; // get the mass + virtual Vector3 get_inverse_inertia() const = 0; // get density of this body space + virtual Basis get_inverse_inertia_tensor() const = 0; // get density of this body space + + virtual void set_linear_velocity(const Vector3 &p_velocity) = 0; + virtual Vector3 get_linear_velocity() const = 0; + + virtual void set_angular_velocity(const Vector3 &p_velocity) = 0; + virtual Vector3 get_angular_velocity() const = 0; + + virtual void set_transform(const Transform &p_transform) = 0; + virtual Transform get_transform() const = 0; + + virtual void add_central_force(const Vector3 &p_force) = 0; + virtual void add_force(const Vector3 &p_force, const Vector3 &p_pos) = 0; + virtual void add_torque(const Vector3 &p_torque) = 0; + virtual void apply_central_impulse(const Vector3 &p_j) = 0; + virtual void apply_impulse(const Vector3 &p_pos, const Vector3 &p_j) = 0; + virtual void apply_torque_impulse(const Vector3 &p_j) = 0; + + virtual void set_sleep_state(bool p_enable) = 0; + virtual bool is_sleeping() const = 0; + + virtual int get_contact_count() const = 0; + + virtual Vector3 get_contact_local_position(int p_contact_idx) const = 0; + virtual Vector3 get_contact_local_normal(int p_contact_idx) const = 0; + virtual float get_contact_impulse(int p_contact_idx) const = 0; + virtual int get_contact_local_shape(int p_contact_idx) const = 0; + + virtual RID get_contact_collider(int p_contact_idx) const = 0; + virtual Vector3 get_contact_collider_position(int p_contact_idx) const = 0; + virtual ObjectID get_contact_collider_id(int p_contact_idx) const = 0; + virtual Object *get_contact_collider_object(int p_contact_idx) const; + virtual int get_contact_collider_shape(int p_contact_idx) const = 0; + virtual Vector3 get_contact_collider_velocity_at_position(int p_contact_idx) const = 0; + + virtual real_t get_step() const = 0; + virtual void integrate_forces(); + + virtual PhysicsDirectSpaceState3D *get_space_state() = 0; + + PhysicsDirectBodyState3D(); +}; + +class PhysicsShapeQueryResult3D; + +class PhysicsShapeQueryParameters3D : public Reference { + + GDCLASS(PhysicsShapeQueryParameters3D, Reference); + friend class PhysicsDirectSpaceState3D; + + RID shape; + Transform transform; + float margin; + Set exclude; + uint32_t collision_mask; + + bool collide_with_bodies; + bool collide_with_areas; + +protected: + static void _bind_methods(); + +public: + void set_shape(const RES &p_shape); + void set_shape_rid(const RID &p_shape); + RID get_shape_rid() const; + + void set_transform(const Transform &p_transform); + Transform get_transform() const; + + void set_margin(float p_margin); + float get_margin() const; + + void set_collision_mask(int p_collision_mask); + int get_collision_mask() const; + + void set_exclude(const Vector &p_exclude); + Vector get_exclude() const; + + void set_collide_with_bodies(bool p_enable); + bool is_collide_with_bodies_enabled() const; + + void set_collide_with_areas(bool p_enable); + bool is_collide_with_areas_enabled() const; + + PhysicsShapeQueryParameters3D(); +}; + +class PhysicsDirectSpaceState3D : public Object { + + GDCLASS(PhysicsDirectSpaceState3D, Object); + +private: + Dictionary _intersect_ray(const Vector3 &p_from, const Vector3 &p_to, const Vector &p_exclude = Vector(), uint32_t p_collision_mask = 0, bool p_collide_with_bodies = true, bool p_collide_with_areas = false); + Array _intersect_shape(const Ref &p_shape_query, int p_max_results = 32); + Array _cast_motion(const Ref &p_shape_query, const Vector3 &p_motion); + Array _collide_shape(const Ref &p_shape_query, int p_max_results = 32); + Dictionary _get_rest_info(const Ref &p_shape_query); + +protected: + static void _bind_methods(); + +public: + struct ShapeResult { + + RID rid; + ObjectID collider_id; + Object *collider; + int shape; + }; + + virtual int intersect_point(const Vector3 &p_point, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + struct RayResult { + + Vector3 position; + Vector3 normal; + RID rid; + ObjectID collider_id; + Object *collider; + int shape; + }; + + virtual bool intersect_ray(const Vector3 &p_from, const Vector3 &p_to, RayResult &r_result, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, bool p_pick_ray = false) = 0; + + virtual int intersect_shape(const RID &p_shape, const Transform &p_xform, float p_margin, ShapeResult *r_results, int p_result_max, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + struct ShapeRestInfo { + + Vector3 point; + Vector3 normal; + RID rid; + ObjectID collider_id; + int shape; + Vector3 linear_velocity; //velocity at contact point + }; + + virtual bool cast_motion(const RID &p_shape, const Transform &p_xform, const Vector3 &p_motion, float p_margin, float &p_closest_safe, float &p_closest_unsafe, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false, ShapeRestInfo *r_info = NULL) = 0; + + virtual bool collide_shape(RID p_shape, const Transform &p_shape_xform, float p_margin, Vector3 *r_results, int p_result_max, int &r_result_count, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + virtual bool rest_info(RID p_shape, const Transform &p_shape_xform, float p_margin, ShapeRestInfo *r_info, const Set &p_exclude = Set(), uint32_t p_collision_mask = 0xFFFFFFFF, bool p_collide_with_bodies = true, bool p_collide_with_areas = false) = 0; + + virtual Vector3 get_closest_point_to_object_volume(RID p_object, const Vector3 p_point) const = 0; + + PhysicsDirectSpaceState3D(); +}; + +class PhysicsShapeQueryResult3D : public Reference { + + GDCLASS(PhysicsShapeQueryResult3D, Reference); + + Vector result; + + friend class PhysicsDirectSpaceState3D; + +protected: + static void _bind_methods(); + +public: + int get_result_count() const; + RID get_result_rid(int p_idx) const; + ObjectID get_result_object_id(int p_idx) const; + Object *get_result_object(int p_idx) const; + int get_result_object_shape(int p_idx) const; + + PhysicsShapeQueryResult3D(); +}; + +class PhysicsServer3D : public Object { + + GDCLASS(PhysicsServer3D, Object); + + static PhysicsServer3D *singleton; + +protected: + static void _bind_methods(); + +public: + static PhysicsServer3D *get_singleton(); + + enum ShapeType { + SHAPE_PLANE, ///< plane:"plane" + SHAPE_RAY, ///< float:"length" + SHAPE_SPHERE, ///< float:"radius" + SHAPE_BOX, ///< vec3:"extents" + SHAPE_CAPSULE, ///< dict( float:"radius", float:"height"):capsule + SHAPE_CYLINDER, ///< dict( float:"radius", float:"height"):cylinder + SHAPE_CONVEX_POLYGON, ///< array of planes:"planes" + SHAPE_CONCAVE_POLYGON, ///< vector3 array:"triangles" , or Dictionary with "indices" (int array) and "triangles" (Vector3 array) + SHAPE_HEIGHTMAP, ///< dict( int:"width", int:"depth",float:"cell_size", float_array:"heights" + SHAPE_CUSTOM, ///< Server-Implementation based custom shape, calling shape_create() with this value will result in an error + }; + + virtual RID shape_create(ShapeType p_shape) = 0; + virtual void shape_set_data(RID p_shape, const Variant &p_data) = 0; + virtual void shape_set_custom_solver_bias(RID p_shape, real_t p_bias) = 0; + + virtual ShapeType shape_get_type(RID p_shape) const = 0; + virtual Variant shape_get_data(RID p_shape) const = 0; + + virtual void shape_set_margin(RID p_shape, real_t p_margin) = 0; + virtual real_t shape_get_margin(RID p_shape) const = 0; + + virtual real_t shape_get_custom_solver_bias(RID p_shape) const = 0; + + /* SPACE API */ + + virtual RID space_create() = 0; + virtual void space_set_active(RID p_space, bool p_active) = 0; + virtual bool space_is_active(RID p_space) const = 0; + + enum SpaceParameter { + + SPACE_PARAM_CONTACT_RECYCLE_RADIUS, + SPACE_PARAM_CONTACT_MAX_SEPARATION, + SPACE_PARAM_BODY_MAX_ALLOWED_PENETRATION, + SPACE_PARAM_BODY_LINEAR_VELOCITY_SLEEP_THRESHOLD, + SPACE_PARAM_BODY_ANGULAR_VELOCITY_SLEEP_THRESHOLD, + SPACE_PARAM_BODY_TIME_TO_SLEEP, + SPACE_PARAM_BODY_ANGULAR_VELOCITY_DAMP_RATIO, + SPACE_PARAM_CONSTRAINT_DEFAULT_BIAS, + SPACE_PARAM_TEST_MOTION_MIN_CONTACT_DEPTH + }; + + virtual void space_set_param(RID p_space, SpaceParameter p_param, real_t p_value) = 0; + virtual real_t space_get_param(RID p_space, SpaceParameter p_param) const = 0; + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectSpaceState3D *space_get_direct_state(RID p_space) = 0; + + virtual void space_set_debug_contacts(RID p_space, int p_max_contacts) = 0; + virtual Vector space_get_contacts(RID p_space) const = 0; + virtual int space_get_contact_count(RID p_space) const = 0; + + //missing space parameters + + /* AREA API */ + + //missing attenuation? missing better override? + + enum AreaParameter { + AREA_PARAM_GRAVITY, + AREA_PARAM_GRAVITY_VECTOR, + AREA_PARAM_GRAVITY_IS_POINT, + AREA_PARAM_GRAVITY_DISTANCE_SCALE, + AREA_PARAM_GRAVITY_POINT_ATTENUATION, + AREA_PARAM_LINEAR_DAMP, + AREA_PARAM_ANGULAR_DAMP, + AREA_PARAM_PRIORITY + }; + + virtual RID area_create() = 0; + + virtual void area_set_space(RID p_area, RID p_space) = 0; + virtual RID area_get_space(RID p_area) const = 0; + + enum AreaSpaceOverrideMode { + AREA_SPACE_OVERRIDE_DISABLED, + AREA_SPACE_OVERRIDE_COMBINE, + AREA_SPACE_OVERRIDE_COMBINE_REPLACE, + AREA_SPACE_OVERRIDE_REPLACE, + AREA_SPACE_OVERRIDE_REPLACE_COMBINE + }; + + virtual void area_set_space_override_mode(RID p_area, AreaSpaceOverrideMode p_mode) = 0; + virtual AreaSpaceOverrideMode area_get_space_override_mode(RID p_area) const = 0; + + virtual void area_add_shape(RID p_area, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; + virtual void area_set_shape(RID p_area, int p_shape_idx, RID p_shape) = 0; + virtual void area_set_shape_transform(RID p_area, int p_shape_idx, const Transform &p_transform) = 0; + + virtual int area_get_shape_count(RID p_area) const = 0; + virtual RID area_get_shape(RID p_area, int p_shape_idx) const = 0; + virtual Transform area_get_shape_transform(RID p_area, int p_shape_idx) const = 0; + + virtual void area_remove_shape(RID p_area, int p_shape_idx) = 0; + virtual void area_clear_shapes(RID p_area) = 0; + + virtual void area_set_shape_disabled(RID p_area, int p_shape_idx, bool p_disabled) = 0; + + virtual void area_attach_object_instance_id(RID p_area, ObjectID p_id) = 0; + virtual ObjectID area_get_object_instance_id(RID p_area) const = 0; + + virtual void area_set_param(RID p_area, AreaParameter p_param, const Variant &p_value) = 0; + virtual void area_set_transform(RID p_area, const Transform &p_transform) = 0; + + virtual Variant area_get_param(RID p_parea, AreaParameter p_param) const = 0; + virtual Transform area_get_transform(RID p_area) const = 0; + + virtual void area_set_collision_mask(RID p_area, uint32_t p_mask) = 0; + virtual void area_set_collision_layer(RID p_area, uint32_t p_layer) = 0; + + virtual void area_set_monitorable(RID p_area, bool p_monitorable) = 0; + + virtual void area_set_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; + virtual void area_set_area_monitor_callback(RID p_area, Object *p_receiver, const StringName &p_method) = 0; + + virtual void area_set_ray_pickable(RID p_area, bool p_enable) = 0; + virtual bool area_is_ray_pickable(RID p_area) const = 0; + + /* BODY API */ + + //missing ccd? + + enum BodyMode { + BODY_MODE_STATIC, + BODY_MODE_KINEMATIC, + BODY_MODE_RIGID, + BODY_MODE_CHARACTER + }; + + virtual RID body_create(BodyMode p_mode = BODY_MODE_RIGID, bool p_init_sleeping = false) = 0; + + virtual void body_set_space(RID p_body, RID p_space) = 0; + virtual RID body_get_space(RID p_body) const = 0; + + virtual void body_set_mode(RID p_body, BodyMode p_mode) = 0; + virtual BodyMode body_get_mode(RID p_body) const = 0; + + virtual void body_add_shape(RID p_body, RID p_shape, const Transform &p_transform = Transform(), bool p_disabled = false) = 0; + virtual void body_set_shape(RID p_body, int p_shape_idx, RID p_shape) = 0; + virtual void body_set_shape_transform(RID p_body, int p_shape_idx, const Transform &p_transform) = 0; + + virtual int body_get_shape_count(RID p_body) const = 0; + virtual RID body_get_shape(RID p_body, int p_shape_idx) const = 0; + virtual Transform body_get_shape_transform(RID p_body, int p_shape_idx) const = 0; + + virtual void body_remove_shape(RID p_body, int p_shape_idx) = 0; + virtual void body_clear_shapes(RID p_body) = 0; + + virtual void body_set_shape_disabled(RID p_body, int p_shape_idx, bool p_disabled) = 0; + + virtual void body_attach_object_instance_id(RID p_body, ObjectID p_id) = 0; + virtual ObjectID body_get_object_instance_id(RID p_body) const = 0; + + virtual void body_set_enable_continuous_collision_detection(RID p_body, bool p_enable) = 0; + virtual bool body_is_continuous_collision_detection_enabled(RID p_body) const = 0; + + virtual void body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; + virtual uint32_t body_get_collision_layer(RID p_body) const = 0; + + virtual void body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; + virtual uint32_t body_get_collision_mask(RID p_body) const = 0; + + virtual void body_set_user_flags(RID p_body, uint32_t p_flags) = 0; + virtual uint32_t body_get_user_flags(RID p_body) const = 0; + + // common body variables + enum BodyParameter { + BODY_PARAM_BOUNCE, + BODY_PARAM_FRICTION, + BODY_PARAM_MASS, ///< unused for static, always infinite + BODY_PARAM_GRAVITY_SCALE, + BODY_PARAM_LINEAR_DAMP, + BODY_PARAM_ANGULAR_DAMP, + BODY_PARAM_MAX, + }; + + virtual void body_set_param(RID p_body, BodyParameter p_param, float p_value) = 0; + virtual float body_get_param(RID p_body, BodyParameter p_param) const = 0; + + virtual void body_set_kinematic_safe_margin(RID p_body, real_t p_margin) = 0; + virtual real_t body_get_kinematic_safe_margin(RID p_body) const = 0; + + //state + enum BodyState { + BODY_STATE_TRANSFORM, + BODY_STATE_LINEAR_VELOCITY, + BODY_STATE_ANGULAR_VELOCITY, + BODY_STATE_SLEEPING, + BODY_STATE_CAN_SLEEP + }; + + virtual void body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; + virtual Variant body_get_state(RID p_body, BodyState p_state) const = 0; + + //do something about it + virtual void body_set_applied_force(RID p_body, const Vector3 &p_force) = 0; + virtual Vector3 body_get_applied_force(RID p_body) const = 0; + + virtual void body_set_applied_torque(RID p_body, const Vector3 &p_torque) = 0; + virtual Vector3 body_get_applied_torque(RID p_body) const = 0; + + virtual void body_add_central_force(RID p_body, const Vector3 &p_force) = 0; + virtual void body_add_force(RID p_body, const Vector3 &p_force, const Vector3 &p_pos) = 0; + virtual void body_add_torque(RID p_body, const Vector3 &p_torque) = 0; + + virtual void body_apply_central_impulse(RID p_body, const Vector3 &p_impulse) = 0; + virtual void body_apply_impulse(RID p_body, const Vector3 &p_pos, const Vector3 &p_impulse) = 0; + virtual void body_apply_torque_impulse(RID p_body, const Vector3 &p_impulse) = 0; + virtual void body_set_axis_velocity(RID p_body, const Vector3 &p_axis_velocity) = 0; + + enum BodyAxis { + BODY_AXIS_LINEAR_X = 1 << 0, + BODY_AXIS_LINEAR_Y = 1 << 1, + BODY_AXIS_LINEAR_Z = 1 << 2, + BODY_AXIS_ANGULAR_X = 1 << 3, + BODY_AXIS_ANGULAR_Y = 1 << 4, + BODY_AXIS_ANGULAR_Z = 1 << 5 + }; + + virtual void body_set_axis_lock(RID p_body, BodyAxis p_axis, bool p_lock) = 0; + virtual bool body_is_axis_locked(RID p_body, BodyAxis p_axis) const = 0; + + //fix + virtual void body_add_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void body_remove_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void body_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; + + virtual void body_set_max_contacts_reported(RID p_body, int p_contacts) = 0; + virtual int body_get_max_contacts_reported(RID p_body) const = 0; + + //missing remove + virtual void body_set_contacts_reported_depth_threshold(RID p_body, float p_threshold) = 0; + virtual float body_get_contacts_reported_depth_threshold(RID p_body) const = 0; + + virtual void body_set_omit_force_integration(RID p_body, bool p_omit) = 0; + virtual bool body_is_omitting_force_integration(RID p_body) const = 0; + + virtual void body_set_force_integration_callback(RID p_body, Object *p_receiver, const StringName &p_method, const Variant &p_udata = Variant()) = 0; + + virtual void body_set_ray_pickable(RID p_body, bool p_enable) = 0; + virtual bool body_is_ray_pickable(RID p_body) const = 0; + + // this function only works on physics process, errors and returns null otherwise + virtual PhysicsDirectBodyState3D *body_get_direct_state(RID p_body) = 0; + + struct MotionResult { + + Vector3 motion; + Vector3 remainder; + + Vector3 collision_point; + Vector3 collision_normal; + Vector3 collider_velocity; + int collision_local_shape; + ObjectID collider_id; + RID collider; + int collider_shape; + Variant collider_metadata; + MotionResult() { + collision_local_shape = 0; + collider_id = ObjectID(); + collider_shape = 0; + } + }; + + virtual bool body_test_motion(RID p_body, const Transform &p_from, const Vector3 &p_motion, bool p_infinite_inertia, MotionResult *r_result = NULL, bool p_exclude_raycast_shapes = true) = 0; + + struct SeparationResult { + + float collision_depth; + Vector3 collision_point; + Vector3 collision_normal; + Vector3 collider_velocity; + int collision_local_shape; + ObjectID collider_id; + RID collider; + int collider_shape; + Variant collider_metadata; + }; + + virtual int body_test_ray_separation(RID p_body, const Transform &p_transform, bool p_infinite_inertia, Vector3 &r_recover_motion, SeparationResult *r_results, int p_result_max, float p_margin = 0.001) = 0; + + /* SOFT BODY */ + + virtual RID soft_body_create(bool p_init_sleeping = false) = 0; + + virtual void soft_body_update_rendering_server(RID p_body, class SoftBodyRenderingServerHandler *p_rendering_server_handler) = 0; + + virtual void soft_body_set_space(RID p_body, RID p_space) = 0; + virtual RID soft_body_get_space(RID p_body) const = 0; + + virtual void soft_body_set_mesh(RID p_body, const REF &p_mesh) = 0; + + virtual void soft_body_set_collision_layer(RID p_body, uint32_t p_layer) = 0; + virtual uint32_t soft_body_get_collision_layer(RID p_body) const = 0; + + virtual void soft_body_set_collision_mask(RID p_body, uint32_t p_mask) = 0; + virtual uint32_t soft_body_get_collision_mask(RID p_body) const = 0; + + virtual void soft_body_add_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void soft_body_remove_collision_exception(RID p_body, RID p_body_b) = 0; + virtual void soft_body_get_collision_exceptions(RID p_body, List *p_exceptions) = 0; + + virtual void soft_body_set_state(RID p_body, BodyState p_state, const Variant &p_variant) = 0; + virtual Variant soft_body_get_state(RID p_body, BodyState p_state) const = 0; + + virtual void soft_body_set_transform(RID p_body, const Transform &p_transform) = 0; + virtual Vector3 soft_body_get_vertex_position(RID p_body, int vertex_index) const = 0; + + virtual void soft_body_set_ray_pickable(RID p_body, bool p_enable) = 0; + virtual bool soft_body_is_ray_pickable(RID p_body) const = 0; + + virtual void soft_body_set_simulation_precision(RID p_body, int p_simulation_precision) = 0; + virtual int soft_body_get_simulation_precision(RID p_body) = 0; + + virtual void soft_body_set_total_mass(RID p_body, real_t p_total_mass) = 0; + virtual real_t soft_body_get_total_mass(RID p_body) = 0; + + virtual void soft_body_set_linear_stiffness(RID p_body, real_t p_stiffness) = 0; + virtual real_t soft_body_get_linear_stiffness(RID p_body) = 0; + + virtual void soft_body_set_areaAngular_stiffness(RID p_body, real_t p_stiffness) = 0; + virtual real_t soft_body_get_areaAngular_stiffness(RID p_body) = 0; + + virtual void soft_body_set_volume_stiffness(RID p_body, real_t p_stiffness) = 0; + virtual real_t soft_body_get_volume_stiffness(RID p_body) = 0; + + virtual void soft_body_set_pressure_coefficient(RID p_body, real_t p_pressure_coefficient) = 0; + virtual real_t soft_body_get_pressure_coefficient(RID p_body) = 0; + + virtual void soft_body_set_pose_matching_coefficient(RID p_body, real_t p_pose_matching_coefficient) = 0; + virtual real_t soft_body_get_pose_matching_coefficient(RID p_body) = 0; + + virtual void soft_body_set_damping_coefficient(RID p_body, real_t p_damping_coefficient) = 0; + virtual real_t soft_body_get_damping_coefficient(RID p_body) = 0; + + virtual void soft_body_set_drag_coefficient(RID p_body, real_t p_drag_coefficient) = 0; + virtual real_t soft_body_get_drag_coefficient(RID p_body) = 0; + + virtual void soft_body_move_point(RID p_body, int p_point_index, const Vector3 &p_global_position) = 0; + virtual Vector3 soft_body_get_point_global_position(RID p_body, int p_point_index) = 0; + + virtual Vector3 soft_body_get_point_offset(RID p_body, int p_point_index) const = 0; + + virtual void soft_body_remove_all_pinned_points(RID p_body) = 0; + virtual void soft_body_pin_point(RID p_body, int p_point_index, bool p_pin) = 0; + virtual bool soft_body_is_point_pinned(RID p_body, int p_point_index) = 0; + + /* JOINT API */ + + enum JointType { + + JOINT_PIN, + JOINT_HINGE, + JOINT_SLIDER, + JOINT_CONE_TWIST, + JOINT_6DOF + + }; + + virtual JointType joint_get_type(RID p_joint) const = 0; + + virtual void joint_set_solver_priority(RID p_joint, int p_priority) = 0; + virtual int joint_get_solver_priority(RID p_joint) const = 0; + + virtual void joint_disable_collisions_between_bodies(RID p_joint, const bool p_disable) = 0; + virtual bool joint_is_disabled_collisions_between_bodies(RID p_joint) const = 0; + + virtual RID joint_create_pin(RID p_body_A, const Vector3 &p_local_A, RID p_body_B, const Vector3 &p_local_B) = 0; + + enum PinJointParam { + PIN_JOINT_BIAS, + PIN_JOINT_DAMPING, + PIN_JOINT_IMPULSE_CLAMP + }; + + virtual void pin_joint_set_param(RID p_joint, PinJointParam p_param, float p_value) = 0; + virtual float pin_joint_get_param(RID p_joint, PinJointParam p_param) const = 0; + + virtual void pin_joint_set_local_a(RID p_joint, const Vector3 &p_A) = 0; + virtual Vector3 pin_joint_get_local_a(RID p_joint) const = 0; + + virtual void pin_joint_set_local_b(RID p_joint, const Vector3 &p_B) = 0; + virtual Vector3 pin_joint_get_local_b(RID p_joint) const = 0; + + enum HingeJointParam { + + HINGE_JOINT_BIAS, + HINGE_JOINT_LIMIT_UPPER, + HINGE_JOINT_LIMIT_LOWER, + HINGE_JOINT_LIMIT_BIAS, + HINGE_JOINT_LIMIT_SOFTNESS, + HINGE_JOINT_LIMIT_RELAXATION, + HINGE_JOINT_MOTOR_TARGET_VELOCITY, + HINGE_JOINT_MOTOR_MAX_IMPULSE, + HINGE_JOINT_MAX + }; + + enum HingeJointFlag { + HINGE_JOINT_FLAG_USE_LIMIT, + HINGE_JOINT_FLAG_ENABLE_MOTOR, + HINGE_JOINT_FLAG_MAX + }; + + virtual RID joint_create_hinge(RID p_body_A, const Transform &p_hinge_A, RID p_body_B, const Transform &p_hinge_B) = 0; + virtual RID joint_create_hinge_simple(RID p_body_A, const Vector3 &p_pivot_A, const Vector3 &p_axis_A, RID p_body_B, const Vector3 &p_pivot_B, const Vector3 &p_axis_B) = 0; + + virtual void hinge_joint_set_param(RID p_joint, HingeJointParam p_param, float p_value) = 0; + virtual float hinge_joint_get_param(RID p_joint, HingeJointParam p_param) const = 0; + + virtual void hinge_joint_set_flag(RID p_joint, HingeJointFlag p_flag, bool p_value) = 0; + virtual bool hinge_joint_get_flag(RID p_joint, HingeJointFlag p_flag) const = 0; + + enum SliderJointParam { + SLIDER_JOINT_LINEAR_LIMIT_UPPER, + SLIDER_JOINT_LINEAR_LIMIT_LOWER, + SLIDER_JOINT_LINEAR_LIMIT_SOFTNESS, + SLIDER_JOINT_LINEAR_LIMIT_RESTITUTION, + SLIDER_JOINT_LINEAR_LIMIT_DAMPING, + SLIDER_JOINT_LINEAR_MOTION_SOFTNESS, + SLIDER_JOINT_LINEAR_MOTION_RESTITUTION, + SLIDER_JOINT_LINEAR_MOTION_DAMPING, + SLIDER_JOINT_LINEAR_ORTHOGONAL_SOFTNESS, + SLIDER_JOINT_LINEAR_ORTHOGONAL_RESTITUTION, + SLIDER_JOINT_LINEAR_ORTHOGONAL_DAMPING, + + SLIDER_JOINT_ANGULAR_LIMIT_UPPER, + SLIDER_JOINT_ANGULAR_LIMIT_LOWER, + SLIDER_JOINT_ANGULAR_LIMIT_SOFTNESS, + SLIDER_JOINT_ANGULAR_LIMIT_RESTITUTION, + SLIDER_JOINT_ANGULAR_LIMIT_DAMPING, + SLIDER_JOINT_ANGULAR_MOTION_SOFTNESS, + SLIDER_JOINT_ANGULAR_MOTION_RESTITUTION, + SLIDER_JOINT_ANGULAR_MOTION_DAMPING, + SLIDER_JOINT_ANGULAR_ORTHOGONAL_SOFTNESS, + SLIDER_JOINT_ANGULAR_ORTHOGONAL_RESTITUTION, + SLIDER_JOINT_ANGULAR_ORTHOGONAL_DAMPING, + SLIDER_JOINT_MAX + + }; + + virtual RID joint_create_slider(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A + + virtual void slider_joint_set_param(RID p_joint, SliderJointParam p_param, float p_value) = 0; + virtual float slider_joint_get_param(RID p_joint, SliderJointParam p_param) const = 0; + + enum ConeTwistJointParam { + CONE_TWIST_JOINT_SWING_SPAN, + CONE_TWIST_JOINT_TWIST_SPAN, + CONE_TWIST_JOINT_BIAS, + CONE_TWIST_JOINT_SOFTNESS, + CONE_TWIST_JOINT_RELAXATION, + CONE_TWIST_MAX + }; + + virtual RID joint_create_cone_twist(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A + + virtual void cone_twist_joint_set_param(RID p_joint, ConeTwistJointParam p_param, float p_value) = 0; + virtual float cone_twist_joint_get_param(RID p_joint, ConeTwistJointParam p_param) const = 0; + + enum G6DOFJointAxisParam { + G6DOF_JOINT_LINEAR_LOWER_LIMIT, + G6DOF_JOINT_LINEAR_UPPER_LIMIT, + G6DOF_JOINT_LINEAR_LIMIT_SOFTNESS, + G6DOF_JOINT_LINEAR_RESTITUTION, + G6DOF_JOINT_LINEAR_DAMPING, + G6DOF_JOINT_LINEAR_MOTOR_TARGET_VELOCITY, + G6DOF_JOINT_LINEAR_MOTOR_FORCE_LIMIT, + G6DOF_JOINT_LINEAR_SPRING_STIFFNESS, + G6DOF_JOINT_LINEAR_SPRING_DAMPING, + G6DOF_JOINT_LINEAR_SPRING_EQUILIBRIUM_POINT, + G6DOF_JOINT_ANGULAR_LOWER_LIMIT, + G6DOF_JOINT_ANGULAR_UPPER_LIMIT, + G6DOF_JOINT_ANGULAR_LIMIT_SOFTNESS, + G6DOF_JOINT_ANGULAR_DAMPING, + G6DOF_JOINT_ANGULAR_RESTITUTION, + G6DOF_JOINT_ANGULAR_FORCE_LIMIT, + G6DOF_JOINT_ANGULAR_ERP, + G6DOF_JOINT_ANGULAR_MOTOR_TARGET_VELOCITY, + G6DOF_JOINT_ANGULAR_MOTOR_FORCE_LIMIT, + G6DOF_JOINT_ANGULAR_SPRING_STIFFNESS, + G6DOF_JOINT_ANGULAR_SPRING_DAMPING, + G6DOF_JOINT_ANGULAR_SPRING_EQUILIBRIUM_POINT, + G6DOF_JOINT_MAX + }; + + enum G6DOFJointAxisFlag { + + G6DOF_JOINT_FLAG_ENABLE_LINEAR_LIMIT, + G6DOF_JOINT_FLAG_ENABLE_ANGULAR_LIMIT, + G6DOF_JOINT_FLAG_ENABLE_ANGULAR_SPRING, + G6DOF_JOINT_FLAG_ENABLE_LINEAR_SPRING, + G6DOF_JOINT_FLAG_ENABLE_MOTOR, + G6DOF_JOINT_FLAG_ENABLE_LINEAR_MOTOR, + G6DOF_JOINT_FLAG_MAX + }; + + virtual RID joint_create_generic_6dof(RID p_body_A, const Transform &p_local_frame_A, RID p_body_B, const Transform &p_local_frame_B) = 0; //reference frame is A + + virtual void generic_6dof_joint_set_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param, float p_value) = 0; + virtual float generic_6dof_joint_get_param(RID p_joint, Vector3::Axis, G6DOFJointAxisParam p_param) = 0; + + virtual void generic_6dof_joint_set_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag, bool p_enable) = 0; + virtual bool generic_6dof_joint_get_flag(RID p_joint, Vector3::Axis, G6DOFJointAxisFlag p_flag) = 0; + + virtual void generic_6dof_joint_set_precision(RID p_joint, int precision) = 0; + virtual int generic_6dof_joint_get_precision(RID p_joint) = 0; + + /* QUERY API */ + + enum AreaBodyStatus { + AREA_BODY_ADDED, + AREA_BODY_REMOVED + }; + + /* MISC */ + + virtual void free(RID p_rid) = 0; + + virtual void set_active(bool p_active) = 0; + virtual void init() = 0; + virtual void step(float p_step) = 0; + virtual void sync() = 0; + virtual void flush_queries() = 0; + virtual void finish() = 0; + + virtual bool is_flushing_queries() const = 0; + + enum ProcessInfo { + + INFO_ACTIVE_OBJECTS, + INFO_COLLISION_PAIRS, + INFO_ISLAND_COUNT + }; + + virtual int get_process_info(ProcessInfo p_info) = 0; + + PhysicsServer3D(); + ~PhysicsServer3D(); +}; + +typedef PhysicsServer3D *(*CreatePhysicsServer3DCallback)(); + +class PhysicsServer3DManager { + struct ClassInfo { + String name; + CreatePhysicsServer3DCallback create_callback; + + ClassInfo() : + name(""), + create_callback(NULL) {} + + ClassInfo(String p_name, CreatePhysicsServer3DCallback p_create_callback) : + name(p_name), + create_callback(p_create_callback) {} + + ClassInfo(const ClassInfo &p_ci) : + name(p_ci.name), + create_callback(p_ci.create_callback) {} + + ClassInfo operator=(const ClassInfo &p_ci) { + name = p_ci.name; + create_callback = p_ci.create_callback; + return *this; + } + }; + + static Vector physics_servers; + static int default_server_id; + static int default_server_priority; + +public: + static const String setting_property_name; + +private: + static void on_servers_changed(); + +public: + static void register_server(const String &p_name, CreatePhysicsServer3DCallback p_creat_callback); + static void set_default_server(const String &p_name, int p_priority = 0); + static int find_server_id(const String &p_name); + static int get_servers_count(); + static String get_server_name(int p_id); + static PhysicsServer3D *new_default_server(); + static PhysicsServer3D *new_server(const String &p_name); +}; + +VARIANT_ENUM_CAST(PhysicsServer3D::ShapeType); +VARIANT_ENUM_CAST(PhysicsServer3D::SpaceParameter); +VARIANT_ENUM_CAST(PhysicsServer3D::AreaParameter); +VARIANT_ENUM_CAST(PhysicsServer3D::AreaSpaceOverrideMode); +VARIANT_ENUM_CAST(PhysicsServer3D::BodyMode); +VARIANT_ENUM_CAST(PhysicsServer3D::BodyParameter); +VARIANT_ENUM_CAST(PhysicsServer3D::BodyState); +VARIANT_ENUM_CAST(PhysicsServer3D::BodyAxis); +VARIANT_ENUM_CAST(PhysicsServer3D::PinJointParam); +VARIANT_ENUM_CAST(PhysicsServer3D::JointType); +VARIANT_ENUM_CAST(PhysicsServer3D::HingeJointParam); +VARIANT_ENUM_CAST(PhysicsServer3D::HingeJointFlag); +VARIANT_ENUM_CAST(PhysicsServer3D::SliderJointParam); +VARIANT_ENUM_CAST(PhysicsServer3D::ConeTwistJointParam); +VARIANT_ENUM_CAST(PhysicsServer3D::G6DOFJointAxisParam); +VARIANT_ENUM_CAST(PhysicsServer3D::G6DOFJointAxisFlag); +VARIANT_ENUM_CAST(PhysicsServer3D::AreaBodyStatus); +VARIANT_ENUM_CAST(PhysicsServer3D::ProcessInfo); + +#endif diff --git a/servers/register_server_types.cpp b/servers/register_server_types.cpp index 574b373c30..fa2a5f23dd 100644 --- a/servers/register_server_types.cpp +++ b/servers/register_server_types.cpp @@ -58,30 +58,30 @@ #include "camera/camera_feed.h" #include "camera_server.h" #include "display_server.h" -#include "navigation_2d_server.h" -#include "navigation_server.h" -#include "physics/physics_server_sw.h" -#include "physics_2d/physics_2d_server_sw.h" -#include "physics_2d/physics_2d_server_wrap_mt.h" -#include "physics_2d_server.h" -#include "physics_server.h" -#include "visual/shader_types.h" -#include "visual_server.h" +#include "navigation_server_2d.h" +#include "navigation_server_3d.h" +#include "physics_2d/physics_server_2d_sw.h" +#include "physics_2d/physics_server_2d_wrap_mt.h" +#include "physics_3d/physics_server_3d_sw.h" +#include "physics_server_2d.h" +#include "physics_server_3d.h" +#include "rendering_server.h" +#include "servers/rendering/shader_types.h" ShaderTypes *shader_types = NULL; -PhysicsServer *_createGodotPhysicsCallback() { - return memnew(PhysicsServerSW); +PhysicsServer3D *_createGodotPhysicsCallback() { + return memnew(PhysicsServer3DSW); } -Physics2DServer *_createGodotPhysics2DCallback() { - return Physics2DServerWrapMT::init_server(); +PhysicsServer2D *_createGodotPhysics2DCallback() { + return PhysicsServer2DWrapMT::init_server(); } static bool has_server_feature_callback(const String &p_feature) { - if (VisualServer::get_singleton()) { - if (VisualServer::get_singleton()->has_os_feature(p_feature)) { + if (RenderingServer::get_singleton()) { + if (RenderingServer::get_singleton()->has_os_feature(p_feature)) { return true; } } @@ -98,10 +98,10 @@ void register_server_types() { OS::get_singleton()->set_has_server_feature_callback(has_server_feature_callback); ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); ClassDB::register_class(); - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); ClassDB::register_class(); ClassDB::register_class(); @@ -159,30 +159,30 @@ void register_server_types() { ClassDB::register_class(); - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); ClassDB::register_class(); - ClassDB::register_class(); + ClassDB::register_class(); - ClassDB::register_class(); - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); - ClassDB::register_virtual_class(); + ClassDB::register_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); + ClassDB::register_virtual_class(); // Physics 2D - GLOBAL_DEF(Physics2DServerManager::setting_property_name, "DEFAULT"); - ProjectSettings::get_singleton()->set_custom_property_info(Physics2DServerManager::setting_property_name, PropertyInfo(Variant::STRING, Physics2DServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); + GLOBAL_DEF(PhysicsServer2DManager::setting_property_name, "DEFAULT"); + ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer2DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer2DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - Physics2DServerManager::register_server("GodotPhysics", &_createGodotPhysics2DCallback); - Physics2DServerManager::set_default_server("GodotPhysics"); + PhysicsServer2DManager::register_server("GodotPhysics", &_createGodotPhysics2DCallback); + PhysicsServer2DManager::set_default_server("GodotPhysics"); // Physics 3D - GLOBAL_DEF(PhysicsServerManager::setting_property_name, "DEFAULT"); - ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServerManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServerManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); + GLOBAL_DEF(PhysicsServer3DManager::setting_property_name, "DEFAULT"); + ProjectSettings::get_singleton()->set_custom_property_info(PhysicsServer3DManager::setting_property_name, PropertyInfo(Variant::STRING, PhysicsServer3DManager::setting_property_name, PROPERTY_HINT_ENUM, "DEFAULT")); - PhysicsServerManager::register_server("GodotPhysics", &_createGodotPhysicsCallback); - PhysicsServerManager::set_default_server("GodotPhysics"); + PhysicsServer3DManager::register_server("GodotPhysics", &_createGodotPhysicsCallback); + PhysicsServer3DManager::set_default_server("GodotPhysics"); } void unregister_server_types() { @@ -192,12 +192,12 @@ void unregister_server_types() { void register_server_singletons() { - Engine::get_singleton()->add_singleton(Engine::Singleton("VisualServer", VisualServer::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("RenderingServer", RenderingServer::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("AudioServer", AudioServer::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer", PhysicsServer::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("Physics2DServer", Physics2DServer::get_singleton())); - Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer", NavigationServer::get_singleton_mut())); - Engine::get_singleton()->add_singleton(Engine::Singleton("Navigation2DServer", Navigation2DServer::get_singleton_mut())); + Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer3D", PhysicsServer3D::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("PhysicsServer2D", PhysicsServer2D::get_singleton())); + Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer", NavigationServer3D::get_singleton_mut())); + Engine::get_singleton()->add_singleton(Engine::Singleton("NavigationServer2D", NavigationServer2D::get_singleton_mut())); Engine::get_singleton()->add_singleton(Engine::Singleton("ARVRServer", ARVRServer::get_singleton())); Engine::get_singleton()->add_singleton(Engine::Singleton("CameraServer", CameraServer::get_singleton())); } diff --git a/servers/rendering/SCsub b/servers/rendering/SCsub new file mode 100644 index 0000000000..fca18bfea0 --- /dev/null +++ b/servers/rendering/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.servers_sources, "*.cpp") + +SConscript("rasterizer_rd/SCsub") diff --git a/servers/rendering/rasterizer.cpp b/servers/rendering/rasterizer.cpp new file mode 100644 index 0000000000..a3f93a3f8c --- /dev/null +++ b/servers/rendering/rasterizer.cpp @@ -0,0 +1,77 @@ +/*************************************************************************/ +/* rasterizer.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer.h" + +#include "core/os/os.h" +#include "core/print_string.h" + +Rasterizer *(*Rasterizer::_create_func)() = NULL; + +void RasterizerScene::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) { + for (Map::Element *E = instances.front(); E; E = E->next()) { + E->key()->dependency_changed(p_aabb, p_dependencies); + } +} +void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted) { + for (Map::Element *E = instances.front(); E; E = E->next()) { + E->key()->dependency_deleted(p_deleted); + } + for (Map::Element *E = instances.front(); E; E = E->next()) { + E->key()->dependencies.erase(this); + } + + instances.clear(); +} + +RasterizerScene::InstanceDependency::~InstanceDependency() { +#ifdef DEBUG_ENABLED + if (instances.size()) { + WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing."); + for (Map::Element *E = instances.front(); E; E = E->next()) { + E->key()->dependencies.erase(this); + } + } +#endif +} + +Rasterizer *Rasterizer::create() { + + return _create_func(); +} + +RasterizerCanvas *RasterizerCanvas::singleton = NULL; + +RasterizerStorage *RasterizerStorage::base_singleton = NULL; + +RasterizerStorage::RasterizerStorage() { + + base_singleton = this; +} diff --git a/servers/rendering/rasterizer.h b/servers/rendering/rasterizer.h new file mode 100644 index 0000000000..f63d1077bb --- /dev/null +++ b/servers/rendering/rasterizer.h @@ -0,0 +1,1307 @@ +/*************************************************************************/ +/* rasterizer.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_H +#define RASTERIZER_H + +#include "core/math/camera_matrix.h" +#include "servers/rendering_server.h" + +#include "core/pair.h" +#include "core/self_list.h" + +class RasterizerScene { + +public: + /* SHADOW ATLAS API */ + + virtual RID shadow_atlas_create() = 0; + virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0; + virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; + virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0; + + virtual void directional_shadow_atlas_set_size(int p_size) = 0; + virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; + virtual void set_directional_shadow_count(int p_count) = 0; + + /* SKY API */ + + virtual RID sky_create() = 0; + virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; + virtual void sky_set_mode(RID p_sky, RS::SkyMode p_samples) = 0; + virtual void sky_set_material(RID p_sky, RID p_material) = 0; + + /* ENVIRONMENT API */ + + virtual RID environment_create() = 0; + + virtual void environment_set_background(RID p_env, RS::EnvironmentBG p_bg) = 0; + virtual void environment_set_sky(RID p_env, RID p_sky) = 0; + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; + virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; + virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; + virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; + virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; +#endif + + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; + virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0; + + virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + + virtual void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; + + virtual void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; + + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; + + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; + virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; + virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; + + virtual bool is_environment(RID p_env) const = 0; + virtual RS::EnvironmentBG environment_get_background(RID p_env) const = 0; + virtual int environment_get_canvas_max_layer(RID p_env) const = 0; + + virtual RID camera_effects_create() = 0; + + virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) = 0; + virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) = 0; + + virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; + virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; + + struct InstanceBase; + + struct InstanceDependency { + + void instance_notify_changed(bool p_aabb, bool p_dependencies); + void instance_notify_deleted(RID p_deleted); + + ~InstanceDependency(); + + private: + friend struct InstanceBase; + Map instances; + }; + + struct InstanceBase { + + RS::InstanceType base_type; + RID base; + + RID skeleton; + RID material_override; + + RID instance_data; + + Transform transform; + + int depth_layer; + uint32_t layer_mask; + uint32_t instance_version; + + //RID sampled_light; + + Vector materials; + Vector light_instances; + Vector reflection_probe_instances; + Vector gi_probe_instances; + + Vector blend_values; + + RS::ShadowCastingSetting cast_shadows; + + //fit in 32 bits + bool mirror : 8; + bool receive_shadows : 8; + bool visible : 8; + bool baked_light : 2; //this flag is only to know if it actually did use baked light + bool dynamic_gi : 2; //this flag is only to know if it actually did use baked light + bool redraw_if_visible : 4; + + float depth; //used for sorting + + SelfList dependency_item; + + InstanceBase *lightmap_capture; + RID lightmap; + Vector lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader + + AABB aabb; + AABB transformed_aabb; + + virtual void dependency_deleted(RID p_dependency) = 0; + virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0; + + Set dependencies; + + void instance_increase_version() { + instance_version++; + } + + void update_dependency(InstanceDependency *p_dependency) { + dependencies.insert(p_dependency); + p_dependency->instances[this] = instance_version; + } + + void clean_up_dependencies() { + List::Element *>> to_clean_up; + for (Set::Element *E = dependencies.front(); E; E = E->next()) { + InstanceDependency *dep = E->get(); + Map::Element *F = dep->instances.find(this); + ERR_CONTINUE(!F); + if (F->get() != instance_version) { + Pair::Element *> p; + p.first = dep; + p.second = F; + to_clean_up.push_back(p); + } + } + + while (to_clean_up.size()) { + to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second); + to_clean_up.pop_front(); + } + } + + void clear_dependencies() { + for (Set::Element *E = dependencies.front(); E; E = E->next()) { + InstanceDependency *dep = E->get(); + dep->instances.erase(this); + } + dependencies.clear(); + } + + InstanceBase() : + dependency_item(this) { + + base_type = RS::INSTANCE_NONE; + cast_shadows = RS::SHADOW_CASTING_SETTING_ON; + receive_shadows = true; + visible = true; + depth_layer = 0; + layer_mask = 1; + instance_version = 0; + baked_light = false; + dynamic_gi = false; + redraw_if_visible = false; + lightmap_capture = NULL; + } + + virtual ~InstanceBase() { + clear_dependencies(); + } + }; + + virtual RID light_instance_create(RID p_light) = 0; + virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0; + virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0; + virtual void light_instance_mark_visible(RID p_light_instance) = 0; + virtual bool light_instances_can_render_shadow_cube() const { return true; } + + virtual RID reflection_atlas_create() = 0; + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0; + + virtual RID reflection_probe_instance_create(RID p_probe) = 0; + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0; + virtual void reflection_probe_release_atlas_index(RID p_instance) = 0; + virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; + virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; + virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; + + virtual RID gi_probe_instance_create(RID p_gi_probe) = 0; + virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0; + virtual bool gi_probe_needs_update(RID p_probe) const = 0; + virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0; + + virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; + + virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0; + virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; + + virtual void set_scene_pass(uint64_t p_pass) = 0; + virtual void set_time(double p_time, double p_step) = 0; + virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) = 0; + + virtual RID render_buffers_create() = 0; + virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0; + + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; + virtual bool screen_space_roughness_limiter_is_active() const = 0; + + virtual bool free(RID p_rid) = 0; + + virtual void update() = 0; + virtual ~RasterizerScene() {} +}; + +class RasterizerStorage { + + Color default_clear_color; + +public: + /* TEXTURE API */ + + virtual RID texture_2d_create(const Ref &p_image) = 0; + virtual RID texture_2d_layered_create(const Vector> &p_layers, RS::TextureLayeredType p_layered_type) = 0; + virtual RID texture_3d_create(const Vector> &p_slices) = 0; //all slices, then all the mipmaps, must be coherent + virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent + + virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; //mostly used for video and streaming + virtual void texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; + virtual void texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap) = 0; + virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; + + //these two APIs can be used together or in combination with the others. + virtual RID texture_2d_placeholder_create() = 0; + virtual RID texture_2d_layered_placeholder_create() = 0; + virtual RID texture_3d_placeholder_create() = 0; + + virtual Ref texture_2d_get(RID p_texture) const = 0; + virtual Ref texture_2d_layer_get(RID p_texture, int p_layer) const = 0; + virtual Ref texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const = 0; + + virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0; +#endif + + virtual void texture_set_path(RID p_texture, const String &p_path) = 0; + virtual String texture_get_path(RID p_texture) const = 0; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; + + virtual void texture_debug_usage(List *r_info) = 0; + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + + virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; + + /* SHADER API */ + + virtual RID shader_create() = 0; + + virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual String shader_get_code(RID p_shader) const = 0; + virtual void shader_get_param_list(RID p_shader, List *p_param_list) const = 0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; + + /* COMMON MATERIAL API */ + + virtual RID material_create() = 0; + + virtual void material_set_render_priority(RID p_material, int priority) = 0; + virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; + + virtual bool material_is_animated(RID p_material) = 0; + virtual bool material_casts_shadows(RID p_material) = 0; + + virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0; + + /* MESH API */ + + virtual RID mesh_create() = 0; + + /// Returns stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) = 0; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) = 0; + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; + + virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data) = 0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; + + virtual int mesh_get_surface_count(RID p_mesh) const = 0; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; + + virtual void mesh_clear(RID p_mesh) = 0; + + /* MULTIMESH API */ + + virtual RID multimesh_create() = 0; + + virtual void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; + + virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) = 0; + virtual Vector multimesh_get_buffer(RID p_multimesh) const = 0; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; + + virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; + + /* IMMEDIATE API */ + + virtual RID immediate_create() = 0; + virtual void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0; + virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; + virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; + virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; + virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; + virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; + virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; + virtual void immediate_end(RID p_immediate) = 0; + virtual void immediate_clear(RID p_immediate) = 0; + virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; + virtual RID immediate_get_material(RID p_immediate) const = 0; + virtual AABB immediate_get_aabb(RID p_immediate) const = 0; + + /* SKELETON API */ + + virtual RID skeleton_create() = 0; + virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; + virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + + /* Light API */ + + virtual RID light_create(RS::LightType p_type) = 0; + + RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); } + RID omni_light_create() { return light_create(RS::LIGHT_OMNI); } + RID spot_light_create() { return light_create(RS::LIGHT_SPOT); } + + virtual void light_set_color(RID p_light, const Color &p_color) = 0; + virtual void light_set_param(RID p_light, RS::LightParam p_param, float p_value) = 0; + virtual void light_set_shadow(RID p_light, bool p_enabled) = 0; + virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0; + virtual void light_set_projector(RID p_light, RID p_texture) = 0; + virtual void light_set_negative(RID p_light, bool p_enable) = 0; + virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; + virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; + + virtual void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) = 0; + + virtual void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) = 0; + virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; + virtual bool light_directional_get_blend_splits(RID p_light) const = 0; + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + virtual RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; + + virtual RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; + virtual RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; + + virtual bool light_has_shadow(RID p_light) const = 0; + + virtual RS::LightType light_get_type(RID p_light) const = 0; + virtual AABB light_get_aabb(RID p_light) const = 0; + virtual float light_get_param(RID p_light, RS::LightParam p_param) = 0; + virtual Color light_get_color(RID p_light) = 0; + virtual bool light_get_use_gi(RID p_light) = 0; + virtual uint64_t light_get_version(RID p_light) const = 0; + + /* PROBE API */ + + virtual RID reflection_probe_create() = 0; + + virtual void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) = 0; + virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) = 0; + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0; + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; + + virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0; + virtual RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0; + virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0; + virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0; + virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0; + virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0; + virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; + + virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; + virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; + + /* GI PROBE API */ + + virtual RID gi_probe_create() = 0; + + virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; + + virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; + virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_octree_cells(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_data_cells(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_distance_field(RID p_gi_probe) const = 0; + + virtual Vector gi_probe_get_level_counts(RID p_gi_probe) const = 0; + virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; + virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; + virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; + virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; + virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; + virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; + virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; + virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; + + virtual uint32_t gi_probe_get_version(RID p_probe) = 0; + + /* LIGHTMAP CAPTURE */ + + struct LightmapCaptureOctree { + + enum { + CHILD_EMPTY = 0xFFFFFFFF + }; + + uint16_t light[6][3]; //anisotropic light + float alpha; + uint32_t children[8]; + }; + + virtual RID lightmap_capture_create() = 0; + virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; + virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) = 0; + virtual Vector lightmap_capture_get_octree(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; + virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; + virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; + virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; + virtual float lightmap_capture_get_energy(RID p_capture) const = 0; + virtual const Vector *lightmap_capture_get_octree_ptr(RID p_capture) const = 0; + + /* PARTICLES */ + + virtual RID particles_create() = 0; + + virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; + virtual bool particles_get_emitting(RID p_particles) = 0; + + virtual void particles_set_amount(RID p_particles, int p_amount) = 0; + virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; + virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; + virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0; + virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0; + virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0; + virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; + virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0; + virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; + virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; + virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; + virtual void particles_restart(RID p_particles) = 0; + + virtual bool particles_is_inactive(RID p_particles) const = 0; + + virtual void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) = 0; + + virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; + virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; + + virtual void particles_request_process(RID p_particles) = 0; + virtual AABB particles_get_current_aabb(RID p_particles) = 0; + virtual AABB particles_get_aabb(RID p_particles) const = 0; + + virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; + + virtual int particles_get_draw_passes(RID p_particles) const = 0; + virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; + + /* RENDER TARGET */ + + enum RenderTargetFlags { + RENDER_TARGET_TRANSPARENT, + RENDER_TARGET_DIRECT_TO_SCREEN, + RENDER_TARGET_FLAG_MAX + }; + + virtual RID render_target_create() = 0; + virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; + virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0; + virtual RID render_target_get_texture(RID p_render_target) = 0; + virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; + virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0; + virtual bool render_target_was_used(RID p_render_target) = 0; + virtual void render_target_set_as_unused(RID p_render_target) = 0; + + virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0; + virtual bool render_target_is_clear_requested(RID p_render_target) = 0; + virtual Color render_target_get_clear_request_color(RID p_render_target) = 0; + virtual void render_target_disable_clear_request(RID p_render_target) = 0; + virtual void render_target_do_clear_request(RID p_render_target) = 0; + + virtual RS::InstanceType get_base_type(RID p_rid) const = 0; + virtual bool free(RID p_rid) = 0; + + virtual bool has_os_feature(const String &p_feature) const = 0; + + virtual void update_dirty_resources() = 0; + + virtual void set_debug_generate_wireframes(bool p_generate) = 0; + + virtual void render_info_begin_capture() = 0; + virtual void render_info_end_capture() = 0; + virtual int get_captured_render_info(RS::RenderInfo p_info) = 0; + + virtual int get_render_info(RS::RenderInfo p_info) = 0; + virtual String get_video_adapter_name() const = 0; + virtual String get_video_adapter_vendor() const = 0; + + static RasterizerStorage *base_singleton; + + void set_default_clear_color(const Color &p_color) { + default_clear_color = p_color; + } + + Color get_default_clear_color() const { + return default_clear_color; + } +#define TIMESTAMP_BEGIN() \ + { \ + if (RSG::storage->capturing_timestamps) RSG::storage->capture_timestamps_begin(); \ + } + +#define RENDER_TIMESTAMP(m_text) \ + { \ + if (RSG::storage->capturing_timestamps) RSG::storage->capture_timestamp(m_text); \ + } + + bool capturing_timestamps = false; + + virtual void capture_timestamps_begin() = 0; + virtual void capture_timestamp(const String &p_name) = 0; + virtual uint32_t get_captured_timestamps_count() const = 0; + virtual uint64_t get_captured_timestamps_frame() const = 0; + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0; + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0; + virtual String get_captured_timestamp_name(uint32_t p_index) const = 0; + + RasterizerStorage(); + virtual ~RasterizerStorage() {} +}; + +class RasterizerCanvas { +public: + static RasterizerCanvas *singleton; + + enum CanvasRectFlags { + + CANVAS_RECT_REGION = 1, + CANVAS_RECT_TILE = 2, + CANVAS_RECT_FLIP_H = 4, + CANVAS_RECT_FLIP_V = 8, + CANVAS_RECT_TRANSPOSE = 16, + CANVAS_RECT_CLIP_UV = 32 + }; + + struct Light { + + bool enabled; + Color color; + Transform2D xform; + float height; + float energy; + float scale; + int z_min; + int z_max; + int layer_min; + int layer_max; + int item_mask; + int item_shadow_mask; + RS::CanvasLightMode mode; + RID texture; + Vector2 texture_offset; + RID canvas; + bool use_shadow; + int shadow_buffer_size; + RS::CanvasLightShadowFilter shadow_filter; + Color shadow_color; + float shadow_smooth; + + //void *texture_cache; // implementation dependent + Rect2 rect_cache; + Transform2D xform_cache; + float radius_cache; //used for shadow far plane + //CameraMatrix shadow_matrix_cache; + + Transform2D light_shader_xform; + //Vector2 light_shader_pos; + + Light *shadows_next_ptr; + Light *filter_next_ptr; + Light *next_ptr; + Light *mask_next_ptr; + + RID light_internal; + uint64_t version; + + int32_t render_index_cache; + + Light() { + version = 0; + enabled = true; + color = Color(1, 1, 1); + shadow_color = Color(0, 0, 0, 0); + height = 0; + z_min = -1024; + z_max = 1024; + layer_min = 0; + layer_max = 0; + item_mask = 1; + scale = 1.0; + energy = 1.0; + item_shadow_mask = -1; + mode = RS::CANVAS_LIGHT_MODE_ADD; + // texture_cache = NULL; + next_ptr = NULL; + mask_next_ptr = NULL; + filter_next_ptr = NULL; + use_shadow = false; + shadow_buffer_size = 2048; + shadow_filter = RS::CANVAS_LIGHT_FILTER_NONE; + shadow_smooth = 0.0; + render_index_cache = -1; + } + }; + + typedef uint64_t TextureBindingID; + + virtual TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) = 0; + virtual void free_texture_binding(TextureBindingID p_binding) = 0; + + //easier wrap to avoid mistakes + + struct Item; + + struct TextureBinding { + + TextureBindingID binding_id; + + _FORCE_INLINE_ void create(RS::CanvasItemTextureFilter p_item_filter, RS::CanvasItemTextureRepeat p_item_repeat, RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { + if (p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { + p_filter = p_item_filter; + } + if (p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { + p_repeat = p_item_repeat; + } + if (p_texture != RID() || p_normalmap != RID() || p_specular != RID() || p_filter != RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT || p_repeat != RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT || p_multimesh.is_valid()) { + ERR_FAIL_COND(binding_id != 0); + binding_id = singleton->request_texture_binding(p_texture, p_normalmap, p_specular, p_filter, p_repeat, p_multimesh); + } + } + + _FORCE_INLINE_ TextureBinding() { binding_id = 0; } + _FORCE_INLINE_ ~TextureBinding() { + if (binding_id) singleton->free_texture_binding(binding_id); + } + }; + + typedef uint64_t PolygonID; + virtual PolygonID request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()) = 0; + virtual void free_polygon(PolygonID p_polygon) = 0; + + //also easier to wrap to avoid mistakes + struct Polygon { + + PolygonID polygon_id; + Rect2 rect_cache; + + _FORCE_INLINE_ void create(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()) { + ERR_FAIL_COND(polygon_id != 0); + { + uint32_t pc = p_points.size(); + const Vector2 *v2 = p_points.ptr(); + rect_cache.position = *v2; + for (uint32_t i = 1; i < pc; i++) { + rect_cache.expand_to(v2[i]); + } + } + polygon_id = singleton->request_polygon(p_indices, p_points, p_colors, p_uvs, p_bones, p_weights); + } + + _FORCE_INLINE_ Polygon() { polygon_id = 0; } + _FORCE_INLINE_ ~Polygon() { + if (polygon_id) singleton->free_polygon(polygon_id); + } + }; + + //item + + struct Item { + + //commands are allocated in blocks of 4k to improve performance + //and cache coherence. + //blocks always grow but never shrink. + + struct CommandBlock { + enum { + MAX_SIZE = 4096 + }; + uint32_t usage; + uint8_t *memory; + }; + + struct Command { + + enum Type { + + TYPE_RECT, + TYPE_NINEPATCH, + TYPE_POLYGON, + TYPE_PRIMITIVE, + TYPE_MESH, + TYPE_MULTIMESH, + TYPE_PARTICLES, + TYPE_TRANSFORM, + TYPE_CLIP_IGNORE, + }; + + Command *next; + Type type; + virtual ~Command() {} + }; + + struct CommandRect : public Command { + + Rect2 rect; + Color modulate; + Rect2 source; + uint8_t flags; + Color specular_shininess; + + TextureBinding texture_binding; + + CommandRect() { + flags = 0; + type = TYPE_RECT; + } + }; + + struct CommandNinePatch : public Command { + + Rect2 rect; + Rect2 source; + float margin[4]; + bool draw_center; + Color color; + RS::NinePatchAxisMode axis_x; + RS::NinePatchAxisMode axis_y; + Color specular_shininess; + TextureBinding texture_binding; + CommandNinePatch() { + draw_center = true; + type = TYPE_NINEPATCH; + } + }; + + struct CommandPolygon : public Command { + + RS::PrimitiveType primitive; + Polygon polygon; + Color specular_shininess; + TextureBinding texture_binding; + CommandPolygon() { + type = TYPE_POLYGON; + } + }; + + struct CommandPrimitive : public Command { + + uint32_t point_count; + Vector2 points[4]; + Vector2 uvs[4]; + Color colors[4]; + Color specular_shininess; + TextureBinding texture_binding; + CommandPrimitive() { + type = TYPE_PRIMITIVE; + } + }; + + struct CommandMesh : public Command { + + RID mesh; + Transform2D transform; + Color modulate; + Color specular_shininess; + TextureBinding texture_binding; + CommandMesh() { type = TYPE_MESH; } + }; + + struct CommandMultiMesh : public Command { + + RID multimesh; + Color specular_shininess; + TextureBinding texture_binding; + CommandMultiMesh() { type = TYPE_MULTIMESH; } + }; + + struct CommandParticles : public Command { + + RID particles; + Color specular_shininess; + TextureBinding texture_binding; + CommandParticles() { type = TYPE_PARTICLES; } + }; + + struct CommandTransform : public Command { + + Transform2D xform; + CommandTransform() { type = TYPE_TRANSFORM; } + }; + + struct CommandClipIgnore : public Command { + + bool ignore; + CommandClipIgnore() { + type = TYPE_CLIP_IGNORE; + ignore = false; + } + }; + + struct ViewportRender { + RenderingServer *owner; + void *udata; + Rect2 rect; + }; + + Transform2D xform; + bool clip; + bool visible; + bool behind; + bool update_when_visible; + //RS::MaterialBlendMode blend_mode; + int light_mask; + int z_final; + + mutable bool custom_rect; + mutable bool rect_dirty; + mutable Rect2 rect; + RID material; + RID skeleton; + + Item *next; + + struct CopyBackBuffer { + Rect2 rect; + Rect2 screen_rect; + bool full; + }; + CopyBackBuffer *copy_back_buffer; + + Color final_modulate; + Transform2D final_transform; + Rect2 final_clip_rect; + Item *final_clip_owner; + Item *material_owner; + ViewportRender *vp_render; + bool distance_field; + bool light_masked; + + Rect2 global_rect_cache; + + const Rect2 &get_rect() const { + if (custom_rect || (!rect_dirty && !update_when_visible)) + return rect; + + //must update rect + + if (commands == NULL) { + + rect = Rect2(); + rect_dirty = false; + return rect; + } + + Transform2D xf; + bool found_xform = false; + bool first = true; + + const Item::Command *c = commands; + + while (c) { + + Rect2 r; + + switch (c->type) { + case Item::Command::TYPE_RECT: { + + const Item::CommandRect *crect = static_cast(c); + r = crect->rect; + + } break; + case Item::Command::TYPE_NINEPATCH: { + + const Item::CommandNinePatch *style = static_cast(c); + r = style->rect; + } break; + + case Item::Command::TYPE_POLYGON: { + + const Item::CommandPolygon *polygon = static_cast(c); + r = polygon->polygon.rect_cache; + } break; + case Item::Command::TYPE_PRIMITIVE: { + + const Item::CommandPrimitive *primitive = static_cast(c); + for (uint32_t j = 0; j < primitive->point_count; j++) { + if (j == 0) { + r.position = primitive->points[0]; + } else { + r.expand_to(primitive->points[j]); + } + } + } break; + case Item::Command::TYPE_MESH: { + + const Item::CommandMesh *mesh = static_cast(c); + AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); + + r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + + } break; + case Item::Command::TYPE_MULTIMESH: { + + const Item::CommandMultiMesh *multimesh = static_cast(c); + AABB aabb = RasterizerStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh); + + r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + + } break; + case Item::Command::TYPE_PARTICLES: { + + const Item::CommandParticles *particles_cmd = static_cast(c); + if (particles_cmd->particles.is_valid()) { + AABB aabb = RasterizerStorage::base_singleton->particles_get_aabb(particles_cmd->particles); + r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); + } + + } break; + case Item::Command::TYPE_TRANSFORM: { + + const Item::CommandTransform *transform = static_cast(c); + xf = transform->xform; + found_xform = true; + [[fallthrough]]; + } + default: { + c = c->next; + continue; + } + } + + if (found_xform) { + r = xf.xform(r); + found_xform = false; + } + + if (first) { + rect = r; + first = false; + } else { + rect = rect.merge(r); + } + c = c->next; + } + + rect_dirty = false; + return rect; + } + + Command *commands; + Command *last_command; + Vector blocks; + uint32_t current_block; + + template + T *alloc_command() { + T *command; + if (commands == NULL) { + // As the most common use case of canvas items is to + // use only one command, the first is done with it's + // own allocation. The rest of them use blocks. + command = memnew(T); + command->next = NULL; + commands = command; + last_command = command; + } else { + //Subsequent commands go into a block. + + while (true) { + if (unlikely(current_block == (uint32_t)blocks.size())) { + // If we need more blocks, we allocate them + // (they won't be freed until this CanvasItem is + // deleted, though). + CommandBlock cb; + cb.memory = (uint8_t *)memalloc(CommandBlock::MAX_SIZE); + cb.usage = 0; + blocks.push_back(cb); + } + + CommandBlock *c = &blocks.write[current_block]; + size_t space_left = CommandBlock::MAX_SIZE - c->usage; + if (space_left < sizeof(T)) { + current_block++; + continue; + } + + //allocate block and add to the linked list + void *memory = c->memory + c->usage; + command = memnew_placement(memory, T); + command->next = NULL; + last_command->next = command; + last_command = command; + c->usage += sizeof(T); + break; + } + } + + rect_dirty = true; + return command; + } + + struct CustomData { + + virtual ~CustomData() {} + }; + + mutable CustomData *custom_data; //implementation dependent + + void clear() { + Command *c = commands; + while (c) { + Command *n = c->next; + if (c == commands) { + memdelete(commands); + commands = NULL; + } else { + c->~Command(); + } + c = n; + } + { + uint32_t cbc = MIN((current_block + 1), (uint32_t)blocks.size()); + CommandBlock *blockptr = blocks.ptrw(); + for (uint32_t i = 0; i < cbc; i++) { + blockptr[i].usage = 0; + } + } + + last_command = NULL; + commands = NULL; + current_block = 0; + clip = false; + rect_dirty = true; + final_clip_owner = NULL; + material_owner = NULL; + light_masked = false; + } + Item() { + commands = NULL; + last_command = NULL; + current_block = 0; + light_mask = 1; + vp_render = NULL; + next = NULL; + final_clip_owner = NULL; + clip = false; + final_modulate = Color(1, 1, 1, 1); + visible = true; + rect_dirty = true; + custom_rect = false; + behind = false; + material_owner = NULL; + copy_back_buffer = NULL; + distance_field = false; + light_masked = false; + update_when_visible = false; + z_final = 0; + custom_data = NULL; + } + virtual ~Item() { + clear(); + for (int i = 0; i < blocks.size(); i++) { + memfree(blocks[i].memory); + } + if (copy_back_buffer) memdelete(copy_back_buffer); + if (custom_data) { + memdelete(custom_data); + } + } + }; + + virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) = 0; + virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; + + struct LightOccluderInstance { + + bool enabled; + RID canvas; + RID polygon; + RID occluder; + Rect2 aabb_cache; + Transform2D xform; + Transform2D xform_cache; + int light_mask; + RS::CanvasOccluderPolygonCullMode cull_cache; + + LightOccluderInstance *next; + + LightOccluderInstance() { + enabled = true; + next = NULL; + light_mask = 1; + cull_cache = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + } + }; + + virtual RID light_create() = 0; + virtual void light_set_texture(RID p_rid, RID p_texture) = 0; + virtual void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) = 0; + virtual void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; + + virtual RID occluder_polygon_create() = 0; + virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines) = 0; + virtual void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) = 0; + + virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0; + + virtual bool free(RID p_rid) = 0; + virtual void update() = 0; + + RasterizerCanvas() { singleton = this; } + virtual ~RasterizerCanvas() {} +}; + +class Rasterizer { +protected: + static Rasterizer *(*_create_func)(); + +public: + static Rasterizer *create(); + + virtual RasterizerStorage *get_storage() = 0; + virtual RasterizerCanvas *get_canvas() = 0; + virtual RasterizerScene *get_scene() = 0; + + virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0; + + virtual void initialize() = 0; + virtual void begin_frame(double frame_step) = 0; + + struct BlitToScreen { + RID render_target; + Rect2i rect; + //lens distorted parameters for VR should go here + }; + + virtual void prepare_for_blitting_render_targets() = 0; + virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; + + virtual void end_frame(bool p_swap_buffers) = 0; + virtual void finalize() = 0; + + virtual bool is_low_end() const = 0; + + virtual ~Rasterizer() {} +}; + +#endif // RASTERIZER_H diff --git a/servers/rendering/rasterizer_rd/SCsub b/servers/rendering/rasterizer_rd/SCsub new file mode 100644 index 0000000000..cc17feeb05 --- /dev/null +++ b/servers/rendering/rasterizer_rd/SCsub @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +Import('env') + +env.add_source_files(env.servers_sources, "*.cpp") + +SConscript("shaders/SCsub") diff --git a/servers/rendering/rasterizer_rd/cubemap_coeffs.h b/servers/rendering/rasterizer_rd/cubemap_coeffs.h new file mode 100644 index 0000000000..1db03ce7c4 --- /dev/null +++ b/servers/rendering/rasterizer_rd/cubemap_coeffs.h @@ -0,0 +1,28 @@ +// Copyright 2016 Activision Publishing, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +#ifndef CUBEMAP_COEFFS_H +#define CUBEMAP_COEFFS_H + +const float low_quality_coeffs[7][5][6][4] = { { { { 0.0002037563, 0.0045063655, -0.0016408688, 0.00012037493 }, { -9.1834951e-05, -0.008947532, -8.1524405e-05, -3.9080094e-05 }, { -2.6038267e-05, -6.8409667e-05, 7.2175702e-05, 0.25492775 }, { -9.9426044e-05, 0.0025427756, -0.00074437925, 1.1773191e-05 }, { -3.2668211e-05, 0.0026930659, -4.824934e-05, -0.0006835048 }, { -0.0002864144, -0.0032220854, 0.0021558286, -0.00014573736 } }, { { 0.00030683201, 0.0026819548, -0.00060011756, -0.0067169226 }, { -0.0030993251, 0.0098575575, 0.0022416671, -8.9075401e-05 }, { 0.00052405626, 0.00057860515, 0.00011654518, -0.048018609 }, { 0.00010850967, -0.0088443512, -0.0018168095, 8.6633128e-05 }, { 0.003333989, -0.0050956447, -8.0414612e-05, 0.0049721239 }, { -4.0961436e-05, -8.5486984e-05, 0.0058683066, 2.2978359e-05 } }, { { 0.99999993, 0.99998625, 0.99999847, 0.99997743 }, { 0.99999519, 0.99991138, 0.99999748, 1 }, { 0.99999986, 0.99999983, 0.99999999, 0.96576708 }, { 0.99999999, 0.99995765, 0.99999807, 1 }, { 0.99999444, 0.99998339, 1, 0.99998741 }, { 0.99999996, 0.99999481, 0.99998046, 0.99999999 } }, { { -0.32267524, -0.65409377, -1.4666488, 0.87153305 }, { -1.264365, 0.89880861, -1.2245906, -0.88501403 }, { -0.31118682, -0.086150323, -0.58811532, 1.1317711 }, { -1.2193493, 1.250379, -1.0871569, -0.12694096 }, { -0.4012249, -0.47436307, -0.59661001, 2.7313005 }, { -1.3109856, 0.60929855, 0.55672643, -0.39880018 } }, { { 0.93273157, 0.59530745, 1.1994788, 0.19102276 }, { 1.2272239, 0.23245736, 1.2577607, 2.5491008 }, { 1.1210098, 0.83074953, 1.3049282, -0.001940633 }, { 1.5839111, 0.10520816, 1.150458, 2.3251789 }, { 0.688692, 0.59807498, 1.3374877, 0.095746692 }, { 1.3054173, 0.36604721, 0.065870226, 1.6496907 } } }, { { { 0.10348445, -4.6771514e-07, -0.011513131, 8.8921052e-05 }, { -0.042152043, 0.013143535, 0.00029120107, 0.036661611 }, { -0.04516036, 0.011438473, -0.0099289792, -0.011707897 }, { -0.034779497, 0.0090981166, -5.4202726e-05, 0.038592793 }, { -0.0071967376, -0.0056614418, -0.012278945, 0.0056867462 }, { -0.037678514, 0.011570177, 0.00029044557, 0.038583909 } }, { { 0.048320869, 1.4603673e-05, 0.0092672368, 0.00033289199 }, { 0.0071001761, -0.0090106091, -0.0027305905, -0.00221479 }, { -0.0027204116, 0.00017921587, 0.015296357, -0.00010306185 }, { 0.0079350203, -0.014772431, -1.2410913e-05, -0.0062296897 }, { 0.025087691, 0.00086046427, 0.015034685, -0.00078224706 }, { 0.00074587265, -0.014602074, 0.00027338224, -0.012848552 } }, { { 0.99345662, 1, 0.99989078, 0.99999994 }, { 0.99908598, 0.99987302, 0.99999623, 0.99932528 }, { 0.99897605, 0.99993456, 0.9998337, 0.99993145 }, { 0.99936351, 0.99984949, 1, 0.9992356 }, { 0.99965935, 0.9999836, 0.99981158, 0.99998352 }, { 0.99928963, 0.99982644, 0.99999992, 0.99917276 } }, { { 3.6882765, 0.15963861, 0.55983965, 0.4075649 }, { 2.1169304, 0.56463157, 0.52957047, 2.0117964 }, { 3.1080461, 0.09682931, 0.42125986, 0.089254784 }, { 1.4247315, 0.48411378, -0.17039102, 1.7431674 }, { 4.0339531, 0.14046159, 0.89848909, 0.011661811 }, { 1.9787852, 0.61750145, 0.63514194, 1.9359003 } }, { { 0.030848793, 1.4472743, 1.4356825, 1.4078009 }, { 0.37639678, 1.0793106, 1.1945413, 0.43983395 }, { 0.27451605, 1.5256415, 1.016769, 1.4850575 }, { 0.54580883, 1.1332879, 3.1331784, 0.60772955 }, { 0.11785158, 1.3928946, 0.94998805, 1.0377182 }, { 0.2842108, 1.0026911, 1.9064553, 0.27147854 } } }, { { { -0.096789259, 0.10326967, 0.0011799959, -0.03077328 }, { 0.08342021, 0.033260738, -0.00045864451, -0.021450568 }, { -0.093369441, -0.05807574, -0.033745214, 0.023817208 }, { 0.056747754, 0.031140512, 0.00019362509, -0.023727797 }, { -0.084538386, -0.040545412, -0.0076838784, 0.03424599 }, { 0.074312056, 0.027619787, 0.0015509082, -0.031043528 } }, { { -0.0085160473, -0.012179292, 0.0049910118, 0.020224799 }, { 0.022559343, -0.016273333, -0.0069382139, 0.00058083224 }, { -0.001115062, 0.035002846, -0.0038974773, -0.039378629 }, { 0.0014921617, -0.00058523872, -0.0011606685, 0.02807528 }, { -0.021454809, 0.052957852, -0.0022083677, -0.027956663 }, { -0.016486487, -0.0040233682, 0.00029949558, 0.021924605 } }, { { 0.99526846, 0.99457883, 0.99998685, 0.99932175 }, { 0.99625908, 0.99931422, 0.99997583, 0.99976974 }, { 0.99563091, 0.99769836, 0.99942287, 0.99894047 }, { 0.99838743, 0.99951485, 0.99999931, 0.99932416 }, { 0.99618922, 0.99777329, 0.99996804, 0.99902234 }, { 0.99709875, 0.9996104, 0.99999875, 0.99927754 } }, { { 3.0342011, 4.8022834, 1.3814123, 1.5280754 }, { 2.9043837, 1.7325954, 1.422223, 2.0569263 }, { 3.0358722, 5.3331504, 1.5680146, 1.6079289 }, { 3.2062833, 1.5368069, 1.0484709, 1.5399477 }, { 2.4471653, 4.0916696, 1.5060688, 1.5807009 }, { 2.6932695, 1.5161537, 1.3991175, 1.6301918 } }, { { 0.50787578, 0.17735471, 1.4006765, 1.0878482 }, { 0.69514518, 1.6765187, 1.2224869, 1.3461327 }, { 0.71381288, 0.17509216, 1.2712934, 0.94575821 }, { 1.1817337, 1.796984, 1.8671538, 1.5708691 }, { 0.55621228, 0.38291359, 1.4128781, 0.82625349 }, { 0.72441647, 1.005794, 1.5522327, 1.6032524 } } }, { { { -0.00041301094, -0.095882618, 0.26932618, -0.25137214 }, { 0.13737415, -0.12694293, -0.0090389663, 0.07227623 }, { -0.005236407, -0.0072961249, 0.27776083, -0.19536433 }, { 0.12781899, -0.042881667, -0.095979169, 0.088937396 }, { 0.037496084, -0.090547583, 0.22112334, -0.21930294 }, { 0.13353408, -0.084346121, -0.011365728, 0.043459312 } }, { { -0.05799135, -0.048612281, 0.02422989, 0.015536268 }, { -0.083144241, 0.039381032, 0.018705957, 0.029297922 }, { 0.026364989, -0.041927591, 0.036718516, 0.0050376168 }, { -0.11562256, 0.043521976, -0.014481644, 0.01529188 }, { -0.047859898, -0.057779647, -0.053171395, -0.0063193506 }, { -0.028781196, 0.041145059, -0.00018523142, 0.053524246 } }, { { 0.998317, 0.99420489, 0.96274416, 0.96776581 }, { 0.98702349, 0.99112796, 0.99978417, 0.99695425 }, { 0.99963867, 0.99909401, 0.95994827, 0.9807178 }, { 0.98503489, 0.99813175, 0.99527799, 0.99591983 }, { 0.99815003, 0.99421459, 0.97379529, 0.97563635 }, { 0.99062621, 0.99558667, 0.99993539, 0.99762039 } }, { { 2.3221943, 2.5383575, 4.3177232, 4.2016467 }, { 3.1936529, 3.0443024, 2.548962, 2.7636456 }, { 2.5923827, 2.3497949, 4.2471014, 4.1975975 }, { 3.3748785, 3.2836577, 2.9220414, 2.7175317 }, { 2.3290083, 2.5560991, 4.3572168, 4.4372585 }, { 3.1512055, 3.2863613, 2.4475378, 2.3620003 } }, { { 0.62833231, 0.52378061, 0.55845033, 0.64883444 }, { 0.76905594, 1.1017801, 1.8714048, 1.5664383 }, { 1.5283278, 1.2423369, 0.62247385, 1.0341956 }, { 0.77484548, 1.6866409, 1.0307399, 1.4224643 }, { 0.85627405, 0.72516079, 0.70094339, 0.7547877 }, { 1.202842, 1.7650605, 1.5938526, 0.97031337 } } }, { { { -0.078108035, -0.049518839, 0.26950139, -0.51522828 }, { 0.43015518, -0.045354216, 0.094550359, -0.2395012 }, { -0.079900522, -0.082582235, 0.24464909, -0.5234896 }, { 0.38422945, -0.023833644, 0.07334288, -0.22827313 }, { -0.075370379, -0.05156594, 0.19883182, -0.45064193 }, { 0.46285395, 0.021899343, 0.10155287, -0.25974773 } }, { { 0.068681419, -0.32175988, 0.15143274, -0.0066205388 }, { -0.17060226, 0.31051319, -0.080511981, -0.1593209 }, { 0.08167251, -0.32517768, 0.10937023, -0.06941926 }, { -0.14580685, 0.32474959, -0.081718057, -0.11068378 }, { 0.053961394, -0.29322836, 0.10408839, -0.02243046 }, { -0.030598471, 0.34332821, -0.091528353, -0.16299796 } }, { { 0.99457629, 0.9455255, 0.95101899, 0.85702741 }, { 0.88648824, 0.94948647, 0.99225906, 0.95773484 }, { 0.99345131, 0.94204015, 0.96342357, 0.84919939 }, { 0.9116513, 0.94549969, 0.99395321, 0.96728511 }, { 0.99569447, 0.95465076, 0.97449039, 0.89242295 }, { 0.88590629, 0.93896015, 0.99061071, 0.95182077 } }, { { 3.6380949, 4.1749529, 4.1351439, 4.8389883 }, { 5.256362, 4.2027959, 3.6096892, 3.9848645 }, { 3.5689427, 3.8620869, 4.0023981, 4.8268584 }, { 5.1128497, 4.468934, 3.5851596, 4.047485 }, { 3.7014988, 4.1310058, 4.2446872, 5.3049323 }, { 4.8659881, 4.3133002, 3.4582876, 3.8863853 } }, { { 1.6276316, 0.7747672, 1.0485958, 0.73900224 }, { 0.72010795, 0.65403093, 1.3179681, 0.65610074 }, { 1.5881174, 0.55108527, 1.0509725, 0.72153362 }, { 1.1389053, 1.0905142, 1.6661598, 0.9987548 }, { 1.977914, 0.83001686, 1.0571479, 0.80249183 }, { 0.94107069, 0.80840873, 0.95379751, 0.50386367 } } }, { { { 0.015525428, -0.48038019, -0.021799698, 0.43629156 }, { 0.045681247, -0.55039024, -0.54573329, 0.57817853 }, { -0.045869129, -0.42209953, -0.14040829, 0.37787106 }, { 0.66327604, -0.70070311, -0.55261635, 0.63446196 }, { 0.015397585, -0.43515767, -0.021927897, 0.4203714 }, { 0.85681772, -0.65394729, -0.67557236, 0.60104142 } }, { { -0.31503888, -0.26745648, 0.26817896, 0.26548747 }, { -0.93282124, -0.033621213, 0.68374802, -0.10858524 }, { -0.21723689, -0.17935495, 0.38521982, 0.2578335 }, { -0.39913153, 0.23555359, 0.59589456, -0.19075103 }, { -0.28851798, -0.24142459, 0.28279261, 0.24766617 }, { -0.29435977, -0.25850549, 0.57790878, -0.200546 } }, { { 0.94895177, 0.83528552, 0.96312243, 0.85974768 }, { 0.35743218, 0.8342303, 0.48442112, 0.80865248 }, { 0.97504059, 0.88863029, 0.9120807, 0.88923301 }, { 0.63305523, 0.67344611, 0.58268761, 0.74904744 }, { 0.95735066, 0.86738225, 0.9589304, 0.87289711 }, { 0.42333878, 0.71100482, 0.45784651, 0.77364753 } }, { { 5.3641275, 5.2550422, 5.3103777, 5.2851215 }, { 5.2657045, 6.2095784, 6.9549598, 4.9205516 }, { 5.163385, 5.3141038, 4.9907618, 5.3583852 }, { 6.1257061, 6.1102338, 6.9549598, 5.3129951 }, { 5.3138838, 5.3257842, 5.3133783, 5.2687156 }, { 5.8915091, 6.153324, 6.9549598, 4.9568971 } }, { { 3.1221918, 1.1882615, 2.6991784, 1.1185048 }, { -0.2322432, -0.16590163, 0.088416958, 0.057399579 }, { 3.4395383, 1.5836276, 2.6242352, 1.2873336 }, { -0.23767634, -0.79425452, 0.20477899, 0.40461516 }, { 2.2521751, 1.1933374, 2.3309484, 1.0185309 }, { -0.099258385, -0.2173726, 0.0736866, 0.15470436 } } }, { { { 0.066050217, -0.33053278, -0.13771479, 0.33278465 }, { 0.00084467977, -0.50077778, -0.30083482, 0.6494273 }, { 0.24880159, -0.30354993, -0.15417892, 0.38203296 }, { -0.073325098, -0.4778777, 0.10779844, 0.66683723 }, { 0.15703809, -0.36335455, -0.15657631, 0.35926503 }, { 0.26127617, -0.29524368, -0.14490804, 0.65461301 } }, { { -0.57970022, -0.33939622, 0.72169742, 0.320959 }, { -0.38698206, -0.12730306, 0.65810895, 0.026509232 }, { -0.6199708, -0.34745658, 0.68683659, 0.34547285 }, { -0.3613378, -0.14006845, 0.65917895, 0.038446867 }, { -0.57778101, -0.35057776, 0.57837882, 0.36488991 }, { -0.50051482, -0.019174387, 0.50816239, 0.02682636 } }, { { 0.8121484, 0.88065787, 0.67837119, 0.88670158 }, { 0.92208686, 0.85616327, 0.69021085, -0.75996148 }, { 0.74413303, 0.88720424, 0.71027063, 0.85714604 }, { 0.92954743, 0.86718726, 0.74421946, -0.74421095 }, { 0.80094204, 0.86317363, 0.8006009, 0.85894353 }, { 0.82536033, 0.95522956, 0.8489833, -0.75548802 } }, { { 5.7725061, 5.1565901, 5.6224483, 5.0847054 }, { 5.7717118, 6.4180057, 6.9797014, -0.03290957 }, { 5.7847117, 5.2015529, 5.614561, 5.2019388 }, { 6.2613999, 6.5807982, 6.9797014, -0.032764603 }, { 5.823775, 5.2332343, 5.826694, 5.197143 }, { 6.3463188, 5.8174311, 6.9797014, -0.032766769 } }, { { 2.96787, 1.3557735, 2.0749129, 1.3066609 }, { -0.92782801, 0.0079162579, -0.33479446, 2.699659e-05 }, { 2.1997063, 3.1083252, 2.6810949, 1.8276262 }, { -0.48654719, -0.10954189, -0.32175132, 5.490092e-05 }, { 3.1970446, 1.787085, 3.062849, 1.6274811 }, { -0.78882801, -0.34050184, -0.59962127, 3.6554198e-05 } } } }; + +const float high_quality_coeffs[7][5][3][24][4] = { { { { { -4.8355339e-06, -4.4902569e-05, -9.2632249e-05, -0.00053773136 }, { 0.0040143823, -0.00060900339, -0.0095301923, -0.0053956011 }, { -0.0005923892, -3.6901978e-05, -5.6694857e-06, -0.00017018564 }, { 0.0012441402, 0.02236187, 0.022751769, 0.0062788948 }, { 0.00013810055, -2.2709815e-05, 0.0054849671, -1.6599195e-05 }, { -0.020320408, -0.017066319, -0.017457746, 0.022910628 }, { 0.00024171724, 9.7419073e-05, -0.00047804272, -0.00010093683 }, { 7.6988167e-05, 1.8551597e-05, -5.7692813e-05, -3.332362e-05 }, { -0.00062766208, 2.713742e-05, 0.00026511682, 2.3841873e-05 }, { -0.00043656844, 0.0028645469, 0.0049817085, 0.0080221478 }, { -3.3210444e-05, -8.0852386e-05, -2.2111492e-06, -8.4430827e-05 }, { 0.010967284, 0.018811225, 0.017569463, -0.0046944996 }, { -0.00018391248, -0.00010462174, -0.00017726, -0.00018490133 }, { 0.00012591989, 0.015965386, 0.015964059, -0.0078018431 }, { -0.006125333, -8.2224165e-05, -0.00020500151, -0.00025207244 }, { -0.00016320041, -0.0001279242, 0.00014038799, 8.1359421e-05 }, { -0.00064341098, -0.0011265496, -0.0011634792, -0.00081607159 }, { 0.00089294825, 0.0061923653, 0.0052662392, -0.00058227469 }, { -2.4001308e-05, -1.3534224e-05, -1.4720478e-05, -2.5120827e-05 }, { 0.00029964918, -0.0045658543, -0.0045581938, 0.0017106208 }, { 7.5790173e-05, -1.8265415e-05, 1.5918205e-05, 5.8524021e-05 }, { 0.0011669872, -0.00017571882, -0.00017190275, -0.0023833977 }, { 0.0033487264, -0.0066535821, -0.0066413786, -0.0032332601 }, { -3.6468807e-05, -0.00068145131, -9.8190714e-05, -8.7169435e-05 } }, { { -0.0010440653, -8.9750644e-05, 4.971182e-05, 0.0044618878 }, { 0.0078333883, -0.00090884312, -0.00046920549, -0.002465051 }, { -0.0058778609, 0.0026554895, -0.00031880506, -0.00010649091 }, { -0.0015095448, 0.0094026506, 0.009492703, 0.0024572848 }, { 0.0047331786, 0.00070722401, 0.0028798817, -0.00039779892 }, { -0.0089878107, -0.0095474878, -0.0097187652, 0.008765907 }, { -4.0435321e-05, -0.00061813281, -0.0060490143, 0.0016259965 }, { -0.00014720558, -1.0601876e-05, 0.00014757138, 0.00016227641 }, { -0.010428289, -0.00031812813, -0.0016172213, -0.00012022134 }, { 0.0040517131, 0.0072972763, 0.0060433905, 0.0025041645 }, { 0.00014090924, 0.00027612853, 0.00015961665, 0.0002605418 }, { -0.00020653783, -0.00048482867, -0.00058472338, 0.00026413759 }, { 0.00056712638, 0.00026385353, 0.00035484947, 0.00033212447 }, { -0.00094663094, 0.0029891757, 0.0029887838, -0.0026583585 }, { -0.0017400246, 0.00042350567, 0.00086128207, 0.00039863587 }, { 0.00059604848, 0.00027495434, -0.00059956434, -4.4981673e-05 }, { -0.010211343, -0.0080580409, -0.0085333216, 0.0023258717 }, { 0.00042832593, 0.0056750222, 0.0048059635, -0.0092168281 }, { 3.0214612e-05, 4.540924e-06, 1.7239937e-05, 2.783598e-05 }, { 0.00029393335, -4.5128636e-05, -4.3089017e-05, 0.00030682556 }, { -4.7077735e-05, -1.3596835e-05, -0.0015338149, -7.4957991e-05 }, { -0.00097136844, 0.00018564298, 0.00021815754, 0.0015095577 }, { 0.00043929849, -0.0014691094, -0.0014671742, -0.00029365954 }, { 8.8554045e-05, 0.0062500772, 0.0001495049, 0.00021007601 } }, { { 0.0020307077, 0.0020947445, 0.0017438295, 0.0084822342 }, { -0.0069727503, -0.0010131005, 0.0055261321, -0.0020442588 }, { 0.00031035611, 0.00010839441, 3.7359209e-06, 4.3112837e-05 }, { 9.1207794e-05, 0.0050148169, 0.0051071455, 0.0033679057 }, { -0.00090101737, -0.00053793176, -0.0025829621, 0.0003241927 }, { -0.0019244714, -0.0033690472, -0.0035193497, 0.0027653636 }, { -0.00065476293, -0.00017787403, 0.00040383136, -0.00018123957 }, { -0.00030640434, -0.00018961553, -0.00011036218, -0.00015793049 }, { 0.001110592, -0.00021252645, 0.00015849587, -3.7758317e-05 }, { 0.00077967828, -0.0051765235, -0.0078505592, -0.010796339 }, { -1.2024951e-05, 6.48806e-05, -3.9409005e-05, 7.4639306e-05 }, { -0.00017352424, -0.00037802595, -0.00045639468, 0.00016843169 }, { -4.2866244e-05, -4.3730932e-06, 7.3574276e-05, 5.6076779e-05 }, { 0.00024802387, 0.0018053101, 0.0018042994, -0.0016700716 }, { 0.0082698262, -0.00014605077, 0.0004377682, 8.1585074e-05 }, { -4.494343e-06, 0.00019781519, -0.00058910268, -0.00027360572 }, { 0.0013016934, 0.0021020456, 0.0022718598, -0.0059377824 }, { 0.002185371, -0.0080788056, -0.0071952836, 0.0039688918 }, { 0.00013048617, 0.0001738124, 0.00012978924, 0.00013813358 }, { 0.00032386518, 0.00023046021, 0.00023064714, 0.00033762343 }, { 0.00023643771, 0.00019652953, 0.0013083597, 0.00024739959 }, { -0.0063957036, -0.0055319023, -0.0054742301, -0.0037204932 }, { -0.0005510683, -0.0007715413, -0.00077385934, -0.001009415 }, { 0.00017904616, -0.00096137522, 0.00030252599, -2.2478138e-05 } } }, { { { -0.00038948583, -0.00040817153, -0.00041280315, -0.0010985631 }, { 0.0025695337, 0.00042904308, 0.0054649973, -0.0055079106 }, { 0.00052050672, 2.2618679e-05, 0.00024058975, -0.00012632201 }, { -0.013468886, 0.0079396715, 0.0079402246, 0.026283756 }, { -7.922122e-05, -3.4761763e-06, -0.0041716347, 0.0001478739 }, { 0.023716381, -0.016415262, -0.015296927, -0.021050827 }, { 3.7654391e-05, 0.00012765816, -0.0001337099, 0.00051483398 }, { 0.00015671907, 0.00010686796, 2.1421097e-05, -2.2281569e-05 }, { 3.1779413e-06, 0.00010449913, -0.00018303614, 7.5382489e-05 }, { -0.00020526765, -0.0011333575, -0.0050720108, 0.0051482782 }, { 4.0450357e-05, 1.0808158e-05, -2.3316095e-05, 9.7767333e-06 }, { -0.019107229, 0.010907324, 0.0048969594, 0.017851514 }, { 7.4048796e-05, -7.041835e-06, 8.0226174e-05, 5.1714105e-05 }, { -0.016564627, 0.0023486944, 0.0023601429, 0.016005248 }, { -0.004528284, 3.6291049e-05, 2.4229636e-05, 0.0024853948 }, { 5.6882054e-05, 6.8805135e-05, 0.00013119897, 0.00010339801 }, { 0.00021183341, 0.0008203137, -7.204401e-05, 0.00062599728 }, { -0.00099314707, 0.0030198762, -0.0038989955, 0.00055571214 }, { -7.4247984e-05, -8.3993373e-05, -5.9133252e-05, -7.7411989e-05 }, { 0.0054296732, -0.00057858871, -0.00058417754, -0.005072911 }, { -0.00019259782, -0.00018772532, -4.2959783e-05, -0.0001827295 }, { -0.00029351865, 0.00013736372, 0.00016666048, 0.00020873447 }, { 0.0069341659, 0.0027612928, 0.0027538377, -0.0061770317 }, { 4.2584714e-05, -0.00037063589, -9.0693123e-06, 0.00011845784 } }, { { 0.0028834168, 0.0031807308, 0.0031352582, 0.01064051 }, { 0.0049297987, -4.2149356e-05, -0.0014926841, -0.0002300371 }, { 0.0020396303, -0.00066042794, -6.4359283e-05, 0.00017835163 }, { -0.0025767816, 0.0025148152, 0.0025224779, 0.0043006543 }, { -0.00042084416, -0.00013534305, 0.002453623, -4.0707749e-05 }, { -0.0001803055, -0.0010450606, -0.00084380806, 0.00014843677 }, { -0.0064067107, 0.00011012652, -0.0022552747, -0.00080508294 }, { -0.00017778763, -4.296789e-05, 0.00015343883, 0.00025036711 }, { 0.002825978, -0.00031945362, -0.00031987612, -0.00021117763 }, { 0.00032791249, -0.00049524542, 0.0049368722, -0.0017186408 }, { -0.0001685943, -0.00016766033, -0.0001755097, -0.00017067307 }, { 0.00023939157, -0.00011793706, -6.0620575e-05, -0.0002706595 }, { -2.9718673e-05, 3.5950879e-05, 1.839844e-05, -2.8718148e-05 }, { -0.0017260981, 0.00012145435, 0.0001236679, 0.0018292155 }, { 0.0036086706, 0.0001026898, -2.5518889e-05, -0.00019830236 }, { -0.00031546808, -0.00042107458, -0.00059963868, -0.00061472497 }, { -0.0074719522, 0.0015719596, -0.0033624165, -0.0092664101 }, { -0.0011285776, 0.0018601435, 0.00052060704, -1.5554679e-05 }, { 4.9853171e-05, 7.3650922e-05, 3.4080107e-05, 5.4255445e-05 }, { 0.00015102779, -2.58105e-05, -2.5851018e-05, -4.5185316e-05 }, { 0.0002057452, 0.00019037765, 0.0040052198, 0.00020046579 }, { 0.0027727314, 0.0040749211, 0.0036050794, 0.0034635222 }, { 0.00042503689, 0.00056027382, 0.00056052971, -8.2485044e-05 }, { -5.6309634e-05, 0.0019722025, 6.4267434e-05, -0.00020376412 } }, { { 0.0051607661, 0.0047835358, 0.0047658352, 0.0054281814 }, { -0.0040939561, 0.0012119183, -0.0023408179, -0.00055891234 }, { -0.0031939804, -0.0015954053, -0.00018570689, 0.00028849431 }, { -0.0075625096, 0.0033878734, 0.0033797415, 0.010242674 }, { -0.002293562, 0.00024245282, 0.0019455622, 0.0039550747 }, { 0.0090386754, -0.0086947671, -0.0082684939, -0.0075613346 }, { -0.00085735117, 3.4822634e-05, -0.0024653972, -0.00090964985 }, { -0.00013750587, -0.00010089501, 6.3555498e-05, 0.0002758494 }, { 0.0060496328, -0.00032664426, 0.0005979723, -0.00018819024 }, { 0.00072724184, 0.00082242885, 0.0045668772, -0.0054557456 }, { -9.6167811e-05, 7.9856612e-05, 0.00015672473, 8.0901183e-05 }, { 0.00038859448, -0.00025360755, -0.00017624981, -0.00049125519 }, { -8.8277361e-05, 2.4159527e-05, -0.00016014627, -2.7854246e-05 }, { -0.0037308647, 0.00041434141, 0.0004167221, 0.0037190244 }, { 0.00050696744, -4.6752715e-05, 0.00033183668, -0.0025882828 }, { -0.00015915702, -0.0002325901, -0.00036157415, -0.00016391937 }, { 0.00012320153, 0.0026711886, 0.0018414591, -0.0058215223 }, { -0.0029409983, -0.00015460743, 0.0031951665, 0.0074654329 }, { 9.9084813e-05, 9.1785865e-05, 5.9300007e-05, 0.00010463304 }, { 0.00024773341, -2.5723276e-05, -2.5709769e-05, -0.00015357475 }, { 0.000416633, 0.00028749584, -0.0038632071, 0.00039869488 }, { 0.00018344152, 3.0811778e-05, -0.00010240082, 0.00059301197 }, { 0.0019217461, 0.00034404024, 0.00034318823, -0.0015867375 }, { -0.00011928879, 0.001178769, -5.8655983e-05, -0.00028461439 } } }, { { { 0.99999992, 0.99999992, 0.99999991, 0.99999925 }, { 0.99998864, 0.99999972, 0.99993965, 0.99997027 }, { 0.99999969, 1, 0.99999997, 0.99999998 }, { 0.99990852, 0.99971841, 0.99970961, 0.9996348 }, { 0.99999999, 1, 0.99997626, 0.99999999 }, { 0.99951219, 0.9997196, 0.99973058, 0.99951587 }, { 0.99999997, 0.99999999, 0.99999988, 0.99999986 }, { 0.99999998, 0.99999999, 1, 1 }, { 0.9999998, 0.99999999, 0.99999995, 1 }, { 0.99999988, 0.99999525, 0.99997473, 0.99995457 }, { 1, 1, 1, 1 }, { 0.99975729, 0.99976356, 0.99983365, 0.99982963 }, { 0.99999998, 0.99999999, 0.99999998, 0.99999998 }, { 0.99986279, 0.99986979, 0.99986978, 0.99984147 }, { 0.99997099, 1, 0.99999998, 0.99999688 }, { 0.99999999, 0.99999999, 0.99999998, 0.99999999 }, { 0.99999977, 0.99999903, 0.99999932, 0.99999947 }, { 0.99999911, 0.99997627, 0.99997853, 0.99999968 }, { 1, 1, 1, 1 }, { 0.99998521, 0.99998941, 0.99998944, 0.99998567 }, { 0.99999998, 0.99999998, 1, 0.99999998 }, { 0.99999928, 0.99999998, 0.99999997, 0.99999714 }, { 0.99997035, 0.99997405, 0.99997415, 0.99997569 }, { 1, 0.9999997, 1, 0.99999999 } }, { { 0.00015966941, 0.00014262676, 0.00020165066, 0.00021618914 }, { 2.8140907e-06, -0.00020325872, 0.00017736728, 6.0386679e-05 }, { -0.0003187876, 5.8862288e-05, 6.2281085e-05, 1.7339908e-05 }, { -2.6587911e-05, -0.00011609007, -0.00011725093, -7.6114852e-05 }, { 0.00013665042, 5.2703844e-06, -0.00031293536, 3.8693931e-05 }, { -9.8143069e-05, -0.00012816332, -0.00012926252, -0.00010623032 }, { 0.00032342312, -1.9200091e-06, -0.00010691485, 6.3541059e-05 }, { -8.0643542e-06, 9.7622933e-06, 2.9924822e-05, -1.988333e-05 }, { 0.00025318464, 1.2588649e-05, 1.4665927e-05, 9.3294806e-06 }, { 2.6875391e-06, -2.4928123e-05, 2.251878e-05, 0.00011026808 }, { 1.767638e-05, 1.0309044e-05, 2.4765648e-05, 1.4397941e-05 }, { 6.9000935e-06, 1.0637078e-05, 1.087637e-05, 6.3065784e-06 }, { 5.532953e-05, 1.6231463e-05, 4.9564371e-05, 3.6623041e-05 }, { -1.6958729e-05, -3.1627491e-05, -3.1524511e-05, -2.9954116e-05 }, { 8.9045086e-05, 2.1005026e-05, 1.3016463e-05, 8.7863053e-05 }, { -2.75035e-05, -3.0440427e-05, -3.5356286e-05, 5.9609261e-06 }, { 0.0001586274, 4.0711165e-05, 3.1563135e-05, 0.0001385483 }, { 8.5548316e-06, 7.4531928e-05, -3.7017413e-05, 2.6874037e-05 }, { -1.3750655e-05, -8.2756032e-06, -2.7214983e-07, -1.4830115e-05 }, { -7.0798362e-07, -3.3187173e-07, -3.3266762e-07, -5.7113855e-07 }, { 4.3615512e-05, -4.4076433e-06, 8.9239586e-06, 3.7278531e-05 }, { -7.7366773e-06, 4.610399e-06, 4.3762687e-06, -5.64067e-06 }, { -3.2666125e-06, -1.0773146e-05, -1.0861965e-05, -1.3327232e-06 }, { -9.1178305e-06, 0.00030171207, -1.5395234e-05, -2.0695425e-07 } }, { { 0.00017159464, 0.00014699558, 0.00018752678, 0.0002227926 }, { -4.6524822e-05, -0.00010460271, 0.00034735325, 0.00010082238 }, { -6.8269006e-05, 1.4343751e-05, 7.7283393e-06, 2.5347136e-05 }, { -6.6149546e-05, -7.1168993e-05, -7.0621016e-05, -0.00015246746 }, { 7.12022e-05, 3.8790461e-05, -0.00023994449, 6.6792921e-05 }, { -0.00014735813, -0.00012658353, -0.00012162488, -0.00012106777 }, { 0.00015161388, -1.4439153e-05, -3.7629923e-06, 8.3140788e-06 }, { 4.0175416e-05, 2.5380268e-05, -2.2894421e-06, 4.6374378e-06 }, { 0.00028906023, 1.7695243e-05, 5.3790587e-06, 1.631859e-05 }, { 1.8890685e-05, -1.6898275e-05, 2.1007663e-05, 6.5179363e-05 }, { -3.9142595e-06, 2.5745488e-05, 1.0803197e-05, 2.7099749e-05 }, { 9.4245546e-06, 1.0010075e-05, 9.058324e-06, 9.8703427e-06 }, { -2.3441863e-06, 2.5490323e-05, -1.0097654e-05, 4.0554798e-05 }, { -4.1443921e-05, -1.996316e-05, -2.0000841e-05, -4.7495655e-05 }, { 0.00012591695, 5.6179903e-05, -1.8415869e-05, -3.8697972e-05 }, { 2.6719505e-05, 2.4195362e-06, 2.4287424e-05, 3.4703059e-05 }, { 7.3804931e-05, 4.9784871e-05, 3.1159931e-06, 0.00015857197 }, { -0.00010634331, -1.6427658e-05, -7.4874306e-05, -6.2620255e-05 }, { -4.2561214e-06, -1.6123179e-05, -1.5507273e-05, -1.2909924e-05 }, { -1.2210463e-06, 1.1546399e-06, 1.1413892e-06, -1.3465856e-06 }, { 3.4909884e-05, -1.2677793e-05, 0.00011543701, 2.413091e-05 }, { -2.1953323e-05, -4.6244252e-06, -3.5624435e-06, 4.2293671e-06 }, { -1.1392936e-05, -4.3970369e-06, -4.4264864e-06, -1.208518e-05 }, { -4.4002617e-05, 0.00020912348, -3.9617824e-05, -4.1725112e-05 } } }, { { { -0.32504349, -0.32502096, -0.32501094, -0.32423576 }, { -0.65602876, -0.65622598, -0.65567173, -0.65525128 }, { -1.4666488, -1.4666488, -1.4666488, -1.4666488 }, { 0.87168363, 0.87181364, 0.87181792, 0.8718169 }, { -1.264365, -1.264365, -1.264365, -1.264365 }, { 0.89917968, 0.89916889, 0.89916525, 0.89927374 }, { -1.2245906, -1.2245906, -1.2245906, -1.2245906 }, { -0.8885678, -0.88856217, -0.88856327, -0.88855044 }, { -0.31799095, -0.31916566, -0.31907669, -0.31918911 }, { -0.08987958, -0.090342401, -0.090004674, -0.090222398 }, { -0.59425693, -0.59433999, -0.59429118, -0.59433553 }, { 1.1317575, 1.1317475, 1.1317412, 1.1317494 }, { -1.2193493, -1.2193493, -1.2193493, -1.2193493 }, { 1.2506981, 1.250675, 1.250675, 1.2506569 }, { -1.08782, -1.0877793, -1.0878022, -1.0878025 }, { -0.13925598, -0.13932948, -0.13919658, -0.13913403 }, { -0.40394684, -0.4042314, -0.40436178, -0.40402218 }, { -0.47762966, -0.47745572, -0.47767784, -0.47713093 }, { -0.60177181, -0.60176862, -0.60177347, -0.60177079 }, { 2.7311956, 2.7311911, 2.7311911, 2.731191 }, { -1.3109856, -1.3109856, -1.3109856, -1.3109856 }, { 0.60942644, 0.60941369, 0.6094123, 0.60944198 }, { 0.55675448, 0.55672275, 0.55672303, 0.5567542 }, { -0.40637059, -0.4057945, -0.40635768, -0.40636681 } }, { { -0.0016154222, -0.0015930079, -0.0015828998, -0.00087447165 }, { -0.0011262472, -0.001324462, -0.00094895016, -0.00062188189 }, { 0, 0, 0, 0 }, { 9.7616744e-05, 0.00010718899, 0.00010718606, 0.00012665246 }, { 0, 0, 0, 0 }, { 0.00013476236, 6.982272e-05, 6.8208505e-05, 0.00014604742 }, { 0, 0, 0, 0 }, { -0.0031089951, -0.0031071196, -0.0031207245, -0.0031097054 }, { -0.0027808116, -0.0035049857, -0.0034100135, -0.0035192661 }, { -0.0018291474, -0.0019603285, -0.0018919656, -0.0019656229 }, { -0.0034301741, -0.0034912573, -0.0034474395, -0.0034893985 }, { -6.156701e-06, -9.8568527e-06, -1.2383692e-05, -9.9984205e-06 }, { 0, 0, 0, 0 }, { 0.00011838153, 0.00011008679, 0.00011008878, 0.00010536608 }, { -0.0006246638, -0.00058479459, -0.00061327452, -0.00061085433 }, { -0.0059197749, -0.0059778169, -0.0059586015, -0.0058798299 }, { -0.0013246996, -0.0016061786, -0.0016081246, -0.0014374546 }, { -0.001593227, -0.0014706843, -0.0015974008, -0.001341579 }, { -0.0027930604, -0.0027920013, -0.0027939865, -0.0027928528 }, { -1.8908723e-06, -4.266382e-06, -4.2210172e-06, -5.0155215e-06 }, { 0, 0, 0, 0 }, { 0.00018508026, 0.00019774537, 0.00019744661, 0.00019538593 }, { 2.3243747e-05, 1.7291398e-05, 1.7309712e-05, 2.9261396e-05 }, { -0.0041402471, -0.0037085946, -0.0041294876, -0.0041316136 } }, { { -0.0018899732, -0.0018719182, -0.0018661076, -0.0012234594 }, { -0.0012968123, -0.0012971446, -0.00093522854, -0.00066475268 }, { 0, 0, 0, 0 }, { 9.1054464e-05, 0.00014124217, 0.00014156806, 0.00012014953 }, { 0, 0, 0, 0 }, { 0.00017026995, 0.00010528413, 0.00010537941, 0.00015698848 }, { 0, 0, 0, 0 }, { -0.0025812972, -0.0025835894, -0.0025789321, -0.002554949 }, { -0.0035568863, -0.0042988014, -0.0042155548, -0.004312546 }, { -0.0024184575, -0.0025111277, -0.0024654994, -0.0023980076 }, { -0.0036993386, -0.0037113013, -0.0036987284, -0.0037094875 }, { -5.074861e-06, -1.1367399e-05, -1.4819989e-05, -9.2705899e-06 }, { 0, 0, 0, 0 }, { 0.00012570403, 0.00012150272, 0.00012149179, 0.00010579599 }, { -0.00062162762, -0.00058131015, -0.00060837583, -0.00060795256 }, { -0.00775735, -0.0077198081, -0.0078365948, -0.0077749317 }, { -0.0015325554, -0.0017125784, -0.001703195, -0.0015662859 }, { -0.0018130784, -0.00177106, -0.001858095, -0.0015845058 }, { -0.003668417, -0.0036659688, -0.0036693421, -0.0036680526 }, { -9.5804016e-06, -9.6276607e-06, -9.630607e-06, -1.2159056e-05 }, { 0, 0, 0, 0 }, { 0.00017930618, 0.00020084683, 0.00020150104, 0.00020810787 }, { 2.3869269e-05, 1.1024793e-05, 1.1041937e-05, 1.6467357e-05 }, { -0.004690782, -0.0044656761, -0.0046782065, -0.0046921455 } } }, { { { 0.23047932, 0.23043226, 0.23041471, 0.22922185 }, { 0.14990977, 0.15703656, 0.15110771, 0.15149153 }, { 0.30629171, 0.30426701, 0.30400037, 0.30403889 }, { 0.03476576, 0.036188528, 0.036216719, 0.037322097 }, { 0.31066251, 0.31090363, 0.31041565, 0.31057779 }, { 0.04875259, 0.046468595, 0.046486323, 0.046584523 }, { 0.31745458, 0.31874472, 0.32086369, 0.31880207 }, { 0.64054942, 0.64062862, 0.64051973, 0.64059059 }, { 0.27309038, 0.27480819, 0.27477284, 0.27486762 }, { 0.196647, 0.19687982, 0.19607604, 0.1957915 }, { 0.32867362, 0.32858008, 0.32856702, 0.328555 }, { -0.0026873031, -0.0042393446, -0.0057894907, -0.0041858859 }, { 0.40254624, 0.4024247, 0.4025598, 0.40243731 }, { 0.019362807, 0.018146218, 0.018146051, 0.019656613 }, { 0.29328089, 0.29403937, 0.29435036, 0.29403094 }, { 0.57111506, 0.57118505, 0.57099608, 0.57099266 }, { 0.16966612, 0.16993739, 0.17069399, 0.16991136 }, { 0.14989055, 0.1489484, 0.14995985, 0.15015916 }, { 0.33606014, 0.33606294, 0.33606393, 0.33605429 }, { 0.015421206, 0.015180692, 0.01518037, 0.015431139 }, { 0.33165237, 0.33185282, 0.33162592, 0.33166981 }, { 0.078137018, 0.078153855, 0.078165152, 0.078332343 }, { 0.002896946, 0.0026038621, 0.0026029604, 0.0022081151 }, { 0.41064398, 0.40987685, 0.41065341, 0.41059166 } }, { { -0.0024316111, -0.0024732789, -0.0024922144, -0.0035874346 }, { 0.0013306961, 0.004171802, 0.0027660627, 0.0023671465 }, { 0.0034411091, 0.0020878413, 0.0020874456, 0.0022028237 }, { -0.0032873976, -0.0021351911, -0.0021071363, -0.0028424534 }, { 0.0017995208, 0.0022319618, 0.0039270256, 0.0021249365 }, { -0.0019590835, -0.0012526895, -0.0012347747, -0.0021069943 }, { 0.0012319531, 0.002255621, 0.0030193583, 0.0020970822 }, { 0.0015144077, 0.0015110104, 0.0014803089, 0.0015340007 }, { -0.0036679996, -0.0028160114, -0.0028586497, -0.0027953731 }, { -0.005445786, -0.0052624873, -0.0054843188, -0.0053271749 }, { 0.00067154572, 0.0007530775, 0.00067974516, 0.00074462315 }, { -0.0035626119, -0.0034186877, -0.0038720517, -0.0040088745 }, { 0.003455851, 0.0035040061, 0.0034671486, 0.0035069881 }, { -0.0047789747, -0.0047994804, -0.0047996451, -0.0044008337 }, { 0.0032403482, 0.0033627856, 0.003429619, 0.0031153117 }, { -0.005027022, -0.0049812, -0.0049604573, -0.0050556194 }, { -0.0020728991, -0.0014784158, -0.001216894, -0.0019213729 }, { -0.00013808007, -0.00067270623, -0.00024001574, -0.00030691077 }, { 0.0004367104, 0.00043390709, 0.00043548166, 0.00043425516 }, { -0.00082746467, -0.00088151411, -0.00088152334, -0.0008043643 }, { 0.0030277712, 0.003133577, 0.0028529862, 0.0030362271 }, { -0.0058721937, -0.0059816331, -0.0059799345, -0.0058882832 }, { -0.0057032562, -0.0057401855, -0.0057416619, -0.0062417688 }, { -0.0014357888, -0.0020782049, -0.0014346823, -0.0014513767 } }, { { -0.0027051235, -0.0027087245, -0.0027052303, -0.0033594951 }, { 0.0028036195, 0.0030416572, 0.0014306948, 0.0017897371 }, { 0.0031113166, 0.0026432303, 0.0025937824, 0.0025394463 }, { -0.0036032904, -0.003447065, -0.0034344406, -0.0024163572 }, { 0.0023912799, 0.0025281229, 0.0038665087, 0.0024214034 }, { -0.0023543827, -0.0024294943, -0.0024539784, -0.0027742617 }, { 0.0020903896, 0.0026617586, 0.003395249, 0.0026261065 }, { 0.0019031008, 0.0019405475, 0.0019426085, 0.0019404325 }, { -0.0040413326, -0.0030964835, -0.0031020735, -0.0030826754 }, { -0.0064568993, -0.0062342438, -0.0064704698, -0.0065636744 }, { 0.0010788406, 0.0010092051, 0.0010264121, 0.00099891228 }, { -0.0040759201, -0.0059224283, -0.0066809927, -0.0049099348 }, { 0.0042962009, 0.0041909175, 0.0043195236, 0.0041900138 }, { -0.0062728983, -0.0070256154, -0.007025641, -0.0061758746 }, { 0.0036210401, 0.0039723998, 0.0042232048, 0.0042757707 }, { -0.0058693852, -0.0058583303, -0.0058544016, -0.005887725 }, { -0.0023099876, -0.0021136245, -0.0017298078, -0.0022483337 }, { -0.00017851962, -0.00014956209, 8.5676316e-05, -0.00024971669 }, { 0.0003734781, 0.00037078986, 0.00037364181, 0.00037070594 }, { -0.00030648905, -0.00038230535, -0.00038223043, -0.00028623253 }, { 0.0032871423, 0.0034163052, 0.0028276655, 0.0032991918 }, { -0.0061331695, -0.0063319797, -0.0063340119, -0.0064390374 }, { -0.0062172888, -0.0059787106, -0.0059793294, -0.0060406701 }, { -0.0018276142, -0.0022170788, -0.0018293949, -0.0018222824 } } } }, { { { { 0.13218089, -0.11654637, -0.11622196, -0.044208736 }, { 0.0074579257, 0.0038503609, 0.0013201096, 4.0415784e-05 }, { -0.025474487, -0.01209255, -0.016535858, 0.012704547 }, { -0.0016894103, -0.0081312144, -0.0033264609, 0.0011923269 }, { -0.068044876, 0.018276873, -0.074833897, 0.01308348 }, { 0.02665691, 0.013515118, 0.026440814, -0.0077037816 }, { 0.0023286096, -0.0025782652, 0.0021644694, -0.0042955294 }, { 0.051356261, -0.031058382, -0.085382962, -0.033103269 }, { -0.081609229, 0.0035270199, -0.015722417, 0.048773789 }, { 0.0023928418, -0.001243811, 0.011910492, -0.011621478 }, { -0.028953904, -0.029335777, -0.0057891432, 0.013874136 }, { -0.012473582, 0.001772629, -0.013983442, 0.014846792 }, { -0.016111661, 0.0018902323, 0.025910586, 0.042848276 }, { 0.026200626, 0.024007879, 0.0017667146, -0.016394032 }, { -0.0067006429, -0.0017968936, 0.009028659, 0.0044060413 }, { 0.019280611, 0.0449581, -0.042852227, -0.066012332 }, { -0.014451123, -0.047772741, -0.047475406, 0.098434178 }, { -0.0028954635, 0.010521833, -0.015741597, -0.00091666191 }, { 0.0020291956, -0.057966746, -0.04525094, 0.032711614 }, { 0.020563445, -0.0078684621, -0.015282237, -0.0019830466 }, { -0.019504171, 0.071338511, 0.0033729474, -0.0095772339 }, { 0.013056103, 0.018719519, 0.0096002937, -0.028774366 }, { -0.00038728577, -0.0010662982, -0.0014333502, 0.00059135695 }, { 0.073844752, -0.05666013, -0.1007151, -0.030440738 } }, { { 0.00017766639, -9.2398532e-05, -3.9442682e-05, -3.9559848e-05 }, { -0.0043956477, 0.00044042277, -0.00047491077, 9.4171117e-05 }, { -0.0042095545, -0.00910753, -0.0014295282, 0.0042595844 }, { 0.00070989004, -0.0009623012, 0.00084162653, -0.00015925965 }, { -0.0017587638, 0.0033199811, -0.00025544613, 0.00083644978 }, { 0.0051797987, 0.0015691893, -0.002324397, 0.0050776381 }, { 0.003911779, 0.00072639703, 2.102924e-05, -0.0029529332 }, { 0.0050240476, -0.00041452319, 3.1730448e-06, -0.0072697591 }, { -1.5023048e-05, 0.00032491246, -9.2151952e-05, 0.0035851726 }, { 0.0030984373, 0.0016428856, 0.0032974124, -0.0036034289 }, { -0.00044578206, -0.0035916409, 0.0028146658, 0.0068013321 }, { 0.00025716711, -0.0024772152, 0.0029660992, -0.0008783244 }, { -0.005543602, -0.00046453249, 0.006815884, 0.0069207512 }, { -0.0033541738, -0.0015140333, -0.004071746, -0.0020908789 }, { 0.0027932918, -0.0012517158, -0.0033509184, -0.001271572 }, { 0.0043481525, -0.00088858735, -0.0081538059, 0.00027985077 }, { 7.4017523e-05, -7.0080388e-05, -7.1766386e-05, 0.00020468758 }, { 0.00044507396, 0.010179106, -0.0048087449, 0.0013487105 }, { 0.00082148695, -0.00042640153, -0.0024255173, 0.0044486011 }, { -0.00026383509, -0.0031871528, -0.008203704, -0.00053957093 }, { -0.0002996462, 0.00070789605, 7.9300612e-05, -0.00024002209 }, { 0.0013722116, 0.0049176054, 0.0029283062, -0.000849108 }, { 0.00026545039, 0.0011783443, 0.00072103548, -0.0007355776 }, { 0.002192273, -0.00294318, 1.5452606e-05, -0.0020953993 } }, { { 2.4074136e-05, -2.4931598e-05, -1.0893587e-05, 1.080951e-05 }, { -0.0061635883, -0.0042963493, -0.00177783, -0.00080292808 }, { 0.0047868795, -0.0050472436, 0.0082439123, -0.0090979713 }, { 0.0017221077, 0.0067285193, 0.0031011872, -0.0019932567 }, { 0.0010926271, -0.0012170693, 0.00012875612, 0.00016441623 }, { -0.0048786273, -0.0041225634, -0.005591426, 0.0043469593 }, { -0.0070664098, -0.0012625813, -0.00022220241, -0.0026120468 }, { -0.0026689917, 0.00030860545, 1.9297947e-05, 0.001274799 }, { 0.0026769559, 0.00016106032, 0.00013829246, -0.0017239107 }, { -0.0042495789, 0.0010270326, -0.00078224804, -0.0019210019 }, { 0.0072385804, 0.0086418476, 0.0061428272, -0.0027142827 }, { 0.0019768127, -0.00057957046, 0.0047464783, -0.004599565 }, { 0.0093618867, -0.0010476542, -0.0038681572, -0.0065219521 }, { -0.0076406673, -0.0036729355, -0.0068804827, 0.0077571478 }, { 0.0012706397, -0.00042567505, -0.002521821, 6.0288127e-05 }, { -0.002041411, 0.000430125, 0.0073620925, 0.0021579456 }, { 0.00012145466, 4.1276616e-05, 4.2449608e-05, 9.8351262e-05 }, { 0.0014376278, -0.007439719, 0.0039006971, 0.00051135138 }, { -7.1665367e-05, 0.00023856335, 0.00015274881, -0.0096946274 }, { -0.00076804256, 0.0040182915, 0.012603411, -0.00059669891 }, { -0.00010641981, -0.00052355992, 0.00057481361, 0.00016456343 }, { -0.0027623375, -0.0036761364, -0.010480297, 0.0066006902 }, { 0.00049081404, 0.00077264749, 0.0021355718, -0.00029188425 }, { 0.00028566818, 0.00097678458, 0.00089022281, -0.00013760767 } } }, { { { -0.0098123577, 0.11017117, 0.11245143, -0.01173447 }, { 0.0036188505, -0.0025878518, -0.00043343726, -0.0038813197 }, { 0.013109746, -0.016775181, -0.0011093308, 0.00083465721 }, { -0.0042515898, -0.0028159364, 0.00027829209, -0.002907578 }, { -0.0081027554, -0.0019330574, 0.061872524, -0.037539524 }, { -0.012923735, 0.021011524, 0.002680406, 0.0034369108 }, { 0.0027819214, 0.0028657905, -0.0034177203, -0.0037322329 }, { -0.0036178174, 0.065792163, 0.13263475, 0.0055427994 }, { 0.027832309, -0.083372016, -0.058757582, 0.016164879 }, { -0.0082343898, 0.011782416, 0.011496052, -0.0027847616 }, { 0.0012516658, -0.014686832, -0.025073035, -0.020700577 }, { 0.0055718234, -0.011543219, -0.012867689, -0.0049474286 }, { 0.028869265, -0.035431559, 0.024976635, -0.01063055 }, { -0.0010657662, 0.014977146, 0.027109, 0.01612865 }, { -0.0021697493, 0.0044220507, 0.0055654161, -0.0032373397 }, { -0.018500666, -0.01979267, -0.0068480612, 0.03908391 }, { 0.063306878, 0.01934691, 0.019254616, -0.099824471 }, { 7.0580666e-05, -0.0015082457, -0.0056893693, 0.00022726294 }, { 0.0077067654, -0.014018834, -0.021406454, -0.0076589993 }, { -0.0013072394, 2.6765854e-05, 0.0028400803, 0.0037431063 }, { -0.025369581, -0.064039908, -0.020594137, -0.086807367 }, { -0.033639351, 0.010434758, 0.00082983507, 0.013145885 }, { 0.00029373395, 7.8193614e-05, 0.00048496415, 0.00062972215 }, { -0.0041597628, 0.024283117, -0.030148407, 0.011456515 } }, { { -1.3484857e-05, -3.7204145e-05, -1.5660577e-05, -2.4497955e-05 }, { -0.0068070249, 0.0041035892, 0.0034647689, 0.0035918321 }, { -0.0053613309, 0.0080593503, 0.0028507084, -0.0023104987 }, { 0.0048581064, 0.0039720065, -0.0019058129, 0.0047295789 }, { -0.00030675956, -0.0007787587, -0.00025201217, 0.00020777843 }, { -0.00026433336, -0.0093672701, -0.0053201627, -0.0059632173 }, { -0.0063062815, 0.0011995204, 0.0001870407, 0.0028197877 }, { -0.00053247524, -0.00066138217, -1.4959372e-05, -0.00036023628 }, { 0.00027591427, 0.00011309835, 2.2453632e-05, -0.00075736359 }, { 0.0015654886, 0.0018114616, -0.0004503446, -8.5866048e-05 }, { 0.003501393, 0.0037179893, 0.008328543, 0.013411108 }, { -0.0035136609, -0.0015054003, 0.0011903964, 0.0022551358 }, { -0.0083723767, 0.0061303554, -0.008056962, 0.0035035183 }, { -0.0023715655, -0.0070468331, -0.010219655, -0.0057856465 }, { -0.0011406634, -0.00021204595, -0.001693195, 0.0011051597 }, { 0.0011643412, 0.00037557194, 0.0048567739, -0.00063996433 }, { -3.1728174e-05, -2.9073903e-06, -3.0243209e-06, 2.579239e-05 }, { 0.00053152589, 0.0029635352, 0.0040743289, -0.00051381046 }, { -0.0017253584, 0.00012081524, 0.00012243664, -0.00063598215 }, { 0.0026711847, -0.0020733972, -0.0027860744, 0.0017065643 }, { 5.7762902e-05, 0.00092043577, -0.0035278882, 0.0007846087 }, { 0.0056127705, -0.0051893669, -0.0027072408, -0.0025630045 }, { -0.00059289151, -0.0004168408, -8.8118696e-05, -0.00073538101 }, { 0.0003388606, -0.00094234652, 3.013109e-05, -0.0010532484 } }, { { -2.9013996e-05, 6.1983083e-05, 2.8401438e-05, -3.4901557e-05 }, { 0.0045230474, -0.0021369843, -0.00422706, -0.0018918027 }, { 0.00017586142, 0.005389053, 0.0071352982, -0.0018278685 }, { -0.0012135723, -0.0035970727, 0.00078957165, -0.0017065397 }, { -0.00067051937, -1.9501585e-05, 4.1968766e-05, -0.0010958091 }, { -0.0015277626, -0.0039952533, -0.00049631478, 0.0018042745 }, { 0.0039376754, -0.00097834328, 6.5894634e-06, -0.0044189106 }, { -0.00067623039, 0.0004690807, 1.4532105e-07, 0.0032984829 }, { 0.0020787449, -0.0016586579, -0.00062367064, 0.0021545362 }, { 0.0016427801, 2.6710288e-05, 0.0016011535, -0.00077649869 }, { 0.0039999622, -0.0014968097, -0.0025647576, 0.0022783424 }, { 0.001558454, -0.00083803058, 0.0018955692, 0.0010432376 }, { 0.010555722, -0.010395022, 0.0050354965, -0.0016177699 }, { 0.00011370745, -0.009328355, -0.0063009522, 0.0024377458 }, { -0.00024433189, 0.00052920244, -0.0013213352, -0.0013503982 }, { -0.0057620093, 0.00095391746, -0.0034768563, 0.00093990705 }, { 0.00012108024, 4.1007202e-05, 4.2193381e-05, -0.00011043617 }, { 0.0038593696, -0.00074282979, -0.0093457897, 0.00027311164 }, { 0.0021514797, -7.8742315e-05, -0.0018813077, -0.0017625098 }, { 0.0038491118, 0.00022570776, -0.0061331041, 0.00014956617 }, { -0.00014676603, -0.00025053931, 0.003376287, -0.00014730695 }, { 0.0016439646, 0.0060569792, 0.00063058918, -0.0034810156 }, { 0.00011722835, 0.00032237223, -0.0012556553, -0.0006887808 }, { 0.00060814722, 0.0003708376, -0.00056515636, -0.00016801817 } } }, { { { 0.99117704, 0.98705585, 0.98683693, 0.9989534 }, { 0.99996564, 0.99998924, 0.99999903, 0.99999247 }, { 0.99958951, 0.99978616, 0.99986266, 0.99991895 }, { 0.99998953, 0.99996298, 0.99999443, 0.99999506 }, { 0.99764936, 0.9998311, 0.99527468, 0.99920949 }, { 0.9995611, 0.99968788, 0.99964679, 0.99996442 }, { 0.99999342, 0.99999257, 0.99999182, 0.99998381 }, { 0.99867384, 0.99734987, 0.98748052, 0.99943657 }, { 0.99627571, 0.99651225, 0.99814846, 0.99867903 }, { 0.99996323, 0.99992981, 0.99986298, 0.99992859 }, { 0.99957996, 0.99946171, 0.99966886, 0.99968945 }, { 0.99990668, 0.9999318, 0.99981943, 0.99987754 }, { 0.99945334, 0.99937032, 0.99935219, 0.99902503 }, { 0.99965614, 0.99959957, 0.99963092, 0.99973552 }, { 0.9999752, 0.99998861, 0.99994375, 0.99998505 }, { 0.99964293, 0.99879278, 0.99905795, 0.99705307 }, { 0.99788947, 0.99867085, 0.99868681, 0.99012413 }, { 0.99999581, 0.99994351, 0.99985991, 0.99999955 }, { 0.99996824, 0.99822008, 0.99874627, 0.99943549 }, { 0.9997877, 0.99996904, 0.99987919, 0.99999103 }, { 0.99948785, 0.99539425, 0.99978223, 0.99617908 }, { 0.99934875, 0.99977032, 0.99995357, 0.99949949 }, { 0.99999988, 0.99999943, 0.99999886, 0.99999963 }, { 0.99726107, 0.99809817, 0.99445842, 0.99947091 } }, { { -2.3481737e-05, -6.7307406e-06, -2.8605869e-06, -2.0372001e-06 }, { 6.6885689e-05, 4.5630281e-06, 3.5788218e-05, 1.0842484e-05 }, { -4.9278613e-05, -2.4660601e-05, 3.1625301e-06, 0.00019708279 }, { 1.2439158e-05, 3.0347865e-05, 8.6153947e-06, 1.0887256e-05 }, { -0.00012454598, -6.513709e-05, -3.5853483e-06, -3.4708286e-06 }, { -0.00013746339, 0.00013516333, 8.4535039e-05, 5.693766e-05 }, { -2.3674091e-05, -3.4690053e-06, 5.3812265e-07, -1.7613197e-05 }, { -0.00025790043, 3.0475251e-05, 2.1174795e-06, -0.00023630753 }, { -8.8624748e-06, 7.9175589e-06, -2.4258477e-07, -0.00017288313 }, { 4.0061469e-05, 0.00069846663, -0.00060299476, -0.00015396968 }, { 5.0667108e-06, 2.306363e-05, 0.00028636884, 3.6246633e-05 }, { 0.00032740524, -0.00037985037, -0.00014841039, -0.00012676016 }, { 8.7000758e-05, 0.00018530207, 1.7669124e-05, -0.00023199594 }, { 9.2332094e-05, 0.00013487652, 0.00034587506, -3.8853378e-05 }, { 6.9809868e-05, -0.00015411544, 0.0013505166, 1.4531796e-06 }, { -6.3782301e-05, 4.8545135e-05, -0.00027083794, 4.5129465e-05 }, { 3.0912438e-06, -3.2982361e-06, -3.3551612e-06, -1.7781589e-05 }, { 9.872609e-06, -2.9944213e-05, -4.5592652e-05, 1.5950681e-05 }, { 1.4767773e-05, -2.2486726e-05, -0.00010613341, -0.00015794394 }, { 2.4386215e-05, -1.1610334e-05, -4.4456294e-05, -5.0215596e-06 }, { -4.2741558e-06, 8.7714242e-06, -6.6343322e-05, 6.7010735e-05 }, { 0.00016489767, -3.3636771e-05, 5.1610504e-05, 5.2803593e-06 }, { 1.1649256e-05, 2.1169993e-05, 1.9755999e-05, 1.3389438e-05 }, { -0.00015815197, -0.00014316145, 2.6536218e-06, -4.6846396e-05 } }, { { -3.5109783e-06, -9.8530632e-06, -4.5020804e-06, 6.9233235e-08 }, { 9.9938991e-06, -2.0914089e-06, 3.5717699e-05, 3.2813664e-06 }, { 0.00012938219, 1.111062e-05, 8.0858608e-05, 0.00018147439 }, { 4.8657525e-06, 8.6580257e-06, 3.6742927e-06, 3.5828406e-06 }, { 6.9905696e-05, 2.0985073e-05, 6.8866215e-06, -4.2552499e-05 }, { 0.00012100208, 9.7821801e-05, 0.00013576456, 6.3686234e-05 }, { 1.954525e-06, -1.0727343e-06, 5.2332444e-07, -5.4034988e-06 }, { 0.00013699813, -2.226833e-05, 1.4994043e-06, 1.7110377e-05 }, { 0.0001678261, -0.00013844113, -3.4281745e-05, 5.3854072e-05 }, { -1.3018868e-05, 0.00022176303, 0.00016983401, 0.00038109805 }, { 0.00019016068, 0.00023448876, 2.643329e-05, 4.6842203e-05 }, { -1.2492528e-05, -0.00059486605, 0.00012427061, 8.1876965e-05 }, { 8.400564e-05, -0.00029859163, -4.884214e-05, 0.0002631806 }, { 0.00019907281, 0.00014046808, 0.00015482448, 4.0461099e-05 }, { -0.00024349239, 0.00081298441, 0.00084294728, 7.9617963e-05 }, { -6.0040835e-05, 3.2352918e-07, 0.00024295599, 0.00011067283 }, { -6.0027092e-06, 1.1975092e-06, 1.2248893e-06, -2.1293392e-05 }, { 1.4478736e-05, 6.8326918e-05, -7.8693614e-06, 9.2888155e-06 }, { -1.6982828e-05, 1.2094341e-05, -3.1693808e-05, 0.00028574477 }, { 3.4480942e-05, 2.6556008e-05, 0.00016193956, -1.8966503e-06 }, { -5.7726961e-06, 2.1091148e-05, 5.8963955e-05, -1.0834372e-05 }, { 0.0001214393, 1.4174882e-05, 0.0001371836, 0.00021757165 }, { 1.0140226e-05, 6.1641031e-06, 1.0590727e-05, 1.0893212e-05 }, { -1.7442656e-05, 4.2353331e-05, 7.4324714e-05, -1.9484775e-06 } } }, { { { 3.7217719, 3.6900797, 3.6899881, 3.6670816 }, { 0.067826319, 0.16468028, 0.083129199, 0.1336756 }, { 0.66338737, 0.23883566, 0.093361469, 0.10095622 }, { 0.27185537, 0.20781392, 0.32216624, 0.29876595 }, { 2.0776462, 2.0006156, 2.0243138, 2.080345 }, { 0.57695783, 0.18015147, -0.11440889, 0.14229144 }, { 0.63833683, 0.41431062, 0.44752994, 0.47594414 }, { 1.7890608, 1.962584, 1.9322155, 1.6588331 }, { 3.0538128, 3.108267, 3.1001573, 2.9593433 }, { -0.28383051, -0.27708376, -0.042513902, -0.085181891 }, { 0.3873435, 0.41697884, 0.39625427, 0.33250735 }, { -0.33498881, -0.40206929, -0.028905862, -0.48179632 }, { 1.1875033, 1.3535177, 1.2526197, 1.3337495 }, { 0.42579488, 0.24951727, 0.18976118, 0.20605317 }, { -0.53212666, -0.3861028, -0.75685995, -0.23411882 }, { 1.6910165, 1.686815, 1.5906473, 1.6528217 }, { 4.0570657, 4.0349492, 4.0350332, 4.0498099 }, { -0.017225465, -0.032503897, 0.46003211, 0.21602109 }, { 1.1196901, 1.00885, 0.91675568, 0.99635794 }, { -0.093891275, 0.0809352, -0.13783332, 0.27130678 }, { 1.9925136, 1.9829394, 1.8820721, 1.9542026 }, { 0.84563763, 0.48476746, 0.37907152, 0.70267878 }, { 0.37054708, 0.4228574, 0.6329822, 0.26197064 }, { 1.9618393, 1.8405969, 1.9440918, 1.901629 } }, { { -5.6047186e-06, 6.0454847e-06, 2.8365975e-06, 6.0894367e-06 }, { -0.00069876506, -0.00029642785, -0.00059516082, -0.00025400441 }, { -0.00020850504, -0.00012959593, -0.00032902532, -0.00058117893 }, { -0.00037901964, -0.00038062016, -0.00023777964, -0.00033714679 }, { -5.9894351e-05, -9.820791e-05, -5.9867157e-06, -6.258549e-06 }, { -0.00035424038, -8.7146215e-05, 3.0398362e-05, -0.00061406521 }, { 0.00014971442, 4.5936211e-05, -5.6259869e-06, 0.00013567035 }, { -0.00016180211, 3.1840487e-06, 3.8979157e-07, -0.00017131994 }, { -1.9877193e-05, 2.5768261e-05, 9.0577543e-06, -0.00013927462 }, { -0.0012323564, -0.00042892846, 7.2082106e-05, 0.00010999853 }, { -0.00034618449, -0.00017058897, -0.00016535057, -0.00096982024 }, { -0.00028039653, -7.155747e-05, -0.00075796707, 0.00062756458 }, { 6.6596276e-05, -7.9730809e-05, -8.0686754e-05, -2.9532397e-05 }, { -0.00084106867, -0.00036762453, 0.00012523548, -0.00052789663 }, { 7.6718268e-05, -0.0010042005, -0.00042802983, -0.0011951304 }, { -3.6972258e-05, 2.1447505e-06, -0.00035448623, -1.0620008e-05 }, { 2.8326169e-05, 2.2049468e-05, 2.2640575e-05, 1.7574827e-05 }, { -0.00014318496, -0.0004811524, -0.00049293303, -0.00067646484 }, { -2.7469144e-05, -5.9653763e-06, -1.3998899e-05, -0.00018475323 }, { -0.00017314302, -0.00010954727, -0.00040004932, 3.31106e-05 }, { -3.6093435e-06, -1.6125243e-05, -4.9195648e-05, 1.5586886e-05 }, { 0.0002059631, -0.0004024722, -0.00047984678, -9.8485329e-05 }, { -0.00094100913, -0.00073046048, -0.00052500163, -0.00068196784 }, { -2.2820197e-05, -5.9454557e-05, -6.2505468e-06, -2.6569804e-05 } }, { { 2.6015883e-05, 8.5398335e-06, 3.8473185e-06, 9.1409625e-06 }, { -0.00041459247, -0.0001855224, -0.00030529542, -0.00016322166 }, { -8.8427847e-05, -0.0002302048, -0.00038072959, -0.00076801295 }, { -0.00027717792, -0.00028594346, -0.00017910208, -0.00027291164 }, { 2.8409311e-05, -3.8005817e-05, -4.2266878e-06, -1.4520383e-05 }, { -0.0001088827, -0.00021924377, 3.9307406e-05, -0.00032488556 }, { 0.00027997916, 3.5103699e-05, -5.7448764e-06, 0.00010259251 }, { -4.7807894e-06, -2.9470863e-05, 2.6656233e-07, -0.00014346393 }, { 0.00015527098, -6.8528726e-05, -1.1206714e-05, 2.3422595e-05 }, { -0.0012763247, -0.00051503472, 0.00058055106, -0.00068688488 }, { -6.1232076e-06, -1.7073841e-05, -0.00033533389, -0.00078769935 }, { -0.00044113485, -0.00027577451, -0.0012008622, 0.00013071136 }, { 1.834948e-05, -0.00015615102, -0.00016449385, 3.6685217e-05 }, { -0.00063618257, -0.00032641968, -5.0281118e-05, -0.00041378992 }, { -0.0010181884, -0.0003871932, -0.00050061147, -0.0018967455 }, { -5.7650067e-05, -5.1145774e-06, -0.00017409773, 1.9512036e-05 }, { 1.5838743e-05, 2.503655e-05, 2.5679098e-05, 2.0053218e-05 }, { -0.00018055811, -0.00044345237, -7.9049557e-05, -0.00095669161 }, { -4.98611e-05, -1.1320605e-06, 3.7756645e-06, -8.7299215e-05 }, { -0.00011794063, -0.00015778552, -0.00036514881, 4.7288704e-05 }, { -5.1753817e-06, -1.5040527e-06, -2.836739e-05, -9.4945229e-06 }, { 0.00016873335, -0.00031983601, -0.00052281245, 0.00019034815 }, { -0.0011988594, -0.0010684975, -0.00057577023, -0.0009143845 }, { 5.0336006e-05, -1.356148e-05, 1.5582694e-05, -2.0666272e-05 } } }, { { { 0.012207721, 0.0044164612, 0.0022704542, 0.0042008503 }, { 0.29516302, 0.139976, 0.35038027, 0.13748343 }, { 0.1462123, 0.12114907, 0.28473665, 0.45762717 }, { 0.17976664, 0.19141553, 0.1209483, 0.16393769 }, { 0.044254492, 0.11383095, 0.0062726904, 0.023550537 }, { 0.14785458, 0.10151341, 0.045717467, 0.42243971 }, { -0.24205201, -0.033590842, 0.0032064617, -0.093924041 }, { 0.10866955, 0.016299431, 0.00081631108, 0.15856447 }, { 0.10108337, 0.057931152, 0.024463589, 0.21514346 }, { 0.47967783, 0.75472932, 0.5653649, 0.64752457 }, { 0.30082544, 0.15124922, 0.23567284, 0.47161499 }, { 0.54286166, 0.61049777, 0.61641378, 0.51181399 }, { 0.39328762, 0.25557559, 0.25875912, 0.22436901 }, { 0.45699569, 0.16989563, 0.2429263, 0.3924359 }, { 0.92996797, 1.1024806, 0.78045387, 1.2298879 }, { 0.19029829, -0.022675055, 0.28113642, 0.034941166 }, { 0.013203939, 0.013034069, 0.013414649, 0.011688038 }, { 0.076026927, 0.13838472, 0.29961655, 0.31531564 }, { 0.089182386, 0.010401684, 0.029374547, 0.22995838 }, { 0.052198894, 0.039866726, 0.11570972, -0.013818992 }, { 0.0062380932, 0.01788119, -0.20765047, 0.013339281 }, { 0.12436441, 0.17318651, 0.21554136, 0.18600144 }, { 0.38005287, 0.32135548, 0.28632777, 0.29211902 }, { 0.03798742, 0.0450845, 0.010912505, 0.039060104 } }, { { 0.00077914246, 0.00011130803, 8.1110229e-05, -0.00035312557 }, { 0.00051711901, 0.00029701387, 0.00040733345, 0.00034149723 }, { 0.00063893978, -0.00013702086, 0.00030866699, -0.00020070677 }, { 7.5899443e-05, 9.7456273e-05, -4.5352178e-05, 7.6172703e-06 }, { 0.00066250814, -0.00073033349, 0.00015225542, -0.0010197351 }, { 0.00040931533, -0.00043022747, 0.00093333285, 0.0002579685 }, { -0.00067488578, -0.0003706974, -0.00044487256, -0.00056555959 }, { 0.00075838366, -0.0021903789, -0.0026744174, -0.00047135202 }, { -0.00081050821, -0.0010297809, -0.00099480849, -0.00074914246 }, { 0.00063637392, 5.248783e-05, 0.00044645091, 0.00018028446 }, { 0.00067430392, 0.0004762628, -0.00032736685, 0.00041933609 }, { 6.2324555e-05, -1.6709531e-06, 0.00057418116, -0.0010360999 }, { -0.00038256183, -0.0010104012, -0.00045533693, -1.3888404e-05 }, { 0.00068274628, 0.00068411875, -0.00091273333, 0.00016211145 }, { -0.00039440715, 0.00027665323, -0.00035895503, 0.00013423207 }, { -0.00061939017, 0.00012140102, 0.00024178233, 0.00064755788 }, { -0.00052441128, -0.00050994483, -0.00051126044, 0.00066320373 }, { 0.00085915332, 0.0013567332, -0.00014328466, 0.00056098523 }, { -0.0012682676, 0.0029139719, 0.0019812291, -0.00053863027 }, { 0.0021895869, 0.00062956835, 0.0018161156, 0.00011699452 }, { -0.0010337306, 0.00016880497, -0.0014942346, -0.0034402453 }, { -0.0025336946, -0.00019468865, -0.00018045349, -5.4312149e-05 }, { 0.00021491979, 4.7651714e-05, -0.00044921151, 0.00046742044 }, { 0.0019408125, 0.00044842687, 0.0026003265, -0.00090116109 } }, { { -0.0006591255, 0.00022873584, 0.00026313866, -0.00060151354 }, { 0.00027198127, 0.00034252944, 0.00033246896, 0.00035232159 }, { -0.00034460639, -5.9085725e-05, 7.836454e-05, -0.00018946388 }, { 0.00018790551, 0.0001918358, 9.7031467e-05, 0.00015259869 }, { -0.0023033429, -0.0012945186, -0.00080964072, -0.00030432514 }, { -0.001359781, 0.00055828912, -0.00041912301, 0.00019263336 }, { -0.00042789448, -0.00018313775, -0.00030217124, -0.00028437496 }, { -0.0018340159, 0.00030654336, -0.00010781402, -0.0011985455 }, { -0.002103478, 0.00029492518, -0.00042283946, -0.001472689 }, { 0.00064558079, 0.00049703204, -0.00018932594, -0.00038268301 }, { -0.00097813334, -0.00057838807, 0.00079268109, 0.00039650774 }, { -0.00017335252, 0.00074363734, 0.0008194423, -0.00065923207 }, { -0.00075344545, -0.00026114262, -0.00054658657, -0.0013814943 }, { -0.00028279346, 0.00055730283, 0.00048990213, -0.00022186466 }, { 0.00013438509, -0.0001962818, -0.00036195953, 0.00042669461 }, { -0.00089003585, -0.0011600794, -0.0012554286, -0.0012892408 }, { -0.00067007058, -0.0010597247, -0.0010590421, 0.00044132516 }, { 0.0011626727, 0.001261033, -0.00072912018, 0.00076332442 }, { -0.001204702, -0.00011230019, 0.00036178615, -0.0017559004 }, { 0.00096282849, 0.001025959, 0.0011696947, 0.00046633555 }, { -0.00082328571, -0.00075771669, -0.0011629302, 0.00073458863 }, { -0.0016869269, -0.00035239862, -0.0004024204, -0.0016276971 }, { 0.00029053123, 0.00013409355, -0.00049087974, 0.00061969429 }, { -0.0013198997, -0.0018615784, -0.0025724061, -0.0015563017 } } } }, { { { { -0.072246889, -0.043157285, 0.043289306, 0.095998047 }, { 0.12597079, 0.24289541, -0.10930005, -0.24150539 }, { 0.031889347, -0.036238337, -0.014521983, -0.018963885 }, { -0.044155351, -0.0077170425, -0.043781059, 0.047982339 }, { 0.093995001, -0.0079510758, -0.04688882, -0.11125523 }, { 0.01700754, -0.0034361033, 0.055252382, -0.053119426 }, { -0.0014957087, -0.00063057103, 0.037930463, 0.017656646 }, { -0.017388477, -0.084085888, -0.067726647, 0.061397079 }, { -0.070625168, -0.061293011, -0.077366932, 0.11518646 }, { -0.14771316, -0.12543895, 0.052150789, 0.10530462 }, { -0.03609139, 0.001131616, -0.039549928, 0.03805765 }, { 0.064364205, 0.066758929, 0.045537002, -0.05510954 }, { 0.049051369, 0.098312455, -0.01079726, -0.11202623 }, { 0.033012208, -0.0013996988, -0.0049458824, -0.028981527 }, { 0.008617177, -0.00017670863, -0.0052380282, -0.0023438457 }, { -0.05901498, -0.050754807, -0.00011829844, 0.037297411 }, { -0.056264446, -0.03645315, -0.066412698, 0.019549244 }, { -0.11401603, -0.11856524, 0.12275022, 0.11635143 }, { -0.0011999881, -0.0016334327, -0.0056868938, 0.013393766 }, { 0.054526972, 0.033632235, 0.062591094, -0.0025531074 }, { 0.073041316, 0.073735243, -0.06935254, -0.11214186 }, { 0.034872822, -0.015473423, 0.037359975, -0.026829465 }, { -0.015137592, -0.0064462553, 0.011771178, 0.0025042048 }, { -0.038708904, -0.033968131, -0.044070885, 0.024422773 } }, { { -0.047895007, -0.016535938, 0.04855533, 0.018341613 }, { 0.004310087, 0.01519838, -0.0033290683, -0.013597406 }, { 0.0015859181, 0.016869623, -0.019279963, -0.01426933 }, { -0.0061048976, 0.031131561, 0.018085381, -0.017927117 }, { 0.052590378, 0.0066156852, -0.0025756141, -0.037241705 }, { 0.0083512619, 0.0046235666, 0.024122126, -0.013443654 }, { 0.0010672274, 0.00053123301, -0.0016276029, -0.04221993 }, { -0.0048754166, -0.021474788, -0.0039993317, 0.011831691 }, { -0.054685347, -0.050242732, -0.007606251, 0.043061893 }, { -7.5644942e-05, 0.00086632318, 0.0001960729, 0.0013264286 }, { 0.0042413724, -0.0057181522, 0.0065940983, -0.0078263328 }, { 0.0031260881, -0.0013520907, 0.025073658, -0.010841673 }, { 0.038353769, 0.06620308, -0.0072105562, -0.079188681 }, { 0.003099559, -0.0022927921, 0.021982683, -0.018991144 }, { 0.012285675, 0.0091834074, -0.0041874571, -0.032253924 }, { -0.014563556, 0.009843969, -0.010490279, 0.012979866 }, { -0.005492286, 0.064109426, -0.034795617, -0.020395732 }, { -0.023364141, -0.059336321, 0.080710391, 0.038948527 }, { 0.0028384819, 0.001822471, 0.0012903958, 0.012781079 }, { -0.004510518, -0.0020008272, 0.0017752876, 0.0077607089 }, { 0.032279653, 0.0041906079, -0.034682371, 0.0061335907 }, { -0.0082992317, -0.025250117, -0.017026845, -0.028345042 }, { -0.013132125, -0.026688493, -0.0014827793, -0.003236826 }, { 0.01650781, 0.002313574, -0.012897922, 0.026077933 } }, { { 0.062668058, 0.0081578851, 0.018952049, -0.012267283 }, { 0.0008567722, 0.0033246009, -0.0037620102, -0.0096317368 }, { -0.0083012273, 0.01184624, -0.01209373, 0.020208536 }, { 0.013862003, 0.019166381, 0.013235471, -0.026788736 }, { -0.021904217, -0.051018749, 0.0020330268, 0.006626371 }, { -0.015856131, 0.0028024655, -0.032825412, -0.018920906 }, { 0.0020870233, 0.0011616727, -0.0032704368, -0.027327141 }, { 0.01934969, 0.002427195, 0.049925128, -0.0061414889 }, { 0.013158375, 0.022248445, 0.040266734, -0.017583455 }, { 1.9024812e-05, 0.00071602053, 0.0012622199, 0.0018791611 }, { -0.0011857767, 0.0023417924, 0.026237548, -0.014687892 }, { -0.041419782, 0.024942194, -0.029143101, 0.036590943 }, { -0.015470651, -0.035208671, -0.038530514, 0.037434376 }, { -0.0029356279, 0.0023358079, 0.017641055, 0.0038203652 }, { -0.0030449623, -0.010187444, 0.0066142145, 0.0037433206 }, { 0.0080034603, 0.011463159, -0.0058129532, 0.011831147 }, { -0.0091743137, 0.045949289, 0.022412137, -0.0067531419 }, { 0.00069946656, -0.0068974782, 0.0091806954, 0.0022160793 }, { -0.0027530077, 0.00089797627, 0.0066153093, -0.010355635 }, { -0.019399018, -0.0085762573, 0.0208003, -0.027739023 }, { -0.014354809, -0.011971089, -0.0031124986, 0.044710091 }, { -0.011411144, 0.0073253411, -0.0087561348, -0.014838738 }, { 0.018837992, 0.00231775, -0.013982978, -0.0020044658 }, { 0.0012069362, 0.0012202952, 0.029106153, 0.00062793994 } } }, { { { 0.054154158, -0.11603661, -0.025631275, 0.054671866 }, { -0.2359715, 0.093194255, 0.21874866, -0.08378526 }, { 0.0089903397, 0.0087113885, -0.015445726, 0.011142042 }, { -0.0055372249, -0.0041494086, -0.033355186, -0.010136823 }, { -0.015010227, -0.0077144008, 0.13058394, -0.016779666 }, { -0.015855009, 0.014090685, 0.026549575, 0.025677527 }, { -0.00065423811, -0.0011506403, 0.028628751, 0.0086359197 }, { -0.010571292, 0.035861454, -0.025871285, -0.024827688 }, { 0.00010603924, 0.011433504, -0.052819957, -0.020208661 }, { 0.12243361, -0.14574398, -0.10091072, 0.054524772 }, { -0.014659734, -0.02291001, 0.010102434, -0.0099333349 }, { -0.0079939087, 0.023468399, 0.044548395, 0.04568814 }, { -0.048188816, 0.016469102, 0.084818672, -0.040634065 }, { 0.015089138, 0.025396216, 0.017000121, 0.010820807 }, { -0.0098155552, -0.00080001495, 0.0020122754, -0.00046896909 }, { -0.0018906417, -0.03909342, -0.020339049, -0.024007559 }, { -0.0012744487, -0.027829333, -0.05202457, -0.024366779 }, { 0.10406956, -0.092281421, -0.050420166, 0.10716663 }, { -0.0049603976, -0.0055370076, -0.0016910106, 0.012172389 }, { -0.0026486448, 0.038673757, -0.0016176887, 0.052692494 }, { -0.03722357, 0.055455783, 0.067738953, -0.0087990582 }, { -0.0026491637, 0.017275247, 0.010687117, 0.020312052 }, { -0.0016032469, 0.0090272843, -0.0079027514, -0.0050039898 }, { -0.0073653412, -0.033150577, 0.0082912493, -0.021457881 } }, { { -0.0059001999, 0.033600833, 0.066374213, -0.018058548 }, { -0.0037864945, -0.0064946131, 0.0018627774, 0.0044899139 }, { 0.0048961861, -0.0034770968, -0.0002311598, -0.0053935761 }, { 0.0090090757, 0.012149811, 0.0029969663, 0.0049403543 }, { -0.042874682, -0.0083455851, -0.0064437344, 0.0010579362 }, { 0.011866873, -0.017157526, -0.014724976, 0.0054373752 }, { -0.0006329516, -0.00024834697, 0.0015416168, -0.014246989 }, { 0.031530357, -0.052715858, -0.0063186617, -0.0070200141 }, { -0.0082273844, 0.053856605, 0.0096812384, 0.01684635 }, { -0.00017150577, 0.00097354737, 0.0013944706, 0.00085166684 }, { -0.013604545, 0.0089329355, -0.013809086, 0.0025044469 }, { -0.020284731, 0.0004724419, -0.045697697, -0.01844702 }, { 0.017874081, -0.0040537465, -0.023316716, -0.026344708 }, { 0.0092557469, -0.014456327, -0.0092919835, 0.0091758924 }, { 0.016058873, 0.0019220807, 0.0031692823, 0.0024577167 }, { -0.021184352, 0.021287579, -0.0048442696, 0.0095799112 }, { 0.035229915, -0.054291919, -0.013871324, 0.035585241 }, { 0.001275203, 0.011513119, 0.020184769, -0.0061701639 }, { 0.011353237, 0.0052697685, 0.0047637419, -0.020278005 }, { 0.0068266296, -0.01173749, 0.037482577, -0.0083236299 }, { 0.025699221, -0.03651135, -0.032342446, -0.0059784486 }, { 0.0029540635, -0.0021598269, 0.0028168477, 0.0044577193 }, { 0.0038274002, -0.0050806333, 0.007628551, 0.0027461742 }, { 0.0056567464, 0.006846664, -0.031161558, -0.0040832656 } }, { { 0.025668431, 0.0093723617, 7.4324163e-05, -0.023051436 }, { -0.010148124, 0.0018159908, 0.0072269566, 0.00082671261 }, { 0.0069741056, 0.023493533, 0.028507618, -0.026874125 }, { 0.0083316277, -0.024891629, 0.013623217, 0.0038373532 }, { -0.020992516, 0.070912136, -0.0014634877, -0.015680371 }, { 0.02178962, -0.003772636, -0.024578501, -0.047467019 }, { 0.0028586275, 0.0033445767, 0.0049576063, -0.017365739 }, { 0.0075721122, 0.010652219, -0.024031886, -0.0001146548 }, { 0.016381176, -0.044765924, -0.038036229, -0.014041395 }, { -0.00082564842, 0.00033107944, 0.00073792054, 0.0005712734 }, { 0.0080934887, 0.014534447, -0.0071347609, 0.0085413493 }, { -0.018211778, 0.0064443848, 0.017393403, 0.011490985 }, { -0.071531366, 0.030059694, 0.049103287, 0.0074609412 }, { 0.00770209, -0.017999995, -0.040048679, -0.0029073853 }, { 0.020442166, 0.0019454488, -0.019644905, 0.021793285 }, { 0.035171271, 0.0080192155, -0.023151504, 0.014168348 }, { -0.048901887, -0.0039613606, 0.0021703807, 0.030275152 }, { 0.044666116, -0.029756153, -0.015570779, 0.034470632 }, { -0.0078700362, 0.0037551741, 0.0003070052, -0.0031237403 }, { 0.015288427, -0.01284757, -0.0075319169, 0.026981487 }, { -0.0093872483, 0.013517073, -0.030221944, 0.058356065 }, { 0.0042326205, -0.016381154, 0.021475001, 0.01008732 }, { 0.0034929117, 0.020531314, -0.0085114063, 0.004821913 }, { 0.014314413, 0.01127037, -0.017197896, 0.0046932185 } } }, { { { 0.99591552, 0.99230689, 0.99873374, 0.99387895 }, { 0.96356049, 0.96556546, 0.96964041, 0.96677566 }, { 0.99945097, 0.99930521, 0.99977525, 0.99975808 }, { 0.99900933, 0.99996161, 0.99848418, 0.99879675 }, { 0.99545951, 0.99993863, 0.99032786, 0.9936502 }, { 0.99972964, 0.99989482, 0.99811938, 0.99825798 }, { 0.99999867, 0.99999914, 0.9988702, 0.99980681 }, { 0.99979292, 0.99581299, 0.99736843, 0.99780458 }, { 0.99750292, 0.99805433, 0.99560254, 0.9931383 }, { 0.98142286, 0.98133774, 0.99352772, 0.9929441 }, { 0.99924096, 0.99973689, 0.99916652, 0.99922617 }, { 0.99789446, 0.9974931, 0.99796885, 0.99743448 }, { 0.9976331, 0.99501931, 0.9963379, 0.99287411 }, { 0.99934104, 0.99967648, 0.99984325, 0.99952138 }, { 0.9999147, 0.99999966, 0.99998426, 0.99999714 }, { 0.99825531, 0.99794572, 0.99979313, 0.99901579 }, { 0.99841509, 0.99894779, 0.99643504, 0.99951192 }, { 0.98801309, 0.98864879, 0.99115599, 0.98740957 }, { 0.99998698, 0.99998334, 0.9999824, 0.99983621 }, { 0.99850879, 0.99868574, 0.99803794, 0.99860752 }, { 0.99663402, 0.99573479, 0.99528974, 0.99365325 }, { 0.99938825, 0.99973103, 0.99924472, 0.99943364 }, { 0.99988413, 0.99993848, 0.99989949, 0.99998434 }, { 0.99922338, 0.99887297, 0.998994, 0.9994714 } }, { { -0.0050599833, 0.003362263, 0.0035202243, -0.00056864904 }, { -0.0014675187, -0.0029154981, -0.00077796172, -0.0027392627 }, { -0.0010916411, 0.00078232803, 0.0014339533, -0.0020166729 }, { 0.011183745, 0.008298699, 0.011631254, 0.00030693508 }, { -0.0012964861, -0.00028098882, 0.00098513135, -0.0052243577 }, { 0.0091119501, 0.002780703, 0.011045274, 0.00334383 }, { 4.1103001e-05, 5.5767744e-05, 0.0030605577, 0.0022152241 }, { 0.00085375099, 0.0026952672, 0.0071937971, 0.0056504112 }, { -0.003773118, 0.0047936307, -4.5743022e-05, -0.0038357994 }, { 2.3815581e-05, 0.0002468657, 0.00013492048, -0.00018410816 }, { 0.0070959632, -0.00205589, 0.0056417297, 0.0030702073 }, { 0.010671769, 0.0074346008, 0.0012867659, 0.0075437523 }, { -0.0013037272, -0.0058374269, 0.0025899757, -0.0071565118 }, { 0.0030041304, 0.0018011397, 0.0093160386, 0.0082062863 }, { 0.0053156934, 0.0036543193, 0.0048724246, 0.0035118324 }, { -0.0053866158, 0.0024053442, 0.00052459148, 0.0090970513 }, { 0.011239324, -0.0010327051, -0.00097551594, 0.0044180668 }, { -0.0024379533, -0.0088232426, -0.012355568, -0.0031875953 }, { 0.0026244123, 0.0011858999, 0.0028110843, -0.001005442 }, { 0.0059514328, 0.0018892606, 0.0050231625, 0.0046700575 }, { 0.00050741664, 0.0096547476, -0.00079618251, 0.0024532112 }, { 0.0058717468, -0.0017457656, 0.0080261577, -0.00048009588 }, { 0.0025457914, 0.0016788968, 0.0013982313, 0.00073909928 }, { 0.0075035778, 0.011234409, 0.0079271096, 0.006672353 } }, { { 0.0095152396, 0.0011785006, -0.00081996856, 0.0018904938 }, { -0.0025430397, -0.0010236291, -0.0020168276, -0.0021827861 }, { 0.0036295778, 0.005406882, 0.0040788276, -0.0057729163 }, { -0.00029952998, 0.0024548208, 0.0088548836, 0.0019084209 }, { 0.0034184324, -0.0088925589, 0.00023040452, 0.00017437939 }, { 0.0037804595, 0.012156355, 0.0041276361, 0.012721488 }, { 7.4846461e-05, 0.00010580108, 0.013483417, 0.0024239851 }, { 0.00026411032, -0.00059353627, 0.0093564271, 0.0061507538 }, { 0.0016065383, -0.0027764641, 0.0013620195, 0.0010062065 }, { 9.7127925e-05, 0.00017275393, 1.0814607e-05, -0.00022627793 }, { 0.0048710612, -0.00014794569, 0.0082832436, -0.00072595412 }, { -0.0027392579, 0.0066783951, 0.00087397132, 0.001567366 }, { -0.003378151, 0.0025916338, -0.0025553201, 0.0030152022 }, { 0.0096818399, 0.0012695523, 0.0072489949, 0.016881099 }, { 0.0022796191, 0.0051693266, 0.0023373397, -0.0041448561 }, { -0.0002074582, 0.0035962454, -0.0007460719, 0.0025086317 }, { 0.0035784996, 0.003162753, 0.0022592918, 0.00024595998 }, { -0.0051294944, -0.0041428868, -0.0027597, -0.0039539398 }, { 0.0022410392, 0.00031263884, 0.0016376751, -0.0022787113 }, { 0.0025647038, 0.0074733037, 0.0051722028, 0.0024463612 }, { 0.0011787227, 0.0071159753, 0.0017217143, 0.0062717989 }, { 0.0046836737, 0.0038976423, 0.00062832002, 0.0027638154 }, { 0.0014142926, 0.0024903802, 0.0015757227, 0.0011628587 }, { 0.0016928585, 0.0043828548, 0.001653268, 0.011450696 } } }, { { { 2.8886078, 2.8900127, 2.7925705, 2.7895874 }, { 4.5455217, 4.5284714, 4.7042338, 4.6915273 }, { 0.96672505, 0.99303664, 0.98927606, 1.0351588 }, { 1.2743756, 1.2525364, 0.99649566, 0.94572778 }, { 2.6910679, 2.6922168, 2.8503404, 2.8246076 }, { 1.256075, 1.2325025, 1.5911826, 1.6091223 }, { 1.3601759, 1.3606869, 1.2793533, 1.240925 }, { 2.0291828, 2.0506809, 1.7341658, 1.6555689 }, { 2.6663531, 2.6921882, 3.1290975, 3.11849 }, { 5.3676887, 5.3663279, 5.3848664, 5.3852162 }, { 1.0586431, 1.0865889, 0.8196623, 0.8076665 }, { 1.6967251, 1.7305944, 1.5450413, 1.6347879 }, { 3.0908857, 3.0706775, 3.2974343, 3.3053965 }, { 1.2172073, 1.3839086, 1.5086796, 1.4295506 }, { 0.97676668, 1.0856738, 0.98747912, 1.0385491 }, { 1.5662275, 1.4603538, 1.784278, 1.6575438 }, { 2.1085757, 2.2092885, 2.1410448, 2.1518347 }, { 4.0214776, 4.006424, 3.7686967, 3.7771354 }, { 1.2089239, 1.2116036, 1.1244311, 1.0901017 }, { 1.1827246, 1.1472796, 1.7516784, 1.7833976 }, { 2.2113439, 2.197512, 2.2692963, 2.2787751 }, { 0.98819531, 1.057833, 1.3587301, 1.3890421 }, { 1.208957, 1.2247867, 1.2301205, 1.2325178 }, { 1.0499613, 1.1319197, 1.4067885, 1.3209087 } }, { { -0.002860931, -0.0033581281, -0.0047612075, -0.0030481839 }, { -0.0017370907, -0.0065700936, -0.0011051926, -0.0046915938 }, { -0.0006126207, 0.0010791181, -0.022876686, -0.015937275 }, { -0.010040922, -0.016433531, -0.0044976975, -0.029838315 }, { 0.00056888968, -0.0093450028, -0.00041549218, -0.0069079656 }, { -0.029781683, -0.019722587, 0.019472312, 0.0016798037 }, { -0.0015128736, -0.0012250172, -0.0091568262, -0.0091368119 }, { 0.0010846814, 0.0017189068, 0.012975603, -0.0051530971 }, { -0.026042808, -0.0090684857, -0.0021498742, -0.0032938309 }, { -0.0012792901, -0.0010431731, -0.0021366737, -0.0025526365 }, { -0.03218779, -0.013848893, -0.021872476, -0.029443623 }, { 0.008300061, 0.011951182, -0.011139414, 0.0098292843 }, { -0.0065854884, -0.020955083, -9.3843515e-05, -0.0078425688 }, { -0.054726229, -0.0073673428, -0.019267231, -0.03383648 }, { -0.049769726, 0.0065482059, -0.010189395, -0.0050480393 }, { 0.022565943, -0.020311569, 0.0091512717, -0.015600752 }, { -0.014418429, 0.0060070592, -0.0055296743, -0.003361885 }, { 8.8146509e-05, -0.0082609252, 0.0036746024, 0.0040108321 }, { 0.0010230427, 4.8153189e-06, 0.0052893378, -0.0096303521 }, { 0.0032909351, -0.010982824, 0.003880027, 0.0097699095 }, { -0.006528317, -0.012608887, -0.0057088008, -0.003867806 }, { -0.046599771, -0.024701737, -0.001078321, -0.0041018649 }, { -0.021680777, -0.021120711, 0.0055144734, -0.0031337995 }, { -0.030559213, 0.0089872726, -0.011166202, -0.0077587071 } }, { { -0.0059548858, -0.0040070313, -0.0062572119, -0.0047711065 }, { -0.0031938803, -0.005431389, -0.0026376521, -0.0046119366 }, { 0.0064917253, 0.013030824, -0.027850471, -0.011824849 }, { -0.032644485, -0.025045016, -0.0034396539, -0.039827623 }, { -0.007691681, -0.014095643, -0.0008171964, -0.0051336386 }, { -0.035626586, -0.021424668, 0.00035790929, 0.0099705685 }, { -0.0019006762, -0.0014887089, -0.0050782898, -0.0096835564 }, { -0.00087496879, 0.0052586834, 0.017041675, -0.00046753956 }, { -0.022489507, -0.0084834888, 0.0017184219, -0.0023910992 }, { -0.0010618265, -0.00085888729, -0.0020035777, -0.0024245283 }, { -0.029245834, -0.038977066, -0.013385246, -0.030312138 }, { -0.0028497869, 0.014205986, -0.0125692, 0.0037959624 }, { -0.0086377959, -0.019175965, -0.007684309, -0.005037677 }, { -0.063945685, -0.0060751259, -0.0057457302, -0.019079575 }, { -0.043745147, 0.013651906, -0.034067394, 0.0012111497 }, { 0.0086647574, -0.019171418, 0.020745219, -0.0055629951 }, { -0.024541273, 0.0072112135, -0.0078821942, -0.0085072621 }, { -0.0018227939, -0.0021153099, 0.008577002, 0.0043865151 }, { -0.013984752, -0.012209334, 0.00023638151, -0.0085025952 }, { -0.0099800075, -0.0095390578, 0.0081328135, 0.012673433 }, { -0.0099975551, -0.0028467616, -0.010712056, -0.0045012212 }, { -0.011329139, -0.0084709831, -0.0070232966, 0.0015504012 }, { -0.015334801, -0.0075637633, -0.01107439, -0.0094188163 }, { -0.017505269, -0.00013701888, -0.033955823, -0.034192649 } } }, { { { 0.16413327, 0.084074422, 0.10646123, 0.18806073 }, { 0.039511019, 0.058967072, 0.035166958, 0.052296507 }, { 0.26970995, 0.21576211, 0.2954278, 0.29870678 }, { 0.40442043, 0.38744132, 0.14502571, 0.24076804 }, { 0.22655046, 0.20912486, 0.015295019, 0.16442957 }, { 0.69235319, 0.6080183, 0.36756076, 0.23314717 }, { 0.085565328, 0.075535626, 0.22162979, 0.33140596 }, { 0.16109547, 0.11961895, 0.26619212, 0.25941009 }, { 0.27077686, 0.23481238, 0.063446408, 0.11614487 }, { 0.026116057, 0.027491327, 0.030421883, 0.039965345 }, { 0.33922592, 0.38039792, 0.27167385, 0.31510976 }, { 0.32744968, 0.22567102, 0.23116584, 0.18867836 }, { 0.29783431, 0.28054079, 0.26752139, 0.23889932 }, { 0.61721263, 0.60602797, 0.51283622, 0.47601102 }, { 0.51383952, 0.53111455, 0.44519064, 0.42875877 }, { 0.3485879, 0.35374178, 0.53292055, 0.53995494 }, { 0.4366997, 0.35554257, 0.14878367, 0.22083288 }, { 0.12855375, 0.16718264, 0.17583661, 0.11125895 }, { 0.35898096, 0.37222307, 0.35439108, 0.35956111 }, { 0.16773044, 0.25668894, 0.23246756, 0.1506316 }, { 0.36172813, 0.26938211, 0.20069185, 0.1714591 }, { 0.3998571, 0.23607244, 0.34121623, 0.29126696 }, { 0.31471307, 0.29500525, 0.39451396, 0.40013999 }, { 0.29554399, 0.28083636, 0.47190649, 0.47892938 } }, { { 0.01419653, -0.061214452, -0.032506906, 0.0078227125 }, { -0.015799432, 0.0136148, -0.0090824684, 0.013638505 }, { 0.023848919, 0.022034707, 0.022812846, 0.022790329 }, { -0.0026324255, -0.0053566952, 0.00027470228, 0.050203583 }, { 0.0035659857, -0.02015272, -0.039043616, 0.054511651 }, { 0.0052075445, 0.0051043119, -0.011801097, -0.0074336577 }, { 0.020735195, 0.01811747, 0.00808952, 0.01140964 }, { -0.0073139049, 0.011075347, 0.0057685988, 0.010251582 }, { 0.024813488, -0.01629986, -0.012536791, -0.01110061 }, { -0.014508648, -0.021444084, -0.023836972, -0.014258253 }, { 0.0079687141, -0.00092011446, 0.060249601, 0.033199468 }, { -0.020822483, -0.013924875, -0.005068391, -0.016928794 }, { -0.030059, -0.013887475, -0.045329289, -0.04449219 }, { 0.007264541, 0.0015213919, -0.0066322618, -0.0036449174 }, { 0.0057175046, 0.0012159867, -0.00054271896, 0.0020625484 }, { 0.0027083179, -0.0012554897, -0.0044854592, -0.0045242423 }, { -0.017906563, -0.028301884, -0.010139427, 0.0035851304 }, { -0.020245794, 0.01149232, 0.011320484, -0.013561794 }, { 0.0068048997, 0.011957759, 0.0046962412, -0.0015476541 }, { -0.0022514613, 0.019996868, 0.0051520398, -0.023405604 }, { 0.0055213198, 0.0070384134, 0.024405643, -0.02050399 }, { 0.039987541, 0.021127504, -0.012323503, -0.0041538161 }, { 0.0072321478, 0.0053097351, 0.0039966161, 0.013617175 }, { 0.030470642, 0.0044694115, -0.0024591651, -0.0027274707 } }, { { -0.040500402, -0.039657034, -0.017497359, -0.017857145 }, { -0.0015646885, -0.020957371, -0.0057356498, -0.0060587007 }, { 0.0070388709, -0.013205178, -0.00033412934, 0.02192306 }, { -0.0042317723, 0.020620857, -0.012309167, 0.065948811 }, { -0.016686589, 0.013616667, 0.030139062, -0.019023551 }, { 0.015181564, 0.008673659, -0.0014559576, -0.025916054 }, { 0.031630671, 0.027030197, -0.026982415, 0.025214731 }, { -0.003845127, -0.00062884599, -0.029488655, -0.0051457939 }, { -0.0032476351, 0.0021153707, -0.033110808, -0.033629213 }, { -0.0064637077, -0.010805748, -0.014982403, -0.0084641529 }, { 0.0087766042, 0.017780238, 0.026838871, 0.032580257 }, { 0.0010700985, -0.037414784, -0.0053773565, 0.0040969752 }, { -0.02637392, -0.050236074, -0.048422986, -0.069357813 }, { -0.0089483588, 0.0026259727, 0.0040142797, -0.010752754 }, { -0.0025658872, 0.0071106029, 0.015467367, 0.0012536589 }, { -0.0037247444, -0.0036991733, -0.015429566, -0.016148852 }, { -0.024788221, -0.045938054, -0.028679471, 0.011593494 }, { -0.032699114, -0.036800967, -0.033870575, -0.031842203 }, { 0.018156047, 0.02457546, 0.0209432, 0.015057433 }, { 0.0043152638, 0.025831372, -0.019608349, -0.026614397 }, { -0.0057047815, -0.013831909, 0.027613211, -0.043616864 }, { 0.014124478, -0.010786326, 0.010775415, -0.023241344 }, { 0.018337827, 0.0048735321, 0.018371717, 0.022106807 }, { 0.013619207, 0.022051384, 0.0082720974, -0.0030262071 } } } }, { { { { 0.083322661, 0.079807165, 0.03660117, -0.051657142 }, { -0.099216074, -0.0080141573, 0.10637241, 0.0367403 }, { 0.20813681, -0.0001361621, -0.20762563, -0.085913357 }, { -0.22091149, 0.10003156, -0.16122219, 0.31542901 }, { 0.16226908, 0.02665194, -0.012123307, -0.16559939 }, { -0.14025496, 0.025804505, 0.076174345, 0.20548591 }, { 0.0035713609, -0.0092551928, -0.099937652, 0.0038879391 }, { 0.12405732, -0.0053373497, -0.030865175, -0.060934551 }, { -0.0060175826, -0.026583926, -0.075326797, -0.0063155886 }, { 0.036389362, 0.054175433, 0.06490927, -0.038784258 }, { 0.30604876, -0.030813476, 0.011402956, -0.21074796 }, { -0.31769497, 0.046793931, -0.038212559, 0.21137297 }, { 0.12952945, 0.20720126, 0.08525845, -0.14568109 }, { -0.09735197, -0.17799099, -0.12256082, 0.038889119 }, { 0.002114572, 0.026037779, -0.0036772795, 0.13478173 }, { 0.094577863, 0.0057382415, -0.087017736, -0.059444148 }, { 0.054953104, 0.071323301, 0.097417831, 8.3254475e-05 }, { -0.11005534, 0.027214076, 0.0059378205, 0.02443999 }, { 0.27096654, 0.1864966, 0.034810947, -0.25886676 }, { -0.35626794, 0.037256657, -0.17795321, 0.52988269 }, { 0.14913899, -0.0086988732, -0.028760192, -0.21779266 }, { -0.16010301, -0.17699785, 0.017269826, 0.17878541 }, { -0.0049504093, -0.02387924, -0.04034852, -0.060461173 }, { 0.10405347, 0.0072745723, -0.10244372, -0.072981984 } }, { { 0.019363393, 5.327311e-05, 0.0075925373, 0.0019542034 }, { -0.051707557, 0.06554253, 0.0050626046, -0.0061857803 }, { 0.022891698, 0.014872273, -0.020436928, 0.0069081531 }, { -0.044566611, 0.019854557, 0.023600607, -0.0055387351 }, { 0.02283957, -0.067086756, 0.088865856, -0.033915007 }, { 0.0020254431, -0.16422426, 0.032495902, 0.012460808 }, { -0.017316175, 0.023440087, 0.011459595, 0.0043887872 }, { 0.027714908, -0.06907548, 0.013578806, -0.009848884 }, { 0.0044782488, 0.0079432606, 0.010143137, 0.023589488 }, { 0.014325082, 0.0075465848, -0.0079373813, -0.0056032635 }, { 0.025123579, 0.01904807, -0.0092328848, -0.019002052 }, { -0.02633985, -0.019560519, -0.065544737, 0.0073352606 }, { 0.044308433, -0.0032233834, 0.01324206, -0.00047128106 }, { -0.076577611, -0.021853603, -0.020190543, 0.0026420865 }, { -0.0029799448, -0.0083566545, 0.14896601, 0.0078617095 }, { 0.021033237, -0.08234711, -0.020642328, -0.0089829962 }, { 0.043793881, 0.0096494147, 0.035831274, -0.01294602 }, { -0.014064874, 0.066144489, 0.0143429, 0.015113964 }, { 0.043111732, 0.0029232804, -0.016912145, 0.012142059 }, { 0.0014186333, -0.0078590166, 0.065781153, -0.038375123 }, { 0.02255714, -0.030191796, -0.078373164, -0.0017593196 }, { -0.033878798, 0.016266579, 0.013539653, 0.043519216 }, { 0.019046482, 0.0080403173, -0.0010755939, 0.03305222 }, { 0.023206448, -0.054323067, -0.035173093, -0.010873592 } }, { { 0.014068291, -0.026418786, 0.016375695, 0.0048801469 }, { 0.024404214, 0.0073572002, -0.027247654, 0.00093849398 }, { 0.012741523, -0.012913063, 0.0054881373, -0.021780769 }, { -0.020497215, 0.057437717, 0.0031122704, 0.014713732 }, { 0.012765254, -0.052846334, 0.048042201, 0.0016578534 }, { 0.031245254, -0.0469321, -0.057199738, 0.012436479 }, { -0.0022837759, 0.0068501747, 0.010541107, -0.0005227683 }, { -0.0187059, 0.0025631581, -0.0082184266, 0.0026294483 }, { 0.0053899388, -0.0199458, 0.0023448066, 0.016215236 }, { 0.021117204, 0.010868775, -0.016412681, -0.016399297 }, { -0.0026199223, -0.011436548, 0.0031355049, 0.011933919 }, { 0.017940023, 0.090292392, -0.061029038, 0.016388845 }, { 0.0074493061, -0.045849358, -0.082612855, 0.025851315 }, { 0.061276666, -0.024654813, 0.035447334, -0.025952766 }, { -0.0068267167, -0.02207426, 0.003724368, 0.0070458116 }, { 0.021714649, -0.017552721, -0.037105408, 0.024398534 }, { 0.0092901891, -0.021559075, 0.009034776, -0.016574279 }, { -0.017218595, -0.041930302, 0.003369899, 0.017959363 }, { -0.0022510875, 0.028106616, -0.042936548, -0.041948028 }, { -0.017145551, -0.032331654, 0.021486923, -0.020295391 }, { -0.023196465, -0.088353584, 0.010086154, 0.018689553 }, { -0.024508386, -0.00058959302, -0.02867958, 0.019018994 }, { 0.0088748911, 0.012528454, -0.016636351, 0.0078166115 }, { 0.00066772723, 0.001693912, 0.032066885, 0.016951148 } } }, { { { 0.015200105, 0.071414961, -0.020616434, 0.0063982643 }, { -0.084578144, -0.12318522, -0.035470756, 0.057833574 }, { 0.19487946, 0.44043059, 0.10981527, -0.31907303 }, { -0.17774238, -0.30460726, -0.53133003, 0.31186606 }, { -0.1172677, 0.3183613, 0.10375266, -0.066515168 }, { 0.054176263, -0.12382077, -0.033807438, 0.039809238 }, { -5.3634009e-05, 0.004084452, 0.005103199, -0.060697866 }, { 0.06093199, 0.060355274, 0.049176467, -0.060579228 }, { 0.054611799, 9.0520863e-05, -0.048891261, -0.047609349 }, { -0.036428706, 0.06336736, 0.0020843807, 0.033254378 }, { 0.26975732, 0.51328693, 0.29976157, 0.049031141 }, { -0.28383516, -0.48219276, -0.27898799, -0.033028759 }, { -0.078976834, 0.14077934, 0.098587186, 0.051336328 }, { 0.076281206, -0.074223398, -0.053178835, -0.099578331 }, { -0.056377095, -0.00066113896, -0.11597726, 0.058805777 }, { -0.0027130032, 0.12007881, 0.0081935835, -0.10415807 }, { -0.019349408, 0.06206561, -0.0079099126, 0.079363093 }, { -0.059959607, -0.0591041, -0.047505451, -0.0031496967 }, { -0.11419194, 0.20904287, 0.53960104, 0.10467592 }, { -0.21312862, -0.34770872, -0.54593093, 0.23230512 }, { -0.073229448, 0.12913, 0.27728133, -0.050627706 }, { 0.082312471, -0.24529296, -0.12381516, 0.05577292 }, { 0.03015389, -0.0015805638, 0.024306632, -0.080697961 }, { 0.061367564, 0.056058289, 0.041197211, -0.015551356 } }, { { -0.029269776, -0.030251548, 0.01352869, 0.0084860712 }, { 0.053983187, 0.047657625, -0.026379004, 0.022474039 }, { 0.011898439, 0.045120742, -0.024430477, -0.081318878 }, { -0.0012641508, -0.018495044, -0.030127865, -0.0088483264 }, { 0.040728292, 0.010691761, -0.023566342, 0.028045232 }, { 0.014593998, 0.0047006468, -0.049032498, -0.011446808 }, { 0.00045433705, -0.0030610749, -0.010359449, -0.0026455857 }, { -0.0026794352, -0.032142744, 0.010153936, -0.0034586152 }, { 0.0097198782, 0.0051005644, 0.03482872, -0.0043676475 }, { -0.0012381415, -0.025746274, -0.0081178021, 0.0041481596 }, { -0.01598781, 0.0048815642, 0.06313106, -0.0062291669 }, { 0.072970618, -0.041153529, -0.007457013, 0.059776924 }, { 0.0024768493, 0.0093018711, 0.024827984, 0.043842172 }, { -0.012927661, -0.023256709, -0.0035951539, -0.069710027 }, { 0.0064149713, 0.0019783425, 0.010135188, 0.019449636 }, { -0.0071551675, 0.015761815, 0.0086309278, 0.038854386 }, { 0.020978109, -0.0056696814, 0.0025526797, -0.017352926 }, { -0.010711116, -0.0097050903, 0.0022304504, -0.0039308489 }, { 0.036904234, 0.025927127, 0.028330671, 0.051193417 }, { -0.00076391153, -0.077528792, -0.029763477, 0.0033945843 }, { -0.01775202, 0.034507636, 0.065392848, -0.017840909 }, { -0.019567742, -0.019880035, 0.055214211, -0.02206159 }, { 0.01110111, 0.0022938832, -0.011417507, 0.017692635 }, { 0.050208493, -0.028178909, 0.0065276591, -0.0056267473 } }, { { 0.0065622702, -0.0012303136, -0.0081183663, 0.00079383048 }, { 0.030775912, 0.052260356, -0.019758331, -0.020044147 }, { 0.019016537, -0.043070451, 0.035298744, -0.040592775 }, { 0.010468089, 0.00057085185, 0.0081761984, 0.0033382478 }, { 0.047189462, -0.052695409, 0.021849623, 0.033585939 }, { 0.0012065616, -0.050287476, -0.065085924, -0.039012886 }, { -0.012294892, 0.006839242, 0.0051165438, -2.0711078e-05 }, { -0.03292822, 0.015299577, 0.0029119931, 0.0073040242 }, { -0.0086784873, 0.0085910164, -0.0059378411, -0.010259049 }, { -0.014191355, -0.011172486, -0.01299927, 0.015386671 }, { 0.040453224, -0.041489173, 0.015047889, 0.064340197 }, { -0.020000046, 0.058477092, -0.0018150465, 0.048536972 }, { -0.006105982, 0.03437044, 0.0087640339, 0.032868283 }, { -0.027120362, 0.016579996, -0.01708524, 0.011178424 }, { 0.030535528, 0.0058718219, -0.031240404, 0.024241052 }, { 0.003729958, -0.055735848, -0.0055392842, 0.03447519 }, { -0.04084502, -0.01227488, 0.0062970198, -0.021996031 }, { 0.053671675, -0.067787009, 0.0053426012, -0.0080796738 }, { -0.021911856, 0.038395527, -0.07713235, 0.024805484 }, { -0.0034319194, 0.0052741327, 0.026402991, 0.0012916612 }, { -0.033119652, -0.0046506889, 0.045613946, -0.050230593 }, { -0.0054612035, -0.033482221, 0.084267507, -0.0224334 }, { -0.0063348693, -0.0074524817, -0.0029629355, 0.035493958 }, { -0.0073519185, 0.045139911, 0.0022901735, -0.041385515 } } }, { { { 0.99640669, 0.99424882, 0.99911727, 0.99864438 }, { 0.99146493, 0.99235134, 0.99369348, 0.99764995 }, { 0.95848895, 0.89778665, 0.9720248, 0.943828 }, { 0.95896077, 0.9472107, 0.83168251, 0.89623886 }, { 0.97975356, 0.94759472, 0.99452924, 0.98394744 }, { 0.98863213, 0.99196902, 0.99652121, 0.97785007 }, { 0.99999362, 0.99994883, 0.99498061, 0.99814861 }, { 0.99040248, 0.99816269, 0.99831309, 0.99630173 }, { 0.99848953, 0.99964658, 0.9959596, 0.99884607 }, { 0.9986735, 0.99651874, 0.99788899, 0.99869411 }, { 0.91299789, 0.85766372, 0.953946, 0.97631002 }, { 0.90471405, 0.87481454, 0.959534, 0.97684726 }, { 0.9884254, 0.96811612, 0.9914694, 0.98799879 }, { 0.99232241, 0.98122887, 0.99103524, 0.99426948 }, { 0.99840731, 0.99966074, 0.99324506, 0.98912879 }, { 0.99551377, 0.99274778, 0.99617307, 0.9927827 }, { 0.99830144, 0.99552039, 0.99521214, 0.99684577 }, { 0.99211525, 0.9978808, 0.99885333, 0.99969634 }, { 0.95579147, 0.95995838, 0.84120087, 0.96022443 }, { 0.90975235, 0.9368621, 0.81871367, 0.8156339 }, { 0.98610091, 0.99158952, 0.96035822, 0.97468107 }, { 0.98366238, 0.9531543, 0.99215501, 0.98230604 }, { 0.99953301, 0.9997136, 0.99888998, 0.99490315 }, { 0.99267663, 0.998401, 0.99388534, 0.99721201 } }, { { -0.0021537732, 0.010607958, -0.0066166595, -0.0027390442 }, { -0.0069401807, 0.0053215201, 0.0062121114, 0.013403291 }, { -0.0035740125, -0.021839368, 0.00042431197, -0.029478899 }, { -0.007886159, -0.0087705321, -0.010570968, 0.0040635318 }, { -0.0021772698, 0.00025306776, -0.0092725896, -0.0075657706 }, { -0.010438319, -0.0072866821, 0.009272756, 0.0043932916 }, { -0.00058203184, 0.0081284104, 0.027749999, 0.0035426599 }, { -0.003604276, -0.012244348, 0.0072177908, 0.0026686264 }, { 0.011192179, 0.0069527119, 0.017278396, -0.0053058312 }, { -0.020276487, -0.0063228657, 0.013968347, -0.0021534789 }, { -0.0037534313, 0.00061399133, -0.02126817, 0.0085256452 }, { 0.015620795, -0.022637876, 0.00069280338, 0.0054369037 }, { 0.0095244184, -0.0026896982, -0.0057963534, 0.0067237437 }, { -0.0085689961, -0.004816024, -0.00088793436, -0.0034021999 }, { 0.015428153, 0.019777562, -0.011217833, 0.0095744159 }, { -0.003802304, 0.0022643577, 0.0054254827, 0.025560756 }, { -0.0053298651, 0.021621993, -0.01864184, 0.019120967 }, { 0.015380344, -0.0027384467, 0.0010235928, 0.0062792725 }, { -0.001166873, -0.0049586656, -0.014850883, 0.00057841904 }, { 0.0032865456, -0.033386196, 0.0032068954, 0.02854738 }, { 0.010308266, -0.000233004, -0.020287643, 0.0044441043 }, { -0.0040523345, 0.0050367711, 0.01627907, -0.010032412 }, { 0.0073463987, 0.00073274858, 0.002814661, 0.030221018 }, { 0.0057509063, -0.011441338, 0.01894259, 0.0077856453 } }, { { -0.0053054924, 0.0037677068, 0.0066263851, 0.0011220287 }, { -0.02212139, 0.013769097, -0.0013834097, 0.014152363 }, { -0.0008493126, 0.021473024, -0.0039313241, -0.017764981 }, { -0.00081897848, -0.0074161164, 0.0038179092, -0.0035760615 }, { 0.014045643, 0.015317904, 0.0045966739, 0.0075917156 }, { 0.0035574126, -0.00017773424, -0.0010937491, -0.0017762282 }, { 0.0072018344, 0.012586227, 0.0138702, -0.0085424173 }, { -0.0055783456, -0.019909385, 0.01190919, -0.0065821489 }, { 1.7402026e-05, 0.0094513341, 0.015333305, -0.0072158969 }, { -0.0063049905, 0.0021776758, 0.014376378, 0.0072426401 }, { -0.0078049673, 0.028764242, -0.0024169449, 0.0077604105 }, { 0.00047536469, 0.029806623, 0.0017798261, 0.00087410198 }, { -0.0030498401, 0.0044874501, 0.0020382571, -0.0011101062 }, { -0.0057084397, -0.0013428994, -0.001024136, 0.0066188614 }, { 0.039201052, 0.015120258, -0.0082642793, 0.0051985023 }, { -0.0091203243, 0.020790215, 0.0025270937, 0.020092044 }, { -0.0029830063, 0.006602841, -0.00833601, 0.044852353 }, { 0.025206353, -0.0038915173, 0.00045914851, 0.0037840538 }, { 0.0014814254, -0.011573911, 0.046232337, -0.015228958 }, { -0.0071984443, 0.0090004063, 0.022942838, 0.016019787 }, { 0.0050929336, 0.0060892107, -0.0061771339, 0.0047850766 }, { -0.011634853, 0.0010276548, 0.022396644, -0.0021248711 }, { -0.012943002, 0.0016430074, 0.02034928, 0.024289705 }, { 0.0051047037, 0.010052556, 0.0020923265, -0.019043181 } } }, { { { 2.1627647, 2.1788232, 1.9290264, 1.8457806 }, { 2.526488, 2.3020441, 2.538915, 2.03484 }, { 3.9987521, 4.3952121, 3.906821, 4.1693278 }, { 4.0400466, 4.1069844, 5.2512999, 5.4283264 }, { 3.0141968, 3.3306035, 3.2224806, 3.2473051 }, { 2.9840674, 3.1294685, 3.2964833, 3.2929246 }, { 1.8346741, 1.8637353, 2.3037966, 2.0860888 }, { 2.691236, 2.6068079, 1.9349032, 2.1632935 }, { 1.9231956, 1.7251627, 2.1609654, 2.1155629 }, { 2.165771, 2.1908952, 1.777038, 2.0223741 }, { 4.5166991, 4.8674508, 3.918546, 3.378087 }, { 4.4502295, 4.5429338, 3.9552598, 3.3580272 }, { 3.0973598, 3.3953852, 2.2704362, 2.6488177 }, { 3.2110537, 3.3104376, 2.515002, 2.3267785 }, { 1.8303675, 1.7094345, 3.1787979, 2.5960104 }, { 2.4391795, 2.8730077, 2.3730261, 2.1545299 }, { 2.2130903, 2.1899209, 2.4997355, 1.9058674 }, { 2.6472893, 2.5455636, 2.1164596, 1.8341163 }, { 3.9428283, 4.0433678, 4.5430063, 4.2482776 }, { 4.1941673, 4.28852, 4.64044, 4.6644567 }, { 3.0873642, 2.649364, 3.6026133, 3.2426354 }, { 3.2415154, 3.5406745, 3.2976852, 3.3100246 }, { 1.8400289, 1.8404692, 1.889289, 2.0125184 }, { 2.7063995, 2.7229173, 2.6289878, 2.4313709 } }, { { -0.015335928, -0.043382119, -0.0054163805, -0.028249934 }, { -0.017200109, 0.0027582413, -0.079612821, -0.0013966663 }, { -0.027233584, -0.018783395, -0.01183278, -0.020918937 }, { -0.0036358348, -0.015712206, -0.0089146421, -0.0057117233 }, { 0.020392865, 0.017743746, -0.068597326, -0.030425581 }, { -0.041123673, -0.020767538, -0.0087941887, -0.0065248183 }, { -0.0055478408, -0.00082196865, 0.0088521402, -0.045916836 }, { -0.010506485, 0.0078523247, -0.030002306, -0.0015085765 }, { 0.01894068, -0.012424968, -0.034837214, -0.045009941 }, { -0.045299587, 0.02630478, -0.017175711, -0.043601235 }, { -0.046003661, -0.020588165, 0.034398873, -0.054653787 }, { -0.0042534368, 0.01325834, -0.0036369576, -0.079162988 }, { -0.028728556, 0.0051289128, 0.012104313, 0.010686997 }, { -0.066337767, 0.00059928728, -0.080303668, 0.011318772 }, { -0.031879871, 0.0011317962, -0.050259029, 0.0031596552 }, { -0.090121238, -0.011196084, -0.072456123, -0.00079731072 }, { -0.024243475, 0.021401076, -0.018209385, -0.0083196072 }, { -0.079888701, 0.0032806631, -0.12762259, -0.04652308 }, { 0.031806075, -0.034165157, -0.015255921, -0.049164663 }, { -0.0012051123, 0.030788487, 0.022291919, 0.0025694519 }, { 0.035836509, 0.0055365388, 0.026704836, 0.0001547235 }, { -0.012129747, -0.0094322145, -0.040637935, -0.12125388 }, { -0.027044986, 0.04531553, -0.033484589, -0.0059927923 }, { 0.0067188802, -0.051166351, -0.048822794, -0.025926988 } }, { { 0.022049053, 0.021265778, -0.040370641, -0.036232952 }, { -0.0058098424, -0.0042264198, -0.077428509, -0.04241654 }, { -0.0026825379, -0.029453318, -0.016181275, -0.028320229 }, { -0.012541692, -0.01345735, 0.00037814888, -0.0046052489 }, { -0.026527394, 0.020033638, -0.025683861, -0.084207169 }, { -0.0010459945, -0.036745215, -0.039772051, 0.024810839 }, { 0.012134618, 0.0068515798, -0.035286972, 0.043129595 }, { -0.077093357, -0.026872688, 0.032800133, -0.090326706 }, { 0.13930909, 0.0081274014, -0.08349188, -0.012200005 }, { -0.091693797, -0.012567011, -0.069736822, -0.0061444184 }, { -0.053061301, 0.003642159, 0.0052515175, -0.036957472 }, { 0.0043493933, -0.013069332, -0.014708126, -0.032765039 }, { -0.016116105, -0.022907609, -0.043503106, -0.013266465 }, { -0.072759977, -0.077354585, 0.0043827591, -0.013821612 }, { -0.032399073, -0.045305037, -0.021840791, 0.073996542 }, { -0.057239255, -0.056581235, -0.038880927, 0.044102943 }, { -0.026951489, -0.088667645, -0.013659704, 0.033527579 }, { 0.034815442, -0.028634059, -0.036666529, 0.011546036 }, { 0.026688447, -0.0081892129, -0.031138092, -0.041739155 }, { 0.0015665701, -0.012701682, 0.0013533943, -0.002849785 }, { 0.032994636, 0.008802974, 0.019032649, 0.0039042621 }, { -0.044544917, 0.0093201326, -0.017968915, 0.01936344 }, { -0.034794535, 0.043032983, -0.051072531, -0.040148303 }, { -0.0030398597, -0.027112065, -0.064007483, -0.01798277 } } }, { { { 0.22040906, 0.24911942, 0.41660708, 0.23632869 }, { 0.25894466, 0.1416669, 0.41902981, 0.35717608 }, { 0.26918091, 0.14566759, 0.2147652, 0.15769391 }, { 0.22500921, 0.12113361, 0.11151768, 0.12348609 }, { 0.25699055, 0.056819107, 0.3859882, 0.4585378 }, { 0.7304995, 0.20719358, 0.44455636, 0.42226989 }, { 0.43602897, 0.51049581, 0.41978824, 0.62521039 }, { 0.42004119, 0.52912054, 0.33314238, 0.38257921 }, { 0.55092562, 0.43085653, 0.31149977, 0.34391138 }, { 0.40391149, 0.48820255, 0.13569806, 0.36060266 }, { 0.13647907, 0.12061002, 0.20668806, 0.30221394 }, { 0.15583476, 0.13133696, 0.22775202, 0.35653823 }, { 0.56336195, 0.25684627, 0.11118383, 0.23109245 }, { 0.45430401, 0.42843367, 0.25496534, 0.097473509 }, { 0.3420223, 0.39418925, 0.26458947, 0.30588082 }, { 0.51345558, 0.3612731, 0.41151773, 0.25269512 }, { 0.29195176, 0.42659964, 0.47971993, 0.32714756 }, { 0.49222777, 0.28477645, 0.74993827, 0.43781271 }, { 0.098434481, 0.31164923, 0.14486345, 0.11466693 }, { 0.070833248, 0.20569754, 0.10233576, 0.047352701 }, { 0.51050902, 0.15597643, 0.1417112, 0.35581415 }, { 0.48261165, 0.14592221, 0.62554576, 0.5209765 }, { 0.33562628, 0.39920067, 0.28183433, 0.297464 }, { 0.366851, 0.59278666, 0.59095922, 0.48385165 } }, { { 0.13792051, 0.072076744, 0.094800532, 0.026318377 }, { 0.13607414, -0.061382542, 0.061800151, -0.020060553 }, { 0.028096406, 0.069282616, 0.010195109, -0.010461141 }, { 0.018651237, 0.02642439, 0.0077552848, -0.051151646 }, { 0.098299803, -0.0085081153, -0.011764584, 0.087405711 }, { 0.064082346, -0.04626424, -0.071480607, 0.064447268 }, { 0.022766233, 0.0167542, -0.021285286, -0.071637286 }, { -0.0202445, 0.011692601, 0.048325551, 0.0097755172 }, { -0.027775183, 0.016463115, 0.060050391, -0.034226107 }, { 0.019412547, 0.059977501, -0.0041737169, 0.031539317 }, { 0.013192979, 0.036015595, -0.049943198, 0.014112312 }, { -0.013272349, 0.035821037, -0.060503687, 0.095316821 }, { 0.038338785, -0.059038809, -0.044954172, -0.00051347307 }, { -0.039594082, 0.018205882, 0.13413799, 0.012292954 }, { 0.015177594, -0.0082493854, 0.00029420179, 0.010356248 }, { 0.100271, -0.13623174, 0.1121235, 0.068902399 }, { 0.025189636, 0.0014918434, 0.0088847718, -0.053714493 }, { 0.06487698, -0.097217547, -0.069537353, 0.032490984 }, { -0.030729608, 0.048956315, 0.016036034, 0.022485239 }, { 0.049839618, 0.01148525, -0.021032427, -0.019665817 }, { -0.0037762817, -0.030422275, -0.062343207, 0.057994884 }, { 0.014035184, -0.021387762, -0.080846143, -0.020681511 }, { -0.03594567, 0.026862531, 0.078975557, -0.034056659 }, { -0.014490672, 0.026128902, 0.045617611, 0.090192953 } }, { { 0.011904288, -0.014624471, 0.042023114, 0.019592867 }, { 0.032705848, 0.00038558691, 0.031901745, 0.027208951 }, { -0.044369719, -0.039761364, -0.013366816, -0.019308126 }, { -0.019051023, -0.00015767269, -0.082968285, -0.035266053 }, { -0.004775162, 0.010889271, 0.0089521094, 0.027037104 }, { 0.005616143, -0.00099668486, 0.0068716426, -0.12649184 }, { 0.018531199, 0.023881776, -0.053798787, -0.041912909 }, { -0.0036187094, 0.11590788, 0.025140733, 0.022280209 }, { -0.02994342, -0.026293799, -0.017204658, 0.044901944 }, { 0.079892089, 0.10816526, 0.14667807, 0.027301352 }, { -0.045296738, -0.066748968, -0.0099354431, -0.070369692 }, { -0.08357374, -0.043311901, 0.013163375, -0.0881777 }, { -0.065923811, -0.10382274, 0.090440302, -0.013617198 }, { -0.092578587, -0.010178017, -0.01416593, 0.0432333 }, { 0.055172515, 0.10021805, -0.0062782668, -0.11791805 }, { -0.039684132, -0.08934283, 0.020686084, -0.0013788117 }, { 0.064624676, 0.051773746, 0.0045383964, -0.037696971 }, { -0.066296373, 0.020570689, -0.017742721, -0.022651449 }, { -0.0061572447, -0.094510525, -0.094775804, -0.038022514 }, { 0.0055683313, 0.039513342, -0.096815654, -0.0065483011 }, { -0.03311602, -0.018395457, 0.0028464434, -0.088048272 }, { -0.073106109, -0.055187863, -0.093209932, -0.10155137 }, { 0.042841842, -0.005778703, 0.074069607, -0.025841052 }, { -0.018569637, 0.063144303, 0.02291584, 0.005525742 } } } }, { { { { -0.20809663, -0.18346453, -0.072140694, -0.0078104407 }, { -0.19490097, 0.25712922, 0.37640771, 0.11563399 }, { 0.26894915, -0.33477877, -0.093739129, -0.55078405 }, { -0.65794103, 0.09211629, -0.19166986, 0.5574327 }, { 0.45579532, 0.23202083, 0.19626303, -0.64130523 }, { -0.018763975, -0.24981569, -0.32514026, -0.11121342 }, { 0.22376238, 0.09515938, 0.071728264, -0.02790747 }, { -0.3053338, 0.34023365, 0.099862481, 0.26163964 }, { -0.21722968, -0.094881958, -0.086364431, -0.0081863581 }, { -0.16090709, 0.23527698, 0.28947119, 0.11309742 }, { 0.26447184, -0.33536416, -0.096418234, -0.26201294 }, { -0.56343769, -0.041662822, -0.24873841, 0.67122901 }, { 0.35362642, 0.2577592, 0.2009013, -0.74233681 }, { -0.047956299, -0.54973418, -0.4958485, -0.12453303 }, { 0.06917425, 0.080509853, 0.0090863722, -0.023518805 }, { -0.27000602, 0.083167162, 0.12715558, 0.12397839 }, { -0.11376964, -0.079199259, 0.019676685, -0.0094352472 }, { -0.19185851, 0.22193112, 0.28110877, -0.06422845 }, { 0.084091992, -0.16151548, 0.091400556, -0.28257376 }, { -0.53821376, 0.21718328, -0.2234907, 0.52302804 }, { 0.71322306, 0.042728493, 0.13229522, -0.61892094 }, { 0.15270046, -0.26304886, -0.33110633, -0.052728951 }, { 0.072398971, 0.25829764, 0.25881687, -0.020942042 }, { -0.26788161, 0.055822039, 0.33817103, 0.42061402 } }, { { 0.088248648, 0.091306255, 0.020476927, 0.0030144802 }, { 0.0087376707, 0.043816157, 0.0022807168, 0.016745414 }, { -0.13412414, 0.12686539, 0.060531476, 0.044582027 }, { 0.019204757, -0.0070891897, 0.091194602, 0.065258927 }, { -0.10429513, -0.027665602, -0.064350626, 0.0053147478 }, { 0.069218141, -0.035018324, -0.088257571, 0.019279642 }, { -0.073137338, 0.040764456, -0.022352804, 0.031743288 }, { 0.040325697, -0.12840825, -0.009582113, 0.034509657 }, { 0.081971224, -0.0035223125, -0.051728499, 0.0038899717 }, { 0.050968435, 0.022254651, 0.18781134, -0.032392139 }, { 0.024342518, 0.13929014, -0.019175435, -0.0011608234 }, { -0.0021942487, -0.01251222, 0.024263454, -0.063179344 }, { -0.13071776, -0.059221747, -0.034153238, 0.036561209 }, { 0.054124093, 0.070495803, 0.081441614, 0.051900357 }, { 0.027480327, 0.028940343, -0.01469313, 0.032388411 }, { -0.039696828, -0.0069393798, -0.011361641, 0.035031025 }, { -0.039730763, 0.0085971581, -0.0077461932, -0.040735188 }, { 0.10893368, 0.00014757217, 0.025489178, -0.11388774 }, { -0.0013816669, 0.0031148929, 0.10281666, -0.019860642 }, { -0.065093128, -0.11495815, 0.041783056, -0.091373461 }, { -0.044985581, 0.0012713031, -0.16078032, 0.17303747 }, { -0.038132358, -0.02995975, -0.037612782, 0.012575173 }, { 0.0042976619, 0.027014275, 0.017518808, 0.030405184 }, { -0.0015298607, 0.029297664, -0.1034349, 0.023450502 } }, { { 0.028785558, -0.028708377, -0.010459636, 2.8360915e-05 }, { 0.091634877, 0.021214811, 0.12282079, 0.080617943 }, { -0.29287977, 0.045481846, 0.014712563, 0.057317576 }, { -0.10728772, 0.03268482, 0.015167285, -0.011256231 }, { 0.09337321, 0.037150859, 0.052549202, -0.042671474 }, { -0.0041288689, -0.024299997, -0.11357403, -0.022045772 }, { -0.041469935, -0.0071353646, -0.0086607538, 0.008536762 }, { 0.033629272, -0.0070042955, -0.037864853, -0.0055907778 }, { 0.016404597, -0.0055321059, -0.020989839, -0.013771265 }, { 0.042552435, 0.04428518, 0.0030587466, 0.044894182 }, { -0.027600219, 0.026831779, 0.051120849, -0.032184808 }, { 0.13870554, 0.15273282, 0.049260112, 0.043371121 }, { -0.018453269, -0.18061413, 0.24805649, -0.031741165 }, { -0.085137374, 0.025935867, 0.015978067, 0.067726486 }, { 0.072393868, 0.0050430488, 0.0016664585, 0.0072097064 }, { 0.033840162, 0.082225764, -0.079387016, 0.033165625 }, { 0.033170766, 0.0012231618, -0.066984982, 0.051671704 }, { 0.017894231, -0.012267532, 0.045536123, -0.07327109 }, { 0.0073109731, -0.063797898, -0.13446413, 0.1408986 }, { -0.045702456, -0.1647051, -0.14336468, 0.054543693 }, { 0.0042448876, -0.13234456, 0.092181719, -0.10440841 }, { -0.060020212, -0.011098469, -0.030257182, -0.030922037 }, { -0.018118661, 0.00067983745, -0.0061776598, -0.031721273 }, { -0.019885189, 0.094157888, 0.014017961, -0.051373389 } } }, { { { 0.12415319, -0.13611564, -0.029441661, -0.14143497 }, { -0.26074418, 0.011913326, -0.033328425, 0.43248793 }, { 0.19336432, 0.37269586, 0.36803538, -0.51720719 }, { -0.15185913, -0.47431781, -0.6593667, 0.23163184 }, { 0.18276216, 0.19248743, 0.65453332, 0.54748087 }, { 0.17751443, -0.0020337696, 0.08506463, -0.40147769 }, { -0.11370932, 0.11523476, -0.010573025, 0.082295392 }, { -0.13666335, -0.32747478, -0.16897386, 0.15359006 }, { 0.11716326, -0.12259922, 0.0033396256, -0.13240653 }, { -0.27776876, -0.10222241, -0.039920479, 0.35499708 }, { 0.090003723, 0.3313923, 0.1871549, 0.003163675 }, { -0.51626118, -0.76341562, -0.56326874, 0.20153559 }, { -0.34172723, 0.26975563, 0.67520079, -0.1252004 }, { 0.45758078, -0.19142179, 0.064180031, -0.48748431 }, { -0.12800789, 0.1399912, 0.0077954775, 0.14379741 }, { -0.13042104, -0.45670817, -0.18831095, 0.0032738639 }, { 0.12446807, -0.11504524, -0.027331682, 0.03861758 }, { -0.31337986, -0.11842668, 0.033415325, 0.45344231 }, { 0.11463107, 0.077427841, 0.060880794, -0.069619455 }, { -0.37772106, -0.59628905, -0.65426572, 0.065297039 }, { 0.29532991, 0.75920243, 0.53294265, -0.15002562 }, { 0.3618333, 0.10488387, 0.36007528, -0.30963565 }, { -0.13738196, 0.20795596, 0.029274703, 0.18017599 }, { -0.10290023, -0.48517535, -0.33278584, 0.56477854 } }, { { -0.0047891472, 0.024629901, 0.015256654, -0.0084462001 }, { 0.056227746, -0.048057782, -0.15671312, 0.06418471 }, { -0.070093217, -0.018057199, 0.062026545, -0.051053726 }, { -0.0091221476, 0.0020547295, -0.087729813, -0.10164738 }, { 0.098917091, -0.066835916, 0.083151519, 0.006342544 }, { 0.0013540606, 0.038719082, 0.036333261, -0.053178668 }, { 0.0083787438, 0.0028359378, 0.0089872852, 0.031308249 }, { 0.014379686, -0.079563474, -0.079160006, -0.016352226 }, { 0.0091376645, -0.016678006, -0.044636785, -0.0011035265 }, { 0.0099146109, 0.027589302, -0.09494437, 0.07451767 }, { 0.017453983, 0.080674871, 0.06341808, 0.048820473 }, { 0.02794057, 0.058230195, -0.010793601, 0.091813872 }, { -0.049633232, -0.1142016, 0.036984283, 0.0034294865 }, { 0.047712957, 0.10161366, 0.13774722, 0.039503136 }, { 0.014194782, -0.014555183, -0.00053182909, 0.0019143477 }, { 0.0014900262, 0.0056176356, -0.034517871, -0.0010707988 }, { 0.013287784, -0.0073967933, -0.019271341, 0.016354896 }, { -0.10345626, 0.023536634, 0.027943639, -0.015686972 }, { -0.025193395, -0.10224801, 0.078686884, -0.048574399 }, { 0.15797878, -0.0012322757, -0.036096649, -0.23983963 }, { -0.10455507, -0.056368102, -0.06570944, 0.29104616 }, { 0.05155239, -0.040940824, -0.038367594, 0.058174485 }, { 0.010471732, -0.066952904, -0.047763843, -0.021124742 }, { -0.033555686, 0.0049111983, -0.026592789, 0.014438586 } }, { { -0.0048440946, 0.025915095, -0.018325403, 0.022133613 }, { 0.059240081, -0.031272176, -0.12967647, -0.17957913 }, { 0.0574837, 0.067005152, 0.024644254, 0.10786296 }, { 0.067084865, 0.008513386, 0.04077659, 0.10587924 }, { 0.026332643, 0.1072618, -0.098375042, -0.001724609 }, { -0.021386362, -0.0020174921, 0.16800158, 0.081359882 }, { -0.018204146, -0.026432136, -0.0068153455, -0.029997667 }, { -0.043221501, -0.016869967, -0.067406967, -0.024965804 }, { -0.0033879999, 0.031310818, -0.010853802, 0.00088944004 }, { -0.068991006, 0.087874253, -0.15737392, -0.088870044 }, { 0.061763806, -0.00072874343, -0.009915009, -0.0178225 }, { -0.07340717, 0.080339271, -0.0027124572, -0.13078641 }, { -0.023682834, 0.16512313, -0.15784472, 0.047978827 }, { 0.0063250439, -0.09953777, 0.094180888, 0.010565041 }, { 0.010047311, -0.042999009, -0.012483998, -0.016966759 }, { -0.048612679, 0.051708319, 0.015059148, 0.0036776472 }, { -0.011737015, -0.0027276603, 0.026535075, -0.065453876 }, { 0.056388137, 0.061461073, -0.12726984, -0.025578248 }, { 0.0016833003, 0.10878558, 0.13254828, -0.017098914 }, { -0.031606282, -0.072245098, 0.12724789, -0.21852899 }, { -0.062502612, -0.073402771, -0.049624729, 0.069066032 }, { -0.075837195, -0.10297347, -0.07249237, -0.11538062 }, { -0.015644005, 0.039474396, 0.074415075, -0.038881161 }, { -0.040175911, 0.034030267, 0.03947059, 0.014167463 } } }, { { { 0.97019677, 0.97355703, 0.99695983, 0.98991674 }, { 0.94552952, 0.96630359, 0.92585444, 0.89419404 }, { 0.9435447, 0.86545998, 0.92507456, 0.65508294 }, { 0.73759908, 0.87552111, 0.72697883, 0.79725496 }, { 0.87111918, 0.95347518, 0.73011435, 0.53758004 }, { 0.9839393, 0.96829127, 0.94183216, 0.90909143 }, { 0.96798791, 0.98876976, 0.99736817, 0.99621717 }, { 0.9423876, 0.88147679, 0.98054848, 0.95286662 }, { 0.96906348, 0.98791034, 0.99625801, 0.99116169 }, { 0.94707625, 0.9665378, 0.9563539, 0.9280011 }, { 0.96018435, 0.88187869, 0.97758711, 0.96505917 }, { 0.64499021, 0.64456248, 0.78794513, 0.71332673 }, { 0.87073007, 0.92778882, 0.70974824, 0.65822558 }, { 0.88787388, 0.81311133, 0.86603417, 0.86420517 }, { 0.98935782, 0.98687417, 0.99992833, 0.98932764 }, { 0.95398485, 0.88572054, 0.97384313, 0.99227952 }, { 0.98567955, 0.99019799, 0.99943274, 0.99920952 }, { 0.93004482, 0.96784384, 0.95909399, 0.88896838 }, { 0.98984254, 0.98382807, 0.99395144, 0.95671584 }, { 0.75342733, 0.77283296, 0.72248756, 0.84981055 }, { 0.63568318, 0.6494505, 0.83574524, 0.77099234 }, { 0.91965169, 0.95906448, 0.87218942, 0.94939213 }, { 0.98786871, 0.94341754, 0.96548269, 0.98341143 }, { 0.95794101, 0.87263324, 0.8802806, 0.71000638 } }, { { -0.0064390277, 0.051629953, -0.011423447, 0.032337826 }, { 0.055030538, 0.061305324, -0.016012659, 0.083766345 }, { 0.052467122, 0.018425134, -0.00054737782, 0.048038459 }, { 0.076436505, 0.016815709, -0.024174832, -0.00829119 }, { 0.057903371, 0.068822104, -0.0064003131, 0.00010695928 }, { 0.067104151, 0.067284611, 0.0074295447, 0.024215238 }, { 0.073380541, 0.01486405, 0.01523157, 0.012966612 }, { -0.0002536971, 0.010628632, 0.00045031869, 0.041891438 }, { 0.055922922, 0.0090823157, 0.011101162, 0.033807592 }, { -0.040264953, 0.022318628, -0.013682045, -0.016112502 }, { -0.034286564, 4.7089727e-05, -0.013030079, -0.012231424 }, { 0.027756308, 0.084041595, 0.018308393, 0.11564334 }, { 0.0026690817, 0.058149333, -0.013682964, 0.052975934 }, { -0.03852481, 0.063493354, 0.059460027, 0.047740976 }, { 0.026410264, -0.0073902435, 0.022353771, 0.012987341 }, { 0.035217135, -0.0023455309, -0.0055505614, 0.010102857 }, { 0.00075590283, 0.038624793, -0.0040614962, 0.070039437 }, { -0.02318411, 0.04527054, 0.013119286, 0.025335215 }, { 0.021268391, 0.044855911, 0.012622905, 0.04827088 }, { -0.0046678346, -0.01934799, 0.018393432, 0.09750434 }, { 0.12480373, 0.059151139, 0.055196092, 0.26701338 }, { -0.0096669036, 0.065624767, 0.016918517, 0.028425135 }, { 0.026488514, -0.0037618693, 0.0077028717, 0.041713399 }, { 0.018628451, 0.033145064, 0.029067918, -0.000924258 } }, { { -0.043525781, 0.028119778, -0.011653105, -0.020930158 }, { -0.028099186, 0.017594088, -0.099226445, 0.10408808 }, { 0.11750066, -0.0010629746, 0.018381448, 0.096538552 }, { 0.0010069446, 0.013799541, 0.1325137, 0.020820734 }, { -0.053571928, -0.0066793785, 0.14596488, -0.03272949 }, { 0.028507895, 0.015474376, -0.025411653, 0.037264272 }, { 0.033698911, 0.018088387, 0.0038898537, 0.03163178 }, { 0.0057766828, 0.015879322, 0.012557033, 0.071771631 }, { -0.0044521866, 0.0083963511, -0.0020426175, 0.023784146 }, { -0.011508765, 0.0075020051, 0.0018808294, 0.040843424 }, { 0.0085150894, 0.0056891711, 0.010134672, 0.046224768 }, { 0.040825446, 0.10099754, 0.021853299, 0.024507528 }, { -0.0055958303, -0.0060958, 0.1115321, -0.021701014 }, { 0.010487817, -0.010033143, -0.031203025, 0.054265436 }, { 0.0040500672, 0.0053935875, 0.018233022, 0.018797311 }, { 0.064057639, 0.014318185, 0.0199119, 0.014366235 }, { 0.02411682, 0.045454692, 0.0030084434, 0.019464939 }, { 0.012500289, 0.027734846, 0.0025097372, 0.047343669 }, { 0.037625829, -0.00064472688, 0.0557556, 0.04785655 }, { 0.0020433437, 0.019929208, 0.087936103, -0.036738471 }, { 0.020811556, 0.0915387, 0.055445303, -0.065132763 }, { 0.03911814, 0.043721622, 0.0074336204, -0.031370424 }, { 0.014072509, -0.014795458, 0.010517063, 0.022409628 }, { -0.0054107234, 0.055313602, 0.053556404, 0.048574319 } } }, { { { 3.4224197, 3.3162336, 3.1136621, 3.3189801 }, { 4.0715355, 3.5614196, 4.1797877, 4.0959601 }, { 4.3979407, 4.1858272, 4.3116447, 4.5467451 }, { 4.4920032, 4.0716439, 4.6107962, 4.5268016 }, { 5.6570832, 4.9036495, 4.7373547, 4.7259419 }, { 3.3277827, 3.6015237, 4.226646, 3.7939772 }, { 3.4893058, 3.3260638, 3.0626103, 3.1798705 }, { 3.6423735, 4.1092281, 3.3264203, 3.7325301 }, { 3.4756581, 3.2550256, 3.224671, 3.4093307 }, { 3.8511362, 3.4821381, 4.3232597, 3.7357164 }, { 3.6688024, 4.0797971, 3.4140927, 3.6881261 }, { 4.5298469, 4.7472506, 4.4046473, 4.7279944 }, { 4.1614448, 4.1242955, 4.6741969, 5.0037875 }, { 4.3148703, 4.3815566, 4.1976536, 3.9032858 }, { 3.2640506, 3.3214728, 2.9463564, 3.3562068 }, { 3.6729325, 3.9218642, 3.4550701, 3.4833871 }, { 3.435975, 3.3079446, 3.3432341, 3.3632985 }, { 3.8404619, 3.4716915, 3.858149, 3.8677391 }, { 3.3181827, 3.8403872, 4.0363918, 3.9604287 }, { 5.0916792, 5.2773748, 4.5404255, 4.377031 }, { 4.6514614, 4.7569957, 4.1233238, 4.4022582 }, { 3.6884833, 3.6283543, 4.1874612, 4.2963913 }, { 3.456705, 3.6250566, 3.5292789, 3.1420033 }, { 3.5986317, 4.0596074, 4.0696874, 4.5327067 } }, { { -0.12592901, -0.14780788, -0.11051274, -0.18767653 }, { -0.020435093, 0.0055221209, -0.021183195, -0.15159792 }, { 0.022498629, -0.025100789, -0.30939177, 0.016420202 }, { 0.21296442, -0.042976575, 0.082118132, 0.14574735 }, { -0.13608022, 0.16141834, -0.015091164, 0.044951541 }, { -0.08235774, -0.10333151, 0.089785432, -0.036620639 }, { -0.17664465, -0.015842477, -0.083075331, -0.15660828 }, { -0.11292423, -0.072894494, -0.068901923, -0.2283674 }, { -0.19063437, -0.071954393, 0.091375283, -0.26993547 }, { 0.042798331, -0.06495575, 0.050221766, 0.024602586 }, { -0.026228614, 0.0049810367, 0.046584088, -0.13067577 }, { 0.072779737, -0.023369437, -0.030275791, 0.19591126 }, { -0.018649072, 0.029208952, 0.012033439, 0.00094798196 }, { -0.094599446, 0.0070746366, -0.0007115864, -0.040175552 }, { -0.027599009, -0.068747365, 0.19480498, -0.19423733 }, { -0.076671551, 0.0075475135, 0.019853903, -0.012984601 }, { 0.064371855, -0.24044027, -0.043765356, 0.0016424127 }, { -0.076744435, 0.035881398, 0.12967612, 0.081825243 }, { -0.15224256, 0.032665115, -0.027927205, 0.076091133 }, { -0.0057973613, -0.14914213, -0.047678749, -0.037214457 }, { 0.10060085, -0.099197666, -0.22704457, -0.0020812401 }, { -0.070664558, -0.13179176, -0.014217065, -0.030410253 }, { -0.12286487, -0.046623366, -0.10695394, -0.0081383175 }, { -0.14561788, 0.02765909, 0.10439783, 0.033139041 } }, { { 0.0063171031, -0.0047223477, -0.056312039, -0.065065766 }, { -0.0059575982, -0.062348475, 0.069540315, -0.090331962 }, { 0.10218203, 0.050383376, -0.0089914697, -0.037837343 }, { -0.0037657879, 0.18278082, 0.079014627, -0.052587294 }, { -0.33929282, 0.018522098, 0.0078923893, 0.042545349 }, { 0.027294929, -0.086490439, -0.0057363347, -0.035932082 }, { -0.061716003, -0.14470599, 0.033117786, -0.08112808 }, { 0.16414856, 0.082471596, -0.058497326, 0.050552718 }, { -0.07627083, -0.0064181717, -0.031179581, -0.075705068 }, { -0.057808009, -0.00074561624, -0.23990956, 0.018671772 }, { 0.1677602, 0.10757253, 0.028015134, -0.23923178 }, { 0.078827365, 0.068682485, 0.056277532, -0.069749241 }, { 0.079502977, 0.05526585, 0.0089767144, -0.15319341 }, { -0.038594242, -0.055488998, -0.043132461, 0.054313031 }, { 0.12890592, -0.082639555, 0.22520491, -0.026781096 }, { -0.071292391, 0.064592881, -0.050368563, -0.072488866 }, { 0.092998671, 0.12152394, 0.033318795, -0.039691417 }, { -0.0049706273, -0.0014175115, -0.11634604, 0.15219284 }, { -0.012414906, 0.035583927, -0.072463074, -0.058394705 }, { -0.071558898, -0.00093653835, 0.013149622, 0.01495775 }, { -0.057103279, 0.013702583, -0.020242751, 0.04649072 }, { -0.083398977, -0.20123674, 0.062758815, -0.043671819 }, { 0.084479675, 0.17868517, -0.021185269, 0.15711776 }, { 0.11862504, 0.079985297, 0.063556911, 0.14639069 } } }, { { { 0.48018566, 0.17712962, 0.45065949, 0.76214707 }, { 0.37788335, 0.385421, 0.24766167, 0.3647243 }, { 0.45095873, 0.2634498, 0.37824131, 0.10713483 }, { 0.18808611, 0.27852978, 0.23671202, 0.23174978 }, { 0.39404781, -0.7399413, 0.28511918, 0.026007027 }, { 0.46587668, 0.46802177, 0.36697974, 0.23706778 }, { 0.48925391, 0.42086488, 0.49570155, 0.45137287 }, { 0.30655255, 0.35196398, 0.23019387, 0.50586011 }, { 0.45798975, 0.34137244, 0.33289763, 0.54218519 }, { 0.42271216, 0.38700914, 0.48791862, 0.15025833 }, { 0.7282781, 0.37956244, 0.25156645, 0.51632504 }, { 0.084933462, 0.15576738, 0.16469359, 0.29684651 }, { 0.34570877, 0.34912791, 0.26663435, 0.11188061 }, { 0.48552914, 0.19012867, 0.12677402, 0.1234341 }, { 0.2190939, 0.41431469, 0.64823269, 0.51846746 }, { 0.49289149, 0.29829354, 0.29090992, 0.36465152 }, { 0.50568056, 0.64150077, 0.40217634, 0.53523743 }, { 0.24945735, 0.47058801, 0.29099852, 0.25452114 }, { 0.49039753, 0.26327736, 0.39431507, 0.50632023 }, { 0.19678915, 0.031547614, 0.22295107, 0.26300048 }, { 0.12409997, 0.11506147, 0.19327618, 0.2174585 }, { 0.15319333, 0.39177705, 0.38498586, 0.25972804 }, { 0.69027161, 0.37279682, 0.31143504, 0.23440833 }, { 0.39682066, 0.3156927, 0.36369313, 0.14308402 } }, { { 0.15030994, 0.15410005, 0.0072554408, -0.22242826 }, { -0.032421729, 0.22531436, 0.22185899, -0.022703209 }, { 0.070341052, 0.30237173, 0.047916387, 0.03629681 }, { -0.024283222, 0.075614195, 0.013940033, -0.016841468 }, { 0.077729482, 0.19455394, -0.02162282, -0.018761003 }, { -0.22986895, 0.18914992, 0.14483608, 0.11173921 }, { 0.14132894, -0.0081864768, -0.11405791, 0.031777789 }, { 0.38775389, 0.0085565642, -0.057167843, 0.09784167 }, { 0.079102739, 0.030530894, 0.041954967, 0.02957611 }, { 0.076915126, 0.18656729, 0.044218872, 0.22478833 }, { 0.017173879, 0.11961351, -0.085099523, 0.22720323 }, { 0.030466202, 0.095221887, -0.042982583, -0.069264747 }, { 0.041170442, -0.090598444, -0.021082598, -0.028016784 }, { -0.082581617, -0.023712106, 0.32427665, 0.1010696 }, { 0.19197752, 0.10900527, -0.0053794951, 0.068553764 }, { 0.18674269, 0.028895321, -0.053421028, 0.063918058 }, { 0.044090722, -0.054247791, 0.05585954, -0.13406746 }, { 0.08358642, -0.032301886, 0.010371619, 0.099505528 }, { 0.16467816, 0.044994571, -0.0045949279, 0.0626774 }, { 0.12942209, 0.092097891, 0.019866495, 0.10340014 }, { 0.037094903, 0.13829877, 0.15116473, -0.048632499 }, { 0.10749044, 0.14329542, -0.061272024, -0.1536028 }, { 0.097716907, 0.044246181, 0.056664419, 0.15804873 }, { 0.031819999, 0.10132976, 0.079198524, 0.017871462 } }, { { 0.056219172, 0.08683492, -0.061488015, 0.065746152 }, { 0.088983664, 0.19773741, -0.096766599, 0.16352101 }, { -0.0097043787, -0.040925999, 0.097458334, 0.032319634 }, { -0.024873518, 0.057873123, -0.0059256291, -0.057498398 }, { -0.13355098, 0.39190863, 0.017449142, -0.0076009344 }, { 0.10319658, 0.22069551, -0.098795717, 0.10603434 }, { 0.090765308, 0.13803326, -0.070647945, 0.14557561 }, { -0.068457348, 0.058955208, -0.050501105, 0.02914144 }, { 0.10363866, 0.060231993, 0.027681685, 0.079659088 }, { 0.01269983, 0.11977996, -0.049648315, 0.089882363 }, { -0.072877286, 0.019348792, 0.13977764, 0.055396044 }, { 0.028834456, -0.1084196, -0.0043985215, -0.072640844 }, { -0.040232522, 0.051835989, -0.02198193, 0.016421295 }, { -0.087848469, -0.04621504, 0.099259188, -0.0025909067 }, { 0.3000131, 0.10526775, 0.016890366, 0.12892588 }, { -0.021028821, -0.024429075, 0.088067677, -0.084594075 }, { 0.086861805, -0.045902006, 0.0058222123, -0.0075466204 }, { 0.14411905, 0.036488937, 0.05091815, 0.16385101 }, { 0.1576814, 0.043890956, -0.064244298, -0.087234754 }, { -0.071100004, 0.16782304, -0.10860149, -0.1601076 }, { 0.032634641, -0.0025068263, -0.093802703, -0.076176546 }, { 0.1121451, 0.15584236, 0.070074778, 0.083736091 }, { 0.16981897, -0.078106227, 0.12480295, -0.0056807652 }, { -0.20300117, -0.017467249, 0.035504155, 0.056546123 } } } }, { { { { 0.014994926, 0.3118252, 0.12179235, -0.2013765 }, { -0.2622824, 0.28086607, 0.018805882, 0.72058929 }, { -0.0081002049, -0.28176506, -0.592214, -0.15032918 }, { 0.18913426, -0.24000825, 0.0020279072, -0.54749128 }, { 0.010237954, 0.76905205, 0.80173664, -0.016024595 }, { -0.53448318, 0.31204229, -0.16183732, 0.76857439 }, { -0.57639279, -0.63719194, -0.71354849, 0.56346054 }, { 0.49443258, 0.15067585, 0.31864726, -0.30570933 }, { -0.20756322, 0.2544828, -0.005298245, 0.0073796841 }, { -0.61822672, 0.21508574, 0.6362534, 0.30433278 }, { -0.0050327191, -0.278054, -0.3460806, 0.29967778 }, { 0.33983098, -0.11715664, -0.21761592, -0.068273894 }, { 0.5550354, 0.44369709, 0.64019993, -0.026032291 }, { -0.72587268, -0.33528197, -0.33592445, 0.53027141 }, { -0.47623191, -0.61767624, -0.61525655, 0.37823554 }, { 0.82869964, 0.219401, -0.018181789, -0.56937955 }, { -0.051792934, 0.3461701, 0.20915925, 0.078166496 }, { -0.26705611, 0.14439061, 0.0055054648, 0.463243 }, { -0.0019649711, -0.34119962, -0.29306531, -0.040223173 }, { 0.29285811, -0.32824753, -0.24768208, -0.29676955 }, { 0.87604898, 0.25374435, 0.2341931, -0.77851996 }, { -0.80404697, 0.011122158, 0.18899178, 0.55592668 }, { -0.78397618, -0.53690406, -0.59931185, 0.62348293 }, { 0.54613799, 0.080819658, 0.12590931, -0.60614071 } }, { { -0.12307869, -0.20242175, 0.21530167, -0.15608553 }, { 0.00052208688, 0.09998365, -0.067550225, -0.14009319 }, { 0.12621699, -0.089024022, 0.022656689, 0.18947331 }, { 0.34838897, -0.04936051, 0.25527451, -0.18942819 }, { 0.013210249, -0.043957685, -0.19088103, -0.034189573 }, { -0.0027790938, -0.026595097, 0.087083287, -0.12513839 }, { -0.038231564, 0.013328425, -0.0091503894, -0.005743873 }, { 0.17205702, -0.14956835, -0.0088915291, 0.18720588 }, { -0.049670195, 0.39532325, 0.080260299, 0.01811245 }, { 0.043555003, -0.30289197, -0.50878196, 0.27306166 }, { 0.02555972, -0.0068359476, 0.061097702, -0.43822038 }, { -0.10926471, 0.1870906, 0.12419548, 0.1245213 }, { -0.012443149, 0.040036941, 0.18601483, 0.02310445 }, { -0.10442982, 0.057455632, 0.13475314, -0.0019859122 }, { -0.068181593, -0.0033655904, 0.01922998, -0.020393828 }, { -0.10660626, 0.0020812455, 0.081209707, 0.077131932 }, { 0.088733212, -0.10430986, 0.45554817, -0.17113078 }, { 0.0046831409, 0.13247549, -0.1077727, 0.15382275 }, { 0.022346595, 0.022924261, -0.35016323, 0.2437608 }, { 0.029795657, 0.23046877, -0.020493651, -0.33214749 }, { -0.016101582, 0.042296203, 0.046779444, 0.037412394 }, { -0.02214903, -0.025218605, 0.14797485, -0.051723623 }, { 0.021321783, 0.010405115, 0.0075476201, 0.0082410917 }, { 0.040559796, 0.027927916, -0.012812736, -0.0096642379 } }, { { -0.055647079, 0.017595207, 0.34495838, -0.03055759 }, { -0.058415094, 0.027416036, 0.18568916, 0.13044498 }, { 0.01482217, -0.17300703, 0.027540135, -0.2744944 }, { 0.25558424, -0.15324455, -0.29751197, -0.11422984 }, { -0.068936732, -0.11425403, 0.094767025, -0.0020892558 }, { 0.040887892, 0.031622148, -0.095292456, -0.02460001 }, { -0.0026237665, 0.017734103, 0.01213911, 0.0056586962 }, { -0.052138375, 0.052245567, 0.04608449, -0.043004468 }, { -0.17693366, 0.0021023738, 0.13167397, -0.14062006 }, { -0.20900333, 0.0057695127, 0.13057243, 0.046715668 }, { -0.020569928, -0.08439655, -0.09683347, 0.038139385 }, { 0.18196242, 0.44461908, -0.11388512, -0.12413082 }, { 0.072801844, -0.0017236427, -0.0026756083, 0.049805114 }, { -0.092195952, -0.0076195172, -0.22763849, -0.11320887 }, { 0.016234922, 0.007258942, 0.078535592, -0.084829275 }, { -0.15320003, 0.057490618, -0.16065455, -0.17063675 }, { -0.012856124, 0.024818957, 0.097529739, 0.11569844 }, { -0.11141243, 0.26677735, 0.1319403, -0.15699502 }, { -0.021128161, -0.12370585, 0.056198856, -0.1836225 }, { -0.01871806, 0.025525037, 0.063822152, 0.066517944 }, { -0.013759301, 0.11401068, -0.04701374, -0.021321516 }, { 0.032714649, -3.161284e-06, 0.026930697, 0.00019593482 }, { 0.10575127, 0.016956425, 0.016873291, 0.0049304377 }, { -0.11938883, 0.31242334, 0.29347156, -0.19514533 } } }, { { { -0.17374661, -0.028781395, -0.25993234, 0.27242277 }, { -0.13675759, -0.62291002, -0.80742781, 0.54260546 }, { 0.16876581, -0.052588487, 0.22415557, -0.59669887 }, { 0.1769234, 0.64210979, 0.81157479, -0.2718564 }, { -0.99873125, -0.013258174, 0.58939675, 0.99930085 }, { -0.30883355, -0.71116337, -0.76218623, 0.096388818 }, { 0.65749012, -0.54533843, -0.57508599, -0.70359398 }, { -0.27406769, 0.61006308, 0.1873512, 0.2563151 }, { -0.78453523, -0.13585943, -0.048534939, 0.02085237 }, { 0.40938527, -0.76981396, -0.42506866, 0.22362984 }, { 0.29003079, -0.20624421, 0.1151133, -0.50558933 }, { 0.0070051806, 0.20763719, 0.59485798, -0.61562639 }, { -0.4371111, 0.48314196, 0.72981069, 0.99889301 }, { 0.58257878, -0.8603979, -0.94188892, -0.83140889 }, { 0.71858167, -0.49534538, -0.63421799, -0.84488463 }, { 0.016158248, 0.65330502, 0.82883727, -0.127372 }, { -0.50292264, -0.14848746, -0.20836533, 0.2471481 }, { -0.15815031, -0.63472031, -0.79826416, 0.15325573 }, { -0.010424343, -0.022843894, 0.099730136, -0.26040744 }, { 0.15069433, 0.31188588, 0.63836617, -0.25234477 }, { -0.36946506, 0.92093529, 0.96548808, 0.62354203 }, { -0.57070465, -0.99847512, -0.47855156, -0.079970605 }, { 0.077467525, -0.71134336, -0.67172579, -0.66364974 }, { -0.27299386, 0.89512951, 0.61598356, 0.49577277 } }, { { 0.070458859, -0.28774455, 0.21287043, -0.094689772 }, { 0.0029548085, -0.31404605, -0.039280892, -0.3652277 }, { -0.033729607, 0.041215792, 0.065844258, -0.21509418 }, { 0.39270582, 0.067526811, 0.15655351, 0.053346856 }, { 0.052704394, -0.087801294, 0.18655104, 0.056114808 }, { -0.074582751, -0.055177669, -0.22165519, 0.13272162 }, { -0.027850171, 0.0029849066, -0.0062314784, -0.010484316 }, { 0.20753796, -0.0087111988, -0.13875075, -0.06137521 }, { 0.089744421, 0.07271039, 0.099417029, -0.22157272 }, { -0.013209094, 0.048633419, -0.26528065, -0.15253703 }, { 0.052922007, 0.24859103, 0.14406684, 0.13857649 }, { 0.00096142813, 0.32643367, 0.17939549, -0.39761314 }, { 0.013505803, -0.036986517, -0.12729111, 0.15459921 }, { -0.00049722057, -0.047063275, -0.0018666598, 0.1067114 }, { -0.074221027, -0.00927958, -0.029535811, -0.024240068 }, { -0.12387933, 0.06626829, 0.16422781, 0.077740779 }, { 0.14560404, -0.082132455, 0.027268021, 0.18857832 }, { 0.10470732, -0.29519533, -0.23666419, 0.10917064 }, { 0.042550279, 0.02436036, -0.31865644, -0.024987356 }, { -0.030434576, 0.082115299, 0.17770796, 0.020944092 }, { -0.17365377, 0.13807361, 0.12476029, 0.072738061 }, { -0.11503962, -0.04022554, 0.028018434, -0.070211356 }, { -0.043677907, 0.0053361863, 0.0039019898, 0.0027489647 }, { 0.27060899, -0.0016552279, 0.14166067, -0.25461265 } }, { { 0.014703402, 0.094752279, -0.32162049, 0.082335322 }, { -0.31539882, 0.44394592, 0.44316202, -0.031456167 }, { -0.024148679, 0.082370612, -0.0031744796, 0.098610537 }, { 0.46130367, -0.19989896, -0.56118891, 0.11979937 }, { 0.11784636, 0.079971516, -0.16977121, 0.014922099 }, { 0.018367216, -0.076519762, 0.13801492, 0.039682415 }, { -0.0027614728, 0.0010389006, -0.023126227, 0.0027068473 }, { 0.22249856, -0.071302328, 0.23721977, 0.10734273 }, { 0.41478408, -0.36611101, 0.18031261, -0.11176768 }, { 0.15800457, 0.23829725, -0.0016193556, 0.2112867 }, { -0.14793833, -0.15378785, 0.0082778301, 0.27105519 }, { -0.064743588, 0.44794816, -0.12599819, 0.4310022 }, { 0.092725214, 0.033947737, 0.19969884, 0.0072363359 }, { -0.074190657, 0.005985921, 0.300818, -0.090919095 }, { 0.024238118, -0.010955859, -0.068086841, -0.021137349 }, { 0.12196721, -0.19977338, -0.64428422, -0.30808722 }, { 0.46567096, -0.042072501, -0.1778338, 0.34294059 }, { -0.32528695, 0.25699981, 0.49346557, -0.20743316 }, { 0.10422458, 0.049488574, 0.49098274, -0.34871439 }, { 0.16431875, -0.050748897, -0.18464312, -0.61695364 }, { -0.1753479, 0.033238479, -0.046267845, -0.012339883 }, { -0.16098841, 0.080519992, -0.11793031, 0.036790025 }, { 0.017193144, -0.0029212372, -0.0044153187, -0.0057094316 }, { 0.23481771, -0.1556448, -0.18775429, -0.013697353 } } }, { { { 0.98467622, 0.94970347, 0.95791534, 0.9408684 }, { 0.95525144, 0.73013516, 0.58966657, 0.43166004 }, { 0.98562289, 0.95804118, 0.77397471, 0.78825859 }, { 0.96588112, 0.72807352, 0.58424502, 0.79142113 }, { -0.049305848, 0.63904864, 0.099145551, -0.03377918 }, { 0.78673348, 0.62998117, 0.62680207, 0.63245759 }, { 0.48526085, 0.544603, 0.40015579, 0.43297544 }, { 0.82487776, 0.77789448, 0.92917353, 0.91697567 }, { 0.58431326, 0.95748667, 0.99880743, 0.99975533 }, { 0.67096902, 0.60093643, 0.64381538, 0.92594344 }, { 0.95700408, 0.93816272, 0.93111608, 0.80905665 }, { 0.94046044, 0.97116483, 0.77381347, 0.78507504 }, { 0.7077214, 0.7547892, 0.23983411, -0.039180128 }, { 0.3656649, 0.38379871, -0.00015338393, 0.16604667 }, { 0.50679735, 0.6108265, 0.46821675, 0.37829596 }, { 0.55946029, 0.72460731, 0.55919425, 0.81214734 }, { 0.86277825, 0.92634645, 0.95542467, 0.96581976 }, { 0.95061533, 0.75913205, 0.60228234, 0.87287949 }, { 0.99994373, 0.93971324, 0.95087677, 0.96466059 }, { 0.9442062, 0.89161694, 0.72879505, 0.92100486 }, { 0.30989313, 0.29579046, 0.11395771, 0.071428407 }, { 0.16674735, -0.054071458, 0.85747916, 0.82737551 }, { 0.61593841, 0.45356879, 0.43544204, 0.41332561 }, { 0.79196443, 0.43841915, 0.77763172, 0.62193473 } }, { { 0.028699614, 0.071974788, -0.028868668, 0.030119772 }, { -0.16988515, -0.35713152, 0.36877151, 0.37172103 }, { 0.024472009, 0.10373643, 0.052160621, -0.12998364 }, { 0.051999909, -0.1688679, 0.05813266, -0.11063347 }, { 0.026373007, 0.067310776, 0.34433164, 0.0017481699 }, { -0.017659611, -0.10215276, -0.23736187, 0.12678732 }, { -0.0019097928, 0.02067204, -0.030447136, -0.0093192388 }, { 0.10615435, 0.11124023, 0.04473958, 0.14369936 }, { 0.14791062, -0.034502091, 0.041456555, 0.06737059 }, { 0.22389399, 0.2668048, 0.25742349, 0.03724758 }, { 0.0046009946, 0.066632032, 0.097957775, 0.22969631 }, { 0.043253167, -0.013638494, 0.071328387, -0.19249903 }, { -0.023561087, 0.011490741, 0.19824644, -0.04133258 }, { -0.057507532, -0.039265903, 0.060469313, 0.37300659 }, { 0.027051207, -0.0086784396, -0.0055877341, -0.0315352 }, { 0.15724931, 0.0099485187, 0.22462997, 0.14112999 }, { 0.13909905, 0.026199511, -0.12430815, -0.076900423 }, { -0.022327596, -0.1975812, 0.49862652, -0.096026553 }, { 0.076782007, 0.041598482, 0.0033451155, 0.039947963 }, { 0.005353589, 0.070993946, 0.0068174778, -0.17805261 }, { -0.059912765, -0.17027417, -0.060069718, 0.1561139 }, { 0.017122435, 0.048532637, -0.05315926, 0.066962855 }, { 0.058014377, 0.021874362, 0.017248667, -0.0069413843 }, { 0.099274028, 0.040622241, 0.040435904, 0.14191123 } }, { { -0.13453832, 0.071519908, -0.1597656, -0.030758273 }, { -0.13511715, 0.32373425, 0.35851035, -0.18685481 }, { 0.021440457, 0.034442875, 0.14324368, 0.15754565 }, { -0.061440371, 0.16837735, 0.47887644, -0.036265812 }, { 0.55060811, 0.14095672, 0.13077418, 0.25515565 }, { -0.084599968, -0.084002143, 0.1542308, 0.044223437 }, { 0.0017727822, 0.025149715, -0.025479364, -0.0023658361 }, { 0.1619123, 0.069159159, -0.016343512, 0.026108175 }, { 0.3296525, 0.029456656, 0.039715069, 0.015958704 }, { -0.093419591, 0.37051381, -0.063182977, -0.017764112 }, { 0.11962535, 0.062511772, -0.070445145, 0.27768911 }, { 0.07458833, -0.16218828, 0.064111239, 0.43889373 }, { -0.0326486, -0.03666828, -0.17597139, 0.34213144 }, { 0.061334301, -0.0099525239, 0.21497301, 0.0074569296 }, { -0.016749445, 0.00054557189, 0.040331287, 0.066200794 }, { 0.20620866, 0.25268529, 0.46594276, 0.059651923 }, { 0.15170896, 0.041438057, 0.021708506, -0.15049245 }, { -0.14317538, 0.13548996, 0.37297491, 0.13718874 }, { 0.053339004, 0.015014013, -0.10418356, -0.13598877 }, { -0.02227412, 0.045548464, 0.21534467, -0.23828118 }, { -0.055326885, 0.11851609, 0.28938409, 0.041373996 }, { -0.1219532, 0.57338554, -0.094571555, 0.025008596 }, { 0.070380772, 0.016993506, 0.018073937, -0.015404818 }, { 0.17033841, 0.12449473, 0.10847869, -0.11141982 } } }, { { { 4.409738, 4.5071479, 5.4761817, 5.3214091 }, { 5.3741435, 4.6270256, 5.4786338, 5.323679 }, { 4.305776, 4.4890731, 4.6894257, 4.6068436 }, { 5.4930574, 4.9116386, 5.4097636, 4.9225404 }, { 5.1861828, 5.5144226, 5.1307797, 5.0804212 }, { 6.1194597, 6.0655136, 5.7369562, 6.1076578 }, { 6.9549598, 6.9281578, 6.9549598, 6.9549598 }, { 4.5030565, 4.5849566, 4.4830953, 4.4904323 }, { 5.3629211, 5.5524848, 4.5719135, 4.9103175 }, { 4.8906163, 5.3972226, 4.8806206, 5.1834202 }, { 4.5047396, 4.5984947, 4.7039612, 4.3422371 }, { 4.5956963, 5.6294962, 4.46025, 4.4827131 }, { 5.8454206, 6.000743, 5.4594428, 4.9952614 }, { 6.09642, 6.3979283, 4.9784963, 5.6878449 }, { 6.9549598, 6.9752898, 6.9549598, 6.9549598 }, { 6.2053562, 4.9984547, 5.3887395, 4.6221036 }, { 4.5265196, 4.3684629, 5.5819288, 5.4957366 }, { 5.2220057, 4.6118907, 5.5046208, 4.9190037 }, { 4.3408178, 4.4980303, 5.4937404, 5.6154153 }, { 4.4802186, 4.4666194, 4.8546878, 5.1764252 }, { 5.7384024, 5.9048089, 5.4636107, 5.0807017 }, { 5.1013817, 5.2237041, 6.0338955, 5.8869417 }, { 6.9414339, 6.9549598, 6.9549598, 6.9549598 }, { 4.3368412, 4.9692663, 4.7090567, 4.9023075 } }, { { 0.0093525884, -0.33796029, -0.4366682, -0.18161326 }, { -0.34446047, 0.10854359, -0.61563912, -0.16514117 }, { 0.055849315, 0.093045585, 0.36722184, 0.085665647 }, { -0.21881508, -0.036846235, -0.25226403, -0.012790033 }, { -0.14697546, -0.026656628, 0.2559775, 0.026279081 }, { 0.073189287, -0.074472165, -0.15439557, 0.020907645 }, { 0, -0.015078298, 0, 0 }, { 0.027540893, -0.30876053, -0.15680794, -0.18470107 }, { -0.072547269, -0.019227086, -0.26735769, -0.1362069 }, { 0.36907279, -0.28005156, 0.01966203, -0.10277819 }, { -0.26755862, 0.066747173, 0.60834173, -0.23356165 }, { -0.12357338, -0.41742338, 0.081840746, -0.14596222 }, { -0.068599762, -0.004402392, -0.17192993, -0.15797464 }, { -0.072923207, -0.02555551, -0.21075071, 0.047272919 }, { 0, 0.0115085, 0, 0 }, { 0.32527558, 0.066048741, -0.28639187, 0.45171914 }, { -0.158086, -0.049098981, -0.17226122, -0.50289857 }, { -0.39456648, 0.031970902, -0.74883626, 0.20536003 }, { 0.22864705, -0.0095988927, -0.1155595, -0.06240073 }, { 0.12336497, -0.34128076, 0.34341316, 0.083678547 }, { -0.032718317, 0.076359349, -0.30099369, -0.016865529 }, { -0.23491753, -0.17228011, -0.044893186, -0.057411459 }, { -0.0077848677, 0, 0, 0 }, { -0.18713605, -0.11612415, 0.30907006, 0.064707406 } }, { { -0.20768494, -0.15642062, -0.079474216, -0.020948121 }, { -0.18767308, -0.013722599, 0.15827086, -0.27421942 }, { -0.11484158, -0.29325715, 0.24426149, 0.34598577 }, { -0.095599056, 0.16784413, 0.23369965, 0.15036114 }, { 0.058496274, -0.064565923, -0.076598803, -0.11988702 }, { -0.03406356, -0.010863931, -0.036116475, 0.0077051595 }, { 0, -0.015078298, 0, 0 }, { -0.21271534, 0.31678528, 0.084310434, -0.039787477 }, { 0.057420352, -0.60894321, -0.14275706, -0.29178151 }, { -0.21477227, 0.091254596, -0.053659362, -0.13299553 }, { -0.24972574, 0.22261101, -0.59415755, -0.13299464 }, { -0.406027, 0.15018847, 0.33281927, 0.28006105 }, { -0.033198856, 0.013081228, 0.0098634494, -0.18858267 }, { -0.16914457, -0.014917022, -0.15618156, 0.038961385 }, { 0, 0.0115085, 0, 0 }, { 0.047340338, -0.052961301, 0.30193278, 0.38564757 }, { -0.2009302, -0.15247105, -0.32333852, 0.22878398 }, { -0.22934017, 0.022888443, 0.30911154, -0.12420416 }, { 0.21191356, -0.33281926, -0.13523708, -0.038546557 }, { 0.28507859, -0.012777666, 0.16285544, -0.12612215 }, { -0.057034227, 0.01719448, -0.037892291, -0.13064036 }, { -0.075888865, 0.041589292, 0.0089100653, -0.10775402 }, { 0.0075560462, 0, 0, 0 }, { -0.18120766, 0.16485298, 0.58949587, 0.072313493 } } }, { { { 0.60381773, 0.64633179, 0.92301353, 0.23720177 }, { 1.1128727, 0.42172315, 1.6605811, 0.22066721 }, { 0.55829912, 0.7107351, 0.47437673, 0.53646626 }, { 0.75684406, 0.65607146, 1.5264507, 0.12817954 }, { -0.25070514, 0.30263175, -0.21070678, -0.2264813 }, { -0.24745858, -0.26801252, 0.2750925, 0.055035565 }, { -0.018769156, -0.066023008, 0.10111114, 0.0089232736 }, { 0.41152465, 0.52508091, 0.4161358, 0.39058287 }, { 0.90919582, 1.2448772, 0.61547497, 0.51303689 }, { 0.2973136, 1.2348603, 0.24154398, 0.76087607 }, { 0.23369317, 0.68368068, 0.81024353, 0.35451079 }, { 0.69272073, 0.47014545, 0.61401877, 0.43768641 }, { -0.44449894, -0.10123077, -0.19173956, -0.15811184 }, { -0.089717, -0.068601549, -0.16704813, -0.29761406 }, { 0.0055968308, -0.089855929, -0.087150641, 0.2244144 }, { 0.38902787, 0.62620686, 1.3314901, 0.26038797 }, { 0.16776511, 0.32722251, 0.71914611, 0.53556119 }, { 0.63106992, 0.46256454, 1.785895, 0.17339911 }, { 0.72516261, 0.44941094, 0.81174974, 0.61247129 }, { 0.56877815, 0.20989179, 0.7607991, 0.017998645 }, { 0.016372087, 0.26062407, -0.32771461, -0.075930098 }, { -0.11957223, -0.22579003, -0.42587945, -0.0015549589 }, { 0.0049992009, 0.053511694, 0.00053268274, 0.022778575 }, { 0.19356675, 0.5564623, 0.74981777, 0.28733119 } }, { { 0.017029304, 0.22690356, 0.25927682, -0.048136042 }, { 0.52936856, -0.26082526, 0.12568074, -0.046727529 }, { 0.08949554, -0.019090555, 0.31477592, -0.067513409 }, { 0.056302335, -0.011819435, -0.063621104, 0.27092306 }, { 0.053971592, -0.17913246, -0.14991651, -0.044263405 }, { 0.29037749, -0.040498369, -0.33600753, 0.16250066 }, { -0.067102844, -0.17843768, 0.033172168, 0.13638573 }, { 0.057127881, -0.044468822, 0.33005778, 0.34775491 }, { -0.14300931, 0.022121077, -0.045281831, -0.065216583 }, { 0.084931489, 0.06688461, 0.15758114, -0.091330485 }, { -0.014274888, 0.29139103, 0.089163749, -0.18005467 }, { -0.2191522, -0.1333803, -0.31948964, -0.28536602 }, { 0.20298891, -0.0031882515, -0.15749696, -0.014977715 }, { -0.14016857, -0.17278064, 0.01369474, 0.10971499 }, { 0.018219806, 0.080447764, 0.0056022696, -0.043028475 }, { -0.076556403, -0.13038184, -0.23788273, 0.5849635 }, { 0.1038427, 0.18199702, 0.35294355, -0.0023601311 }, { 0.22294845, -0.37427713, 0.2907529, 0.26234219 }, { 0.40809306, 0.12982813, 0.42857338, 0.14064303 }, { 0.4265028, 0.18710053, 0.15310514, 0.067551813 }, { -0.18986488, -0.029676062, -0.087045959, -0.14788626 }, { -0.07865478, 0.011558295, -0.018262356, 0.38992629 }, { 0.22297641, 0.072192947, 0.064119712, 0.12862555 }, { -0.069262467, -0.14990585, 0.31342655, -0.15002022 } }, { { 0.25288162, -0.096551539, 0.051695506, 0.20925392 }, { 0.23093904, 0.096712594, 0.19826434, 0.32530694 }, { 0.14114785, 0.071010138, -0.17642029, 0.092260082 }, { 0.39001648, -0.17666595, 0.088397252, 0.1462816 }, { 0.12484597, 0.066920676, -0.16116194, 0.21758387 }, { 0.15625272, -0.00043631439, -0.07868976, -0.19261141 }, { -0.0142415, 0.06356153, 0.026276923, -0.024546668 }, { 0.097089221, 0.085426402, 0.11936115, 0.012042542 }, { 0.52509109, -0.22465399, -0.11490612, 0.023562122 }, { -0.12418278, 0.11985465, 0.087804943, 0.25283464 }, { 0.10716753, -0.036426901, 0.2469409, -0.095816257 }, { -0.095364501, 0.14001518, -0.068636804, -0.082487255 }, { 0.074490355, 0.25323233, 0.17863748, 0.12482145 }, { -0.019616587, -0.0053326518, 0.047558858, 0.066104462 }, { 0.12647102, 0.25712368, 0.12306783, -0.050252261 }, { -0.13375041, 0.17825067, 0.026649645, -0.33338076 }, { 0.16384463, -0.022241979, 0.17817325, 0.6808721 }, { 0.42075944, -0.024292721, -0.11323318, 0.45027063 }, { -0.023953485, 0.25719992, 0.28680108, 0.33600529 }, { 0.013445546, 0.22504275, 0.17408162, 0.52860686 }, { -0.098839039, -0.27017244, 0.10293505, -0.012472685 }, { 0.074267375, -0.0056418849, 0.17632358, 0.21754089 }, { 0.1491061, 0.017927571, -0.0217757, -0.0039381966 }, { 0.067239102, -0.74624136, 0.12992555, -0.058866581 } } } }, { { { { 0.1270204, 0.7650174, 0.55252173, 0.05956498 }, { -0.36870832, 0.31227245, 0.52167466, 0.4282174 }, { -0.036761861, -0.5477415, -0.76091563, -0.37583127 }, { 0.17129434, -0.14281209, -0.40463148, -0.56367877 }, { 0.07429238, 0.45420144, 0.41919765, 0.019225986 }, { -0.44125436, -0.05567539, 0.080551064, 0.54444995 }, { -0.36600455, -0.55359309, -0.3290331, 0.33946169 }, { 0.65253747, 0.015186649, 0.0665303, -0.64649501 }, { 0.05392469, 0.54355001, 0.7539307, -0.41089455 }, { -0.29264863, 0.49684721, 0.39184208, 0.47737193 }, { 0.10885354, -0.80803227, -0.7443769, -0.3736688 }, { 0.1939378, -0.079590275, -0.42241709, -0.75536039 }, { 0.44776697, 0.44884546, 0.427965, 0.3297221 }, { -0.34595785, 0.27723463, 0.12245317, 0.43884357 }, { 0.18467758, -0.55582608, -0.99421464, -0.0096027817 }, { 0.6672057, -0.038103784, -0.048616141, -0.68508055 }, { -0.016615937, 0.62001729, 0.50530563, -0.22211425 }, { -0.16823123, 0.31934529, 0.47092187, 0.4884373 }, { 0.03194189, -0.5624624, -0.44688229, 0.223814 }, { 0.17828041, -0.080017082, -0.44239439, -0.46726625 }, { 0.19895649, 0.82568772, 0.47859751, 0.064443297 }, { -0.47464217, 0.011895223, 0.01123465, -0.010697203 }, { -0.17670677, -0.66931423, -0.5814681, -0.01325001 }, { 0.65193874, -0.010713062, -0.007915928, -0.65520853 } }, { { -0.01027431, -0.0019056004, 0.0020213958, 0.0064495753 }, { 0.0058416688, 0.0051314639, 0.021497114, 0.005870592 }, { -0.00035518612, -0.00087553938, -0.0029318969, 0.0087577986 }, { -0.0048770476, -0.015949665, -0.034816051, -0.006104917 }, { 0.0015371362, -0.0012591621, 0.01241148, 0.00096621463 }, { 0.0032416133, 0.021025709, 0.0036344622, 0.0015436078 }, { -0.0093946276, 0.0046564763, 0.028177476, -0.01022744 }, { 0.00014675555, 0.030031482, -0.0092302407, -0.001999398 }, { -0.049980321, 0.024752279, 0.016684689, -0.0045230976 }, { 0.0067493834, 0.014071508, 0.0079316435, 0.034593704 }, { 0.01971715, -0.0037227013, -0.013430278, -0.024257585 }, { -0.004342319, 0.024001878, -0.013356442, -0.022792018 }, { -0.0051709665, -0.017029547, 0.040567567, 0.0052520812 }, { 0.0090399102, 0.0079604733, 0.00018765016, -0.0092868977 }, { -0.020304032, 0.0056590257, -0.0045373063, -0.018653318 }, { -9.9636934e-05, 0.002001886, 0.0046843544, 0.0055608043 }, { 0.0018025744, -0.0025962216, 0.0068285574, -0.014851062 }, { 0.00041645221, 0.0054738242, 0.0076769026, -0.013419208 }, { 0.0038347099, -0.0042555066, -0.0066470075, 0.0039146778 }, { -0.009084153, 0.024461537, 0.0034578066, -0.0054827001 }, { 0.0033463477, 0.0045594748, 0.00037604935, -0.01571513 }, { -0.012589588, 0.029678359, -0.019924871, -0.004708459 }, { -0.0002642682, -0.0051057336, -0.0042867302, -0.00041141781 }, { -0.00086487068, -0.0025170841, 0.0030062196, -0.0030385417 } }, { { -0.01027431, -0.0019056004, 0.0020213958, 0.0064495753 }, { 0.0058416688, 0.0051314639, 0.021497114, 0.005870592 }, { -0.00035518612, -0.00087553938, -0.0029318969, 0.0087577986 }, { -0.0048770476, -0.015949665, -0.034816051, -0.006104917 }, { 0.0015371362, -0.0012591621, 0.01241148, 0.00096621463 }, { 0.0032416133, 0.021025709, 0.0036344622, 0.0015436078 }, { -0.0093946276, 0.0046564763, 0.028177476, -0.01022744 }, { 0.00014675555, 0.030031482, -0.0092302407, -0.001999398 }, { -0.049980321, 0.024752279, 0.016684689, -0.0045230976 }, { 0.0067493834, 0.014071508, 0.0079316435, 0.034593704 }, { 0.01971715, -0.0037227013, -0.013430278, -0.024257585 }, { -0.004342319, 0.024001878, -0.013356442, -0.022792018 }, { -0.0051709665, -0.017029547, 0.040567567, 0.0052520812 }, { 0.0090399102, 0.0079604733, 0.00018765016, -0.0092868977 }, { -0.020304032, 0.0056590257, -0.0045373063, -0.018653318 }, { -9.9636934e-05, 0.002001886, 0.0046843544, 0.0055608043 }, { 0.0018025744, -0.0025962216, 0.0068285574, -0.014851062 }, { 0.00041645221, 0.0054738242, 0.0076769026, -0.013419208 }, { 0.0038347099, -0.0042555066, -0.0066470075, 0.0039146778 }, { -0.009084153, 0.024461537, 0.0034578066, -0.0054827001 }, { 0.0033463477, 0.0045594748, 0.00037604935, -0.01571513 }, { -0.012589588, 0.029678359, -0.019924871, -0.004708459 }, { -0.0002642682, -0.0051057336, -0.0042867302, -0.00041141781 }, { -0.00086487068, -0.0025170841, 0.0030062196, -0.0030385417 } } }, { { { -0.68772793, 0.19029367, -0.17427646, 0.60300616 }, { -0.29980532, -0.22397537, -0.4071009, 0.36277983 }, { 0.75628069, -0.13426242, 0.13645381, -0.74653491 }, { 0.14891408, -0.13497977, 0.36807879, -0.39814386 }, { -0.20608987, -0.076497863, -0.19510375, 0.34604256 }, { -0.02421123, -0.4588774, -0.64965351, 0.083039161 }, { 0.51918764, -0.30614677, -0.25791921, -0.40837612 }, { 0.028860181, 0.63152733, 0.5876224, -0.033139773 }, { -0.63418144, 0.046874151, 0.24431924, 0.71662556 }, { -0.29088451, -0.21455586, -0.73980807, 0.65038559 }, { 0.78663226, 0.00020858525, 0.40361403, -0.75720144 }, { 0.1998276, 0.54590973, 0.1773378, -0.35464319 }, { -0.40236144, 0.31362578, -0.34406026, 0.38120073 }, { -0.27845549, -0.46862161, -0.47141499, 0.095899189 }, { 0.6004921, 0.28051621, -0.011378178, -0.98141078 }, { 0.032724674, 0.66798127, 0.66430425, -0.05209965 }, { -0.59603974, -0.083198329, 0.34616224, 0.42082916 }, { -0.14262632, -0.21418442, -0.37504914, 0.32676687 }, { 0.58204273, 0.0067537174, -0.35923481, -0.40792038 }, { 0.15607366, 0.17215007, 0.34414936, -0.33566945 }, { -0.44862333, 0.004919013, 0.0076768115, 0.41897935 }, { -0.022062848, -0.39695079, -0.0062786656, 0.042925103 }, { 0.65953535, -0.15521993, 0.011867978, -0.57721165 }, { 0.031305912, 0.65627006, 0.66779002, -0.029815636 } }, { { 0.011457792, -0.011774949, -0.012205337, 0.0048139052 }, { -0.024024566, 0.018313023, -0.023210623, -0.0046351547 }, { 0.0039133571, 0.0046801024, -0.020590099, -0.0018568631 }, { -0.015369931, -0.0092621276, -0.026149742, 0.0010335971 }, { 0.032555144, -0.01336897, -0.022733265, -0.027997469 }, { -0.028161537, -0.00073877629, -0.023989631, 0.0055660453 }, { -0.012966193, 0.003944376, 0.025685982, -0.0017458044 }, { 0.00015626641, -0.009524206, 0.0083025026, -0.00049753811 }, { -0.02358661, 0.006370149, 0.00087066462, -0.00054248544 }, { -0.0024571244, -0.023218369, -0.010895303, -0.0095647684 }, { 0.0069970393, -0.00093403301, -0.0081922371, -0.00026359768 }, { 0.0065921354, 0.028846533, -0.045676337, 0.006070217 }, { 0.0045248423, -0.0084676847, 0.028756195, 0.020612871 }, { 0.0037691244, -0.0069385161, -0.00029501448, -0.0017839033 }, { -0.0048675353, -0.011930456, 0.0044251285, -0.00016323616 }, { -0.0012291164, -0.0019575288, 0.0078250029, -0.0011151155 }, { 0.00503333, -0.0094538968, 0.0092375183, 0.018207648 }, { 0.0080615812, -0.0073583459, -0.0166794, 0.016416158 }, { 0.002192959, -0.01153759, -0.0048668362, -0.0071123281 }, { -0.010116143, -0.010224552, 0.010897731, 0.00093792816 }, { 0.017199359, -0.0087516179, 0.0021169251, -0.020946959 }, { -0.01570063, 0.020087246, 0.014492818, -0.016014018 }, { 0.0023484072, 0.0015070243, -0.00045616273, -0.001211882 }, { 0.0018090492, -0.0012261901, 0.0012809284, 0.00096488905 } }, { { 0.011457792, -0.011774949, -0.012205337, 0.0048139052 }, { -0.024024566, 0.018313023, -0.023210623, -0.0046351547 }, { 0.0039133571, 0.0046801024, -0.020590099, -0.0018568631 }, { -0.015369931, -0.0092621276, -0.026149742, 0.0010335971 }, { 0.032555144, -0.01336897, -0.022733265, -0.027997469 }, { -0.028161537, -0.00073877629, -0.023989631, 0.0055660453 }, { -0.012966193, 0.003944376, 0.025685982, -0.0017458044 }, { 0.00015626641, -0.009524206, 0.0083025026, -0.00049753811 }, { -0.02358661, 0.006370149, 0.00087066462, -0.00054248544 }, { -0.0024571244, -0.023218369, -0.010895303, -0.0095647684 }, { 0.0069970393, -0.00093403301, -0.0081922371, -0.00026359768 }, { 0.0065921354, 0.028846533, -0.045676337, 0.006070217 }, { 0.0045248423, -0.0084676847, 0.028756195, 0.020612871 }, { 0.0037691244, -0.0069385161, -0.00029501448, -0.0017839033 }, { -0.0048675353, -0.011930456, 0.0044251285, -0.00016323616 }, { -0.0012291164, -0.0019575288, 0.0078250029, -0.0011151155 }, { 0.00503333, -0.0094538968, 0.0092375183, 0.018207648 }, { 0.0080615812, -0.0073583459, -0.0166794, 0.016416158 }, { 0.002192959, -0.01153759, -0.0048668362, -0.0071123281 }, { -0.010116143, -0.010224552, 0.010897731, 0.00093792816 }, { 0.017199359, -0.0087516179, 0.0021169251, -0.020946959 }, { -0.01570063, 0.020087246, 0.014492818, -0.016014018 }, { 0.0023484072, 0.0015070243, -0.00045616273, -0.001211882 }, { 0.0018090492, -0.0012261901, 0.0012809284, 0.00096488905 } } }, { { { 0.71476997, 0.61525336, 0.81507512, 0.79550964 }, { 0.87986984, 0.9232123, 0.74974956, 0.82765975 }, { 0.65321366, 0.82580437, 0.63434042, 0.54903231 }, { 0.97390084, 0.98050251, 0.83713283, 0.72370416 }, { 0.97570877, 0.88760866, 0.88668363, 0.9380218 }, { 0.89705541, 0.88675351, 0.75595095, 0.83467284 }, { 0.77232433, 0.77447327, 0.9084134, 0.84734569 }, { -0.75720667, -0.77520488, -0.80639546, -0.76219811 }, { 0.77130152, 0.83806694, 0.60983327, 0.56357207 }, { 0.91090229, 0.84089752, 0.54694041, 0.59085922 }, { 0.60775044, 0.58913818, 0.53197627, 0.53574024 }, { 0.96044628, 0.83405513, 0.88888419, 0.55105253 }, { 0.79850486, 0.83676557, 0.83574428, 0.86369517 }, { 0.89597751, 0.83876978, 0.87336884, 0.8934314 }, { 0.77801249, 0.78253947, 0.10680725, 0.19167855 }, { -0.74415432, -0.74320194, -0.74587957, -0.72660186 }, { 0.802783, 0.78016447, 0.79046691, 0.87952719 }, { 0.97537479, 0.92311625, 0.79848027, 0.80910594 }, { 0.8125306, 0.82679528, 0.81929639, 0.88516002 }, { 0.97152309, 0.98181547, 0.82815966, 0.81791703 }, { 0.87129411, 0.56410602, 0.87800085, 0.905706 }, { 0.87990229, 0.91776281, 0.99991718, 0.99902102 }, { 0.73060786, 0.72658464, 0.81348263, 0.81648708 }, { -0.75762512, -0.75445002, -0.74430762, -0.75485946 } }, { { 0.018332644, 0.0084005452, -0.0018937689, -0.0035491975 }, { 0.0016556654, 0.0049261013, -0.021796869, 0.0025973591 }, { -0.0019671758, 0.00051947074, 0.0071261223, 0.0056689139 }, { 0.00041901024, -0.0023903288, -0.0035639711, -0.0036673013 }, { 0.009963464, 0.00099195429, -0.0042516892, 0.0092605531 }, { 0.0034813664, 0.0028575465, -0.016343415, -0.0014475905 }, { 0.0053571039, 0.0051116063, 0.016171091, -0.00052744238 }, { 0.00013272575, -0.0095491849, 0.0070156475, 0.0017057538 }, { 0.028067438, -0.0086835729, -0.0087852674, 0.0035321054 }, { 0.0025007808, -0.0075654884, -0.012551417, -0.0068823899 }, { -0.00017607308, 0.002636122, -0.011272055, -0.010314896 }, { 0.010646599, 0.00042804331, 0.013900837, -0.01279076 }, { 0.0059898286, 0.012331371, -0.0073125296, 0.016248603 }, { 0.031579315, -0.0057840222, -0.00018304192, 0.005171422 }, { 0.010928513, 0.0092660887, 0.030404621, 0.0053167707 }, { -0.00014899672, -0.0035246494, 0.0075862845, -0.005861723 }, { 0.0067791918, 0.0021224495, -0.0071755505, -0.010370936 }, { 0.0015352958, -0.0025785166, -0.0092688001, 0.003966373 }, { 0.0036915074, -0.002306452, -0.005736452, -0.0033594125 }, { 0.0065128512, 0.006188005, 0.00088322638, -0.0016227066 }, { 0.0092720771, -0.0046684631, -7.3769604e-05, 0.013807013 }, { -0.0031421984, 0.010622679, 0.00041591214, 0.0032786075 }, { -0.0021421613, -0.0041675589, -0.0029529994, -0.00085350449 }, { -0.00069204344, -0.0010785124, 0.00097549628, 0.0025280456 } }, { { 0.018332644, 0.0084005452, -0.0018937689, -0.0035491975 }, { 0.0016556654, 0.0049261013, -0.021796869, 0.0025973591 }, { -0.0019671758, 0.00051947074, 0.0071261223, 0.0056689139 }, { 0.00041901024, -0.0023903288, -0.0035639711, -0.0036673013 }, { 0.009963464, 0.00099195429, -0.0042516892, 0.0092605531 }, { 0.0034813664, 0.0028575465, -0.016343415, -0.0014475905 }, { 0.0053571039, 0.0051116063, 0.016171091, -0.00052744238 }, { 0.00013272575, -0.0095491849, 0.0070156475, 0.0017057538 }, { 0.028067438, -0.0086835729, -0.0087852674, 0.0035321054 }, { 0.0025007808, -0.0075654884, -0.012551417, -0.0068823899 }, { -0.00017607308, 0.002636122, -0.011272055, -0.010314896 }, { 0.010646599, 0.00042804331, 0.013900837, -0.01279076 }, { 0.0059898286, 0.012331371, -0.0073125296, 0.016248603 }, { 0.031579315, -0.0057840222, -0.00018304192, 0.005171422 }, { 0.010928513, 0.0092660887, 0.030404621, 0.0053167707 }, { -0.00014899672, -0.0035246494, 0.0075862845, -0.005861723 }, { 0.0067791918, 0.0021224495, -0.0071755505, -0.010370936 }, { 0.0015352958, -0.0025785166, -0.0092688001, 0.003966373 }, { 0.0036915074, -0.002306452, -0.005736452, -0.0033594125 }, { 0.0065128512, 0.006188005, 0.00088322638, -0.0016227066 }, { 0.0092720771, -0.0046684631, -7.3769604e-05, 0.013807013 }, { -0.0031421984, 0.010622679, 0.00041591214, 0.0032786075 }, { -0.0021421613, -0.0041675589, -0.0029529994, -0.00085350449 }, { -0.00069204344, -0.0010785124, 0.00097549628, 0.0025280456 } } }, { { { 5.3792285, 5.1960477, 5.5112916, 5.6615254 }, { 5.0489877, 5.2428834, 5.1752035, 5.1109826 }, { 5.5205204, 5.7511938, 5.0202917, 4.9168865 }, { 4.9522523, 4.8880256, 5.1015936, 5.2858816 }, { 5.7256502, 5.7919759, 5.645241, 5.6035708 }, { 6.4076931, 6.4822111, 6.2642633, 6.3925959 }, { 6.9797014, 6.981436, 7.0028674, 6.9976464 }, { -0.03290957, -0.03290957, -0.03290957, -0.03290957 }, { 5.4977854, 5.7684965, 5.3463095, 4.8810492 }, { 4.9869047, 5.4896416, 4.9647805, 4.884877 }, { 5.3141219, 5.3357788, 4.7695434, 4.8709631 }, { 5.2056063, 5.407802, 5.2123857, 4.9428208 }, { 6.2188218, 6.17756, 6.2751008, 6.3672109 }, { 6.9105856, 6.7986798, 6.5712335, 6.5907061 }, { 6.9797014, 6.9797014, 5.6859993, 5.5642483 }, { -0.032764603, -0.032764603, -0.032764603, -0.032764603 }, { 5.7724142, 6.0929556, 5.99581, 5.9265164 }, { 4.9363192, 4.9823732, 5.1732995, 5.2475265 }, { 5.8365191, 5.9972902, 5.9778441, 5.9270668 }, { 4.8706768, 5.0194503, 5.155585, 5.2188041 }, { 6.1569904, 6.0563989, 6.0989699, 6.2139837 }, { 5.8727399, 5.8948086, 5.5734095, 5.5536103 }, { 6.9797014, 6.9797014, 6.9797014, 6.9797014 }, { -0.032766769, -0.032766769, -0.032766769, -0.032766769 } }, { { 0.0011802354, -0.006546101, -0.02103972, 0.0008654047 }, { -0.015460534, 0.017874544, 0.0029121134, 0.023511773 }, { -0.040909245, 0.011927691, 0.011991588, 0.01677931 }, { -0.015633544, -0.0042321141, 0.026623034, 0.0080414514 }, { 0.012614382, 0.0065080145, 0.035716738, -0.0080665814 }, { -0.0057849744, -0.017478461, -0.031219642, 0.00016446523 }, { 0, 0.00032235028, 0, 0 }, { 0, 0, 0, 0 }, { -0.068586697, -0.024228236, -0.012857221, -0.039493706 }, { -0.018078201, -0.015140979, 0.00072119173, -0.051249859 }, { -0.054228277, 0.0097895101, 0.0019832646, -0.011715411 }, { -0.042326208, -0.010160072, 0.037088052, -0.031848667 }, { 0.00067130897, -0.013966717, -0.017268559, -0.0074614576 }, { 0.070515961, 0.012848107, -0.0008396517, 0.0049006506 }, { 0, 0, -0.063014256, -0.0085124986 }, { 0, 0, 0, 0 }, { -0.040302299, 0.0048936307, 0.0064406394, 0.0034044871 }, { -0.010453589, 0.0035820836, -0.017384391, -0.038199947 }, { -0.044968611, -0.0088322127, 0.020303819, 0.0058131005 }, { -0.0056838535, 0.010211409, -0.010999927, -0.027621859 }, { 0.0064753811, -0.0059341242, -0.014902755, 0.0082868118 }, { -0.0013222735, 0.0028492181, -0.023523273, -0.02576271 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, { { 0.0011802354, -0.006546101, -0.02103972, 0.00086540469 }, { -0.015460534, 0.017874544, 0.0029121134, 0.023511773 }, { -0.040909245, 0.011927691, 0.011991588, 0.01677931 }, { -0.015633544, -0.0042321141, 0.026623034, 0.0080414514 }, { 0.012614382, 0.0065080145, 0.035716738, -0.0080665814 }, { -0.0057849744, -0.017478461, -0.031219642, 0.00016446523 }, { 0, 0.00032235028, 0, 0 }, { 0, 0, 0, 0 }, { -0.068586697, -0.024228236, -0.012857221, -0.039493706 }, { -0.018078201, -0.015140979, 0.00072119173, -0.051249859 }, { -0.054228277, 0.0097895101, 0.0019832646, -0.011715411 }, { -0.042326208, -0.010160072, 0.037088052, -0.031848667 }, { 0.00067130897, -0.013966717, -0.017268559, -0.0074614576 }, { 0.070515961, 0.012848107, -0.0008396517, 0.0049006506 }, { 0, 0, -0.063014256, -0.0085124986 }, { 0, 0, 0, 0 }, { -0.040302299, 0.0048936307, 0.0064406394, 0.0034044871 }, { -0.010453589, 0.0035820836, -0.017384391, -0.038199947 }, { -0.044968611, -0.0088322127, 0.020303819, 0.0058131005 }, { -0.0056838535, 0.010211409, -0.010999927, -0.027621859 }, { 0.0064753811, -0.0059341242, -0.014902755, 0.0082868118 }, { -0.0013222735, 0.0028492181, -0.023523273, -0.02576271 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } }, { { { 0.72189984, 0.22069996, 0.71952927, 0.77725949 }, { 0.4054405, 0.20582059, 0.2747016, 0.37612563 }, { 0.58887422, 0.27441131, 0.19468101, 0.21480554 }, { 0.46814145, 0.34317, 0.46068212, 0.13962064 }, { -0.18134132, -0.26668789, -0.60984999, -0.67879259 }, { -0.47870351, -0.34453227, 0.32494779, 0.10292971 }, { 0.087252967, 0.066950358, 0.31813819, 0.071094818 }, { -0.0031436256, 0.038245091, -0.0076651913, -0.015389479 }, { 1.2668531, 1.2894974, 0.40584018, 0.51755806 }, { 1.3207257, 1.3403747, 0.54924634, 0.40282713 }, { 0.78581828, 0.56379328, 0.27901993, 0.56429306 }, { 0.8748226, 1.0271253, 1.0085726, 0.3888545 }, { -0.22577636, -0.32895071, -0.2846317, -0.11679531 }, { 0.26477285, 0.3179447, -0.063393238, 0.024059773 }, { -0.15463395, -0.22721468, -0.20680404, -0.15700788 }, { 0.012107106, -0.0061245949, -0.024224367, 0.005040693 }, { 0.97943693, 0.64840429, 0.45106998, 0.40771935 }, { 0.49907853, 0.1562184, 0.34338458, 0.39710628 }, { 0.95047709, 0.53336107, 0.38318275, 0.44919148 }, { 0.41892697, 0.069965886, 0.45831656, 0.38821529 }, { -0.20216736, -0.43209441, -0.57684857, -0.40189427 }, { -0.63992377, -0.40683032, -0.59207903, -0.57251716 }, { -0.047117438, -0.1880015, -0.12265155, 0.00059988607 }, { -0.011836442, -0.010049497, -0.0026152072, 0.016137736 } }, { { 0.092068993, 0.0045466749, 0.0054574031, 0.02582156 }, { 0.022115456, -0.015664041, -0.022004653, 0.041431654 }, { 0.029951298, -0.0004408542, 0.0087496069, 0.017850027 }, { 0.029086373, 0.022116039, 0.044010315, 0.001644876 }, { 0.016256387, 0.0083249367, 0.019570849, -0.0021276222 }, { 0.0079070076, -0.024696939, 0.044311101, 0.023671132 }, { -0.0081796119, -0.0024995551, 0.033501743, -0.031958988 }, { 0.0065005403, -0.076642001, 0.015736477, 0.030966939 }, { 0.029110717, 0.039154477, -0.074376619, 0.025532063 }, { -0.10980761, 0.0038346834, 0.014449171, -0.030702653 }, { -0.00068350423, -0.037251569, -0.008409224, -0.026322878 }, { 0.035406012, 0.064176275, 0.031437854, -0.0344642 }, { 0.037145809, -0.024909212, 0.041030386, 0.035216105 }, { -0.093276646, -0.013904083, -0.019536023, -0.023834405 }, { 0.042751846, -0.03620164, 0.081115921, 0.018379967 }, { -0.023909625, 0.012833691, 0.048086442, -0.0097340268 }, { 0.039552712, -0.00026806514, 0.011646753, 0.0065939486 }, { 0.058985248, 0.020165701, 0.0076721521, 0.033274221 }, { 0.052889871, 0.0042520093, 0.016490396, 0.009287973 }, { 0.044305975, -0.0016263469, 0.041390177, 0.033541355 }, { 0.014595133, -0.004801042, -0.0049517302, 0.015714264 }, { 0.00075086205, 0.0080838736, -0.037611057, -0.030488441 }, { 0.0019178075, -0.0082517768, -0.002525773, 0.0043993022 }, { 0.023774971, 0.020335611, 0.0056643868, -0.032100338 } }, { { 0.092068993, 0.0045466749, 0.0054574031, 0.02582156 }, { 0.022115456, -0.015664041, -0.022004653, 0.041431654 }, { 0.029951298, -0.0004408542, 0.0087496069, 0.017850027 }, { 0.029086373, 0.022116039, 0.044010315, 0.001644876 }, { 0.016256387, 0.0083249367, 0.019570849, -0.0021276222 }, { 0.0079070076, -0.024696939, 0.044311101, 0.023671132 }, { -0.0081796119, -0.0024995551, 0.033501743, -0.031958988 }, { 0.0065005403, -0.076642001, 0.015736477, 0.030966939 }, { 0.029110717, 0.039154477, -0.074376619, 0.025532063 }, { -0.10980761, 0.0038346834, 0.014449171, -0.030702653 }, { -0.00068350423, -0.037251569, -0.008409224, -0.026322878 }, { 0.035406012, 0.064176275, 0.031437854, -0.0344642 }, { 0.037145809, -0.024909212, 0.041030386, 0.035216105 }, { -0.093276646, -0.013904083, -0.019536023, -0.023834405 }, { 0.042751846, -0.03620164, 0.081115921, 0.018379967 }, { -0.023909625, 0.012833691, 0.048086442, -0.0097340268 }, { 0.039552712, -0.00026806514, 0.011646753, 0.0065939486 }, { 0.058985248, 0.020165701, 0.0076721521, 0.033274221 }, { 0.052889871, 0.0042520093, 0.016490396, 0.009287973 }, { 0.044305975, -0.0016263469, 0.041390177, 0.033541355 }, { 0.014595133, -0.004801042, -0.0049517303, 0.015714264 }, { 0.00075086205, 0.0080838736, -0.037611057, -0.030488441 }, { 0.0019178075, -0.0082517768, -0.002525773, 0.0043993022 }, { 0.023774971, 0.020335611, 0.0056643868, -0.032100338 } } } } }; + +#endif diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.cpp b/servers/rendering/rasterizer_rd/light_cluster_builder.cpp new file mode 100644 index 0000000000..943ef1c7fa --- /dev/null +++ b/servers/rendering/rasterizer_rd/light_cluster_builder.cpp @@ -0,0 +1,255 @@ +/*************************************************************************/ +/* light_cluster_builder.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "light_cluster_builder.h" + +void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection) { + view_xform = p_view_transform; + projection = p_cam_projection; + z_near = -projection.get_z_near(); + z_far = -projection.get_z_far(); + + //reset counts + light_count = 0; + refprobe_count = 0; + item_count = 0; + sort_id_count = 0; +} + +void LightClusterBuilder::bake_cluster() { + + float slice_depth = (z_near - z_far) / depth; + + uint8_t *cluster_dataw = cluster_data.ptrw(); + Cell *cluster_data_ptr = (Cell *)cluster_dataw; + //clear the cluster + zeromem(cluster_data_ptr, (width * height * depth * sizeof(Cell))); + + /* Step 1, create cell positions and count them */ + + for (uint32_t i = 0; i < item_count; i++) { + + const Item &item = items[i]; + + int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth); + int to_slice = Math::floor((z_near - item.aabb.position.z) / slice_depth); + + if (from_slice >= (int)depth || to_slice < 0) { + continue; //sorry no go + } + + from_slice = MAX(0, from_slice); + to_slice = MIN((int)depth - 1, to_slice); + + for (int j = from_slice; j <= to_slice; j++) { + + Vector3 min = item.aabb.position; + Vector3 max = item.aabb.position + item.aabb.size; + + float limit_near = MIN((z_near - slice_depth * j), max.z); + float limit_far = MAX((z_near - slice_depth * (j + 1)), min.z); + + max.z = limit_near; + min.z = limit_near; + + Vector3 proj_min = projection.xform(min); + Vector3 proj_max = projection.xform(max); + + int near_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width)); + int near_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height)); + int near_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width)); + int near_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height)); + + max.z = limit_far; + min.z = limit_far; + + proj_min = projection.xform(min); + proj_max = projection.xform(max); + + int far_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width)); + int far_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height)); + int far_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width)); + int far_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height)); + + //print_line(itos(j) + " near - " + Vector2i(near_from_x, near_from_y) + " -> " + Vector2i(near_to_x, near_to_y)); + //print_line(itos(j) + " far - " + Vector2i(far_from_x, far_from_y) + " -> " + Vector2i(far_to_x, far_to_y)); + + int from_x = MIN(near_from_x, far_from_x); + int from_y = MIN(near_from_y, far_from_y); + int to_x = MAX(near_to_x, far_to_x); + int to_y = MAX(near_to_y, far_to_y); + + if (from_x >= (int)width || to_x < 0 || from_y >= (int)height || to_y < 0) { + continue; + } + + int sx = MAX(0, from_x); + int sy = MAX(0, from_y); + int dx = MIN((int)width - 1, to_x); + int dy = MIN((int)height - 1, to_y); + + //print_line(itos(j) + " - " + Vector2i(sx, sy) + " -> " + Vector2i(dx, dy)); + + for (int x = sx; x <= dx; x++) { + for (int y = sy; y <= dy; y++) { + uint32_t offset = j * (width * height) + y * width + x; + + if (unlikely(sort_id_count == sort_id_max)) { + sort_id_max = nearest_power_of_2_templated(sort_id_max + 1); + sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max); + if (ids.size()) { + + ids.resize(sort_id_max); + RD::get_singleton()->free(items_buffer); + items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max); + } + } + + sort_ids[sort_id_count].cell_index = offset; + sort_ids[sort_id_count].item_index = item.index; + sort_ids[sort_id_count].item_type = item.type; + + sort_id_count++; + + //for now, only count + cluster_data_ptr[offset].item_pointers[item.type]++; + //print_line("at offset " + itos(offset) + " value: " + itos(cluster_data_ptr[offset].item_pointers[item.type])); + } + } + } + } + + /* Step 2, Assign pointers (and reset counters) */ + + uint32_t offset = 0; + for (uint32_t i = 0; i < (width * height * depth); i++) { + for (int j = 0; j < ITEM_TYPE_MAX; j++) { + uint32_t count = cluster_data_ptr[i].item_pointers[j]; //save count + cluster_data_ptr[i].item_pointers[j] = offset; //replace count by pointer + offset += count; //increase offset by count; + } + } + + //print_line("offset: " + itos(offset)); + /* Step 3, Place item lists */ + + uint32_t *ids_ptr = ids.ptrw(); + + for (uint32_t i = 0; i < sort_id_count; i++) { + const SortID &id = sort_ids[i]; + Cell &cell = cluster_data_ptr[id.cell_index]; + uint32_t pointer = cell.item_pointers[id.item_type] & POINTER_MASK; + uint32_t counter = cell.item_pointers[id.item_type] >> COUNTER_SHIFT; + ids_ptr[pointer + counter] = id.item_index; + + cell.item_pointers[id.item_type] = pointer | ((counter + 1) << COUNTER_SHIFT); + } + + RD::get_singleton()->texture_update(cluster_texture, 0, cluster_data, true); + RD::get_singleton()->buffer_update(items_buffer, 0, offset * sizeof(uint32_t), ids_ptr, true); +} + +void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) { + + if (width == p_width && height == p_height && depth == p_depth) { + return; + } + if (cluster_texture.is_valid()) { + RD::get_singleton()->free(cluster_texture); + } + + width = p_width; + height = p_height; + depth = p_depth; + + cluster_data.resize(width * height * depth * sizeof(Cell)); + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + tf.type = RD::TEXTURE_TYPE_3D; + tf.width = width; + tf.height = height; + tf.depth = depth; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + + cluster_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } +} + +RID LightClusterBuilder::get_cluster_texture() const { + return cluster_texture; +} +RID LightClusterBuilder::get_cluster_indices_buffer() const { + return items_buffer; +} + +LightClusterBuilder::LightClusterBuilder() { + //initialize accumulators to something + lights = (LightData *)memalloc(sizeof(LightData) * 1024); + light_max = 1024; + + refprobes = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024); + refprobe_max = 1024; + + decals = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024); + decal_max = 1024; + + items = (Item *)memalloc(sizeof(Item) * 1024); + item_max = 1024; + + sort_ids = (SortID *)memalloc(sizeof(SortID) * 1024); + ids.resize(2014); + items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024); + item_max = 1024; +} +LightClusterBuilder::~LightClusterBuilder() { + + if (cluster_data.size()) { + RD::get_singleton()->free(cluster_texture); + } + + if (lights) { + memfree(lights); + } + if (refprobes) { + memfree(refprobes); + } + if (decals) { + memfree(decals); + } + if (items) { + memfree(items); + } + if (sort_ids) { + memfree(sort_ids); + RD::get_singleton()->free(items_buffer); + } +} diff --git a/servers/rendering/rasterizer_rd/light_cluster_builder.h b/servers/rendering/rasterizer_rd/light_cluster_builder.h new file mode 100644 index 0000000000..3411ed07a0 --- /dev/null +++ b/servers/rendering/rasterizer_rd/light_cluster_builder.h @@ -0,0 +1,291 @@ +/*************************************************************************/ +/* light_cluster_builder.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef LIGHT_CLUSTER_BUILDER_H +#define LIGHT_CLUSTER_BUILDER_H + +#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" + +class LightClusterBuilder { +public: + enum LightType { + LIGHT_TYPE_OMNI, + LIGHT_TYPE_SPOT + }; + + enum ItemType { + ITEM_TYPE_OMNI_LIGHT, + ITEM_TYPE_SPOT_LIGHT, + ITEM_TYPE_REFLECTION_PROBE, + ITEM_TYPE_DECAL, + ITEM_TYPE_MAX //should always be 4 + }; + + enum { + COUNTER_SHIFT = 20, //one million total ids + POINTER_MASK = (1 << COUNTER_SHIFT) - 1, + COUNTER_MASK = 0xfff // 4096 items per cell + }; + +private: + struct LightData { + float position[3]; + uint32_t type; + float radius; + float spot_aperture; + uint32_t pad[2]; + }; + + uint32_t light_count = 0; + uint32_t light_max = 0; + LightData *lights = nullptr; + + struct OrientedBoxData { + float position[3]; + uint32_t pad; + float x_axis[3]; + uint32_t pad2; + float y_axis[3]; + uint32_t pad3; + float z_axis[3]; + uint32_t pad4; + }; + + uint32_t refprobe_count = 0; + uint32_t refprobe_max = 0; + OrientedBoxData *refprobes = nullptr; + + uint32_t decal_count = 0; + uint32_t decal_max = 0; + OrientedBoxData *decals = nullptr; + + struct Item { + AABB aabb; + ItemType type; + uint32_t index; + }; + + Item *items = nullptr; + uint32_t item_count = 0; + uint32_t item_max = 0; + + uint32_t width = 0; + uint32_t height = 0; + uint32_t depth = 0; + + struct Cell { + uint32_t item_pointers[ITEM_TYPE_MAX]; + }; + + Vector cluster_data; + RID cluster_texture; + + struct SortID { + uint32_t cell_index; + uint32_t item_index; + ItemType item_type; + }; + + SortID *sort_ids = nullptr; + Vector ids; + uint32_t sort_id_count = 0; + uint32_t sort_id_max = 0; + RID items_buffer; + + Transform view_xform; + CameraMatrix projection; + float z_far = 0; + float z_near = 0; + + _FORCE_INLINE_ void _add_item(const AABB &p_aabb, ItemType p_type, uint32_t p_index) { + if (unlikely(item_count == item_max)) { + item_max = nearest_power_of_2_templated(item_max + 1); + items = (Item *)memrealloc(items, sizeof(Item) * item_max); + } + + Item &item = items[item_count]; + item.aabb = p_aabb; + item.index = p_index; + item.type = p_type; + item_count++; + } + +public: + void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection); + + _FORCE_INLINE_ void add_light(LightType p_type, const Transform &p_transform, float p_radius, float p_spot_aperture) { + if (unlikely(light_count == light_max)) { + light_max = nearest_power_of_2_templated(light_max + 1); + lights = (LightData *)memrealloc(lights, sizeof(LightData) * light_max); + } + + LightData &ld = lights[light_count]; + ld.type = p_type; + ld.position[0] = p_transform.origin.x; + ld.position[1] = p_transform.origin.y; + ld.position[2] = p_transform.origin.z; + ld.radius = p_radius; + ld.spot_aperture = p_spot_aperture; + + Transform xform = view_xform * p_transform; + + ld.radius *= xform.basis.get_uniform_scale(); + + AABB aabb; + + switch (p_type) { + case LIGHT_TYPE_OMNI: { + aabb.position = xform.origin; + aabb.size = Vector3(ld.radius, ld.radius, ld.radius); + aabb.position -= aabb.size; + aabb.size *= 2.0; + + _add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count); + } break; + case LIGHT_TYPE_SPOT: { + Vector3 v(0, 0, -1); + v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z + v.normalize(); + v *= ld.radius; + v.y = v.x; + + aabb.position = xform.origin; + aabb.expand_to(xform.xform(v)); + aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z))); + aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z))); + aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z))); + _add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count); + } break; + } + + light_count++; + } + + _FORCE_INLINE_ void add_reflection_probe(const Transform &p_transform, const Vector3 &p_half_extents) { + + if (unlikely(refprobe_count == refprobe_max)) { + refprobe_max = nearest_power_of_2_templated(refprobe_max + 1); + refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max); + } + + OrientedBoxData &rp = refprobes[refprobe_count]; + Vector3 origin = p_transform.origin; + rp.position[0] = origin.x; + rp.position[1] = origin.y; + rp.position[2] = origin.z; + + Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x; + rp.x_axis[0] = x_axis.x; + rp.x_axis[1] = x_axis.y; + rp.x_axis[2] = x_axis.z; + + Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y; + rp.y_axis[0] = y_axis.x; + rp.y_axis[1] = y_axis.y; + rp.y_axis[2] = y_axis.z; + + Vector3 z_axis = p_transform.basis.get_axis(2) * p_half_extents.z; + rp.z_axis[0] = z_axis.x; + rp.z_axis[1] = z_axis.y; + rp.z_axis[2] = z_axis.z; + + AABB aabb; + + aabb.position = origin + x_axis + y_axis + z_axis; + aabb.expand_to(origin + x_axis + y_axis - z_axis); + aabb.expand_to(origin + x_axis - y_axis + z_axis); + aabb.expand_to(origin + x_axis - y_axis - z_axis); + aabb.expand_to(origin - x_axis + y_axis + z_axis); + aabb.expand_to(origin - x_axis + y_axis - z_axis); + aabb.expand_to(origin - x_axis - y_axis + z_axis); + aabb.expand_to(origin - x_axis - y_axis - z_axis); + + _add_item(aabb, ITEM_TYPE_REFLECTION_PROBE, refprobe_count); + + refprobe_count++; + } + + _FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector2 &p_half_extents, float p_depth) { + + if (unlikely(decal_count == decal_max)) { + decal_max = nearest_power_of_2_templated(decal_max + 1); + decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max); + } + + OrientedBoxData &dc = decals[decal_count]; + + Vector3 z_axis = -p_transform.basis.get_axis(2) * p_depth * 0.5; + dc.z_axis[0] = z_axis.x; + dc.z_axis[1] = z_axis.y; + dc.z_axis[2] = z_axis.z; + + Vector3 origin = p_transform.origin - z_axis; + dc.position[0] = origin.x; + dc.position[1] = origin.y; + dc.position[2] = origin.z; + + Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x; + dc.x_axis[0] = x_axis.x; + dc.x_axis[1] = x_axis.y; + dc.x_axis[2] = x_axis.z; + + Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y; + dc.y_axis[0] = y_axis.x; + dc.y_axis[1] = y_axis.y; + dc.y_axis[2] = y_axis.z; + + AABB aabb; + + aabb.position = origin + x_axis + y_axis + z_axis; + aabb.expand_to(origin + x_axis + y_axis - z_axis); + aabb.expand_to(origin + x_axis - y_axis + z_axis); + aabb.expand_to(origin + x_axis - y_axis - z_axis); + aabb.expand_to(origin - x_axis + y_axis + z_axis); + aabb.expand_to(origin - x_axis + y_axis - z_axis); + aabb.expand_to(origin - x_axis - y_axis + z_axis); + aabb.expand_to(origin - x_axis - y_axis - z_axis); + + _add_item(aabb, ITEM_TYPE_DECAL, decal_count); + + decal_count++; + } + + void bake_cluster(); + + void setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth); + + RID get_cluster_texture() const; + RID get_cluster_indices_buffer() const; + + LightClusterBuilder(); + ~LightClusterBuilder(); +}; + +#endif // LIGHT_CLUSTER_BUILDER_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp new file mode 100644 index 0000000000..8d52ffd7b9 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.cpp @@ -0,0 +1,2558 @@ +/*************************************************************************/ +/* rasterizer_canvas_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer_canvas_rd.h" +#include "core/math/math_funcs.h" +#include "core/project_settings.h" +#include "rasterizer_rd.h" + +void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { + + p_mat4[0] = p_transform.elements[0][0]; + p_mat4[1] = p_transform.elements[0][1]; + p_mat4[2] = 0; + p_mat4[3] = 0; + p_mat4[4] = p_transform.elements[1][0]; + p_mat4[5] = p_transform.elements[1][1]; + p_mat4[6] = 0; + p_mat4[7] = 0; + p_mat4[8] = 0; + p_mat4[9] = 0; + p_mat4[10] = 1; + p_mat4[11] = 0; + p_mat4[12] = p_transform.elements[2][0]; + p_mat4[13] = p_transform.elements[2][1]; + p_mat4[14] = 0; + p_mat4[15] = 1; +} + +void RasterizerCanvasRD::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) { + + p_mat2x4[0] = p_transform.elements[0][0]; + p_mat2x4[1] = p_transform.elements[1][0]; + p_mat2x4[2] = 0; + p_mat2x4[3] = p_transform.elements[2][0]; + + p_mat2x4[4] = p_transform.elements[0][1]; + p_mat2x4[5] = p_transform.elements[1][1]; + p_mat2x4[6] = 0; + p_mat2x4[7] = p_transform.elements[2][1]; +} + +void RasterizerCanvasRD::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) { + + p_mat2x3[0] = p_transform.elements[0][0]; + p_mat2x3[1] = p_transform.elements[0][1]; + p_mat2x3[2] = p_transform.elements[1][0]; + p_mat2x3[3] = p_transform.elements[1][1]; + p_mat2x3[4] = p_transform.elements[2][0]; + p_mat2x3[5] = p_transform.elements[2][1]; +} + +void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, float *p_mat4) { + + p_mat4[0] = p_transform.basis.elements[0][0]; + p_mat4[1] = p_transform.basis.elements[1][0]; + p_mat4[2] = p_transform.basis.elements[2][0]; + p_mat4[3] = 0; + p_mat4[4] = p_transform.basis.elements[0][1]; + p_mat4[5] = p_transform.basis.elements[1][1]; + p_mat4[6] = p_transform.basis.elements[2][1]; + p_mat4[7] = 0; + p_mat4[8] = p_transform.basis.elements[0][2]; + p_mat4[9] = p_transform.basis.elements[1][2]; + p_mat4[10] = p_transform.basis.elements[2][2]; + p_mat4[11] = 0; + p_mat4[12] = p_transform.origin.x; + p_mat4[13] = p_transform.origin.y; + p_mat4[14] = p_transform.origin.z; + p_mat4[15] = 1; +} + +void RasterizerCanvasRD::_update_specular_shininess(const Color &p_transform, uint32_t *r_ss) { + + *r_ss = uint32_t(CLAMP(p_transform.a * 255.0, 0, 255)) << 24; + *r_ss |= uint32_t(CLAMP(p_transform.b * 255.0, 0, 255)) << 16; + *r_ss |= uint32_t(CLAMP(p_transform.g * 255.0, 0, 255)) << 8; + *r_ss |= uint32_t(CLAMP(p_transform.r * 255.0, 0, 255)); +} + +RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { + + Vector uniform_set; + + { // COLOR TEXTURE + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; + RID texture = storage->texture_get_rd_texture(p_texture); + if (!texture.is_valid()) { + //use default white texture + texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + u.ids.push_back(texture); + uniform_set.push_back(u); + } + + { // NORMAL TEXTURE + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + RID texture = storage->texture_get_rd_texture(p_normalmap); + if (!texture.is_valid()) { + //use default normal texture + texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + } + u.ids.push_back(texture); + uniform_set.push_back(u); + } + + { // SPECULAR TEXTURE + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 3; + RID texture = storage->texture_get_rd_texture(p_specular); + if (!texture.is_valid()) { + //use default white texture + texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + u.ids.push_back(texture); + uniform_set.push_back(u); + } + + { // SAMPLER + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 4; + RID sampler = storage->sampler_rd_get_default(p_filter, p_repeat); + ERR_FAIL_COND_V(sampler.is_null(), RID()); + u.ids.push_back(sampler); + uniform_set.push_back(u); + } + + { // MULTIMESH TEXTURE BUFFER + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; + u.binding = 5; + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER)); + uniform_set.push_back(u); + } + + return RD::get_singleton()->uniform_set_create(uniform_set, shader.default_version_rd_shader, 0); +} + +RasterizerCanvas::TextureBindingID RasterizerCanvasRD::request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { + + if (p_filter == RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { + p_filter = default_samplers.default_filter; + } + + if (p_repeat == RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { + p_repeat = default_samplers.default_repeat; + } + + TextureBindingKey key; + key.texture = p_texture; + key.normalmap = p_normalmap; + key.specular = p_specular; + key.multimesh = p_multimesh; + key.texture_filter = p_filter; + key.texture_repeat = p_repeat; + + TextureBinding *binding; + TextureBindingID id; + { + TextureBindingID *idptr = bindings.texture_key_bindings.getptr(key); + + if (!idptr) { + id = bindings.id_generator++; + bindings.texture_key_bindings[key] = id; + binding = memnew(TextureBinding); + binding->key = key; + binding->id = id; + + bindings.texture_bindings[id] = binding; + + } else { + id = *idptr; + binding = bindings.texture_bindings[id]; + } + } + + binding->reference_count++; + + if (binding->to_dispose.in_list()) { + //was queued for disposal previously, but ended up reused. + bindings.to_dispose_list.remove(&binding->to_dispose); + } + + if (binding->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) { + binding->uniform_set = _create_texture_binding(p_texture, p_normalmap, p_specular, p_filter, p_repeat, p_multimesh); + } + + return id; +} + +void RasterizerCanvasRD::free_texture_binding(TextureBindingID p_binding) { + + TextureBinding **binding_ptr = bindings.texture_bindings.getptr(p_binding); + ERR_FAIL_COND(!binding_ptr); + TextureBinding *binding = *binding_ptr; + ERR_FAIL_COND(binding->reference_count == 0); + binding->reference_count--; + if (binding->reference_count == 0) { + bindings.to_dispose_list.add(&binding->to_dispose); + } +} + +void RasterizerCanvasRD::_dispose_bindings() { + + while (bindings.to_dispose_list.first()) { + TextureBinding *binding = bindings.to_dispose_list.first()->self(); + if (binding->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) { + RD::get_singleton()->free(binding->uniform_set); + } + + bindings.texture_key_bindings.erase(binding->key); + bindings.texture_bindings.erase(binding->id); + bindings.to_dispose_list.remove(&binding->to_dispose); + memdelete(binding); + } +} + +RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, const Vector &p_bones, const Vector &p_weights) { + + // Care must be taken to generate array formats + // in ways where they could be reused, so we will + // put single-occuring elements first, and repeated + // elements later. This way the generated formats are + // the same no matter the length of the arrays. + // This dramatically reduces the amount of pipeline objects + // that need to be created for these formats. + + uint32_t vertex_count = p_points.size(); + uint32_t stride = 2; //vertices always repeat + if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { + stride += 4; + } + if ((uint32_t)p_uvs.size() == vertex_count) { + stride += 2; + } + if ((uint32_t)p_bones.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) { + stride += 4; + } + + uint32_t buffer_size = stride * p_points.size(); + + Vector polygon_buffer; + polygon_buffer.resize(buffer_size * sizeof(float)); + Vector descriptions; + descriptions.resize(4); + Vector buffers; + buffers.resize(4); + + { + const uint8_t *r = polygon_buffer.ptr(); + float *fptr = (float *)r; + uint32_t *uptr = (uint32_t *)r; + uint32_t base_offset = 0; + { //vertices + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + vd.offset = base_offset * sizeof(float); + vd.location = RS::ARRAY_VERTEX; + vd.stride = stride * sizeof(float); + + descriptions.write[0] = vd; + + const Vector2 *points_ptr = p_points.ptr(); + + for (uint32_t i = 0; i < vertex_count; i++) { + fptr[base_offset + i * stride + 0] = points_ptr[i].x; + fptr[base_offset + i * stride + 1] = points_ptr[i].y; + } + + base_offset += 2; + } + + //colors + if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + vd.offset = base_offset * sizeof(float); + vd.location = RS::ARRAY_COLOR; + vd.stride = stride * sizeof(float); + + descriptions.write[1] = vd; + + if (p_colors.size() == 1) { + Color color = p_colors[0]; + for (uint32_t i = 0; i < vertex_count; i++) { + fptr[base_offset + i * stride + 0] = color.r; + fptr[base_offset + i * stride + 1] = color.g; + fptr[base_offset + i * stride + 2] = color.b; + fptr[base_offset + i * stride + 3] = color.a; + } + } else { + const Color *color_ptr = p_colors.ptr(); + + for (uint32_t i = 0; i < vertex_count; i++) { + fptr[base_offset + i * stride + 0] = color_ptr[i].r; + fptr[base_offset + i * stride + 1] = color_ptr[i].g; + fptr[base_offset + i * stride + 2] = color_ptr[i].b; + fptr[base_offset + i * stride + 3] = color_ptr[i].a; + } + } + base_offset += 4; + } else { + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + vd.offset = 0; + vd.location = RS::ARRAY_COLOR; + vd.stride = 0; + + descriptions.write[1] = vd; + buffers.write[1] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_COLOR); + } + + //uvs + if ((uint32_t)p_uvs.size() == vertex_count) { + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + vd.offset = base_offset * sizeof(float); + vd.location = RS::ARRAY_TEX_UV; + vd.stride = stride * sizeof(float); + + descriptions.write[2] = vd; + + const Vector2 *uv_ptr = p_uvs.ptr(); + + for (uint32_t i = 0; i < vertex_count; i++) { + fptr[base_offset + i * stride + 0] = uv_ptr[i].x; + fptr[base_offset + i * stride + 1] = uv_ptr[i].y; + } + base_offset += 2; + } else { + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + vd.offset = 0; + vd.location = RS::ARRAY_TEX_UV; + vd.stride = 0; + + descriptions.write[2] = vd; + buffers.write[2] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_TEX_UV); + } + + //bones + if ((uint32_t)p_indices.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) { + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + vd.offset = base_offset * sizeof(float); + vd.location = RS::ARRAY_BONES; + vd.stride = stride * sizeof(float); + + descriptions.write[3] = vd; + + const int *bone_ptr = p_bones.ptr(); + const float *weight_ptr = p_weights.ptr(); + + for (uint32_t i = 0; i < vertex_count; i++) { + + uint16_t *bone16w = (uint16_t *)&uptr[base_offset + i * stride]; + uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride + 2]; + + bone16w[0] = bone_ptr[i * 4 + 0]; + bone16w[1] = bone_ptr[i * 4 + 1]; + bone16w[2] = bone_ptr[i * 4 + 2]; + bone16w[3] = bone_ptr[i * 4 + 3]; + + weight16w[0] = CLAMP(weight_ptr[i * 4 + 0] * 65535, 0, 65535); + weight16w[1] = CLAMP(weight_ptr[i * 4 + 1] * 65535, 0, 65535); + weight16w[2] = CLAMP(weight_ptr[i * 4 + 2] * 65535, 0, 65535); + weight16w[3] = CLAMP(weight_ptr[i * 4 + 3] * 65535, 0, 65535); + } + + base_offset += 4; + } else { + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + vd.offset = 0; + vd.location = RS::ARRAY_BONES; + vd.stride = 0; + + descriptions.write[3] = vd; + buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES); + } + + //check that everything is as it should be + ERR_FAIL_COND_V(base_offset != stride, 0); //bug + } + + RD::VertexFormatID vertex_id = RD::get_singleton()->vertex_format_create(descriptions); + ERR_FAIL_COND_V(vertex_id == RD::INVALID_ID, 0); + + PolygonBuffers pb; + pb.vertex_buffer = RD::get_singleton()->vertex_buffer_create(polygon_buffer.size(), polygon_buffer); + for (int i = 0; i < descriptions.size(); i++) { + if (buffers[i] == RID()) { //if put in vertex, use as vertex + buffers.write[i] = pb.vertex_buffer; + } + } + + pb.vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), vertex_id, buffers); + + if (p_indices.size()) { + //create indices, as indices were requested + Vector index_buffer; + index_buffer.resize(p_indices.size() * sizeof(int32_t)); + { + uint8_t *w = index_buffer.ptrw(); + copymem(w, p_indices.ptr(), sizeof(int32_t) * p_indices.size()); + } + pb.index_buffer = RD::get_singleton()->index_buffer_create(p_indices.size(), RD::INDEX_BUFFER_FORMAT_UINT32, index_buffer); + pb.indices = RD::get_singleton()->index_array_create(pb.index_buffer, 0, p_indices.size()); + } + + pb.vertex_format_id = vertex_id; + + PolygonID id = polygon_buffers.last_id++; + + polygon_buffers.polygons[id] = pb; + + return id; +} + +void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) { + + PolygonBuffers *pb_ptr = polygon_buffers.polygons.getptr(p_polygon); + ERR_FAIL_COND(!pb_ptr); + + PolygonBuffers &pb = *pb_ptr; + + if (pb.indices.is_valid()) { + RD::get_singleton()->free(pb.indices); + } + if (pb.index_buffer.is_valid()) { + RD::get_singleton()->free(pb.index_buffer); + } + + RD::get_singleton()->free(pb.vertex_array); + RD::get_singleton()->free(pb.vertex_buffer); + + polygon_buffers.polygons.erase(p_polygon); +} + +Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD::DrawListID p_draw_list, uint32_t &flags) { + + TextureBinding **texture_binding_ptr = bindings.texture_bindings.getptr(p_binding); + ERR_FAIL_COND_V(!texture_binding_ptr, Size2i()); + TextureBinding *texture_binding = *texture_binding_ptr; + + if (texture_binding->key.normalmap.is_valid()) { + flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; + } + if (texture_binding->key.specular.is_valid()) { + flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + if (!RD::get_singleton()->uniform_set_is_valid(texture_binding->uniform_set)) { + //texture may have changed (erased or replaced, see if we can fix) + texture_binding->uniform_set = _create_texture_binding(texture_binding->key.texture, texture_binding->key.normalmap, texture_binding->key.specular, texture_binding->key.texture_filter, texture_binding->key.texture_repeat, texture_binding->key.multimesh); + ERR_FAIL_COND_V(!texture_binding->uniform_set.is_valid(), Size2i(1, 1)); + } + + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, texture_binding->uniform_set, 0); + if (texture_binding->key.texture.is_valid()) { + return storage->texture_2d_get_size(texture_binding->key.texture); + } else { + return Size2i(1, 1); + } +} + +//////////////////// +void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { + + //create an empty push constant + + PushConstant push_constant; + Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; + _update_transform_2d_to_mat2x3(base_transform, push_constant.world); + + Color base_color = p_item->final_modulate; + + for (int i = 0; i < 4; i++) { + push_constant.modulation[i] = 0; + push_constant.ninepatch_margins[i] = 0; + push_constant.src_rect[i] = 0; + push_constant.dst_rect[i] = 0; + } + push_constant.flags = 0; + push_constant.color_texture_pixel_size[0] = 0; + push_constant.color_texture_pixel_size[1] = 0; + + push_constant.pad[0] = 0; + push_constant.pad[1] = 0; + + push_constant.lights[0] = 0; + push_constant.lights[1] = 0; + push_constant.lights[2] = 0; + push_constant.lights[3] = 0; + + uint32_t base_flags = 0; + + bool light_uniform_set_dirty = false; + + if (!p_item->custom_data) { + p_item->custom_data = memnew(ItemStateData); + light_uniform_set_dirty = true; + } + + ItemStateData *state_data = (ItemStateData *)p_item->custom_data; + + Light *light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; + uint16_t light_count = 0; + PipelineLightMode light_mode; + + { + + Light *light = p_lights; + + while (light) { + + if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { + + uint32_t light_index = light->render_index_cache; + push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); + + if (!light_uniform_set_dirty && (state_data->light_cache[light_count].light != light || state_data->light_cache[light_count].light_version != light->version)) { + light_uniform_set_dirty = true; + } + + light_cache[light_count] = light; + + light_count++; + if (light->mode == RS::CANVAS_LIGHT_MODE_MASK) { + base_flags |= FLAGS_USING_LIGHT_MASK; + } + if (light_count == state.max_lights_per_item) { + break; + } + } + light = light->next_ptr; + } + + if (light_count != state_data->light_cache_count) { + light_uniform_set_dirty = true; + } + base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; + } + + { + + RID &canvas_item_state = light_count ? state_data->state_uniform_set_with_light : state_data->state_uniform_set; + + bool invalid_uniform = canvas_item_state.is_valid() && !RD::get_singleton()->uniform_set_is_valid(canvas_item_state); + + if (canvas_item_state.is_null() || invalid_uniform || (light_count > 0 && light_uniform_set_dirty)) { + //re create canvas state + Vector uniforms; + + if (state_data->state_uniform_set_with_light.is_valid() && !invalid_uniform) { + RD::get_singleton()->free(canvas_item_state); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(state.canvas_state_buffer); + uniforms.push_back(u); + } + + if (false && p_item->skeleton.is_valid()) { + //bind skeleton stuff + } else { + //bind default + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; + u.binding = 1; + u.ids.push_back(shader.default_skeleton_texture_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 2; + u.ids.push_back(shader.default_skeleton_uniform_buffer); + uniforms.push_back(u); + } + } + + //validate and update lighs if they are being used + + if (light_count > 0) { + //recreate uniform set + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 3; + u.ids.push_back(state.lights_uniform_buffer); + uniforms.push_back(u); + } + + { + + RD::Uniform u_lights; + u_lights.type = RD::UNIFORM_TYPE_TEXTURE; + u_lights.binding = 4; + + RD::Uniform u_shadows; + u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; + u_shadows.binding = 5; + + //lights + for (uint32_t i = 0; i < state.max_lights_per_item; i++) { + if (i < light_count) { + + CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal); + ERR_CONTINUE(!cl); + + RID rd_texture; + + if (cl->texture.is_valid()) { + rd_texture = storage->texture_get_rd_texture(cl->texture); + } + if (rd_texture.is_valid()) { + u_lights.ids.push_back(rd_texture); + } else { + u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + } + if (cl->shadow.texture.is_valid()) { + u_shadows.ids.push_back(cl->shadow.texture); + } else { + u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + } + } else { + u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + } + } + + uniforms.push_back(u_lights); + uniforms.push_back(u_shadows); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 6; + u.ids.push_back(state.shadow_sampler); + uniforms.push_back(u); + } + + canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 2); + } else { + canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2); + } + } + + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, canvas_item_state, 2); + } + + light_mode = light_count > 0 ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED; + + PipelineVariants *pipeline_variants = p_pipeline_variants; + + bool reclip = false; + + const Item::Command *c = p_item->commands; + while (c) { + push_constant.flags = base_flags; //reset on each command for sanity + push_constant.specular_shininess = 0xFFFFFFFF; + + switch (c->type) { + case Item::Command::TYPE_RECT: { + + const Item::CommandRect *rect = static_cast(c); + + //bind pipeline + { + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + } + + //bind textures + + Size2 texpixel_size; + { + texpixel_size = _bind_texture_binding(rect->texture_binding.binding_id, p_draw_list, push_constant.flags); + texpixel_size.x = 1.0 / texpixel_size.x; + texpixel_size.y = 1.0 / texpixel_size.y; + } + + if (rect->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(rect->specular_shininess, &push_constant.specular_shininess); + + Rect2 src_rect; + Rect2 dst_rect; + + if (texpixel_size != Vector2()) { + push_constant.color_texture_pixel_size[0] = texpixel_size.x; + push_constant.color_texture_pixel_size[1] = texpixel_size.y; + + src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1); + dst_rect = Rect2(rect->rect.position, rect->rect.size); + + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + if (rect->flags & CANVAS_RECT_FLIP_H) { + src_rect.size.x *= -1; + } + + if (rect->flags & CANVAS_RECT_FLIP_V) { + src_rect.size.y *= -1; + } + + if (rect->flags & CANVAS_RECT_TRANSPOSE) { + dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform + } + + if (rect->flags & CANVAS_RECT_CLIP_UV) { + push_constant.flags |= FLAGS_CLIP_RECT_UV; + } + + } else { + dst_rect = Rect2(rect->rect.position, rect->rect.size); + + if (dst_rect.size.width < 0) { + dst_rect.position.x += dst_rect.size.width; + dst_rect.size.width *= -1; + } + if (dst_rect.size.height < 0) { + dst_rect.position.y += dst_rect.size.height; + dst_rect.size.height *= -1; + } + + src_rect = Rect2(0, 0, 1, 1); + texpixel_size = Vector2(1, 1); + } + + push_constant.modulation[0] = rect->modulate.r * base_color.r; + push_constant.modulation[1] = rect->modulate.g * base_color.g; + push_constant.modulation[2] = rect->modulate.b * base_color.b; + push_constant.modulation[3] = rect->modulate.a * base_color.a; + + push_constant.src_rect[0] = src_rect.position.x; + push_constant.src_rect[1] = src_rect.position.y; + push_constant.src_rect[2] = src_rect.size.width; + push_constant.src_rect[3] = src_rect.size.height; + + push_constant.dst_rect[0] = dst_rect.position.x; + push_constant.dst_rect[1] = dst_rect.position.y; + push_constant.dst_rect[2] = dst_rect.size.width; + push_constant.dst_rect[3] = dst_rect.size.height; + + push_constant.color_texture_pixel_size[0] = texpixel_size.x; + push_constant.color_texture_pixel_size[1] = texpixel_size.y; + + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); + RD::get_singleton()->draw_list_draw(p_draw_list, true); + + } break; + + case Item::Command::TYPE_NINEPATCH: { + + const Item::CommandNinePatch *np = static_cast(c); + + //bind pipeline + { + RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + } + + //bind textures + + Size2 texpixel_size; + { + texpixel_size = _bind_texture_binding(np->texture_binding.binding_id, p_draw_list, push_constant.flags); + texpixel_size.x = 1.0 / texpixel_size.x; + texpixel_size.y = 1.0 / texpixel_size.y; + } + + if (np->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(np->specular_shininess, &push_constant.specular_shininess); + + Rect2 src_rect; + Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); + + if (texpixel_size == Size2()) { + + texpixel_size = Size2(1, 1); + src_rect = Rect2(0, 0, 1, 1); + + } else { + + if (np->source != Rect2()) { + src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height); + texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height); + } else { + src_rect = Rect2(0, 0, 1, 1); + } + } + + push_constant.modulation[0] = np->color.r * base_color.r; + push_constant.modulation[1] = np->color.g * base_color.g; + push_constant.modulation[2] = np->color.b * base_color.b; + push_constant.modulation[3] = np->color.a * base_color.a; + + push_constant.src_rect[0] = src_rect.position.x; + push_constant.src_rect[1] = src_rect.position.y; + push_constant.src_rect[2] = src_rect.size.width; + push_constant.src_rect[3] = src_rect.size.height; + + push_constant.dst_rect[0] = dst_rect.position.x; + push_constant.dst_rect[1] = dst_rect.position.y; + push_constant.dst_rect[2] = dst_rect.size.width; + push_constant.dst_rect[3] = dst_rect.size.height; + + push_constant.color_texture_pixel_size[0] = texpixel_size.x; + push_constant.color_texture_pixel_size[1] = texpixel_size.y; + + push_constant.flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; + push_constant.flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; + + if (np->draw_center) { + push_constant.flags |= FLAGS_NINEPACH_DRAW_CENTER; + } + + push_constant.ninepatch_margins[0] = np->margin[MARGIN_LEFT]; + push_constant.ninepatch_margins[1] = np->margin[MARGIN_TOP]; + push_constant.ninepatch_margins[2] = np->margin[MARGIN_RIGHT]; + push_constant.ninepatch_margins[3] = np->margin[MARGIN_BOTTOM]; + + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); + RD::get_singleton()->draw_list_draw(p_draw_list, true); + + } break; + case Item::Command::TYPE_POLYGON: { + + const Item::CommandPolygon *polygon = static_cast(c); + + PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id); + ERR_CONTINUE(!pb); + //bind pipeline + { + static const PipelineVariant variant[RS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; + ERR_CONTINUE(polygon->primitive < 0 || polygon->primitive >= RS::PRIMITIVE_MAX); + RID pipeline = pipeline_variants->variants[light_mode][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + } + + if (polygon->primitive == RS::PRIMITIVE_LINES) { + //not supported in most hardware, so pointless + //RD::get_singleton()->draw_list_set_line_width(p_draw_list, polygon->line_width); + } + + //bind textures + + Size2 texpixel_size; + { + texpixel_size = _bind_texture_binding(polygon->texture_binding.binding_id, p_draw_list, push_constant.flags); + texpixel_size.x = 1.0 / texpixel_size.x; + texpixel_size.y = 1.0 / texpixel_size.y; + } + + if (polygon->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(polygon->specular_shininess, &push_constant.specular_shininess); + + push_constant.modulation[0] = base_color.r; + push_constant.modulation[1] = base_color.g; + push_constant.modulation[2] = base_color.b; + push_constant.modulation[3] = base_color.a; + + for (int j = 0; j < 4; j++) { + push_constant.src_rect[j] = 0; + push_constant.dst_rect[j] = 0; + push_constant.ninepatch_margins[j] = 0; + } + + push_constant.color_texture_pixel_size[0] = texpixel_size.x; + push_constant.color_texture_pixel_size[1] = texpixel_size.y; + + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); + RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); + if (pb->indices.is_valid()) { + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, pb->indices); + } + RD::get_singleton()->draw_list_draw(p_draw_list, pb->indices.is_valid()); + + } break; + case Item::Command::TYPE_PRIMITIVE: { + + const Item::CommandPrimitive *primitive = static_cast(c); + + //bind pipeline + { + static const PipelineVariant variant[4] = { PIPELINE_VARIANT_PRIMITIVE_POINTS, PIPELINE_VARIANT_PRIMITIVE_LINES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES }; + ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4); + RID pipeline = pipeline_variants->variants[light_mode][variant[primitive->point_count - 1]].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); + } + + //bind textures + + { + _bind_texture_binding(primitive->texture_binding.binding_id, p_draw_list, push_constant.flags); + } + + if (primitive->specular_shininess.a < 0.999) { + push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; + } + + _update_specular_shininess(primitive->specular_shininess, &push_constant.specular_shininess); + + RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3, primitive->point_count) - 1]); + + for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) { + push_constant.points[j * 2 + 0] = primitive->points[j].x; + push_constant.points[j * 2 + 1] = primitive->points[j].y; + push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x; + push_constant.uvs[j * 2 + 1] = primitive->uvs[j].y; + Color col = primitive->colors[j] * base_color; + push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); + push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); + } + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); + RD::get_singleton()->draw_list_draw(p_draw_list, true); + + if (primitive->point_count == 4) { + for (uint32_t j = 1; j < 3; j++) { + //second half of triangle + push_constant.points[j * 2 + 0] = primitive->points[j + 1].x; + push_constant.points[j * 2 + 1] = primitive->points[j + 1].y; + push_constant.uvs[j * 2 + 0] = primitive->uvs[j + 1].x; + push_constant.uvs[j * 2 + 1] = primitive->uvs[j + 1].y; + Color col = primitive->colors[j + 1] * base_color; + push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); + push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); + } + + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); + RD::get_singleton()->draw_list_draw(p_draw_list, true); + } + + } break; + case Item::Command::TYPE_MESH: + case Item::Command::TYPE_MULTIMESH: + case Item::Command::TYPE_PARTICLES: { + ERR_PRINT("FIXME: Mesh, MultiMesh and Particles render commands are unimplemented currently, they need to be ported to the 4.0 rendering architecture."); +#ifndef _MSC_VER +#warning Item::Command types for Mesh, MultiMesh and Particles need to be implemented. +#endif + // See #if 0'ed code below to port from GLES3. + } break; + +#if 0 + case Item::Command::TYPE_MESH: { + + Item::CommandMesh *mesh = static_cast(c); + _set_texture_rect_mode(false); + + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform); + + RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); + if (mesh_data) { + + for (int j = 0; j < mesh_data->surfaces.size(); j++) { + RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; + // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing + glBindVertexArray(s->array_id); + + glVertexAttrib4f(RS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a); + + if (s->index_array_len) { + glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); + } else { + glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); + } + + glBindVertexArray(0); + } + } + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); + + } break; + case Item::Command::TYPE_MULTIMESH: { + + Item::CommandMultiMesh *mmesh = static_cast(c); + + RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); + + if (!multi_mesh) + break; + + RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); + + if (!mesh_data) + break; + + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != RS::MULTIMESH_CUSTOM_DATA_NONE); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); + //reset shader and force rebind + state.using_texture_rect = true; + _set_texture_rect_mode(false); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + } + + int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); + + if (amount == -1) { + amount = multi_mesh->size; + } + + for (int j = 0; j < mesh_data->surfaces.size(); j++) { + RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; + // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing + glBindVertexArray(s->instancing_array_id); + + glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer + + int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; + glEnableVertexAttribArray(8); + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0)); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); + glVertexAttribDivisor(9, 1); + + int color_ofs; + + if (multi_mesh->transform_format == RS::MULTIMESH_TRANSFORM_3D) { + glEnableVertexAttribArray(10); + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); + glVertexAttribDivisor(10, 1); + color_ofs = 12 * 4; + } else { + glDisableVertexAttribArray(10); + glVertexAttrib4f(10, 0, 0, 1, 0); + color_ofs = 8 * 4; + } + + int custom_data_ofs = color_ofs; + + switch (multi_mesh->color_format) { + + case RS::MULTIMESH_COLOR_NONE: { + glDisableVertexAttribArray(11); + glVertexAttrib4f(11, 1, 1, 1, 1); + } break; + case RS::MULTIMESH_COLOR_8BIT: { + glEnableVertexAttribArray(11); + glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); + glVertexAttribDivisor(11, 1); + custom_data_ofs += 4; + + } break; + case RS::MULTIMESH_COLOR_FLOAT: { + glEnableVertexAttribArray(11); + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); + glVertexAttribDivisor(11, 1); + custom_data_ofs += 4 * 4; + } break; + } + + switch (multi_mesh->custom_data_format) { + + case RS::MULTIMESH_CUSTOM_DATA_NONE: { + glDisableVertexAttribArray(12); + glVertexAttrib4f(12, 1, 1, 1, 1); + } break; + case RS::MULTIMESH_CUSTOM_DATA_8BIT: { + glEnableVertexAttribArray(12); + glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); + glVertexAttribDivisor(12, 1); + + } break; + case RS::MULTIMESH_CUSTOM_DATA_FLOAT: { + glEnableVertexAttribArray(12); + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); + glVertexAttribDivisor(12, 1); + } break; + } + + if (s->index_array_len) { + glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); + } else { + glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); + } + + glBindVertexArray(0); + } + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); + state.using_texture_rect = true; + _set_texture_rect_mode(false); + + } break; + case Item::Command::TYPE_PARTICLES: { + + Item::CommandParticles *particles_cmd = static_cast(c); + + RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles); + if (!particles) + break; + + if (particles->inactive && !particles->emitting) + break; + + glVertexAttrib4f(RS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white + + RenderingServerRaster::redraw_request(); + + storage->particles_request_process(particles_cmd->particles); + //enable instancing + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); + //reset shader and force rebind + state.using_texture_rect = true; + _set_texture_rect_mode(false); + + RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map); + + if (texture) { + Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); + } else { + state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); + } + + if (!particles->use_local_coords) { + + Transform2D inv_xf; + inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y)); + inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y)); + inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y)); + inv_xf.affine_invert(); + + state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); + } + + glBindVertexArray(data.particle_quad_array); //use particle quad array + glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer + + int stride = sizeof(float) * 4 * 6; + + int amount = particles->amount; + + if (particles->draw_order != RS::PARTICLES_DRAW_ORDER_LIFETIME) { + + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); + glVertexAttribDivisor(12, 1); + + glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); + } else { + //split + int split = int(Math::ceil(particles->phase * particles->amount)); + + if (amount - split > 0) { + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); + glVertexAttribDivisor(12, 1); + + glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split); + } + + if (split > 0) { + glEnableVertexAttribArray(8); //xform x + glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); + glVertexAttribDivisor(8, 1); + glEnableVertexAttribArray(9); //xform y + glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); + glVertexAttribDivisor(9, 1); + glEnableVertexAttribArray(10); //xform z + glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); + glVertexAttribDivisor(10, 1); + glEnableVertexAttribArray(11); //color + glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); + glVertexAttribDivisor(11, 1); + glEnableVertexAttribArray(12); //custom + glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); + glVertexAttribDivisor(12, 1); + + glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split); + } + } + + glBindVertexArray(0); + + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); + state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); + state.using_texture_rect = true; + _set_texture_rect_mode(false); + + } break; +#endif + case Item::Command::TYPE_TRANSFORM: { + + const Item::CommandTransform *transform = static_cast(c); + _update_transform_2d_to_mat2x3(base_transform * transform->xform, push_constant.world); + + } break; + case Item::Command::TYPE_CLIP_IGNORE: { + + const Item::CommandClipIgnore *ci = static_cast(c); + if (current_clip) { + + if (ci->ignore != reclip) { + + if (ci->ignore) { + RD::get_singleton()->draw_list_disable_scissor(p_draw_list); + reclip = true; + } else { + + RD::get_singleton()->draw_list_enable_scissor(p_draw_list, current_clip->final_clip_rect); + reclip = false; + } + } + } + + } break; + } + + c = c->next; + } + + if (current_clip && reclip) { + //will make it re-enable clipping if needed afterwards + current_clip = NULL; + } +} + +void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set) { + + Item *current_clip = NULL; + + Transform2D canvas_transform_inverse = p_canvas_transform_inverse; + + RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); + + Vector clear_colors; + bool clear = false; + if (storage->render_target_is_clear_requested(p_to_render_target)) { + clear = true; + clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target)); + storage->render_target_disable_clear_request(p_to_render_target); + } +#ifndef _MSC_VER +#warning TODO obtain from framebuffer format eventually when this is implemented +#endif + + RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); + + if (p_screen_uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 3); + } + RID prev_material; + + PipelineVariants *pipeline_variants = &shader.pipeline_variants; + + for (int i = 0; i < p_item_count; i++) { + + Item *ci = items[i]; + + if (current_clip != ci->final_clip_owner) { + + current_clip = ci->final_clip_owner; + + //setup clip + if (current_clip) { + + RD::get_singleton()->draw_list_enable_scissor(draw_list, current_clip->final_clip_rect); + + } else { + + RD::get_singleton()->draw_list_disable_scissor(draw_list); + } + } + + if (ci->material != prev_material) { + + MaterialData *material_data = NULL; + if (ci->material.is_valid()) { + material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); + } + + if (material_data) { + + if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) { + pipeline_variants = &material_data->shader_data->pipeline_variants; + if (material_data->uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, 1); + } + } else { + pipeline_variants = &shader.pipeline_variants; + } + } else { + pipeline_variants = &shader.pipeline_variants; + } + } + + _render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants); + + prev_material = ci->material; + } + + RD::get_singleton()->draw_list_end(); +} + +void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) { + + int item_count = 0; + + //setup canvas state uniforms if needed + + Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); + + { + //update canvas state uniform buffer + State::Buffer state_buffer; + + Size2i ssize = storage->render_target_get_size(p_to_render_target); + + Transform screen_transform; + screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); + screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); + _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); + _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); + + Transform2D normal_transform = p_canvas_transform; + normal_transform.elements[0].normalize(); + normal_transform.elements[1].normalize(); + normal_transform.elements[2] = Vector2(); + _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); + + state_buffer.canvas_modulate[0] = p_modulate.r; + state_buffer.canvas_modulate[1] = p_modulate.g; + state_buffer.canvas_modulate[2] = p_modulate.b; + state_buffer.canvas_modulate[3] = p_modulate.a; + + Size2 render_target_size = storage->render_target_get_size(p_to_render_target); + state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x; + state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y; + + state_buffer.time = state.time; + RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true); + } + + //setup lights if exist + + { + + Light *l = p_light_list; + uint32_t index = 0; + + while (l) { + + if (index == state.max_lights_per_render) { + l->render_index_cache = -1; + l = l->next_ptr; + continue; + } + + CanvasLight *clight = canvas_light_owner.getornull(l->light_internal); + if (!clight) { //unused or invalid texture + l->render_index_cache = -1; + l = l->next_ptr; + ERR_CONTINUE(!clight); + } + Transform2D to_light_xform = (p_canvas_transform * l->light_shader_xform).affine_inverse(); + + Vector2 canvas_light_pos = p_canvas_transform.xform(l->xform.get_origin()); //convert light position to canvas coordinates, as all computation is done in canvas coords to avoid precision loss + state.light_uniforms[index].position[0] = canvas_light_pos.x; + state.light_uniforms[index].position[1] = canvas_light_pos.y; + + _update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix); + _update_transform_2d_to_mat2x4(l->xform_cache.affine_inverse(), state.light_uniforms[index].shadow_matrix); + + state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss + for (int i = 0; i < 4; i++) { + state.light_uniforms[index].shadow_color[i] = l->shadow_color[i]; + state.light_uniforms[index].color[i] = l->color[i]; + } + + state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate + + if (clight->shadow.texture.is_valid()) { + state.light_uniforms[index].shadow_pixel_size = (1.0 / clight->shadow.size) * (1.0 + l->shadow_smooth); + } else { + state.light_uniforms[index].shadow_pixel_size = 1.0; + } + + state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT; + state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT; + if (clight->shadow.texture.is_valid()) { + state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW; + } + + l->render_index_cache = index; + + index++; + l = l->next_ptr; + } + + if (index > 0) { + RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * index, &state.light_uniforms[0], true); + } + } + + //fill the list until rendering is possible. + bool material_screen_texture_found = false; + Item *ci = p_item_list; + Rect2 back_buffer_rect; + bool backbuffer_copy = false; + RID screen_uniform_set; + + while (ci) { + + if (ci->copy_back_buffer) { + backbuffer_copy = true; + + if (ci->copy_back_buffer->full) { + back_buffer_rect = Rect2(); + } else { + back_buffer_rect = ci->copy_back_buffer->rect; + } + } + + if (ci->material.is_valid()) { + MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); + if (md && md->shader_data->valid) { + + if (md->shader_data->uses_screen_texture) { + if (!material_screen_texture_found) { + backbuffer_copy = true; + back_buffer_rect = Rect2(); + } + if (screen_uniform_set.is_null()) { + RID backbuffer_shader = shader.canvas_shader.version_get_shader(md->shader_data->version, 0); //any version is fine + screen_uniform_set = storage->render_target_get_back_buffer_uniform_set(p_to_render_target, backbuffer_shader); + } + } + + if (md->last_frame != RasterizerRD::get_frame_number()) { + md->last_frame = RasterizerRD::get_frame_number(); + if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { + // uniform set may be gone because a dependency was erased. In this case, it will happen + // if a texture is deleted, so just re-create it. + storage->material_force_update_textures(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); + } + } + } + } + + if (backbuffer_copy) { + //render anything pending, including clearing if no items + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set); + item_count = 0; + + storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect); + + backbuffer_copy = false; + material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies + } + + items[item_count++] = ci; + + if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { + _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set); + //then reset + item_count = 0; + } + + ci = ci->next; + } +} + +RID RasterizerCanvasRD::light_create() { + + CanvasLight canvas_light; + canvas_light.shadow.size = 0; + return canvas_light_owner.make_rid(canvas_light); +} + +void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(!cl); + if (cl->texture == p_texture) { + return; + } + + cl->texture = p_texture; +} +void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(!cl); + ERR_FAIL_COND(p_resolution < 64); + if (cl->shadow.texture.is_valid() == p_enable && p_resolution == cl->shadow.size) { + return; + } + + if (cl->shadow.texture.is_valid()) { + + RD::get_singleton()->free(cl->shadow.fb); + RD::get_singleton()->free(cl->shadow.depth); + RD::get_singleton()->free(cl->shadow.texture); + cl->shadow.fb = RID(); + cl->shadow.texture = RID(); + cl->shadow.depth = RID(); + } + + if (p_enable) { + + Vector fb_textures; + + { //texture + RD::TextureFormat tf; + tf.type = RD::TEXTURE_TYPE_2D; + tf.width = p_resolution; + tf.height = 1; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + + cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + fb_textures.push_back(cl->shadow.texture); + } + { + RD::TextureFormat tf; + tf.type = RD::TEXTURE_TYPE_2D; + tf.width = p_resolution; + tf.height = 1; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; + //chunks to write + cl->shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + fb_textures.push_back(cl->shadow.depth); + } + + cl->shadow.fb = RD::get_singleton()->framebuffer_create(fb_textures); + } + + cl->shadow.size = p_resolution; +} + +void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { + + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND(cl->shadow.texture.is_null()); + + for (int i = 0; i < 4; i++) { + + //make sure it remains orthogonal, makes easy to read angle later + + //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); + + Vector cc; + cc.push_back(Color(p_far, p_far, p_far, 1.0)); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, Rect2i((cl->shadow.size / 4) * i, 0, (cl->shadow.size / 4), 1)); + + CameraMatrix projection; + { + real_t fov = 90; + real_t nearp = p_near; + real_t farp = p_far; + real_t aspect = 1.0; + + real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); + real_t ymin = -ymax; + real_t xmin = ymin * aspect; + real_t xmax = ymax * aspect; + + projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); + } + + Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); + projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); + + ShadowRenderPushConstant push_constant; + for (int y = 0; y < 4; y++) { + for (int x = 0; x < 4; x++) { + push_constant.projection[y * 4 + x] = projection.matrix[y][x]; + } + } + static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; + push_constant.direction[0] = directions[i].x; + push_constant.direction[1] = directions[i].y; + push_constant.pad[0] = 0; + push_constant.pad[1] = 0; + + /*if (i == 0) + *p_xform_cache = projection;*/ + + LightOccluderInstance *instance = p_occluders; + + while (instance) { + + OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder); + + if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) { + + instance = instance->next; + continue; + } + + _update_transform_2d_to_mat2x4(p_light_xform * instance->xform_cache, push_constant.modelview); + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]); + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array); + RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + + instance = instance->next; + } + + RD::get_singleton()->draw_list_end(); + } +} + +RID RasterizerCanvasRD::occluder_polygon_create() { + + OccluderPolygon occluder; + occluder.point_count = 0; + occluder.cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + return occluder_polygon_owner.make_rid(occluder); +} + +void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines) { + + OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); + ERR_FAIL_COND(!oc); + + if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) { + + RD::get_singleton()->free(oc->vertex_array); + RD::get_singleton()->free(oc->vertex_buffer); + RD::get_singleton()->free(oc->index_array); + RD::get_singleton()->free(oc->index_buffer); + + oc->vertex_array = RID(); + oc->vertex_buffer = RID(); + oc->index_array = RID(); + oc->index_buffer = RID(); + } + + if (p_lines.size()) { + + Vector geometry; + Vector indices; + int lc = p_lines.size(); + + geometry.resize(lc * 6 * sizeof(float)); + indices.resize(lc * 3 * sizeof(uint16_t)); + + { + uint8_t *vw = geometry.ptrw(); + float *vwptr = (float *)vw; + uint8_t *iw = indices.ptrw(); + uint16_t *iwptr = (uint16_t *)iw; + + const Vector2 *lr = p_lines.ptr(); + + const int POLY_HEIGHT = 16384; + + for (int i = 0; i < lc / 2; i++) { + + vwptr[i * 12 + 0] = lr[i * 2 + 0].x; + vwptr[i * 12 + 1] = lr[i * 2 + 0].y; + vwptr[i * 12 + 2] = POLY_HEIGHT; + + vwptr[i * 12 + 3] = lr[i * 2 + 1].x; + vwptr[i * 12 + 4] = lr[i * 2 + 1].y; + vwptr[i * 12 + 5] = POLY_HEIGHT; + + vwptr[i * 12 + 6] = lr[i * 2 + 1].x; + vwptr[i * 12 + 7] = lr[i * 2 + 1].y; + vwptr[i * 12 + 8] = -POLY_HEIGHT; + + vwptr[i * 12 + 9] = lr[i * 2 + 0].x; + vwptr[i * 12 + 10] = lr[i * 2 + 0].y; + vwptr[i * 12 + 11] = -POLY_HEIGHT; + + iwptr[i * 6 + 0] = i * 4 + 0; + iwptr[i * 6 + 1] = i * 4 + 1; + iwptr[i * 6 + 2] = i * 4 + 2; + + iwptr[i * 6 + 3] = i * 4 + 2; + iwptr[i * 6 + 4] = i * 4 + 3; + iwptr[i * 6 + 5] = i * 4 + 0; + } + } + + //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush + + if (oc->vertex_array.is_null()) { + //create from scratch + //vertices + oc->vertex_buffer = RD::get_singleton()->vertex_buffer_create(lc * 6 * sizeof(real_t), geometry); + + Vector buffer; + buffer.push_back(oc->vertex_buffer); + oc->vertex_array = RD::get_singleton()->vertex_array_create(4 * lc / 2, shadow_render.vertex_format, buffer); + //indices + + oc->index_buffer = RD::get_singleton()->index_buffer_create(3 * lc, RD::INDEX_BUFFER_FORMAT_UINT16, indices); + oc->index_array = RD::get_singleton()->index_array_create(oc->index_buffer, 0, 3 * lc); + + } else { + //update existing + const uint8_t *vr = geometry.ptr(); + RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, geometry.size(), vr); + const uint8_t *ir = indices.ptr(); + RD::get_singleton()->buffer_update(oc->index_buffer, 0, indices.size(), ir); + } + } +} +void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode) { + OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); + ERR_FAIL_COND(!oc); + oc->cull_mode = p_mode; +} + +void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + uses_screen_texture = false; + uses_material_samplers = false; + + if (code == String()) { + return; //just invalid, but no error + } + + ShaderCompilerRD::GeneratedCode gen_code; + + int light_mode = LIGHT_MODE_NORMAL; + int blend_mode = BLEND_MODE_MIX; + uses_screen_texture = false; + + ShaderCompilerRD::IdentifierActions actions; + + actions.render_mode_values["blend_add"] = Pair(&blend_mode, BLEND_MODE_ADD); + actions.render_mode_values["blend_mix"] = Pair(&blend_mode, BLEND_MODE_MIX); + actions.render_mode_values["blend_sub"] = Pair(&blend_mode, BLEND_MODE_SUB); + actions.render_mode_values["blend_mul"] = Pair(&blend_mode, BLEND_MODE_MUL); + actions.render_mode_values["blend_premul_alpha"] = Pair(&blend_mode, BLEND_MODE_PMALPHA); + actions.render_mode_values["blend_disabled"] = Pair(&blend_mode, BLEND_MODE_DISABLED); + + actions.render_mode_values["unshaded"] = Pair(&light_mode, LIGHT_MODE_UNSHADED); + actions.render_mode_values["light_only"] = Pair(&light_mode, LIGHT_MODE_LIGHT_ONLY); + + actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; + + actions.uniforms = &uniforms; + + RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; + + Error err = canvas_singleton->shader.compiler.compile(RS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); + + ERR_FAIL_COND(err != OK); + + if (version.is_null()) { + version = canvas_singleton->shader.canvas_shader.version_create(); + } + + if (gen_code.texture_uniforms.size() || uses_screen_texture) { //requires the samplers + gen_code.defines.push_back("\n#define USE_MATERIAL_SAMPLERS\n"); + uses_material_samplers = true; + } +#if 0 + print_line("**compiling shader:"); + print_line("**defines:\n"); + for (int i = 0; i < gen_code.defines.size(); i++) { + print_line(gen_code.defines[i]); + } + print_line("\n**uniforms:\n" + gen_code.uniforms); + print_line("\n**vertex_globals:\n" + gen_code.vertex_global); + print_line("\n**vertex_code:\n" + gen_code.vertex); + print_line("\n**fragment_globals:\n" + gen_code.fragment_global); + print_line("\n**fragment_code:\n" + gen_code.fragment); + print_line("\n**light_code:\n" + gen_code.light); +#endif + canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + //update them pipelines + + RD::PipelineColorBlendState::Attachment attachment; + + switch (blend_mode) { + case BLEND_MODE_DISABLED: { + + // nothing to do here, disabled by default + + } break; + case BLEND_MODE_MIX: { + + attachment.enable_blend = true; + attachment.alpha_blend_op = RD::BLEND_OP_ADD; + attachment.color_blend_op = RD::BLEND_OP_ADD; + attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + } break; + case BLEND_MODE_ADD: { + + attachment.enable_blend = true; + attachment.alpha_blend_op = RD::BLEND_OP_ADD; + attachment.color_blend_op = RD::BLEND_OP_ADD; + attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + + } break; + case BLEND_MODE_SUB: { + + attachment.enable_blend = true; + attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT; + attachment.color_blend_op = RD::BLEND_OP_SUBTRACT; + attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + + } break; + case BLEND_MODE_MUL: { + attachment.enable_blend = true; + attachment.alpha_blend_op = RD::BLEND_OP_ADD; + attachment.color_blend_op = RD::BLEND_OP_ADD; + attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR; + attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO; + attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA; + attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + + } break; + case BLEND_MODE_PMALPHA: { + attachment.enable_blend = true; + attachment.alpha_blend_op = RD::BLEND_OP_ADD; + attachment.color_blend_op = RD::BLEND_OP_ADD; + attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE; + attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + } break; + } + + RD::PipelineColorBlendState blend_state; + blend_state.attachments.push_back(attachment); + + //update pipelines + + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { + for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { + RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, + RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_LINESTRIPS, + RD::RENDER_PRIMITIVE_POINTS, + }; + + ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { + { //non lit + SHADER_VARIANT_QUAD, + SHADER_VARIANT_NINEPATCH, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE_POINTS, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES_POINTS }, + { //lit + SHADER_VARIANT_QUAD_LIGHT, + SHADER_VARIANT_NINEPATCH_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + }; + + RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); + pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); + } + } + + valid = true; +} + +void RasterizerCanvasRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { + if (!p_texture.is_valid()) { + default_texture_params.erase(p_name); + } else { + default_texture_params[p_name] = p_texture; + } +} +void RasterizerCanvasRD::ShaderData::get_param_list(List *p_param_list) const { + + Map order; + + for (Map::Element *E = uniforms.front(); E; E = E->next()) { + + if (E->get().texture_order >= 0) { + order[E->get().texture_order + 100000] = E->key(); + } else { + order[E->get().order] = E->key(); + } + } + + for (Map::Element *E = order.front(); E; E = E->next()) { + + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); + pi.name = E->get(); + p_param_list->push_back(pi); + } +} + +bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool RasterizerCanvasRD::ShaderData::is_animated() const { + return false; +} +bool RasterizerCanvasRD::ShaderData::casts_shadows() const { + return false; +} +Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); + } + return Variant(); +} + +RasterizerCanvasRD::ShaderData::ShaderData() { + valid = false; + uses_screen_texture = false; + uses_material_samplers = false; +} + +RasterizerCanvasRD::ShaderData::~ShaderData() { + RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; + ERR_FAIL_COND(!canvas_singleton); + //pipeline variants will clear themselves if shader is gone + if (version.is_valid()) { + canvas_singleton->shader.canvas_shader.version_free(version); + } +} + +RasterizerStorageRD::ShaderData *RasterizerCanvasRD::_create_shader_func() { + ShaderData *shader_data = memnew(ShaderData); + return shader_data; +} +void RasterizerCanvasRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + + RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; + + if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(shader_data->ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + + update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); + } + + uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); + + if ((uint32_t)texture_cache.size() != tex_uniform_count) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + + update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false); + } + + if (shader_data->ubo_size == 0 && !shader_data->uses_material_samplers) { + // This material does not require an uniform set, so don't create it. + return; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return; + } + + Vector uniforms; + + { + if (shader_data->uses_material_samplers) { + //needs samplers for the material (uses custom textures) create them + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 0; + u.ids.resize(12); + RID *ids_ptr = u.ids.ptrw(); + ids_ptr[0] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = canvas_singleton->storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + uniforms.push_back(u); + } + + if (shader_data->ubo_size) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 1; + u.ids.push_back(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (uint32_t i = 0; i < tex_uniform_count; i++) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2 + i; + u.ids.push_back(textures[i]); + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), 1); +} +RasterizerCanvasRD::MaterialData::~MaterialData() { + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } +} + +RasterizerStorageRD::MaterialData *RasterizerCanvasRD::_create_material_func(ShaderData *p_shader) { + MaterialData *material_data = memnew(MaterialData); + material_data->shader_data = p_shader; + material_data->last_frame = false; + //update will happen later anyway so do nothing. + return material_data; +} + +void RasterizerCanvasRD::set_time(double p_time) { + state.time = p_time; +} + +void RasterizerCanvasRD::update() { + _dispose_bindings(); +} + +RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { + storage = p_storage; + + { //create default samplers + + default_samplers.default_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; + default_samplers.default_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; + } + + { //shader variants + + uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + + String global_defines; + if (textures_per_stage <= 16) { + //ARM pretty much, and very old Intel GPUs under Linux + state.max_lights_per_item = 4; //sad + global_defines += "#define MAX_LIGHT_TEXTURES 4\n"; + } else if (textures_per_stage <= 32) { + //Apple (Metal) + state.max_lights_per_item = 8; //sad + global_defines += "#define MAX_LIGHT_TEXTURES 8\n"; + } else { + //Anything else (16 lights per item) + state.max_lights_per_item = DEFAULT_MAX_LIGHTS_PER_ITEM; + global_defines += "#define MAX_LIGHT_TEXTURES " + itos(DEFAULT_MAX_LIGHTS_PER_ITEM) + "\n"; + } + + uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); + if (uniform_max_size < 65536) { + //Yes, you guessed right, ARM again + state.max_lights_per_render = 64; + global_defines += "#define MAX_LIGHTS 64\n"; + } else { + state.max_lights_per_render = DEFAULT_MAX_LIGHTS_PER_RENDER; + global_defines += "#define MAX_LIGHTS " + itos(DEFAULT_MAX_LIGHTS_PER_RENDER) + "\n"; + } + + state.light_uniforms = memnew_arr(LightUniform, state.max_lights_per_render); + Vector variants; + //non light variants + variants.push_back(""); //none by default is first variant + variants.push_back("#define USE_NINEPATCH\n"); //ninepatch is the second variant + variants.push_back("#define USE_PRIMITIVE\n"); //primitive is the third + variants.push_back("#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size + variants.push_back("#define USE_ATTRIBUTES\n"); // attributes for vertex arrays + variants.push_back("#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size + //light variants + variants.push_back("#define USE_LIGHTING\n"); //none by default is first variant + variants.push_back("#define USE_LIGHTING\n#define USE_NINEPATCH\n"); //ninepatch is the second variant + variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n"); //primitive is the third + variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size + variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n"); // attributes for vertex arrays + variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size + + shader.canvas_shader.initialize(variants, global_defines); + + shader.default_version = shader.canvas_shader.version_create(); + shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD); + shader.default_version_rd_shader_light = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD_LIGHT); + + for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { + for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { + RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, + RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_LINESTRIPS, + RD::RENDER_PRIMITIVE_POINTS, + }; + + ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { + { //non lit + SHADER_VARIANT_QUAD, + SHADER_VARIANT_NINEPATCH, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE_POINTS, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES_POINTS }, + { //lit + SHADER_VARIANT_QUAD_LIGHT, + SHADER_VARIANT_NINEPATCH_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, + }; + + RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); + shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0); + } + } + } + + { + //shader compiler + ShaderCompilerRD::DefaultIdentifierActions actions; + + actions.renames["VERTEX"] = "vertex"; + actions.renames["LIGHT_VERTEX"] = "light_vertex"; + actions.renames["SHADOW_VERTEX"] = "shadow_vertex"; + actions.renames["UV"] = "uv"; + actions.renames["POINT_SIZE"] = "gl_PointSize"; + + actions.renames["WORLD_MATRIX"] = "world_matrix"; + actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform"; + actions.renames["SCREEN_MATRIX"] = "canvas_data.screen_transform"; + actions.renames["TIME"] = "canvas_data.time"; + actions.renames["AT_LIGHT_PASS"] = "false"; + actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; + + actions.renames["COLOR"] = "color"; + actions.renames["NORMAL"] = "normal"; + actions.renames["NORMALMAP"] = "normal_map"; + actions.renames["NORMALMAP_DEPTH"] = "normal_depth"; + actions.renames["TEXTURE"] = "color_texture"; + actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size"; + actions.renames["NORMAL_TEXTURE"] = "normal_texture"; + actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture"; + actions.renames["SPECULAR_SHININESS"] = "specular_shininess"; + actions.renames["SCREEN_UV"] = "screen_uv"; + actions.renames["SCREEN_TEXTURE"] = "screen_texture"; + actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size"; + actions.renames["FRAGCOORD"] = "gl_FragCoord"; + actions.renames["POINT_COORD"] = "gl_PointCoord"; + + actions.renames["LIGHT_POSITION"] = "light_pos"; + actions.renames["LIGHT_COLOR"] = "light_color"; + actions.renames["LIGHT_ENERGY"] = "light_energy"; + actions.renames["LIGHT"] = "light"; + actions.renames["SHADOW_MODULATE"] = "shadow_modulate"; + + actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; + actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; + actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; + actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; + actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; + + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + + actions.custom_samplers["TEXTURE"] = "texture_sampler"; + actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler"; + actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler"; + actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture + actions.sampler_array_name = "material_samplers"; + actions.base_texture_binding_index = 2; + actions.texture_layout_set = 1; + actions.base_uniform_string = "material."; + actions.default_filter = ShaderLanguage::FILTER_LINEAR; + actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; + actions.base_varying_index = 4; + + shader.compiler.initialize(actions); + } + + { //shadow rendering + Vector versions; + versions.push_back(String()); //no versions + shadow_render.shader.initialize(versions); + + { + Vector attachments; + + RD::AttachmentFormat af_color; + af_color.format = RD::DATA_FORMAT_R32_SFLOAT; + af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + attachments.push_back(af_color); + + RD::AttachmentFormat af_depth; + af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + attachments.push_back(af_depth); + + shadow_render.framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments); + } + + //pipelines + Vector vf; + RD::VertexDescription vd; + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + vd.location = 0; + vd.offset = 0; + vd.stride = sizeof(float) * 3; + vf.push_back(vd); + shadow_render.vertex_format = RD::get_singleton()->vertex_format_create(vf); + + shadow_render.shader_version = shadow_render.shader.version_create(); + + for (int i = 0; i < 3; i++) { + RD::PipelineRasterizationState rs; + rs.cull_mode = i == 0 ? RD::POLYGON_CULL_DISABLED : (i == 1 ? RD::POLYGON_CULL_FRONT : RD::POLYGON_CULL_BACK); + RD::PipelineDepthStencilState ds; + ds.enable_depth_write = true; + ds.enable_depth_test = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS; + shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + { //bindings + bindings.id_generator = 0; + //generate for 0 + bindings.default_empty = request_texture_binding(RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, RID()); + + { //state allocate + state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); + state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); + + RD::SamplerState shadow_sampler_state; + shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + shadow_sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; //shadow wrap around + shadow_sampler_state.compare_op = RD::COMPARE_OP_GREATER; + state.shadow_sampler = RD::get_singleton()->sampler_create(shadow_sampler_state); + } + } + + { + //polygon buffers + polygon_buffers.last_id = 1; + } + + { // default index buffer + + Vector pv; + pv.resize(6 * 4); + { + uint8_t *w = pv.ptrw(); + int *p32 = (int *)w; + p32[0] = 0; + p32[1] = 1; + p32[2] = 2; + p32[3] = 0; + p32[4] = 2; + p32[5] = 3; + } + shader.quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); + shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6); + } + + { //primitive + primitive_arrays.index_array[0] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 1); + primitive_arrays.index_array[1] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 2); + primitive_arrays.index_array[2] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 3); + primitive_arrays.index_array[3] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6); + } + + { //default skeleton buffer + + shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); + SkeletonUniform su; + _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse); + _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform); + RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su); + + shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT); + } + + //create functions for shader and material + storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_shader_funcs); + storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_material_funcs); + + state.time = 0; + + static_assert(sizeof(PushConstant) == 128); +} + +bool RasterizerCanvasRD::free(RID p_rid) { + + if (canvas_light_owner.owns(p_rid)) { + CanvasLight *cl = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND_V(!cl, false); + light_set_use_shadow(p_rid, false, 64); + canvas_light_owner.free(p_rid); + } else if (occluder_polygon_owner.owns(p_rid)) { + occluder_polygon_set_shape_as_lines(p_rid, Vector()); + occluder_polygon_owner.free(p_rid); + } else { + return false; + } + + return true; +} + +RasterizerCanvasRD::~RasterizerCanvasRD() { + + //canvas state + + { + if (state.canvas_state_buffer.is_valid()) { + RD::get_singleton()->free(state.canvas_state_buffer); + } + + memdelete_arr(state.light_uniforms); + RD::get_singleton()->free(state.lights_uniform_buffer); + RD::get_singleton()->free(shader.default_skeleton_uniform_buffer); + RD::get_singleton()->free(shader.default_skeleton_texture_buffer); + } + + //shadow rendering + { + + shadow_render.shader.version_free(shadow_render.shader_version); + //this will also automatically clear all pipelines + RD::get_singleton()->free(state.shadow_sampler); + } + //bindings + { + + free_texture_binding(bindings.default_empty); + + //dispose pending + _dispose_bindings(); + //anything remains? + if (bindings.texture_bindings.size()) { + ERR_PRINT("Some texture bindings were not properly freed (leaked canvasitems?"); + const TextureBindingID *key = NULL; + while ((key = bindings.texture_bindings.next(key))) { + TextureBinding *tb = bindings.texture_bindings[*key]; + tb->reference_count = 1; + free_texture_binding(*key); + } + //dispose pending + _dispose_bindings(); + } + } + + //shaders + + shader.canvas_shader.version_free(shader.default_version); + + //buffers + { + RD::get_singleton()->free(shader.quad_index_array); + RD::get_singleton()->free(shader.quad_index_buffer); + //primitives are erase by dependency + } + + //pipelines don't need freeing, they are all gone after shaders are gone +} diff --git a/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h new file mode 100644 index 0000000000..0c151975bc --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h @@ -0,0 +1,501 @@ +/*************************************************************************/ +/* rasterizer_canvas_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_CANVAS_RD_H +#define RASTERIZER_CANVAS_RD_H + +#include "servers/rendering/rasterizer.h" +#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" +#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/canvas.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl.gen.h" +#include "servers/rendering/rendering_device.h" + +class RasterizerCanvasRD : public RasterizerCanvas { + + RasterizerStorageRD *storage; + + enum ShaderVariant { + SHADER_VARIANT_QUAD, + SHADER_VARIANT_NINEPATCH, + SHADER_VARIANT_PRIMITIVE, + SHADER_VARIANT_PRIMITIVE_POINTS, + SHADER_VARIANT_ATTRIBUTES, + SHADER_VARIANT_ATTRIBUTES_POINTS, + SHADER_VARIANT_QUAD_LIGHT, + SHADER_VARIANT_NINEPATCH_LIGHT, + SHADER_VARIANT_PRIMITIVE_LIGHT, + SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, + SHADER_VARIANT_ATTRIBUTES_LIGHT, + SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, + SHADER_VARIANT_MAX + }; + + enum { + FLAGS_INSTANCING_STRIDE_MASK = 0xF, + FLAGS_INSTANCING_ENABLED = (1 << 4), + FLAGS_INSTANCING_HAS_COLORS = (1 << 5), + FLAGS_INSTANCING_COLOR_8BIT = (1 << 6), + FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 7), + FLAGS_INSTANCING_CUSTOM_DATA_8_BIT = (1 << 8), + + FLAGS_CLIP_RECT_UV = (1 << 9), + FLAGS_TRANSPOSE_RECT = (1 << 10), + FLAGS_USING_LIGHT_MASK = (1 << 11), + + FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), + FLAGS_USING_PARTICLES = (1 << 13), + FLAGS_USE_PIXEL_SNAP = (1 << 14), + + FLAGS_USE_SKELETON = (1 << 15), + FLAGS_NINEPATCH_H_MODE_SHIFT = 16, + FLAGS_NINEPATCH_V_MODE_SHIFT = 18, + FLAGS_LIGHT_COUNT_SHIFT = 20, + + FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), + FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27) + + }; + + enum { + LIGHT_FLAGS_TEXTURE_MASK = 0xFFFF, + LIGHT_FLAGS_BLEND_SHIFT = 16, + LIGHT_FLAGS_BLEND_MASK = (3 << 16), + LIGHT_FLAGS_BLEND_MODE_ADD = (0 << 16), + LIGHT_FLAGS_BLEND_MODE_SUB = (1 << 16), + LIGHT_FLAGS_BLEND_MODE_MIX = (2 << 16), + LIGHT_FLAGS_BLEND_MODE_MASK = (3 << 16), + LIGHT_FLAGS_HAS_SHADOW = (1 << 20), + LIGHT_FLAGS_FILTER_SHIFT = 22 + + }; + + enum { + MAX_RENDER_ITEMS = 256 * 1024, + MAX_LIGHT_TEXTURES = 1024, + DEFAULT_MAX_LIGHTS_PER_ITEM = 16, + DEFAULT_MAX_LIGHTS_PER_RENDER = 256 + }; + + /****************/ + /**** SHADER ****/ + /****************/ + + enum PipelineVariant { + PIPELINE_VARIANT_QUAD, + PIPELINE_VARIANT_NINEPATCH, + PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, + PIPELINE_VARIANT_PRIMITIVE_LINES, + PIPELINE_VARIANT_PRIMITIVE_POINTS, + PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, + PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP, + PIPELINE_VARIANT_ATTRIBUTE_LINES, + PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, + PIPELINE_VARIANT_ATTRIBUTE_POINTS, + PIPELINE_VARIANT_MAX + }; + enum PipelineLightMode { + PIPELINE_LIGHT_MODE_DISABLED, + PIPELINE_LIGHT_MODE_ENABLED, + PIPELINE_LIGHT_MODE_MAX + }; + + struct PipelineVariants { + RenderPipelineVertexFormatCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX]; + }; + + struct { + CanvasShaderRD canvas_shader; + RID default_version; + RID default_version_rd_shader; + RID default_version_rd_shader_light; + RID quad_index_buffer; + RID quad_index_array; + PipelineVariants pipeline_variants; + + // default_skeleton uniform set + RID default_skeleton_uniform_buffer; + RID default_skeleton_texture_buffer; + + ShaderCompilerRD compiler; + } shader; + + struct ShaderData : public RasterizerStorageRD::ShaderData { + + enum BlendMode { //used internally + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + BLEND_MODE_PMALPHA, + BLEND_MODE_DISABLED, + }; + + enum LightMode { + LIGHT_MODE_NORMAL, + LIGHT_MODE_UNSHADED, + LIGHT_MODE_LIGHT_ONLY + }; + + bool valid; + RID version; + PipelineVariants pipeline_variants; + String path; + + Map uniforms; + Vector texture_uniforms; + + Vector ubo_offsets; + uint32_t ubo_size; + + String code; + Map default_texture_params; + + bool uses_screen_texture; + bool uses_material_samplers; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void get_param_list(List *p_param_list) const; + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + ShaderData(); + virtual ~ShaderData(); + }; + + RasterizerStorageRD::ShaderData *_create_shader_func(); + static RasterizerStorageRD::ShaderData *_create_shader_funcs() { + return static_cast(singleton)->_create_shader_func(); + } + + struct MaterialData : public RasterizerStorageRD::MaterialData { + uint64_t last_frame; + ShaderData *shader_data; + RID uniform_buffer; + RID uniform_set; + Vector texture_cache; + Vector ubo_data; + + virtual void set_render_priority(int p_priority) {} + virtual void set_next_pass(RID p_pass) {} + virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~MaterialData(); + }; + + RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { + return static_cast(singleton)->_create_material_func(static_cast(p_shader)); + } + + /**************************/ + /**** TEXTURE BINDINGS ****/ + /**************************/ + + // bindings used to render commands, + // cached for performance. + + struct TextureBindingKey { + RID texture; + RID normalmap; + RID specular; + RID multimesh; + RS::CanvasItemTextureFilter texture_filter; + RS::CanvasItemTextureRepeat texture_repeat; + bool operator==(const TextureBindingKey &p_key) const { + return texture == p_key.texture && normalmap == p_key.normalmap && specular == p_key.specular && multimesh == p_key.specular && texture_filter == p_key.texture_filter && texture_repeat == p_key.texture_repeat; + } + }; + + struct TextureBindingKeyHasher { + static _FORCE_INLINE_ uint32_t hash(const TextureBindingKey &p_key) { + uint32_t hash = hash_djb2_one_64(p_key.texture.get_id()); + hash = hash_djb2_one_64(p_key.normalmap.get_id(), hash); + hash = hash_djb2_one_64(p_key.specular.get_id(), hash); + hash = hash_djb2_one_64(p_key.multimesh.get_id(), hash); + hash = hash_djb2_one_32(uint32_t(p_key.texture_filter) << 16 | uint32_t(p_key.texture_repeat), hash); + return hash; + } + }; + + struct TextureBinding { + TextureBindingID id; + TextureBindingKey key; + SelfList to_dispose; + uint32_t reference_count; + RID uniform_set; + TextureBinding() : + to_dispose(this) { + reference_count = 0; + } + }; + + struct { + SelfList::List to_dispose_list; + + TextureBindingID id_generator; + HashMap texture_key_bindings; + HashMap texture_bindings; + + TextureBindingID default_empty; + } bindings; + + RID _create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh); + void _dispose_bindings(); + + struct { + RS::CanvasItemTextureFilter default_filter; + RS::CanvasItemTextureRepeat default_repeat; + } default_samplers; + + /******************/ + /**** POLYGONS ****/ + /******************/ + + struct PolygonBuffers { + RD::VertexFormatID vertex_format_id; + RID vertex_buffer; + RID vertex_array; + RID index_buffer; + RID indices; + }; + + struct { + HashMap polygons; + PolygonID last_id; + } polygon_buffers; + + /********************/ + /**** PRIMITIVES ****/ + /********************/ + + struct { + RID index_array[4]; + } primitive_arrays; + + /*******************/ + /**** MATERIALS ****/ + /*******************/ + + /******************/ + /**** LIGHTING ****/ + /******************/ + + struct CanvasLight { + + RID texture; + struct { + int size; + RID texture; + RID depth; + RID fb; + } shadow; + }; + + RID_Owner canvas_light_owner; + + struct ShadowRenderPushConstant { + float projection[16]; + float modelview[8]; + float direction[2]; + float pad[2]; + }; + + struct OccluderPolygon { + + RS::CanvasOccluderPolygonCullMode cull_mode; + int point_count; + RID vertex_buffer; + RID vertex_array; + RID index_buffer; + RID index_array; + }; + + struct LightUniform { + float matrix[8]; //light to texture coordinate matrix + float shadow_matrix[8]; //light to shadow coordinate matrix + float color[4]; + float shadow_color[4]; + float position[2]; + uint32_t flags; //index to light texture + float height; + float shadow_pixel_size; + float pad[3]; + }; + + RID_Owner occluder_polygon_owner; + + struct { + CanvasOcclusionShaderRD shader; + RID shader_version; + RID render_pipelines[3]; + RD::VertexFormatID vertex_format; + RD::FramebufferFormatID framebuffer_format; + } shadow_render; + + /***************/ + /**** STATE ****/ + /***************/ + + //state that does not vary across rendering all items + + struct ItemStateData : public Item::CustomData { + + struct LightCache { + uint64_t light_version; + Light *light; + }; + + LightCache light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; + uint32_t light_cache_count; + RID state_uniform_set_with_light; + RID state_uniform_set; + ItemStateData() { + + for (int i = 0; i < DEFAULT_MAX_LIGHTS_PER_ITEM; i++) { + light_cache[i].light_version = 0; + light_cache[i].light = NULL; + } + light_cache_count = 0xFFFFFFFF; + } + + ~ItemStateData() { + if (state_uniform_set_with_light.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set_with_light)) { + RD::get_singleton()->free(state_uniform_set_with_light); + } + if (state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set)) { + RD::get_singleton()->free(state_uniform_set); + } + } + }; + + struct State { + + //state buffer + struct Buffer { + float canvas_transform[16]; + float screen_transform[16]; + float canvas_normal_transform[16]; + float canvas_modulate[4]; + float screen_pixel_size[2]; + float time; + float pad; + + //uint32_t light_count; + //uint32_t pad[3]; + }; + + LightUniform *light_uniforms; + + RID lights_uniform_buffer; + RID canvas_state_buffer; + RID shadow_sampler; + + uint32_t max_lights_per_render; + uint32_t max_lights_per_item; + + double time; + } state; + + struct PushConstant { + float world[6]; + uint32_t flags; + uint32_t specular_shininess; + union { + //rect + struct { + float modulation[4]; + float ninepatch_margins[4]; + float dst_rect[4]; + float src_rect[4]; + float pad[2]; + }; + //primitive + struct { + float points[6]; // vec2 points[3] + float uvs[6]; // vec2 points[3] + uint32_t colors[6]; // colors encoded as half + }; + }; + float color_texture_pixel_size[2]; + uint32_t lights[4]; + }; + + struct SkeletonUniform { + float skeleton_transform[16]; + float skeleton_inverse[16]; + }; + + Item *items[MAX_RENDER_ITEMS]; + + Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags); + void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants); + void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set); + + _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); + _FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); + + _FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4); + _FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4); + + _FORCE_INLINE_ void _update_specular_shininess(const Color &p_transform, uint32_t *r_ss); + +public: + TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat, RID p_multimesh); + void free_texture_binding(TextureBindingID p_binding); + + PolygonID request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()); + void free_polygon(PolygonID p_polygon); + + RID light_create(); + void light_set_texture(RID p_rid, RID p_texture); + void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution); + void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders); + + RID occluder_polygon_create(); + void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines); + void occluder_polygon_set_cull_mode(RID p_occluder, RS::CanvasOccluderPolygonCullMode p_mode); + + void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform); + + void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){}; + + void draw_window_margins(int *p_margins, RID *p_margin_textures) {} + + void set_time(double p_time); + void update(); + bool free(RID p_rid); + RasterizerCanvasRD(RasterizerStorageRD *p_storage); + ~RasterizerCanvasRD(); +}; + +#endif // RASTERIZER_CANVAS_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp new file mode 100644 index 0000000000..cc94815152 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.cpp @@ -0,0 +1,1092 @@ +/*************************************************************************/ +/* rasterizer_effects_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer_effects_rd.h" +#include "core/os/os.h" +#include "core/project_settings.h" +#include "cubemap_coeffs.h" + +static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) { + p_array[0] = p_basis.elements[0][0]; + p_array[1] = p_basis.elements[1][0]; + p_array[2] = p_basis.elements[2][0]; + p_array[3] = 0; + p_array[4] = p_basis.elements[0][1]; + p_array[5] = p_basis.elements[1][1]; + p_array[6] = p_basis.elements[2][1]; + p_array[7] = 0; + p_array[8] = p_basis.elements[0][2]; + p_array[9] = p_basis.elements[1][2]; + p_array[10] = p_basis.elements[2][2]; + p_array[11] = 0; +} + +RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) { + + if (image_to_uniform_set_cache.has(p_image)) { + RID uniform_set = image_to_uniform_set_cache[p_image]; + if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + return uniform_set; + } + } + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 0; + u.ids.push_back(p_image); + uniforms.push_back(u); + //any thing with the same configuration (one texture in binding 0 for set 0), is good + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1); + + image_to_uniform_set_cache[p_image] = uniform_set; + + return uniform_set; +} + +RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { + + if (texture_to_uniform_set_cache.has(p_texture)) { + RID uniform_set = texture_to_uniform_set_cache[p_texture]; + if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + return uniform_set; + } + } + + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.ids.push_back(p_texture); + uniforms.push_back(u); + //any thing with the same configuration (one texture in binding 0 for set 0), is good + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blur.shader.version_get_shader(blur.shader_version, 0), 0); + + texture_to_uniform_set_cache[p_texture] = uniform_set; + + return uniform_set; +} + +RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { + + if (texture_to_compute_uniform_set_cache.has(p_texture)) { + RID uniform_set = texture_to_compute_uniform_set_cache[p_texture]; + if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + return uniform_set; + } + } + + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); + u.ids.push_back(p_texture); + uniforms.push_back(u); + //any thing with the same configuration (one texture in binding 0 for set 0), is good + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0); + + texture_to_compute_uniform_set_cache[p_texture] = uniform_set; + + return uniform_set; +} + +void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) { + + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + if (p_flip_y) { + blur.push_constant.flags |= BLUR_FLAG_FLIP_Y; + } + if (p_force_luminance) { + blur.push_constant.flags |= BLUR_COPY_FORCE_LUMINANCE; + } + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector(), 1.0, 0, p_rect); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) { + + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + + if (p_region != Rect2()) { + blur.push_constant.flags = BLUR_FLAG_USE_BLUR_SECTION; + blur.push_constant.section[0] = p_region.position.x; + blur.push_constant.section[1] = p_region.position.y; + blur.push_constant.section[2] = p_region.size.width; + blur.push_constant.section[3] = p_region.size.height; + } + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) { + + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + + uint32_t base_flags = 0; + if (p_region != Rect2()) { + base_flags = BLUR_FLAG_USE_BLUR_SECTION; + blur.push_constant.section[0] = p_region.position.x; + blur.push_constant.section[1] = p_region.position.y; + blur.push_constant.section[2] = p_region.size.width; + blur.push_constant.section[3] = p_region.size.height; + } + + blur.push_constant.pixel_size[0] = p_pixel_size.x; + blur.push_constant.pixel_size[1] = p_pixel_size.y; + + //HORIZONTAL + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + //VERTICAL + draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + blur.push_constant.flags = base_flags; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { + + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + + BlurMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; + uint32_t base_flags = 0; + + blur.push_constant.pixel_size[0] = p_pixel_size.x; + blur.push_constant.pixel_size[1] = p_pixel_size.y; + + blur.push_constant.glow_strength = p_strength; + blur.push_constant.glow_bloom = p_bloom; + blur.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold; + blur.push_constant.glow_hdr_scale = p_hdr_bleed_scale; + blur.push_constant.glow_exposure = p_exposure; + blur.push_constant.glow_white = 0; //actually unused + blur.push_constant.glow_luminance_cap = p_luminance_cap; + blur.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also + + //HORIZONTAL + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + if (p_auto_exposure.is_valid() && p_first_pass) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1); + } + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); + + blur_mode = BLUR_MODE_GAUSSIAN_GLOW; + + //VERTICAL + draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + blur.push_constant.flags = base_flags; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) { + + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + + blur.push_constant.pixel_size[0] = p_pixel_size.x; + blur.push_constant.pixel_size[1] = p_pixel_size.y; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_MIPMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) { + + CopyToDPPushConstant push_constant; + push_constant.bias = p_bias; + push_constant.z_far = p_z_far; + push_constant.z_near = p_z_near; + push_constant.z_flip = p_dp_flip; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector(), 1.0, 0, p_rect); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) { + + zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant)); + + tonemap.push_constant.use_bcs = p_settings.use_bcs; + tonemap.push_constant.bcs[0] = p_settings.brightness; + tonemap.push_constant.bcs[1] = p_settings.contrast; + tonemap.push_constant.bcs[2] = p_settings.saturation; + + tonemap.push_constant.use_glow = p_settings.use_glow; + tonemap.push_constant.glow_intensity = p_settings.glow_intensity; + tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags; + tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x; + tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y; + tonemap.push_constant.glow_mode = p_settings.glow_mode; + + TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL; + + tonemap.push_constant.tonemapper = p_settings.tonemap_mode; + tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure; + tonemap.push_constant.exposure = p_settings.exposure; + tonemap.push_constant.white = p_settings.white; + tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey; + + tonemap.push_constant.use_color_correction = p_settings.use_color_correction; + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3); + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant)); + RD::get_singleton()->draw_list_draw(draw_list, true); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { + + luminance_reduce.push_constant.source_size[0] = p_source_size.x; + luminance_reduce.push_constant.source_size[1] = p_source_size.y; + luminance_reduce.push_constant.max_luminance = p_max_luminance; + luminance_reduce.push_constant.min_luminance = p_min_luminance; + luminance_reduce.push_constant.exposure_adjust = p_adjust; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + for (int i = 0; i < p_reduce.size(); i++) { + + if (i == 0) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_texture), 0); + } else { + + RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done + + if (i == p_reduce.size() - 1 && !p_set) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_WRITE]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_prev_luminance), 2); + } else { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE]); + } + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i - 1]), 0); + } + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i]), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &luminance_reduce.push_constant, sizeof(LuminanceReducePushConstant)); + + int32_t x_groups = (luminance_reduce.push_constant.source_size[0] - 1) / 8 + 1; + int32_t y_groups = (luminance_reduce.push_constant.source_size[1] - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + + luminance_reduce.push_constant.source_size[0] = MAX(luminance_reduce.push_constant.source_size[0] / 8, 1); + luminance_reduce.push_constant.source_size[1] = MAX(luminance_reduce.push_constant.source_size[1] / 8, 1); + } + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RenderingServer::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { + + bokeh.push_constant.blur_far_active = p_dof_far; + bokeh.push_constant.blur_far_begin = p_dof_far_begin; + bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; + + bokeh.push_constant.blur_near_active = p_dof_near; + bokeh.push_constant.blur_near_begin = p_dof_near_begin; + bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size); + bokeh.push_constant.use_jitter = p_use_jitter; + bokeh.push_constant.jitter_seed = Math::randf() * 1000.0; + + bokeh.push_constant.z_near = p_cam_znear; + bokeh.push_constant.z_far = p_cam_zfar; + bokeh.push_constant.orthogonal = p_cam_orthogonal; + bokeh.push_constant.blur_size = p_bokeh_size; + + bokeh.push_constant.second_pass = false; + bokeh.push_constant.half_size = false; + + bokeh.push_constant.blur_scale = 0.5; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + /* FIRST PASS */ + // The alpha channel of the source color texture is filled with the expected circle size + // If used for DOF far, the size is positive, if used for near, its negative. + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BLUR_SIZE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_texture), 1); + + int32_t x_groups = (p_base_texture_size.x - 1) / 8 + 1; + int32_t y_groups = (p_base_texture_size.y - 1) / 8 + 1; + bokeh.push_constant.size[0] = p_base_texture_size.x; + bokeh.push_constant.size[1] = p_base_texture_size.y; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (p_bokeh_shape == RS::DOF_BOKEH_BOX || p_bokeh_shape == RS::DOF_BOKEH_HEXAGON) { + + //second pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[p_bokeh_shape == RS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]); + + static const int quality_samples[4] = { 6, 12, 12, 24 }; + + bokeh.push_constant.steps = quality_samples[p_quality]; + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1); + + x_groups = ((p_base_texture_size.x >> 1) - 1) / 8 + 1; + y_groups = ((p_base_texture_size.y >> 1) - 1) / 8 + 1; + bokeh.push_constant.size[0] = p_base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + bokeh.push_constant.blur_size *= 0.5; + + } else { + //medium and high quality use full size + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //third pass + bokeh.push_constant.second_pass = true; + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture2), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 1); + } + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (p_quality == RS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == RS::DOF_BLUR_QUALITY_LOW) { + //forth pass, upscale for low quality + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture2), 1); + + x_groups = (p_base_texture_size.x - 1) / 8 + 1; + y_groups = (p_base_texture_size.y - 1) / 8 + 1; + bokeh.push_constant.size[0] = p_base_texture_size.x; + bokeh.push_constant.size[1] = p_base_texture_size.y; + bokeh.push_constant.half_size = false; + bokeh.push_constant.second_pass = false; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + } + } else { + //circle + + //second pass + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BOKEH_CIRCULAR]); + + static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; + + bokeh.push_constant.steps = 0; + bokeh.push_constant.blur_scale = quality_scale[p_quality]; + + //circle always runs in half size, otherwise too expensive + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1); + + x_groups = ((p_base_texture_size.x >> 1) - 1) / 8 + 1; + y_groups = ((p_base_texture_size.y >> 1) - 1) / 8 + 1; + bokeh.push_constant.size[0] = p_base_texture_size.x >> 1; + bokeh.push_constant.size[1] = p_base_texture_size.y >> 1; + bokeh.push_constant.half_size = true; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + //circle is just one pass, then upscale + + // upscale + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1); + + x_groups = (p_base_texture_size.x - 1) / 8 + 1; + y_groups = (p_base_texture_size.y - 1) / 8 + 1; + bokeh.push_constant.size[0] = p_base_texture_size.x; + bokeh.push_constant.size[1] = p_base_texture_size.y; + bokeh.push_constant.half_size = false; + bokeh.push_constant.second_pass = false; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + } + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness) { + + //minify first + ssao.minify_push_constant.orthogonal = p_projection.is_orthogonal(); + ssao.minify_push_constant.z_near = p_projection.get_z_near(); + ssao.minify_push_constant.z_far = p_projection.get_z_far(); + ssao.minify_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; + ssao.minify_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; + ssao.minify_push_constant.source_size[0] = p_depth_buffer_size.x; + ssao.minify_push_constant.source_size[1] = p_depth_buffer_size.y; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + /* FIRST PASS */ + // Minify the depth buffer. + + for (int i = 0; i < depth_mipmaps.size(); i++) { + + if (i == 0) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_FIRST]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); + } else { + if (i == 1) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_MIPMAP]); + } + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i - 1]), 0); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i]), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.minify_push_constant, sizeof(SSAOMinifyPushConstant)); + // shrink after set + ssao.minify_push_constant.source_size[0] = MAX(1, ssao.minify_push_constant.source_size[0] >> 1); + ssao.minify_push_constant.source_size[1] = MAX(1, ssao.minify_push_constant.source_size[1] >> 1); + + int x_groups = (ssao.minify_push_constant.source_size[0] - 1) / 8 + 1; + int y_groups = (ssao.minify_push_constant.source_size[1] - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + } + + /* SECOND PASS */ + // Gather samples + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[(SSAO_GATHER_LOW + p_quality) + (p_half_size ? 4 : 0)]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 1); + if (!p_half_size) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 2); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_normal_buffer), 3); + + ssao.gather_push_constant.screen_size[0] = p_depth_buffer_size.x; + ssao.gather_push_constant.screen_size[1] = p_depth_buffer_size.y; + if (p_half_size) { + ssao.gather_push_constant.screen_size[0] >>= 1; + ssao.gather_push_constant.screen_size[1] >>= 1; + } + ssao.gather_push_constant.z_far = p_projection.get_z_far(); + ssao.gather_push_constant.z_near = p_projection.get_z_near(); + ssao.gather_push_constant.orthogonal = p_projection.is_orthogonal(); + + ssao.gather_push_constant.proj_info[0] = -2.0f / (ssao.gather_push_constant.screen_size[0] * p_projection.matrix[0][0]); + ssao.gather_push_constant.proj_info[1] = -2.0f / (ssao.gather_push_constant.screen_size[1] * p_projection.matrix[1][1]); + ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; + ssao.gather_push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; + //ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; + //ssao.gather_push_constant.proj_info[3] = -(1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; + + ssao.gather_push_constant.radius = p_radius; + + ssao.gather_push_constant.proj_scale = float(p_projection.get_pixels_per_meter(ssao.gather_push_constant.screen_size[0])); + ssao.gather_push_constant.bias = p_bias; + ssao.gather_push_constant.intensity_div_r6 = p_intensity / pow(p_radius, 6.0f); + + ssao.gather_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; + ssao.gather_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); + + int x_groups = (ssao.gather_push_constant.screen_size[0] - 1) / 8 + 1; + int y_groups = (ssao.gather_push_constant.screen_size[1] - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + /* THIRD PASS */ + // Blur horizontal + + ssao.blur_push_constant.edge_sharpness = p_edge_sharpness; + ssao.blur_push_constant.filter_scale = p_blur; + ssao.blur_push_constant.screen_size[0] = ssao.gather_push_constant.screen_size[0]; + ssao.blur_push_constant.screen_size[1] = ssao.gather_push_constant.screen_size[1]; + ssao.blur_push_constant.z_far = p_projection.get_z_far(); + ssao.blur_push_constant.z_near = p_projection.get_z_near(); + ssao.blur_push_constant.orthogonal = p_projection.is_orthogonal(); + ssao.blur_push_constant.axis[0] = 1; + ssao.blur_push_constant.axis[1] = 0; + + if (p_blur != RS::ENV_SSAO_BLUR_DISABLED) { + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); + if (p_half_size) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 1); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao2), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + RD::get_singleton()->compute_list_add_barrier(compute_list); + + /* THIRD PASS */ + // Blur vertical + + ssao.blur_push_constant.axis[0] = 0; + ssao.blur_push_constant.axis[1] = 1; + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao2), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 3); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + } + if (p_half_size) { //must upscale + + /* FOURTH PASS */ + // upscale if half size + //back to full size + ssao.blur_push_constant.screen_size[0] = p_depth_buffer_size.x; + ssao.blur_push_constant.screen_size[1] = p_depth_buffer_size.y; + + RD::get_singleton()->compute_list_add_barrier(compute_list); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_BLUR_UPSCALE]); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 3); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 2); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); //not used but set anyway + + x_groups = (p_depth_buffer_size.x - 1) / 8 + 1; + y_groups = (p_depth_buffer_size.y - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + } + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { + + roughness_limiter.push_constant.screen_size[0] = p_size.x; + roughness_limiter.push_constant.screen_size[1] = p_size.y; + roughness_limiter.push_constant.curve = p_curve; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness_limiter.pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_normal), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_roughness), 1); + + int x_groups = (p_size.x - 1) / 8 + 1; + int y_groups = (p_size.y - 1) / 8 + 1; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness_limiter.push_constant, sizeof(RoughnessLimiterPushConstant)); //not used but set anyway + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { + + zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); + + roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; + roughness.push_constant.roughness = p_roughness; + roughness.push_constant.sample_count = p_sample_count; + roughness.push_constant.use_direct_write = p_roughness == 0.0; + roughness.push_constant.face_size = p_size; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipeline); + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1); + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); + + int x_groups = (p_size - 1) / 8 + 1; + int y_groups = (p_size - 1) / 8 + 1; + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1); + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { + + cubemap_downsampler.push_constant.face_size = p_size.x; + + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1); + + int x_groups = (p_size.x - 1) / 8 + 1; + int y_groups = (p_size.y - 1) / 8 + 1; + + RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant)); + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector p_dest_cubemap, bool p_use_array) { + + Vector uniforms; + for (int i = 0; i < p_dest_cubemap.size(); i++) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = i; + u.ids.push_back(p_dest_cubemap[i]); + uniforms.push_back(u); + } + if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { + RD::get_singleton()->free(filter.image_uniform_set); + } + filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, 0), 2); + + int pipeline = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY; + pipeline = filter.use_high_quality ? pipeline : pipeline + 1; + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.pipelines[pipeline]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap, true), 0); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2); + + int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64 + + RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face + + RD::get_singleton()->compute_list_end(); +} + +void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) { + + SkyPushConstant sky_push_constant; + + zeromem(&sky_push_constant, sizeof(SkyPushConstant)); + + sky_push_constant.proj[0] = p_camera.matrix[2][0]; + sky_push_constant.proj[1] = p_camera.matrix[0][0]; + sky_push_constant.proj[2] = p_camera.matrix[2][1]; + sky_push_constant.proj[3] = p_camera.matrix[1][1]; + sky_push_constant.position[0] = p_position.x; + sky_push_constant.position[1] = p_position.y; + sky_push_constant.position[2] = p_position.z; + sky_push_constant.multiplier = p_multiplier; + sky_push_constant.time = p_time; + store_transform_3x3(p_orientation, sky_push_constant.orientation); + + RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb); + + RD::DrawListID draw_list = p_list; + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format)); + + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_lights, 3); + + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, true); +} + +RasterizerEffectsRD::RasterizerEffectsRD() { + + { + // Initialize blur + Vector blur_modes; + blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); + blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n"); + blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n"); + blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n"); + blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); + blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n"); + blur_modes.push_back("\n#define MODE_SSAO_MERGE\n"); + blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); + blur_modes.push_back("\n#define MODE_MIPMAP\n"); + + blur.shader.initialize(blur_modes); + zeromem(&blur.push_constant, sizeof(BlurPushConstant)); + blur.shader_version = blur.shader.version_create(); + + for (int i = 0; i < BLUR_MODE_MAX; i++) { + blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + { + // Initialize roughness + Vector cubemap_roughness_modes; + cubemap_roughness_modes.push_back(""); + roughness.shader.initialize(cubemap_roughness_modes); + + roughness.shader_version = roughness.shader.version_create(); + + roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0)); + } + + { + // Initialize tonemapper + Vector tonemap_modes; + tonemap_modes.push_back("\n"); + tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n"); + + tonemap.shader.initialize(tonemap_modes); + + tonemap.shader_version = tonemap.shader.version_create(); + + for (int i = 0; i < TONEMAP_MODE_MAX; i++) { + tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + { + // Initialize luminance_reduce + Vector luminance_reduce_modes; + luminance_reduce_modes.push_back("\n#define READ_TEXTURE\n"); + luminance_reduce_modes.push_back("\n"); + luminance_reduce_modes.push_back("\n#define WRITE_LUMINANCE\n"); + + luminance_reduce.shader.initialize(luminance_reduce_modes); + + luminance_reduce.shader_version = luminance_reduce.shader.version_create(); + + for (int i = 0; i < LUMINANCE_REDUCE_MAX; i++) { + luminance_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, i)); + } + } + + { + // Initialize copier + Vector copy_modes; + copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n"); + + copy.shader.initialize(copy_modes); + + copy.shader_version = copy.shader.version_create(); + + for (int i = 0; i < COPY_MODE_MAX; i++) { + copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + { + // Initialize bokeh + Vector bokeh_modes; + bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n"); + bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n"); + bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n"); + + bokeh.shader.initialize(bokeh_modes); + + bokeh.shader_version = bokeh.shader.version_create(); + + for (int i = 0; i < BOKEH_MAX; i++) { + bokeh.pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.shader.version_get_shader(bokeh.shader_version, i)); + } + } + + { + // Initialize ssao + uint32_t pipeline = 0; + { + Vector ssao_modes; + ssao_modes.push_back("\n#define MINIFY_START\n"); + ssao_modes.push_back("\n"); + + ssao.minify_shader.initialize(ssao_modes); + + ssao.minify_shader_version = ssao.minify_shader.version_create(); + + for (int i = 0; i <= SSAO_MINIFY_MIPMAP; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.minify_shader.version_get_shader(ssao.minify_shader_version, i)); + pipeline++; + } + } + { + Vector ssao_modes; + ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n"); + ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n#define USE_HALF_SIZE\n"); + ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n#define USE_HALF_SIZE\n"); + + ssao.gather_shader.initialize(ssao_modes); + + ssao.gather_shader_version = ssao.gather_shader.version_create(); + + for (int i = SSAO_GATHER_LOW; i <= SSAO_GATHER_ULTRA_HALF; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i - SSAO_GATHER_LOW)); + pipeline++; + } + } + { + Vector ssao_modes; + ssao_modes.push_back("\n#define MODE_FULL_SIZE\n"); + ssao_modes.push_back("\n"); + ssao_modes.push_back("\n#define MODE_UPSCALE\n"); + + ssao.blur_shader.initialize(ssao_modes); + + ssao.blur_shader_version = ssao.blur_shader.version_create(); + + for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_UPSCALE; i++) { + ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS)); + pipeline++; + } + } + + ERR_FAIL_COND(pipeline != SSAO_MAX); + } + + { + // Initialize roughness limiter + Vector shader_modes; + shader_modes.push_back(""); + + roughness_limiter.shader.initialize(shader_modes); + + roughness_limiter.shader_version = roughness_limiter.shader.version_create(); + + roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0)); + } + + { + //Initialize cubemap downsampler + Vector cubemap_downsampler_modes; + cubemap_downsampler_modes.push_back(""); + cubemap_downsampler.shader.initialize(cubemap_downsampler_modes); + + cubemap_downsampler.shader_version = cubemap_downsampler.shader.version_create(); + + cubemap_downsampler.pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, 0)); + } + + { + // Initialize cubemap filter + filter.use_high_quality = GLOBAL_GET("rendering/quality/reflections/fast_filter_high_quality"); + + Vector cubemap_filter_modes; + cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n"); + cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n"); + cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n"); + cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n"); + filter.shader.initialize(cubemap_filter_modes); + filter.shader_version = filter.shader.version_create(); + + for (int i = 0; i < FILTER_MODE_MAX; i++) { + filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.shader.version_get_shader(filter.shader_version, i)); + } + + if (filter.use_high_quality) { + filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs)); + RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0], false); + } else { + filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs)); + RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0], false); + } + + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(filter.coefficient_buffer); + uniforms.push_back(u); + } + filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); + } + + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.max_lod = 0; + + default_sampler = RD::get_singleton()->sampler_create(sampler); + + sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.mip_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.max_lod = 1e20; + + default_mipmap_sampler = RD::get_singleton()->sampler_create(sampler); + + { //create index array for copy shaders + Vector pv; + pv.resize(6 * 4); + { + uint8_t *w = pv.ptrw(); + int *p32 = (int *)w; + p32[0] = 0; + p32[1] = 1; + p32[2] = 2; + p32[3] = 0; + p32[4] = 2; + p32[5] = 3; + } + index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); + index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6); + } +} + +RasterizerEffectsRD::~RasterizerEffectsRD() { + if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { + RD::get_singleton()->free(filter.image_uniform_set); + } + + if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) { + RD::get_singleton()->free(filter.uniform_set); + } + + RD::get_singleton()->free(default_sampler); + RD::get_singleton()->free(default_mipmap_sampler); + RD::get_singleton()->free(index_buffer); //array gets freed as dependency + RD::get_singleton()->free(filter.coefficient_buffer); + blur.shader.version_free(blur.shader_version); + roughness.shader.version_free(roughness.shader_version); + tonemap.shader.version_free(tonemap.shader_version); + luminance_reduce.shader.version_free(luminance_reduce.shader_version); + copy.shader.version_free(copy.shader_version); + bokeh.shader.version_free(bokeh.shader_version); + ssao.minify_shader.version_free(ssao.minify_shader_version); + ssao.gather_shader.version_free(ssao.gather_shader_version); + ssao.blur_shader.version_free(ssao.blur_shader_version); + roughness_limiter.shader.version_free(roughness_limiter.shader_version); + cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version); + filter.shader.version_free(filter.shader_version); +} diff --git a/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h new file mode 100644 index 0000000000..69da5dc6d4 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_effects_rd.h @@ -0,0 +1,457 @@ +/*************************************************************************/ +/* rasterizer_effects_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_EFFECTS_RD_H +#define RASTERIZER_EFFECTS_RD_H + +#include "core/math/camera_matrix.h" +#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/blur.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/copy.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/ssao.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/tonemap.glsl.gen.h" + +#include "servers/rendering_server.h" + +class RasterizerEffectsRD { + + enum BlurMode { + BLUR_MODE_GAUSSIAN_BLUR, + BLUR_MODE_GAUSSIAN_GLOW, + BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, + BLUR_MODE_DOF_NEAR_LOW, + BLUR_MODE_DOF_NEAR_MEDIUM, + BLUR_MODE_DOF_NEAR_HIGH, + BLUR_MODE_DOF_NEAR_MERGE_LOW, + BLUR_MODE_DOF_NEAR_MERGE_MEDIUM, + BLUR_MODE_DOF_NEAR_MERGE_HIGH, + BLUR_MODE_DOF_FAR_LOW, + BLUR_MODE_DOF_FAR_MEDIUM, + BLUR_MODE_DOF_FAR_HIGH, + BLUR_MODE_SSAO_MERGE, + BLUR_MODE_SIMPLY_COPY, + BLUR_MODE_MIPMAP, + BLUR_MODE_MAX, + + }; + + enum { + BLUR_FLAG_HORIZONTAL = (1 << 0), + BLUR_FLAG_USE_BLUR_SECTION = (1 << 1), + BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), + BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), + BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4), + BLUR_FLAG_FLIP_Y = (1 << 5), + BLUR_COPY_FORCE_LUMINANCE = (1 << 6) + }; + + struct BlurPushConstant { + float section[4]; + float pixel_size[2]; + uint32_t flags; + uint32_t pad; + //glow + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + //dof + float dof_begin; + float dof_end; + float dof_radius; + float dof_pad; + + float dof_dir[2]; + float camera_z_far; + float camera_z_near; + + float ssao_color[4]; + }; + + struct Blur { + BlurPushConstant push_constant; + BlurShaderRD shader; + RID shader_version; + RenderPipelineVertexFormatCacheRD pipelines[BLUR_MODE_MAX]; + + } blur; + + struct CubemapRoughnessPushConstant { + uint32_t face_id; + uint32_t sample_count; + float roughness; + uint32_t use_direct_write; + float face_size; + float pad[3]; + }; + + struct CubemapRoughness { + + CubemapRoughnessPushConstant push_constant; + CubemapRoughnessShaderRD shader; + RID shader_version; + RID pipeline; + } roughness; + + enum TonemapMode { + TONEMAP_MODE_NORMAL, + TONEMAP_MODE_BICUBIC_GLOW_FILTER, + TONEMAP_MODE_MAX + }; + + struct TonemapPushConstant { + float bcs[3]; + uint32_t use_bcs; + + uint32_t use_glow; + uint32_t use_auto_exposure; + uint32_t use_color_correction; + uint32_t tonemapper; + + uint32_t glow_texture_size[2]; + + float glow_intensity; + uint32_t glow_level_flags; + uint32_t glow_mode; + + float exposure; + float white; + float auto_exposure_grey; + }; + + struct Tonemap { + + TonemapPushConstant push_constant; + TonemapShaderRD shader; + RID shader_version; + RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX]; + } tonemap; + + enum LuminanceReduceMode { + LUMINANCE_REDUCE_READ, + LUMINANCE_REDUCE, + LUMINANCE_REDUCE_WRITE, + LUMINANCE_REDUCE_MAX + }; + + struct LuminanceReducePushConstant { + int32_t source_size[2]; + float max_luminance; + float min_luminance; + float exposure_adjust; + float pad[3]; + }; + + struct LuminanceReduce { + + LuminanceReducePushConstant push_constant; + LuminanceReduceShaderRD shader; + RID shader_version; + RID pipelines[LUMINANCE_REDUCE_MAX]; + } luminance_reduce; + + struct CopyToDPPushConstant { + float bias; + float z_far; + float z_near; + uint32_t z_flip; + }; + + enum CopyMode { + COPY_MODE_CUBE_TO_DP, + COPY_MODE_MAX + }; + + struct Copy { + + CopyShaderRD shader; + RID shader_version; + RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX]; + } copy; + + struct BokehPushConstant { + uint32_t size[2]; + float z_far; + float z_near; + + uint32_t orthogonal; + float blur_size; + float blur_scale; + uint32_t steps; + + uint32_t blur_near_active; + float blur_near_begin; + float blur_near_end; + uint32_t blur_far_active; + + float blur_far_begin; + float blur_far_end; + uint32_t second_pass; + uint32_t half_size; + + uint32_t use_jitter; + float jitter_seed; + uint32_t pad[2]; + }; + + enum BokehMode { + BOKEH_GEN_BLUR_SIZE, + BOKEH_GEN_BOKEH_BOX, + BOKEH_GEN_BOKEH_HEXAGONAL, + BOKEH_GEN_BOKEH_CIRCULAR, + BOKEH_COMPOSITE, + BOKEH_MAX + }; + + struct Bokeh { + + BokehPushConstant push_constant; + BokehDofShaderRD shader; + RID shader_version; + RID pipelines[BOKEH_MAX]; + } bokeh; + + enum SSAOMode { + SSAO_MINIFY_FIRST, + SSAO_MINIFY_MIPMAP, + SSAO_GATHER_LOW, + SSAO_GATHER_MEDIUM, + SSAO_GATHER_HIGH, + SSAO_GATHER_ULTRA, + SSAO_GATHER_LOW_HALF, + SSAO_GATHER_MEDIUM_HALF, + SSAO_GATHER_HIGH_HALF, + SSAO_GATHER_ULTRA_HALF, + SSAO_BLUR_PASS, + SSAO_BLUR_PASS_HALF, + SSAO_BLUR_UPSCALE, + SSAO_MAX + }; + + struct SSAOMinifyPushConstant { + float pixel_size[2]; + float z_far; + float z_near; + int32_t source_size[2]; + uint32_t orthogonal; + uint32_t pad; + }; + + struct SSAOGatherPushConstant { + int32_t screen_size[2]; + float z_far; + float z_near; + + uint32_t orthogonal; + float intensity_div_r6; + float radius; + float bias; + + float proj_info[4]; + float pixel_size[2]; + float proj_scale; + uint32_t pad; + }; + + struct SSAOBlurPushConstant { + float edge_sharpness; + int32_t filter_scale; + float z_far; + float z_near; + uint32_t orthogonal; + uint32_t pad[3]; + int32_t axis[2]; + int32_t screen_size[2]; + }; + + struct SSAO { + + SSAOMinifyPushConstant minify_push_constant; + SsaoMinifyShaderRD minify_shader; + RID minify_shader_version; + + SSAOGatherPushConstant gather_push_constant; + SsaoShaderRD gather_shader; + RID gather_shader_version; + + SSAOBlurPushConstant blur_push_constant; + SsaoBlurShaderRD blur_shader; + RID blur_shader_version; + + RID pipelines[SSAO_MAX]; + } ssao; + + struct RoughnessLimiterPushConstant { + int32_t screen_size[2]; + float curve; + uint32_t pad; + }; + + struct RoughnessLimiter { + + RoughnessLimiterPushConstant push_constant; + RoughnessLimiterShaderRD shader; + RID shader_version; + RID pipeline; + + } roughness_limiter; + + struct CubemapDownsamplerPushConstant { + uint32_t face_size; + float pad[3]; + }; + + struct CubemapDownsampler { + + CubemapDownsamplerPushConstant push_constant; + CubemapDownsamplerShaderRD shader; + RID shader_version; + RID pipeline; + + } cubemap_downsampler; + + enum CubemapFilterMode { + FILTER_MODE_HIGH_QUALITY, + FILTER_MODE_LOW_QUALITY, + FILTER_MODE_HIGH_QUALITY_ARRAY, + FILTER_MODE_LOW_QUALITY_ARRAY, + FILTER_MODE_MAX, + }; + + struct CubemapFilter { + + CubemapFilterShaderRD shader; + RID shader_version; + RID pipelines[FILTER_MODE_MAX]; + RID uniform_set; + RID image_uniform_set; + RID coefficient_buffer; + bool use_high_quality; + + } filter; + + struct SkyPushConstant { + float orientation[12]; + float proj[4]; + float position[3]; + float multiplier; + float time; + float pad[3]; + }; + + RID default_sampler; + RID default_mipmap_sampler; + RID index_buffer; + RID index_array; + + Map texture_to_uniform_set_cache; + + Map image_to_uniform_set_cache; + Map texture_to_compute_uniform_set_cache; + + RID _get_uniform_set_from_image(RID p_texture); + RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); + RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); + +public: + //TODO must re-do most of the shaders in compute + + void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region); + void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false); + void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region); + void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); + + void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); + void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size); + void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip); + void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); + void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, RS::DOFBokehShape p_bokeh_shape, RS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); + + struct TonemapSettings { + + bool use_glow = false; + enum GlowMode { + GLOW_MODE_ADD, + GLOW_MODE_SCREEN, + GLOW_MODE_SOFTLIGHT, + GLOW_MODE_REPLACE, + GLOW_MODE_MIX + }; + + GlowMode glow_mode = GLOW_MODE_ADD; + float glow_intensity = 1.0; + uint32_t glow_level_flags = 0; + Vector2i glow_texture_size; + bool glow_use_bicubic_upscale = false; + RID glow_texture; + + RS::EnvironmentToneMapper tonemap_mode = RS::ENV_TONE_MAPPER_LINEAR; + float exposure = 1.0; + float white = 1.0; + + bool use_auto_exposure = false; + float auto_exposure_grey = 0.5; + RID exposure_texture; + + bool use_bcs = false; + float brightness = 1.0; + float contrast = 1.0; + float saturation = 1.0; + + bool use_color_correction = false; + RID color_correction_texture; + }; + + void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings); + + void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, RS::EnvironmentSSAOQuality p_quality, RS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness); + + void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); + void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); + void cubemap_filter(RID p_source_cubemap, Vector p_dest_cubemap, bool p_use_array); + void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position); + + RasterizerEffectsRD(); + ~RasterizerEffectsRD(); +}; + +#endif // !RASTERIZER_EFFECTS_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp new file mode 100644 index 0000000000..9c54f0caae --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.cpp @@ -0,0 +1,177 @@ +/*************************************************************************/ +/* rasterizer_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer_rd.h" + +void RasterizerRD::prepare_for_blitting_render_targets() { + RD::get_singleton()->prepare_screen_for_drawing(); +} + +void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen); + + for (int i = 0; i < p_amount; i++) { + RID texture = storage->render_target_get_texture(p_render_targets[i].render_target); + ERR_CONTINUE(texture.is_null()); + RID rd_texture = storage->texture_get_rd_texture(texture); + ERR_CONTINUE(rd_texture.is_null()); + if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) { + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; + u.binding = 0; + u.ids.push_back(copy_viewports_sampler); + u.ids.push_back(rd_texture); + uniforms.push_back(u); + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_viewports_rd_shader, 0); + + render_target_descriptors[rd_texture] = uniform_set; + } + + Size2 screen_size(RD::get_singleton()->screen_get_width(p_screen), RD::get_singleton()->screen_get_height(p_screen)); + + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_viewports_rd_pipeline); + RD::get_singleton()->draw_list_bind_index_array(draw_list, copy_viewports_rd_array); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); + + float push_constant[4] = { + p_render_targets[i].rect.position.x / screen_size.width, + p_render_targets[i].rect.position.y / screen_size.height, + p_render_targets[i].rect.size.width / screen_size.width, + p_render_targets[i].rect.size.height / screen_size.height, + }; + RD::get_singleton()->draw_list_set_push_constant(draw_list, push_constant, 4 * sizeof(float)); + RD::get_singleton()->draw_list_draw(draw_list, true); + } + + RD::get_singleton()->draw_list_end(); +} + +void RasterizerRD::begin_frame(double frame_step) { + frame++; + time += frame_step; + canvas->set_time(time); + scene->set_time(time, frame_step); +} + +void RasterizerRD::end_frame(bool p_swap_buffers) { + +#ifndef _MSC_VER +#warning TODO: likely passa bool to swap buffers to avoid display? +#endif + RD::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display? +} + +void RasterizerRD::initialize() { + + { //create framebuffer copy shader + RenderingDevice::ShaderStageData vert; + vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX; + vert.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_VERTEX, + "#version 450\n" + "layout(push_constant, binding = 0, std140) uniform Pos { vec4 dst_rect; } pos;\n" + "layout(location =0) out vec2 uv;\n" + "void main() { \n" + " vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));\n" + " uv = base_arr[gl_VertexIndex];\n" + " vec2 vtx = pos.dst_rect.xy+uv*pos.dst_rect.zw;\n" + " gl_Position = vec4(vtx * 2.0 - 1.0,0.0,1.0);\n" + "}\n"); + + RenderingDevice::ShaderStageData frag; + frag.shader_stage = RenderingDevice::SHADER_STAGE_FRAGMENT; + frag.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_FRAGMENT, + "#version 450\n" + "layout (location = 0) in vec2 uv;\n" + "layout (location = 0) out vec4 color;\n" + "layout (binding = 0) uniform sampler2D src_rt;\n" + "void main() { color=texture(src_rt,uv); }\n"); + + Vector source; + source.push_back(vert); + source.push_back(frag); + String error; + copy_viewports_rd_shader = RD::get_singleton()->shader_create(source); + if (!copy_viewports_rd_shader.is_valid()) { + print_line("Failed compilation: " + error); + } + } + + { //create index array for copy shader + Vector pv; + pv.resize(6 * 4); + { + uint8_t *w = pv.ptrw(); + int *p32 = (int *)w; + p32[0] = 0; + p32[1] = 1; + p32[2] = 2; + p32[3] = 0; + p32[4] = 2; + p32[5] = 3; + } + copy_viewports_rd_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); + copy_viewports_rd_array = RD::get_singleton()->index_array_create(copy_viewports_rd_index_buffer, 0, 6); + } + + { //pipeline + copy_viewports_rd_pipeline = RD::get_singleton()->render_pipeline_create(copy_viewports_rd_shader, RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RenderingDevice::PipelineColorBlendState::create_disabled(), 0); + } + { // sampler + copy_viewports_sampler = RD::get_singleton()->sampler_create(RD::SamplerState()); + } +} + +ThreadWorkPool RasterizerRD::thread_work_pool; +uint32_t RasterizerRD::frame = 1; + +void RasterizerRD::finalize() { + + thread_work_pool.finish(); + + memdelete(scene); + memdelete(canvas); + memdelete(storage); + + //only need to erase these, the rest are erased by cascade + RD::get_singleton()->free(copy_viewports_rd_index_buffer); + RD::get_singleton()->free(copy_viewports_rd_shader); + RD::get_singleton()->free(copy_viewports_sampler); +} + +RasterizerRD::RasterizerRD() { + thread_work_pool.init(); + time = 0; + + storage = memnew(RasterizerStorageRD); + canvas = memnew(RasterizerCanvasRD(storage)); + scene = memnew(RasterizerSceneHighEndRD(storage)); +} diff --git a/servers/rendering/rasterizer_rd/rasterizer_rd.h b/servers/rendering/rasterizer_rd/rasterizer_rd.h new file mode 100644 index 0000000000..756b9499ca --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_rd.h @@ -0,0 +1,95 @@ +/*************************************************************************/ +/* rasterizer_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_RD_H +#define RASTERIZER_RD_H + +#include "core/os/os.h" +#include "core/thread_work_pool.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering/rasterizer_rd/rasterizer_canvas_rd.h" +#include "servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h" +#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" + +class RasterizerRD : public Rasterizer { +protected: + RasterizerCanvasRD *canvas; + RasterizerStorageRD *storage; + RasterizerSceneHighEndRD *scene; + + RID copy_viewports_rd_shader; + RID copy_viewports_rd_pipeline; + RID copy_viewports_rd_index_buffer; + RID copy_viewports_rd_array; + RID copy_viewports_sampler; + + Map render_target_descriptors; + + double time; + + static uint32_t frame; + +public: + RasterizerStorage *get_storage() { return storage; } + RasterizerCanvas *get_canvas() { return canvas; } + RasterizerScene *get_scene() { return scene; } + + void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {} + + void initialize(); + void begin_frame(double frame_step); + void prepare_for_blitting_render_targets(); + void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount); + + void end_frame(bool p_swap_buffers); + void finalize(); + + static _ALWAYS_INLINE_ uint64_t get_frame_number() { return frame; } + + static Error is_viable() { + return OK; + } + + static Rasterizer *_create_current() { + return memnew(RasterizerRD); + } + + static void make_current() { + _create_func = _create_current; + } + + virtual bool is_low_end() const { return false; } + + static ThreadWorkPool thread_work_pool; + + RasterizerRD(); + ~RasterizerRD() {} +}; +#endif // RASTERIZER_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp new file mode 100644 index 0000000000..bf3cd045f1 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.cpp @@ -0,0 +1,2729 @@ +/*************************************************************************/ +/* rasterizer_scene_high_end_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer_scene_high_end_rd.h" +#include "core/project_settings.h" +#include "servers/rendering/rendering_device.h" +#include "servers/rendering/rendering_server_raster.h" + +static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) { + p_array[0] = p_mtx.basis.elements[0][0]; + p_array[1] = p_mtx.basis.elements[1][0]; + p_array[2] = p_mtx.basis.elements[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.basis.elements[0][1]; + p_array[5] = p_mtx.basis.elements[1][1]; + p_array[6] = p_mtx.basis.elements[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.basis.elements[0][2]; + p_array[9] = p_mtx.basis.elements[1][2]; + p_array[10] = p_mtx.basis.elements[2][2]; + p_array[11] = 0; + p_array[12] = p_mtx.origin.x; + p_array[13] = p_mtx.origin.y; + p_array[14] = p_mtx.origin.z; + p_array[15] = 1; +} + +static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) { + p_array[0] = p_mtx.basis.elements[0][0]; + p_array[1] = p_mtx.basis.elements[1][0]; + p_array[2] = p_mtx.basis.elements[2][0]; + p_array[3] = 0; + p_array[4] = p_mtx.basis.elements[0][1]; + p_array[5] = p_mtx.basis.elements[1][1]; + p_array[6] = p_mtx.basis.elements[2][1]; + p_array[7] = 0; + p_array[8] = p_mtx.basis.elements[0][2]; + p_array[9] = p_mtx.basis.elements[1][2]; + p_array[10] = p_mtx.basis.elements[2][2]; + p_array[11] = 0; +} + +static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + + p_array[i * 4 + j] = p_mtx.matrix[i][j]; + } + } +} + +/* SCENE SHADER */ +void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + uses_screen_texture = false; + + if (code == String()) { + return; //just invalid, but no error + } + + ShaderCompilerRD::GeneratedCode gen_code; + + int blend_mode = BLEND_MODE_MIX; + int depth_testi = DEPTH_TEST_ENABLED; + int cull = CULL_BACK; + + uses_point_size = false; + uses_alpha = false; + uses_blend_alpha = false; + uses_depth_pre_pass = false; + uses_discard = false; + uses_roughness = false; + uses_normal = false; + bool wireframe = false; + + unshaded = false; + uses_vertex = false; + uses_sss = false; + uses_screen_texture = false; + uses_depth_texture = false; + uses_normal_texture = false; + uses_time = false; + writes_modelview_or_projection = false; + uses_world_coordinates = false; + + int depth_drawi = DEPTH_DRAW_OPAQUE; + + ShaderCompilerRD::IdentifierActions actions; + + actions.render_mode_values["blend_add"] = Pair(&blend_mode, BLEND_MODE_ADD); + actions.render_mode_values["blend_mix"] = Pair(&blend_mode, BLEND_MODE_MIX); + actions.render_mode_values["blend_sub"] = Pair(&blend_mode, BLEND_MODE_SUB); + actions.render_mode_values["blend_mul"] = Pair(&blend_mode, BLEND_MODE_MUL); + + actions.render_mode_values["depth_draw_never"] = Pair(&depth_drawi, DEPTH_DRAW_DISABLED); + actions.render_mode_values["depth_draw_opaque"] = Pair(&depth_drawi, DEPTH_DRAW_OPAQUE); + actions.render_mode_values["depth_draw_always"] = Pair(&depth_drawi, DEPTH_DRAW_ALWAYS); + + actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED); + + actions.render_mode_values["cull_disabled"] = Pair(&cull, CULL_DISABLED); + actions.render_mode_values["cull_front"] = Pair(&cull, CULL_FRONT); + actions.render_mode_values["cull_back"] = Pair(&cull, CULL_BACK); + + actions.render_mode_flags["unshaded"] = &unshaded; + actions.render_mode_flags["wireframe"] = &wireframe; + + actions.usage_flag_pointers["ALPHA"] = &uses_alpha; + actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; + + actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; + + actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; + actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; + actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; + actions.usage_flag_pointers["DISCARD"] = &uses_discard; + actions.usage_flag_pointers["TIME"] = &uses_time; + actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; + actions.usage_flag_pointers["NORMAL"] = &uses_normal; + actions.usage_flag_pointers["NORMALMAP"] = &uses_normal; + + actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; + actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; + + actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection; + actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection; + actions.write_flag_pointers["VERTEX"] = &uses_vertex; + + actions.uniforms = &uniforms; + + RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; + + Error err = scene_singleton->shader.compiler.compile(RS::SHADER_SPATIAL, code, &actions, path, gen_code); + + ERR_FAIL_COND(err != OK); + + if (version.is_null()) { + version = scene_singleton->shader.scene_shader.version_create(); + } + + depth_draw = DepthDraw(depth_drawi); + depth_test = DepthTest(depth_testi); + +#if 0 + print_line("**compiling shader:"); + print_line("**defines:\n"); + for (int i = 0; i < gen_code.defines.size(); i++) { + print_line(gen_code.defines[i]); + } + print_line("\n**uniforms:\n" + gen_code.uniforms); + print_line("\n**vertex_globals:\n" + gen_code.vertex_global); + print_line("\n**vertex_code:\n" + gen_code.vertex); + print_line("\n**fragment_globals:\n" + gen_code.fragment_global); + print_line("\n**fragment_code:\n" + gen_code.fragment); + print_line("\n**light_code:\n" + gen_code.light); +#endif + scene_singleton->shader.scene_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + ERR_FAIL_COND(!scene_singleton->shader.scene_shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + //blend modes + + RD::PipelineColorBlendState::Attachment blend_attachment; + + switch (blend_mode) { + case BLEND_MODE_MIX: { + + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + } break; + case BLEND_MODE_ADD: { + + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + uses_blend_alpha = true; //force alpha used because of blend + + } break; + case BLEND_MODE_SUB: { + + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT; + blend_attachment.color_blend_op = RD::BLEND_OP_SUBTRACT; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; + uses_blend_alpha = true; //force alpha used because of blend + + } break; + case BLEND_MODE_MUL: { + blend_attachment.enable_blend = true; + blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; + blend_attachment.color_blend_op = RD::BLEND_OP_ADD; + blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR; + blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO; + blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA; + blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; + uses_blend_alpha = true; //force alpha used because of blend + } break; + } + + RD::PipelineColorBlendState blend_state_blend; + blend_state_blend.attachments.push_back(blend_attachment); + RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); + RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); + RD::PipelineColorBlendState blend_state_depth_normal = RD::PipelineColorBlendState::create_disabled(1); + RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(2); + + //update pipelines + + RD::PipelineDepthStencilState depth_stencil_state; + + if (depth_test != DEPTH_TEST_DISABLED) { + depth_stencil_state.enable_depth_test = true; + depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; + depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; + } + + for (int i = 0; i < CULL_VARIANT_MAX; i++) { + + RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = { + { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK }, + { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT }, + { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED } + }; + + RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull]; + + for (int j = 0; j < RS::PRIMITIVE_MAX; j++) { + + RD::RenderPrimitive primitive_rd_table[RS::PRIMITIVE_MAX] = { + RD::RENDER_PRIMITIVE_POINTS, + RD::RENDER_PRIMITIVE_LINES, + RD::RENDER_PRIMITIVE_LINESTRIPS, + RD::RENDER_PRIMITIVE_TRIANGLES, + RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, + }; + + RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j]; + + for (int k = 0; k < SHADER_VERSION_MAX; k++) { + + RD::PipelineRasterizationState raster_state; + raster_state.cull_mode = cull_mode_rd; + raster_state.wireframe = wireframe; + + RD::PipelineColorBlendState blend_state; + RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; + + if (uses_alpha || uses_blend_alpha) { + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { + blend_state = blend_state_blend; + if (depth_draw == DEPTH_DRAW_OPAQUE) { + depth_stencil.enable_depth_write = false; //alpha does not draw depth + } + } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) { + if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { + //none, blend state contains nothing + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + } else { + blend_state = blend_state_opaque; //writes to normal and roughness in opaque way + } + } else { + pipelines[i][j][k].clear(); + continue; // do not use this version (will error if using it is attempted) + } + } else { + + if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { + blend_state = blend_state_opaque; + } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { + //none, leave empty + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL) { + blend_state = blend_state_depth_normal; + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { + blend_state = blend_state_depth_normal; + } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { + blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way + + } else { + //specular write + blend_state = blend_state_opaque_specular; + } + } + + RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k); + pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, RD::PipelineMultisampleState(), depth_stencil, blend_state, 0); + } + } + } + + valid = true; +} + +void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { + if (!p_texture.is_valid()) { + default_texture_params.erase(p_name); + } else { + default_texture_params[p_name] = p_texture; + } +} + +void RasterizerSceneHighEndRD::ShaderData::get_param_list(List *p_param_list) const { + + Map order; + + for (Map::Element *E = uniforms.front(); E; E = E->next()) { + + if (E->get().texture_order >= 0) { + order[E->get().texture_order + 100000] = E->key(); + } else { + order[E->get().order] = E->key(); + } + } + + for (Map::Element *E = order.front(); E; E = E->next()) { + + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); + pi.name = E->get(); + p_param_list->push_back(pi); + } +} + +bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool RasterizerSceneHighEndRD::ShaderData::is_animated() const { + return false; +} + +bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const { + return false; +} +Variant RasterizerSceneHighEndRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); + } + return Variant(); +} + +RasterizerSceneHighEndRD::ShaderData::ShaderData() { + valid = false; + uses_screen_texture = false; +} + +RasterizerSceneHighEndRD::ShaderData::~ShaderData() { + RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; + ERR_FAIL_COND(!scene_singleton); + //pipeline variants will clear themselves if shader is gone + if (version.is_valid()) { + scene_singleton->shader.scene_shader.version_free(version); + } +} + +RasterizerStorageRD::ShaderData *RasterizerSceneHighEndRD::_create_shader_func() { + ShaderData *shader_data = memnew(ShaderData); + return shader_data; +} + +void RasterizerSceneHighEndRD::MaterialData::set_render_priority(int p_priority) { + priority = p_priority - RS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits +} + +void RasterizerSceneHighEndRD::MaterialData::set_next_pass(RID p_pass) { + next_pass = p_pass; +} + +void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + + RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; + + if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(shader_data->ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + + update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); + } + + uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); + + if ((uint32_t)texture_cache.size() != tex_uniform_count) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + + update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); + } + + if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { + // This material does not require an uniform set, so don't create it. + return; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return; + } + + Vector uniforms; + + { + + if (shader_data->ubo_size) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (uint32_t i = 0; i < tex_uniform_count; i++) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1 + i; + u.ids.push_back(textures[i]); + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); +} + +RasterizerSceneHighEndRD::MaterialData::~MaterialData() { + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } +} + +RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_func(ShaderData *p_shader) { + MaterialData *material_data = memnew(MaterialData); + material_data->shader_data = p_shader; + material_data->last_frame = false; + //update will happen later anyway so do nothing. + return material_data; +} + +RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() { + clear(); +} + +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { + + if (!specular.is_valid()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = width; + tf.height = height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector fb; + fb.push_back(color); + fb.push_back(specular); + fb.push_back(depth); + + color_specular_fb = RD::get_singleton()->framebuffer_create(fb); + } +} + +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { + + if (specular.is_valid()) { + RD::get_singleton()->free(specular); + specular = RID(); + } + + color_specular_fb = RID(); + color_fb = RID(); + + if (normal_buffer.is_valid()) { + RD::get_singleton()->free(normal_buffer); + normal_buffer = RID(); + depth_normal_fb = RID(); + } + + if (roughness_buffer.is_valid()) { + RD::get_singleton()->free(roughness_buffer); + roughness_buffer = RID(); + depth_normal_roughness_fb = RID(); + } +} + +void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) { + clear(); + + width = p_width; + height = p_height; + + color = p_color_buffer; + depth = p_depth_buffer; + + { + Vector fb; + fb.push_back(p_color_buffer); + fb.push_back(depth); + + color_fb = RD::get_singleton()->framebuffer_create(fb); + } + { + Vector fb; + fb.push_back(depth); + + depth_fb = RD::get_singleton()->framebuffer_create(fb); + } +} + +void RasterizerSceneHighEndRD::_allocate_normal_texture(RenderBufferDataHighEnd *rb) { + if (rb->normal_buffer.is_valid()) { + return; + } + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rb->normal_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector fb; + fb.push_back(rb->depth); + fb.push_back(rb->normal_buffer); + rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); + + _render_buffers_clear_uniform_set(rb); +} + +void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighEnd *rb) { + + if (rb->roughness_buffer.is_valid()) { + return; + } + + ERR_FAIL_COND(rb->normal_buffer.is_null()); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rb->roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector fb; + fb.push_back(rb->depth); + fb.push_back(rb->normal_buffer); + fb.push_back(rb->roughness_buffer); + rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); + + _render_buffers_clear_uniform_set(rb); +} + +RasterizerSceneRD::RenderBufferData *RasterizerSceneHighEndRD::_create_render_buffer_data() { + return memnew(RenderBufferDataHighEnd); +} + +bool RasterizerSceneHighEndRD::free(RID p_rid) { + if (RasterizerSceneRD::free(p_rid)) { + return true; + } + return false; +} + +void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) { + + for (int i = 0; i < p_element_count; i++) { + + const RenderList::Element *e = p_elements[i]; + InstanceData &id = scene_state.instances[i]; + store_transform(e->instance->transform, id.transform); + store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform); + id.flags = 0; + id.mask = e->instance->layer_mask; + + if (e->instance->base_type == RS::INSTANCE_MULTIMESH) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; + uint32_t stride; + if (storage->multimesh_get_transform_format(e->instance->base) == RS::MULTIMESH_TRANSFORM_2D) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; + stride = 2; + } else { + stride = 3; + } + if (storage->multimesh_uses_colors(e->instance->base)) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; + stride += 1; + } + if (storage->multimesh_uses_custom_data(e->instance->base)) { + id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; + stride += 1; + } + + id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); + } else if (e->instance->base_type == RS::INSTANCE_MESH) { + if (e->instance->skeleton.is_valid()) { + id.flags |= INSTANCE_DATA_FLAG_SKELETON; + } + } + + if (p_for_depth) { + id.gi_offset = 0xFFFFFFFF; + continue; + } + + if (!e->instance->gi_probe_instances.empty()) { + uint32_t written = 0; + for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) { + RID probe = e->instance->gi_probe_instances[j]; + int slot = gi_probe_instance_get_slot(probe); + if (slot < 0) { + continue; //unallocated, dont render + } + + if (render_pass != gi_probe_instance_get_render_pass(probe)) { + continue; //not rendered in this frame + } + + uint32_t index = gi_probe_instance_get_render_index(probe); + + if (written == 0) { + id.gi_offset = index; + written = 1; + } else { + id.gi_offset = index << 16; + written = 2; + break; + } + } + if (written == 0) { + id.gi_offset = 0xFFFFFFFF; + } else if (written == 1) { + id.gi_offset |= 0xFFFF0000; + } + } else { + id.gi_offset = 0xFFFFFFFF; + } + } + + RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true); +} + +/// RENDERING /// + +void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set) { + + RD::DrawListID draw_list = p_draw_list; + RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; + + //global scope bindings + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET); + if (p_radiance_uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_radiance_uniform_set, RADIANCE_UNIFORM_SET); + } else { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_radiance_uniform_set, RADIANCE_UNIFORM_SET); + } + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, view_dependant_uniform_set, VIEW_DEPENDANT_UNIFORM_SET); + if (p_render_buffers_uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); + } else { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); + } + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); + + MaterialData *prev_material = nullptr; + + RID prev_vertex_array_rd; + RID prev_index_array_rd; + RID prev_pipeline_rd; + RID prev_xforms_uniform_set; + + PushConstant push_constant; + zeromem(&push_constant, sizeof(PushConstant)); + + for (int i = 0; i < p_element_count; i++) { + + const RenderList::Element *e = p_elements[i]; + + MaterialData *material = e->material; + ShaderData *shader = material->shader_data; + RID xforms_uniform_set; + + //find cull variant + ShaderData::CullVariant cull_variant; + + if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == RS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { + cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED; + } else { + bool mirror = e->instance->mirror; + if (p_reverse_cull) { + mirror = !mirror; + } + cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL; + } + + //find primitive and vertex format + RS::PrimitiveType primitive; + + switch (e->instance->base_type) { + case RS::INSTANCE_MESH: { + primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index); + if (e->instance->skeleton.is_valid()) { + xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); + } + } break; + case RS::INSTANCE_MULTIMESH: { + RID mesh = storage->multimesh_get_mesh(e->instance->base); + ERR_CONTINUE(!mesh.is_valid()); //should be a bug + primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index); + + xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); + + } break; + case RS::INSTANCE_IMMEDIATE: { + ERR_CONTINUE(true); //should be a bug + } break; + case RS::INSTANCE_PARTICLES: { + ERR_CONTINUE(true); //should be a bug + } break; + default: { + ERR_CONTINUE(true); //should be a bug + } + } + + ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. + + switch (p_pass_mode) { + case PASS_MODE_COLOR: + case PASS_MODE_COLOR_TRANSPARENT: { + if (e->uses_lightmap) { + shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS; + } else if (e->uses_vct) { + shader_version = SHADER_VERSION_VCT_COLOR_PASS; + } else { + shader_version = SHADER_VERSION_COLOR_PASS; + } + } break; + case PASS_MODE_COLOR_SPECULAR: { + if (e->uses_lightmap) { + shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR; + } else if (e->uses_vct) { + shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR; + } else { + shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; + } + } break; + case PASS_MODE_SHADOW: + case PASS_MODE_DEPTH: { + shader_version = SHADER_VERSION_DEPTH_PASS; + } break; + case PASS_MODE_SHADOW_DP: { + shader_version = SHADER_VERSION_DEPTH_PASS_DP; + } break; + case PASS_MODE_DEPTH_NORMAL: { + shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL; + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; + } break; + case PASS_MODE_DEPTH_MATERIAL: { + shader_version = SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; + } break; + } + + RenderPipelineVertexFormatCacheRD *pipeline = nullptr; + + pipeline = &shader->pipelines[cull_variant][primitive][shader_version]; + + RD::VertexFormatID vertex_format = -1; + RID vertex_array_rd; + RID index_array_rd; + + switch (e->instance->base_type) { + case RS::INSTANCE_MESH: { + storage->mesh_surface_get_arrays_and_format(e->instance->base, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); + } break; + case RS::INSTANCE_MULTIMESH: { + RID mesh = storage->multimesh_get_mesh(e->instance->base); + ERR_CONTINUE(!mesh.is_valid()); //should be a bug + storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); + } break; + case RS::INSTANCE_IMMEDIATE: { + ERR_CONTINUE(true); //should be a bug + } break; + case RS::INSTANCE_PARTICLES: { + ERR_CONTINUE(true); //should be a bug + } break; + default: { + ERR_CONTINUE(true); //should be a bug + } + } + + if (prev_vertex_array_rd != vertex_array_rd) { + RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); + prev_vertex_array_rd = vertex_array_rd; + } + + if (prev_index_array_rd != index_array_rd) { + if (index_array_rd.is_valid()) { + RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array_rd); + } + prev_index_array_rd = index_array_rd; + } + + RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format); + + if (pipeline_rd != prev_pipeline_rd) { + // checking with prev shader does not make so much sense, as + // the pipeline may still be different. + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline_rd); + prev_pipeline_rd = pipeline_rd; + } + + if (xforms_uniform_set.is_valid() && prev_xforms_uniform_set != xforms_uniform_set) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, xforms_uniform_set, TRANSFORMS_UNIFORM_SET); + prev_xforms_uniform_set = xforms_uniform_set; + } + + if (material != prev_material) { + //update uniform set + if (material->uniform_set.is_valid()) { + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET); + } + + prev_material = material; + } + + push_constant.index = i; + RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant)); + + switch (e->instance->base_type) { + case RS::INSTANCE_MESH: { + RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid()); + } break; + case RS::INSTANCE_MULTIMESH: { + uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base); + RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); + } break; + case RS::INSTANCE_IMMEDIATE: { + + } break; + case RS::INSTANCE_PARTICLES: { + + } break; + default: { + ERR_CONTINUE(true); //should be a bug + } + } + } +} + +void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers) { + + //CameraMatrix projection = p_cam_projection; + //projection.flip_y(); // Vulkan and modern APIs use Y-Down + CameraMatrix correction; + correction.set_depth_correction(p_flip_y); + CameraMatrix projection = correction * p_cam_projection; + + //store camera into ubo + store_camera(projection, scene_state.ubo.projection_matrix); + store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); + store_transform(p_cam_transform, scene_state.ubo.camera_matrix); + store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); + + scene_state.ubo.z_far = p_zfar; + scene_state.ubo.z_near = p_znear; + + scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x; + scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y; + + if (p_shadow_atlas.is_valid()) { + Vector2 sas = shadow_atlas_get_size(p_shadow_atlas); + scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x; + scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y; + } + { + Vector2 dss = directional_shadow_get_size(); + scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x; + scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y; + } + //time global variables + scene_state.ubo.time = time; + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + + scene_state.ubo.use_ambient_light = true; + scene_state.ubo.ambient_light_color_energy[0] = 1; + scene_state.ubo.ambient_light_color_energy[1] = 1; + scene_state.ubo.ambient_light_color_energy[2] = 1; + scene_state.ubo.ambient_light_color_energy[3] = 1.0; + scene_state.ubo.use_ambient_cubemap = false; + scene_state.ubo.use_reflection_cubemap = false; + scene_state.ubo.ssao_enabled = false; + + } else if (is_environment(p_environment)) { + + RS::EnvironmentBG env_bg = environment_get_background(p_environment); + RS::EnvironmentAmbientSource ambient_src = environment_get_ambient_light_ambient_source(p_environment); + + float bg_energy = environment_get_bg_energy(p_environment); + scene_state.ubo.ambient_light_color_energy[3] = bg_energy; + + scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_environment); + + //ambient + if (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && (env_bg == RS::ENV_BG_CLEAR_COLOR || env_bg == RS::ENV_BG_COLOR)) { + + Color color = env_bg == RS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_environment); + color = color.to_linear(); + + scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; + scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy; + scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy; + scene_state.ubo.use_ambient_light = true; + scene_state.ubo.use_ambient_cubemap = false; + } else { + + float energy = environment_get_ambient_light_ambient_energy(p_environment); + Color color = environment_get_ambient_light_color(p_environment); + color = color.to_linear(); + scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; + scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; + scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; + + Basis sky_transform = environment_get_sky_orientation(p_environment); + sky_transform = sky_transform.inverse() * p_cam_transform.basis; + store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); + + scene_state.ubo.use_ambient_cubemap = (ambient_src == RS::ENV_AMBIENT_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ambient_src == RS::ENV_AMBIENT_SOURCE_SKY; + scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == RS::ENV_AMBIENT_SOURCE_COLOR; + } + + //specular + RS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_environment); + if ((ref_src == RS::ENV_REFLECTION_SOURCE_BG && env_bg == RS::ENV_BG_SKY) || ref_src == RS::ENV_REFLECTION_SOURCE_SKY) { + scene_state.ubo.use_reflection_cubemap = true; + } else { + scene_state.ubo.use_reflection_cubemap = false; + } + + scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_environment); + scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_environment); + scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_environment); + + Color ao_color = environment_get_ao_color(p_environment); + scene_state.ubo.ao_color[0] = ao_color.r; + scene_state.ubo.ao_color[1] = ao_color.g; + scene_state.ubo.ao_color[2] = ao_color.b; + scene_state.ubo.ao_color[3] = ao_color.a; + + } else { + + if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { + scene_state.ubo.use_ambient_light = false; + } else { + scene_state.ubo.use_ambient_light = true; + Color clear_color = p_default_bg_color; + clear_color = clear_color.to_linear(); + scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; + scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; + scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; + scene_state.ubo.ambient_light_color_energy[3] = 1.0; + } + + scene_state.ubo.use_ambient_cubemap = false; + scene_state.ubo.use_reflection_cubemap = false; + } + + scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active(); + + RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); +} + +void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) { + + RID m_src; + + m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material; + + if (unlikely(get_debug_draw_mode() != RS::VIEWPORT_DEBUG_DRAW_DISABLED)) { + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { + m_src = overdraw_material; + } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME) { + m_src = wireframe_material; + } else if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_LIGHTING) { + m_src = default_material; + } + } + + MaterialData *material = NULL; + + if (m_src.is_valid()) { + material = (MaterialData *)storage->material_get_data(m_src, RasterizerStorageRD::SHADER_TYPE_3D); + if (!material || !material->shader_data->valid) { + material = NULL; + } + } + + if (!material) { + material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); + m_src = default_material; + } + + ERR_FAIL_COND(!material); + + _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index); + + while (material->next_pass.is_valid()) { + + material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D); + if (!material || !material->shader_data->valid) + break; + _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index); + } +} + +void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index) { + + bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; + bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); + bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; + bool has_alpha = has_base_alpha || has_blend_alpha; + + if (p_material->shader_data->uses_sss) { + scene_state.used_sss = true; + } + + if (p_material->shader_data->uses_screen_texture) { + scene_state.used_screen_texture = true; + } + + if (p_material->shader_data->uses_depth_texture) { + scene_state.used_depth_texture = true; + } + + if (p_material->shader_data->uses_normal_texture) { + scene_state.used_normal_texture = true; + } + + if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) { + + if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { + //conditions in which no depth pass should be processed + return; + } + + if (p_pass_mode != PASS_MODE_DEPTH_MATERIAL && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { + //shader does not use discard and does not write a vertex position, use generic material + if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) { + p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); + } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL && !p_material->shader_data->uses_normal) { + p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); + } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) { + p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); + } + } + + has_alpha = false; + } + + RenderList::Element *e = (has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) ? render_list.add_alpha_element() : render_list.add_element(); + + if (!e) + return; + + e->instance = p_instance; + e->material = p_material; + e->surface_index = p_surface; + e->sort_key = 0; + + if (e->material->last_pass != render_pass) { + if (!RD::get_singleton()->uniform_set_is_valid(e->material->uniform_set)) { + //uniform set no longer valid, probably a texture changed + storage->material_force_update_textures(p_material_rid, RasterizerStorageRD::SHADER_TYPE_3D); + } + e->material->last_pass = render_pass; + e->material->index = scene_state.current_material_index++; + if (e->material->shader_data->last_pass != render_pass) { + e->material->shader_data->last_pass = scene_state.current_material_index++; + e->material->shader_data->index = scene_state.current_shader_index++; + } + } + e->geometry_index = p_geometry_index; + e->material_index = e->material->index; + e->uses_instancing = e->instance->base_type == RS::INSTANCE_MULTIMESH; + e->uses_lightmap = e->instance->lightmap.is_valid(); + e->uses_vct = e->instance->gi_probe_instances.size(); + e->shader_index = e->shader_index; + e->depth_layer = e->instance->depth_layer; + e->priority = p_material->priority; + + if (p_material->shader_data->uses_time) { + RenderingServerRaster::redraw_request(); + } +} + +void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) { + + scene_state.current_shader_index = 0; + scene_state.current_material_index = 0; + scene_state.used_sss = false; + scene_state.used_screen_texture = false; + scene_state.used_normal_texture = false; + scene_state.used_depth_texture = false; + + uint32_t geometry_index = 0; + + //fill list + + for (int i = 0; i < p_cull_count; i++) { + + InstanceBase *inst = p_cull_result[i]; + + //add geometry for drawing + switch (inst->base_type) { + + case RS::INSTANCE_MESH: { + + const RID *materials = NULL; + uint32_t surface_count; + + materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count); + if (!materials) { + continue; //nothing to do + } + + const RID *inst_materials = inst->materials.ptr(); + + for (uint32_t j = 0; j < surface_count; j++) { + + RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j]; + + uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index); + _add_geometry(inst, j, material, p_pass_mode, surface_index); + } + + //mesh->last_pass=frame; + + } break; + + case RS::INSTANCE_MULTIMESH: { + + if (storage->multimesh_get_instances_to_draw(inst->base) == 0) { + //not visible, 0 instances + continue; + } + + RID mesh = storage->multimesh_get_mesh(inst->base); + if (!mesh.is_valid()) { + continue; + } + + const RID *materials = NULL; + uint32_t surface_count; + + materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); + if (!materials) { + continue; //nothing to do + } + + for (uint32_t j = 0; j < surface_count; j++) { + + uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index); + _add_geometry(inst, j, materials[j], p_pass_mode, surface_index); + } + + } break; +#if 0 + case RS::INSTANCE_IMMEDIATE: { + + RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); + ERR_CONTINUE(!immediate); + + _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass); + + } break; + case RS::INSTANCE_PARTICLES: { + + RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(inst->base); + ERR_CONTINUE(!particles); + + for (int j = 0; j < particles->draw_passes.size(); j++) { + + RID pmesh = particles->draw_passes[j]; + if (!pmesh.is_valid()) + continue; + RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(pmesh); + if (!mesh) + continue; //mesh not assigned + + int ssize = mesh->surfaces.size(); + + for (int k = 0; k < ssize; k++) { + + RasterizerStorageGLES3::Surface *s = mesh->surfaces[k]; + _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass); + } + } + + } break; +#endif + default: { + } + } + } +} + +void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) { + + for (int i = 0; i < p_reflection_probe_cull_count; i++) { + + RID rpi = p_reflection_probe_cull_result[i]; + + if (i >= (int)scene_state.max_reflections) { + reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set + continue; + } + + reflection_probe_instance_set_render_index(rpi, i); + + RID base_probe = reflection_probe_instance_get_probe(rpi); + + ReflectionData &reflection_ubo = scene_state.reflections[i]; + + Vector3 extents = storage->reflection_probe_get_extents(base_probe); + + reflection_ubo.box_extents[0] = extents.x; + reflection_ubo.box_extents[1] = extents.y; + reflection_ubo.box_extents[2] = extents.z; + reflection_ubo.index = reflection_probe_instance_get_atlas_index(rpi); + + Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe); + + reflection_ubo.box_offset[0] = origin_offset.x; + reflection_ubo.box_offset[1] = origin_offset.y; + reflection_ubo.box_offset[2] = origin_offset.z; + reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe); + + float intensity = storage->reflection_probe_get_intensity(base_probe); + bool interior = storage->reflection_probe_is_interior(base_probe); + bool box_projection = storage->reflection_probe_is_box_projection(base_probe); + + reflection_ubo.params[0] = intensity; + reflection_ubo.params[1] = 0; + reflection_ubo.params[2] = interior ? 1.0 : 0.0; + reflection_ubo.params[3] = box_projection ? 1.0 : 0.0; + + if (interior) { + Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear(); + float interior_ambient_energy = storage->reflection_probe_get_interior_ambient_energy(base_probe); + float interior_ambient_probe_contrib = storage->reflection_probe_get_interior_ambient_probe_contribution(base_probe); + reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; + reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; + reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy; + reflection_ubo.ambient[3] = interior_ambient_probe_contrib; + } else { + Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear(); + if (is_environment(p_environment)) { + Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear(); + float env_ambient_energy = environment_get_ambient_light_ambient_energy(p_environment); + ambient_linear = env_ambient_color; + ambient_linear.r *= env_ambient_energy; + ambient_linear.g *= env_ambient_energy; + ambient_linear.b *= env_ambient_energy; + } + + reflection_ubo.ambient[0] = ambient_linear.r; + reflection_ubo.ambient[1] = ambient_linear.g; + reflection_ubo.ambient[2] = ambient_linear.b; + reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light + } + + Transform transform = reflection_probe_instance_get_transform(rpi); + Transform proj = (p_camera_inverse_transform * transform).inverse(); + store_transform(proj, reflection_ubo.local_matrix); + + cluster_builder.add_reflection_probe(transform, extents); + + reflection_probe_instance_set_render_pass(rpi, render_pass); + } + + if (p_reflection_probe_cull_count) { + RD::get_singleton()->buffer_update(scene_state.reflection_buffer, 0, MIN(scene_state.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), scene_state.reflections, true); + } +} + +void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) { + + int index = 0; + + for (int i = 0; i < p_gi_probe_probe_cull_count; i++) { + + RID rpi = p_gi_probe_probe_cull_result[i]; + + if (index >= (int)scene_state.max_gi_probes) { + continue; + } + + int slot = gi_probe_instance_get_slot(rpi); + if (slot < 0) { + continue; //not usable + } + + RID base_probe = gi_probe_instance_get_base_probe(rpi); + + GIProbeData &gi_probe_ubo = scene_state.gi_probes[index]; + + Transform to_cell = gi_probe_instance_get_transform_to_cell(rpi) * p_camera_transform; + + store_transform(to_cell, gi_probe_ubo.xform); + + Vector3 bounds = storage->gi_probe_get_octree_size(base_probe); + + gi_probe_ubo.bounds[0] = bounds.x; + gi_probe_ubo.bounds[1] = bounds.y; + gi_probe_ubo.bounds[2] = bounds.z; + + gi_probe_ubo.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe); + gi_probe_ubo.bias = storage->gi_probe_get_bias(base_probe); + gi_probe_ubo.normal_bias = storage->gi_probe_get_normal_bias(base_probe); + gi_probe_ubo.blend_ambient = !storage->gi_probe_is_interior(base_probe); + gi_probe_ubo.texture_slot = gi_probe_instance_get_slot(rpi); + gi_probe_ubo.anisotropy_strength = storage->gi_probe_get_anisotropy_strength(base_probe); + gi_probe_ubo.ao = storage->gi_probe_get_ao(base_probe); + gi_probe_ubo.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f); + + if (gi_probe_is_anisotropic()) { + gi_probe_ubo.texture_slot *= 3; + } + + gi_probe_instance_set_render_index(rpi, index); + gi_probe_instance_set_render_pass(rpi, render_pass); + + index++; + } + + if (index) { + RD::get_singleton()->buffer_update(scene_state.gi_probe_buffer, 0, index * sizeof(GIProbeData), scene_state.gi_probes, true); + } +} + +void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) { + + uint32_t light_count = 0; + scene_state.ubo.directional_light_count = 0; + sky_scene_state.directional_light_count = 0; + + for (int i = 0; i < p_light_cull_count; i++) { + + RID li = p_light_cull_result[i]; + RID base = light_instance_get_base_light(li); + + ERR_CONTINUE(base.is_null()); + + RS::LightType type = storage->light_get_type(base); + switch (type) { + + case RS::LIGHT_DIRECTIONAL: { + + if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) { + continue; + } + + DirectionalLightData &light_data = scene_state.directional_lights[scene_state.ubo.directional_light_count]; + + Transform light_transform = light_instance_get_base_transform(li); + + Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized(); + + light_data.direction[0] = direction.x; + light_data.direction[1] = direction.y; + light_data.direction[2] = direction.z; + + float sign = storage->light_is_negative(base) ? -1 : 1; + + light_data.energy = sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI; + + Color linear_col = storage->light_get_color(base).to_linear(); + light_data.color[0] = linear_col.r; + light_data.color[1] = linear_col.g; + light_data.color[2] = linear_col.b; + + light_data.specular = storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR); + light_data.mask = storage->light_get_cull_mask(base); + + Color shadow_col = storage->light_get_shadow_color(base).to_linear(); + + light_data.shadow_color[0] = shadow_col.r; + light_data.shadow_color[1] = shadow_col.g; + light_data.shadow_color[2] = shadow_col.b; + + light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base); + + if (light_data.shadow_enabled) { + + RS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base); + + int limit = smode == RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); + light_data.blend_splits = storage->light_directional_get_blend_splits(base); + for (int j = 0; j < 4; j++) { + Rect2 atlas_rect = light_instance_get_directional_shadow_atlas_rect(li, j); + CameraMatrix matrix = light_instance_get_shadow_camera(li, j); + float split = light_instance_get_directional_shadow_split(li, MIN(limit, j)); + + CameraMatrix bias; + bias.set_light_bias(); + CameraMatrix rectm; + rectm.set_light_atlas_rect(atlas_rect); + + Transform modelview = (p_camera_inverse_transform * light_instance_get_shadow_transform(li, j)).inverse(); + + CameraMatrix shadow_mtx = rectm * bias * matrix * modelview; + light_data.shadow_split_offsets[j] = split; + store_camera(shadow_mtx, light_data.shadow_matrices[j]); + } + + float fade_start = storage->light_get_param(base, RS::LIGHT_PARAM_SHADOW_FADE_START); + light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep + light_data.fade_to = -light_data.shadow_split_offsets[3]; + } + + // Copy to SkyDirectionalLightData + if (sky_scene_state.directional_light_count < sky_scene_state.max_directional_lights) { + + SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.directional_light_count]; + + Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); + + sky_light_data.direction[0] = world_direction.x; + sky_light_data.direction[1] = world_direction.y; + sky_light_data.direction[2] = -world_direction.z; + + sky_light_data.energy = light_data.energy / Math_PI; + + sky_light_data.color[0] = light_data.color[0]; + sky_light_data.color[1] = light_data.color[1]; + sky_light_data.color[2] = light_data.color[2]; + + sky_light_data.enabled = true; + sky_scene_state.directional_light_count++; + } + + scene_state.ubo.directional_light_count++; + } break; + case RS::LIGHT_SPOT: + case RS::LIGHT_OMNI: { + + if (light_count >= scene_state.max_lights) { + continue; + } + + Transform light_transform = light_instance_get_base_transform(li); + + LightData &light_data = scene_state.lights[light_count]; + + float sign = storage->light_is_negative(base) ? -1 : 1; + Color linear_col = storage->light_get_color(base).to_linear(); + + light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_ATTENUATION)); + light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, RS::LIGHT_PARAM_ENERGY) * Math_PI); + + light_data.color_specular[0] = MIN(uint32_t(linear_col.r * 255), 255); + light_data.color_specular[1] = MIN(uint32_t(linear_col.g * 255), 255); + light_data.color_specular[2] = MIN(uint32_t(linear_col.b * 255), 255); + light_data.color_specular[3] = MIN(uint32_t(storage->light_get_param(base, RS::LIGHT_PARAM_SPECULAR) * 255), 255); + + float radius = MAX(0.001, storage->light_get_param(base, RS::LIGHT_PARAM_RANGE)); + light_data.inv_radius = 1.0 / radius; + + Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin); + + light_data.position[0] = pos.x; + light_data.position[1] = pos.y; + light_data.position[2] = pos.z; + + Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized(); + + light_data.direction[0] = direction.x; + light_data.direction[1] = direction.y; + light_data.direction[2] = direction.z; + + light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ATTENUATION)); + float spot_angle = storage->light_get_param(base, RS::LIGHT_PARAM_SPOT_ANGLE); + light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle))); + + light_data.mask = storage->light_get_cull_mask(base); + + Color shadow_color = storage->light_get_shadow_color(base); + + bool has_shadow = p_using_shadows && storage->light_has_shadow(base); + light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255); + light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255); + light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255); + light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0; + + light_data.atlas_rect[0] = 0; + light_data.atlas_rect[1] = 0; + light_data.atlas_rect[2] = 0; + light_data.atlas_rect[3] = 0; + + if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) { + // fill in the shadow information + + Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas); + + if (type == RS::LIGHT_OMNI) { + + light_data.atlas_rect[0] = rect.position.x; + light_data.atlas_rect[1] = rect.position.y; + light_data.atlas_rect[2] = rect.size.width; + light_data.atlas_rect[3] = rect.size.height * 0.5; + + Transform proj = (p_camera_inverse_transform * light_transform).inverse(); + + store_transform(proj, light_data.shadow_matrix); + } else if (type == RS::LIGHT_SPOT) { + + Transform modelview = (p_camera_inverse_transform * light_transform).inverse(); + CameraMatrix bias; + bias.set_light_bias(); + CameraMatrix rectm; + rectm.set_light_atlas_rect(rect); + + CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview; + store_camera(shadow_mtx, light_data.shadow_matrix); + } + } + + light_instance_set_index(li, light_count); + + cluster_builder.add_light(type == RS::LIGHT_SPOT ? LightClusterBuilder::LIGHT_TYPE_SPOT : LightClusterBuilder::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle); + + light_count++; + } break; + } + + light_instance_set_render_pass(li, render_pass); + + //update UBO for forward rendering, blit to texture for clustered + } + + if (light_count) { + RD::get_singleton()->buffer_update(scene_state.light_buffer, 0, sizeof(LightData) * light_count, scene_state.lights, true); + } + + if (scene_state.ubo.directional_light_count) { + RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * scene_state.ubo.directional_light_count, scene_state.directional_lights, true); + } +} + +void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) { + + RenderBufferDataHighEnd *render_buffer = NULL; + if (p_render_buffer.is_valid()) { + render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer); + } + + //first of all, make a new render pass + render_pass++; + + //fill up ubo +#if 0 + storage->info.render.object_count += p_cull_count; + + Environment *env = environment_owner.getornull(p_environment); + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); + + if (shadow_atlas && shadow_atlas->size) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); + glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); + scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size; + scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size; + } + + if (reflection_atlas && reflection_atlas->size) { + glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); + glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); + } +#endif + + RENDER_TIMESTAMP("Setup 3D Scene"); + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_UNSHADED) { + p_light_cull_count = 0; + p_reflection_probe_cull_count = 0; + p_gi_probe_cull_count = 0; + } + + bool using_shadows = true; + + if (p_reflection_probe.is_valid()) { + scene_state.ubo.reflection_multiplier = 0.0; + if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_reflection_probe))) { + using_shadows = false; + } + } else { + scene_state.ubo.reflection_multiplier = 1.0; + } + + //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size; + + scene_state.ubo.shadow_z_offset = 0; + scene_state.ubo.shadow_z_slope_scale = 0; + + Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); + scene_state.ubo.viewport_size[0] = vp_he.x; + scene_state.ubo.viewport_size[1] = vp_he.y; + + Size2 screen_pixel_size; + Size2i screen_size; + RID opaque_framebuffer; + RID depth_framebuffer; + RID alpha_framebuffer; + + PassMode depth_pass_mode = PASS_MODE_DEPTH; + Vector depth_pass_clear; + + if (render_buffer) { + screen_pixel_size.width = 1.0 / render_buffer->width; + screen_pixel_size.height = 1.0 / render_buffer->height; + screen_size.x = render_buffer->width; + screen_size.y = render_buffer->height; + + opaque_framebuffer = render_buffer->color_fb; + + if (p_environment.is_valid() && environment_is_ssr_enabled(p_environment)) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; + } else if (screen_space_roughness_limiter_is_active()) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL; + //we need to allocate both these, if not allocated + _allocate_normal_texture(render_buffer); + _allocate_roughness_texture(render_buffer); + } else if (p_environment.is_valid() && (environment_is_ssao_enabled(p_environment) || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { + depth_pass_mode = PASS_MODE_DEPTH_NORMAL; + } + + switch (depth_pass_mode) { + case PASS_MODE_DEPTH: { + depth_framebuffer = render_buffer->depth_fb; + } break; + case PASS_MODE_DEPTH_NORMAL: { + _allocate_normal_texture(render_buffer); + depth_framebuffer = render_buffer->depth_normal_fb; + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + } break; + case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { + _allocate_normal_texture(render_buffer); + _allocate_roughness_texture(render_buffer); + depth_framebuffer = render_buffer->depth_normal_roughness_fb; + depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); + depth_pass_clear.push_back(Color()); + } break; + default: { + }; + } + + alpha_framebuffer = opaque_framebuffer; + + } else if (p_reflection_probe.is_valid()) { + uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe); + screen_pixel_size.width = 1.0 / resolution; + screen_pixel_size.height = 1.0 / resolution; + screen_size.x = resolution; + screen_size.y = resolution; + + opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass); + depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_reflection_probe, p_reflection_probe_pass); + alpha_framebuffer = opaque_framebuffer; + + if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { + p_environment = RID(); //no environment on interiors + } + + } else { + ERR_FAIL(); //bug? + } + + cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster + + _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows); + _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment); + _setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform); + _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); + + cluster_builder.bake_cluster(); //bake to cluster + + _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) + + render_list.clear(); + _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr); + + RID radiance_uniform_set; + bool draw_sky = false; + + Color clear_color; + bool keep_color = false; + + if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { + clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black + } else if (is_environment(p_environment)) { + RS::EnvironmentBG bg_mode = environment_get_background(p_environment); + float bg_energy = environment_get_bg_energy(p_environment); + switch (bg_mode) { + case RS::ENV_BG_CLEAR_COLOR: { + clear_color = p_default_bg_color; + clear_color.r *= bg_energy; + clear_color.g *= bg_energy; + clear_color.b *= bg_energy; + } break; + case RS::ENV_BG_COLOR: { + clear_color = environment_get_bg_color(p_environment); + clear_color.r *= bg_energy; + clear_color.g *= bg_energy; + clear_color.b *= bg_energy; + } break; + case RS::ENV_BG_SKY: { + RID sky = environment_get_sky(p_environment); + if (sky.is_valid()) { + + RENDER_TIMESTAMP("Setup Sky"); + CameraMatrix projection = p_cam_projection; + if (p_reflection_probe.is_valid()) { + CameraMatrix correction; + correction.set_depth_correction(true); + projection = correction * p_cam_projection; + } + + _setup_sky(p_environment, p_cam_transform.origin, screen_size); + _update_sky(p_environment, projection, p_cam_transform); + radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET); + + draw_sky = true; + } + } break; + case RS::ENV_BG_CANVAS: { + keep_color = true; + } break; + case RS::ENV_BG_KEEP: { + keep_color = true; + } break; + case RS::ENV_BG_CAMERA_FEED: { + + } break; + default: { + } + } + } else { + + clear_color = p_default_bg_color; + } + + _setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas); + + render_list.sort_by_key(false); + + _fill_instances(render_list.elements, render_list.element_count, false); + + bool can_continue = true; //unless the middle buffers are needed + bool debug_giprobes = get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; + bool using_separate_specular = false; + + bool depth_pre_pass = depth_framebuffer.is_valid(); + RID render_buffers_uniform_set; + + if (depth_pre_pass) { //depth pre pass + RENDER_TIMESTAMP("Render Depth Pre-Pass"); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID()); + RD::get_singleton()->draw_list_end(); + } + + if (p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment)) { + _process_ssao(p_render_buffer, p_environment, render_buffer->normal_buffer, p_cam_projection); + } + + if (p_render_buffer.is_valid() && screen_space_roughness_limiter_is_active()) { + storage->get_effects()->roughness_limit(render_buffer->normal_buffer, render_buffer->roughness_buffer, Size2(render_buffer->width, render_buffer->height), screen_space_roughness_limiter_get_curve()); + } + + if (p_render_buffer.is_valid()) { + //update the render buffers uniform set in case it changed + _update_render_buffers_uniform_set(p_render_buffer); + render_buffers_uniform_set = render_buffer->uniform_set; + } + + _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid()); + + RENDER_TIMESTAMP("Render Opaque Pass"); + + { + bool will_continue = (can_continue || draw_sky || debug_giprobes); + //regular forward for now + Vector c; + c.push_back(clear_color.to_linear()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); + RD::get_singleton()->draw_list_end(); + } + + if (debug_giprobes) { + //debug giprobes + bool will_continue = (can_continue || draw_sky); + CameraMatrix dc; + dc.set_depth_correction(true); + CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse()); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + for (int i = 0; i < p_gi_probe_cull_count; i++) { + _debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); + } + RD::get_singleton()->draw_list_end(); + } + + if (draw_sky) { + RENDER_TIMESTAMP("Render Sky"); + + CameraMatrix projection = p_cam_projection; + if (p_reflection_probe.is_valid()) { + CameraMatrix correction; + correction.set_depth_correction(true); + projection = correction * p_cam_projection; + } + + _draw_sky(can_continue, opaque_framebuffer, p_environment, projection, p_cam_transform); + + if (using_separate_specular && !can_continue) { + //can't continue, so close the buffers + //RD::get_singleton()->draw_list_begin(render_buffer->color_specular_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c); + //RD::get_singleton()->draw_list_end(); + } + } + + RENDER_TIMESTAMP("Render Transparent Pass"); + + _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); + + render_list.sort_by_reverse_depth_and_priority(true); + + _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false); + + { + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); + RD::get_singleton()->draw_list_end(); + } + + //_render_list +#if 0 + if (state.directional_light_count == 0) { + directional_light = NULL; + _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, false, shadow_atlas != NULL); + } else { + for (int i = 0; i < state.directional_light_count; i++) { + directional_light = directional_lights[i]; + _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0); + _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != NULL); + } + } +#endif + +#if 0 + _post_process(env, p_cam_projection); + // Needed only for debugging + /* if (shadow_atlas && storage->frame.current_rt) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + } + + if (storage->frame.current_rt) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color); + //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); + storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1)); + } + + if (reflection_atlas && storage->frame.current_rt) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); + storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + } + + if (directional_shadow.fbo) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); + storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + } + + if ( env_radiance_tex) { + + //_copy_texture_to_front_buffer(shadow_atlas->depth); + storage->canvas->canvas_begin(); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, env_radiance_tex); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + }*/ + //disable all stuff +#endif +} +void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) { + + RENDER_TIMESTAMP("Setup Rendering Shadow"); + + _update_render_base_uniform_set(); + + render_pass++; + + scene_state.ubo.shadow_z_offset = p_bias; + scene_state.ubo.shadow_z_slope_scale = p_normal_bias; + scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; + + _setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar); + + render_list.clear(); + + PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; + + _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); + + _setup_view_dependant_uniform_set(RID(), RID()); + + RENDER_TIMESTAMP("Render Shadow"); + + render_list.sort_by_key(false); + + _fill_instances(render_list.elements, render_list.element_count, true); + + { + //regular forward for now + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, RID(), RID()); + RD::get_singleton()->draw_list_end(); + } +} + +void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { + RENDER_TIMESTAMP("Setup Rendering Shadow"); + + _update_render_base_uniform_set(); + + render_pass++; + + scene_state.ubo.shadow_z_offset = 0; + scene_state.ubo.shadow_z_slope_scale = 0; + scene_state.ubo.dual_paraboloid_side = 0; + + _setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); + + render_list.clear(); + + PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; + _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); + + _setup_view_dependant_uniform_set(RID(), RID()); + + RENDER_TIMESTAMP("Render Material"); + + render_list.sort_by_key(false); + + _fill_instances(render_list.elements, render_list.element_count, true); + + { + //regular forward for now + Vector clear; + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + clear.push_back(Color(0, 0, 0, 0)); + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); + _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID()); + RD::get_singleton()->draw_list_end(); + } +} + +void RasterizerSceneHighEndRD::_base_uniforms_changed() { + + if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + RD::get_singleton()->free(render_base_uniform_set); + } + render_base_uniform_set = RID(); +} + +void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { + + if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + + if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { + RD::get_singleton()->free(render_base_uniform_set); + } + + Vector uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 1; + u.ids.resize(12); + RID *ids_ptr = u.ids.ptrw(); + ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.ids.push_back(shadow_sampler); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(scene_state.uniform_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(scene_state.instance_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 5; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(scene_state.light_buffer); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 6; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(scene_state.reflection_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 7; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(scene_state.directional_light_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 8; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(scene_state.gi_probe_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 9; + u.type = RD::UNIFORM_TYPE_TEXTURE; + int slot_count = gi_probe_get_slots().size(); + if (gi_probe_is_anisotropic()) { + u.ids.resize(slot_count * 3); + } else { + u.ids.resize(slot_count); + } + + for (int i = 0; i < slot_count; i++) { + + RID probe = gi_probe_get_slots()[i]; + + if (gi_probe_is_anisotropic()) { + if (probe.is_null()) { + RID empty_tex = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + u.ids.write[i * 3 + 0] = empty_tex; + u.ids.write[i * 3 + 1] = empty_tex; + u.ids.write[i * 3 + 2] = empty_tex; + } else { + u.ids.write[i * 3 + 0] = gi_probe_instance_get_texture(probe); + u.ids.write[i * 3 + 1] = gi_probe_instance_get_aniso_texture(probe, 0); + u.ids.write[i * 3 + 2] = gi_probe_instance_get_aniso_texture(probe, 1); + } + } else { + if (probe.is_null()) { + u.ids.write[i] = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + } else { + u.ids.write[i] = gi_probe_instance_get_texture(probe); + } + } + } + + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 10; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.ids.push_back(cluster_builder.get_cluster_texture()); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 11; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(cluster_builder.get_cluster_indices_buffer()); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 12; + u.type = RD::UNIFORM_TYPE_TEXTURE; + if (directional_shadow_get_texture().is_valid()) { + u.ids.push_back(directional_shadow_get_texture()); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + } + uniforms.push_back(u); + } + + render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET); + } +} + +void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas) { + + if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { + RD::get_singleton()->free(view_dependant_uniform_set); + } + + //default render buffer and scene state uniform set + + Vector uniforms; + + { + + RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); + RD::Uniform u; + u.binding = 0; + u.type = RD::UNIFORM_TYPE_TEXTURE; + if (ref_texture.is_valid()) { + u.ids.push_back(ref_texture); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); + } + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture; + if (p_shadow_atlas.is_valid()) { + texture = shadow_atlas_get_texture(p_shadow_atlas); + } + if (!texture.is_valid()) { + texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + u.ids.push_back(texture); + uniforms.push_back(u); + } + + view_dependant_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, VIEW_DEPENDANT_UNIFORM_SET); +} + +void RasterizerSceneHighEndRD::_render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb) { + + if (!rb->uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { + RD::get_singleton()->free(rb->uniform_set); + } + rb->uniform_set = RID(); +} + +void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_buffers) { + + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + _render_buffers_clear_uniform_set(rb); +} + +RID RasterizerSceneHighEndRD::_render_buffers_get_roughness_texture(RID p_render_buffers) { + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + return rb->roughness_buffer; +} + +RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_buffers) { + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + return rb->normal_buffer; +} + +void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) { + + RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); + + if (rb->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { + + Vector uniforms; + { + RD::Uniform u; + u.binding = 0; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = false && rb->depth.is_valid() ? rb->depth : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 1; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID bbt = render_buffers_get_back_buffer_texture(p_render_buffers); + RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.binding = 2; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb->normal_buffer.is_valid() ? rb->normal_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 3; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = rb->roughness_buffer.is_valid() ? rb->roughness_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.binding = 4; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID aot = render_buffers_get_ao_texture(p_render_buffers); + RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + rb->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); + } +} + +RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = NULL; + +void RasterizerSceneHighEndRD::set_time(double p_time, double p_step) { + time = p_time; + RasterizerSceneRD::set_time(p_time, p_step); +} + +RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage) : + RasterizerSceneRD(p_storage) { + singleton = this; + storage = p_storage; + + /* SCENE SHADER */ + + { + String defines; + defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n"; + if (is_using_radiance_cubemap_array()) { + defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; + } + + uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); + + { //reflections + uint32_t reflection_buffer_size; + if (uniform_max_size < 65536) { + //Yes, you guessed right, ARM again + reflection_buffer_size = uniform_max_size; + } else { + reflection_buffer_size = 65536; + } + + scene_state.max_reflections = reflection_buffer_size / sizeof(ReflectionData); + scene_state.reflections = memnew_arr(ReflectionData, scene_state.max_reflections); + scene_state.reflection_buffer = RD::get_singleton()->uniform_buffer_create(reflection_buffer_size); + defines += "\n#define MAX_REFLECTION_DATA_STRUCTS " + itos(scene_state.max_reflections) + "\n"; + } + + { //lights + scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData); + uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData); + scene_state.lights = memnew_arr(LightData, scene_state.max_lights); + scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size); + defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n"; + + scene_state.max_directional_lights = 8; + uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData); + scene_state.directional_lights = memnew_arr(DirectionalLightData, scene_state.max_directional_lights); + scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); + defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n"; + } + + { //giprobes + int slot_count = gi_probe_get_slots().size(); + if (gi_probe_is_anisotropic()) { + slot_count *= 3; + defines += "\n#define GI_PROBE_USE_ANISOTROPY\n"; + } + + if (gi_probe_get_quality() == GIPROBE_QUALITY_ULTRA_LOW) { + defines += "\n#define GI_PROBE_LOW_QUALITY\n"; + } else if (gi_probe_get_quality() == GIPROBE_QUALITY_HIGH) { + defines += "\n#define GI_PROBE_HIGH_QUALITY\n"; + } + + defines += "\n#define MAX_GI_PROBE_TEXTURES " + itos(slot_count) + "\n"; + + uint32_t giprobe_buffer_size; + if (uniform_max_size < 65536) { + //Yes, you guessed right, ARM again + giprobe_buffer_size = uniform_max_size; + } else { + giprobe_buffer_size = 65536; + } + + giprobe_buffer_size = MIN(sizeof(GIProbeData) * gi_probe_get_slots().size(), giprobe_buffer_size); + scene_state.max_gi_probes = giprobe_buffer_size / sizeof(GIProbeData); + scene_state.gi_probes = memnew_arr(GIProbeData, scene_state.max_gi_probes); + scene_state.gi_probe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * scene_state.max_gi_probes); + defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n"; + } + + Vector shader_versions; + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n#define MODE_RENDER_ROUGHNESS\n"); + shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); + shader_versions.push_back(""); + shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); + shader_versions.push_back("\n#define USE_VOXEL_CONE_TRACING\n"); + shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_VOXEL_CONE_TRACING\n"); + shader_versions.push_back("\n#define USE_LIGHTMAP\n"); + shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); + shader.scene_shader.initialize(shader_versions, defines); + } + + storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_shader_funcs); + storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_material_funcs); + + { + //shader compiler + ShaderCompilerRD::DefaultIdentifierActions actions; + + actions.renames["WORLD_MATRIX"] = "world_matrix"; + actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; + actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; + actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; + actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; + actions.renames["MODELVIEW_MATRIX"] = "modelview"; + actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; + + actions.renames["VERTEX"] = "vertex"; + actions.renames["NORMAL"] = "normal"; + actions.renames["TANGENT"] = "tangent"; + actions.renames["BINORMAL"] = "binormal"; + actions.renames["POSITION"] = "position"; + actions.renames["UV"] = "uv_interp"; + actions.renames["UV2"] = "uv2_interp"; + actions.renames["COLOR"] = "color_interp"; + actions.renames["POINT_SIZE"] = "gl_PointSize"; + actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; + + //builtins + + actions.renames["TIME"] = "scene_data.time"; + actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size"; + + actions.renames["FRAGCOORD"] = "gl_FragCoord"; + actions.renames["FRONT_FACING"] = "gl_FrontFacing"; + actions.renames["NORMALMAP"] = "normalmap"; + actions.renames["NORMALMAP_DEPTH"] = "normaldepth"; + actions.renames["ALBEDO"] = "albedo"; + actions.renames["ALPHA"] = "alpha"; + actions.renames["METALLIC"] = "metallic"; + actions.renames["SPECULAR"] = "specular"; + actions.renames["ROUGHNESS"] = "roughness"; + actions.renames["RIM"] = "rim"; + actions.renames["RIM_TINT"] = "rim_tint"; + actions.renames["CLEARCOAT"] = "clearcoat"; + actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions.renames["ANISOTROPY"] = "anisotropy"; + actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; + actions.renames["SSS_STRENGTH"] = "sss_strength"; + actions.renames["TRANSMISSION"] = "transmission"; + actions.renames["AO"] = "ao"; + actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; + actions.renames["EMISSION"] = "emission"; + actions.renames["POINT_COORD"] = "gl_PointCoord"; + actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; + actions.renames["SCREEN_UV"] = "screen_uv"; + actions.renames["SCREEN_TEXTURE"] = "color_buffer"; + actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; + actions.renames["NORMAL_TEXTURE"] = "normal_buffer"; + actions.renames["DEPTH"] = "gl_FragDepth"; + actions.renames["OUTPUT_IS_SRGB"] = "true"; + + //for light + actions.renames["VIEW"] = "view"; + actions.renames["LIGHT_COLOR"] = "light_color"; + actions.renames["LIGHT"] = "light"; + actions.renames["ATTENUATION"] = "attenuation"; + actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; + actions.renames["SPECULAR_LIGHT"] = "specular_light"; + + actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; + actions.usage_defines["BINORMAL"] = "@TANGENT"; + actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; + actions.usage_defines["RIM_TINT"] = "@RIM"; + actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; + actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; + actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; + actions.usage_defines["AO"] = "#define AO_USED\n"; + actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n"; + actions.usage_defines["UV"] = "#define UV_USED\n"; + actions.usage_defines["UV2"] = "#define UV2_USED\n"; + actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; + actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; + actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; + actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; + actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; + + actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; + actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n"; + actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + + actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + + actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; + actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; + actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; + actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; + + bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); + + if (!force_lambert) { + actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; + } + + actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; + actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; + actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; + + bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx"); + + if (!force_blinn) { + actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; + } else { + actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; + } + + actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; + actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; + actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; + actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; + actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; + actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; + actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; + actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; + + actions.sampler_array_name = "material_samplers"; + actions.base_texture_binding_index = 1; + actions.texture_layout_set = MATERIAL_UNIFORM_SET; + actions.base_uniform_string = "material."; + actions.base_varying_index = 10; + + actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; + actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; + + shader.compiler.initialize(actions); + } + + //render list + render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000); + render_list.init(); + render_pass = 0; + + { + + scene_state.max_instances = render_list.max_elements; + scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances); + scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances); + } + + scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); + + { + //default material and shader + default_shader = storage->shader_create(); + storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n"); + default_material = storage->material_create(); + storage->material_set_shader(default_material, default_shader); + + MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); + default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); + } + + { + + overdraw_material_shader = storage->shader_create(); + storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); + overdraw_material = storage->material_create(); + storage->material_set_shader(overdraw_material, overdraw_material_shader); + + wireframe_material_shader = storage->shader_create(); + storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }"); + wireframe_material = storage->material_create(); + storage->material_set_shader(wireframe_material, wireframe_material_shader); + } + + { + default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.ids.push_back(default_vec4_xform_buffer); + u.binding = 0; + uniforms.push_back(u); + + default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, TRANSFORMS_UNIFORM_SET); + } + { + + RD::SamplerState sampler; + sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler.enable_compare = true; + sampler.compare_op = RD::COMPARE_OP_LESS; + shadow_sampler = RD::get_singleton()->sampler_create(sampler); + } + + { + Vector uniforms; + + RD::Uniform u; + u.binding = 0; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); + u.ids.push_back(texture); + uniforms.push_back(u); + + default_radiance_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RADIANCE_UNIFORM_SET); + } + + { //render buffers + Vector uniforms; + for (int i = 0; i < 5; i++) { + RD::Uniform u; + u.binding = i; + u.type = RD::UNIFORM_TYPE_TEXTURE; + RID texture = storage->texture_rd_get_default(i == 0 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE : (i == 2 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL : RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); + u.ids.push_back(texture); + uniforms.push_back(u); + } + + default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); + } + + cluster_builder.setup(16, 8, 24); +} + +RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { + directional_shadow_atlas_set_size(0); + + //clear base uniform set if still valid + if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { + RD::get_singleton()->free(view_dependant_uniform_set); + } + + RD::get_singleton()->free(default_render_buffers_uniform_set); + RD::get_singleton()->free(default_radiance_uniform_set); + RD::get_singleton()->free(default_vec4_xform_buffer); + RD::get_singleton()->free(shadow_sampler); + + storage->free(wireframe_material_shader); + storage->free(overdraw_material_shader); + storage->free(default_shader); + + storage->free(wireframe_material); + storage->free(overdraw_material); + storage->free(default_material); + + { + RD::get_singleton()->free(scene_state.uniform_buffer); + RD::get_singleton()->free(scene_state.instance_buffer); + RD::get_singleton()->free(scene_state.gi_probe_buffer); + RD::get_singleton()->free(scene_state.directional_light_buffer); + RD::get_singleton()->free(scene_state.light_buffer); + RD::get_singleton()->free(scene_state.reflection_buffer); + memdelete_arr(scene_state.instances); + memdelete_arr(scene_state.gi_probes); + memdelete_arr(scene_state.directional_lights); + memdelete_arr(scene_state.lights); + memdelete_arr(scene_state.reflections); + } +} diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h new file mode 100644 index 0000000000..4c3422cedb --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_high_end_rd.h @@ -0,0 +1,585 @@ +/*************************************************************************/ +/* rasterizer_scene_high_end_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_SCENE_HIGHEND_RD_H +#define RASTERIZER_SCENE_HIGHEND_RD_H + +#include "servers/rendering/rasterizer_rd/light_cluster_builder.h" +#include "servers/rendering/rasterizer_rd/rasterizer_scene_rd.h" +#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl.gen.h" + +class RasterizerSceneHighEndRD : public RasterizerSceneRD { + + enum { + SCENE_UNIFORM_SET = 0, + RADIANCE_UNIFORM_SET = 1, + VIEW_DEPENDANT_UNIFORM_SET = 2, + RENDER_BUFFERS_UNIFORM_SET = 3, + TRANSFORMS_UNIFORM_SET = 4, + MATERIAL_UNIFORM_SET = 5 + }; + + /* Scene Shader */ + + enum ShaderVersion { + SHADER_VERSION_DEPTH_PASS, + SHADER_VERSION_DEPTH_PASS_DP, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL, + SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, + SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, + SHADER_VERSION_COLOR_PASS, + SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_VCT_COLOR_PASS, + SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_LIGHTMAP_COLOR_PASS, + SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, + SHADER_VERSION_MAX + }; + + struct { + SceneHighEndShaderRD scene_shader; + ShaderCompilerRD compiler; + } shader; + + RasterizerStorageRD *storage; + + /* Material */ + + struct ShaderData : public RasterizerStorageRD::ShaderData { + + enum BlendMode { //used internally + BLEND_MODE_MIX, + BLEND_MODE_ADD, + BLEND_MODE_SUB, + BLEND_MODE_MUL, + }; + + enum DepthDraw { + DEPTH_DRAW_DISABLED, + DEPTH_DRAW_OPAQUE, + DEPTH_DRAW_ALWAYS + }; + + enum DepthTest { + DEPTH_TEST_DISABLED, + DEPTH_TEST_ENABLED + }; + + enum Cull { + CULL_DISABLED, + CULL_FRONT, + CULL_BACK + }; + + enum CullVariant { + CULL_VARIANT_NORMAL, + CULL_VARIANT_REVERSED, + CULL_VARIANT_DOUBLE_SIDED, + CULL_VARIANT_MAX + + }; + + bool valid; + RID version; + uint32_t vertex_input_mask; + RenderPipelineVertexFormatCacheRD pipelines[CULL_VARIANT_MAX][RS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; + + String path; + + Map uniforms; + Vector texture_uniforms; + + Vector ubo_offsets; + uint32_t ubo_size; + + String code; + Map default_texture_params; + + DepthDraw depth_draw; + DepthTest depth_test; + + bool uses_point_size; + bool uses_alpha; + bool uses_blend_alpha; + bool uses_depth_pre_pass; + bool uses_discard; + bool uses_roughness; + bool uses_normal; + + bool unshaded; + bool uses_vertex; + bool uses_sss; + bool uses_screen_texture; + bool uses_depth_texture; + bool uses_normal_texture; + bool uses_time; + bool writes_modelview_or_projection; + bool uses_world_coordinates; + + uint64_t last_pass = 0; + uint32_t index = 0; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void get_param_list(List *p_param_list) const; + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + ShaderData(); + virtual ~ShaderData(); + }; + + RasterizerStorageRD::ShaderData *_create_shader_func(); + static RasterizerStorageRD::ShaderData *_create_shader_funcs() { + return static_cast(singleton)->_create_shader_func(); + } + + struct MaterialData : public RasterizerStorageRD::MaterialData { + uint64_t last_frame; + ShaderData *shader_data; + RID uniform_buffer; + RID uniform_set; + Vector texture_cache; + Vector ubo_data; + uint64_t last_pass = 0; + uint32_t index = 0; + RID next_pass; + uint8_t priority; + virtual void set_render_priority(int p_priority); + virtual void set_next_pass(RID p_pass); + virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~MaterialData(); + }; + + RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); + static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { + return static_cast(singleton)->_create_material_func(static_cast(p_shader)); + } + + /* Push Constant */ + + struct PushConstant { + uint32_t index; + uint32_t pad[3]; + }; + + /* Framebuffer */ + + struct RenderBufferDataHighEnd : public RenderBufferData { + //for rendering, may be MSAAd + RID color; + RID depth; + RID specular; + RID normal_buffer; + RID roughness_buffer; + RID depth_fb; + RID depth_normal_fb; + RID depth_normal_roughness_fb; + RID color_fb; + RID color_specular_fb; + int width, height; + + void ensure_specular(); + void clear(); + virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa); + + RID uniform_set; + + ~RenderBufferDataHighEnd(); + }; + + virtual RenderBufferData *_create_render_buffer_data(); + void _allocate_normal_texture(RenderBufferDataHighEnd *rb); + void _allocate_roughness_texture(RenderBufferDataHighEnd *rb); + + RID shadow_sampler; + RID render_base_uniform_set; + RID view_dependant_uniform_set; + + virtual void _base_uniforms_changed(); + void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); + virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); + virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers); + virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); + + void _update_render_base_uniform_set(); + void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas); + void _update_render_buffers_uniform_set(RID p_render_buffers); + + /* Scene State UBO */ + + struct ReflectionData { //should always be 128 bytes + float box_extents[3]; + float index; + float box_offset[3]; + uint32_t mask; + float params[4]; // intensity, 0, interior , boxproject + float ambient[4]; // ambient color, energy + float local_matrix[16]; // up to here for spot and omni, rest is for directional + }; + + struct LightData { + float position[3]; + float inv_radius; + float direction[3]; + uint16_t attenuation_energy[2]; //16 bits attenuation, then energy + uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm) + uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float) + uint32_t mask; + uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm) + float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv + float shadow_matrix[16]; + }; + + struct DirectionalLightData { + + float direction[3]; + float energy; + float color[3]; + float specular; + float shadow_color[3]; + uint32_t mask; + uint32_t blend_splits; + uint32_t shadow_enabled; + float fade_from; + float fade_to; + float shadow_split_offsets[4]; + float shadow_matrices[4][16]; + }; + + struct GIProbeData { + float xform[16]; + float bounds[3]; + float dynamic_range; + + float bias; + float normal_bias; + uint32_t blend_ambient; + uint32_t texture_slot; + + float anisotropy_strength; + float ao; + float ao_size; + uint32_t pad[1]; + }; + + enum { + INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, + INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, + INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, + INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16, + INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7, + INSTANCE_DATA_FLAG_SKELETON = 1 << 19, + }; + + struct InstanceData { + float transform[16]; + float normal_transform[16]; + uint32_t flags; + uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer + uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap) + uint32_t mask; + }; + + struct SceneState { + struct UBO { + float projection_matrix[16]; + float inv_projection_matrix[16]; + + float camera_matrix[16]; + float inv_camera_matrix[16]; + + float viewport_size[2]; + float screen_pixel_size[2]; + + float shadow_z_offset; + float shadow_z_slope_scale; + + float time; + float reflection_multiplier; + + float ambient_light_color_energy[4]; + + float ambient_color_sky_mix; + uint32_t use_ambient_light; + uint32_t use_ambient_cubemap; + uint32_t use_reflection_cubemap; + + float radiance_inverse_xform[12]; + + float shadow_atlas_pixel_size[2]; + float directional_shadow_pixel_size[2]; + + uint32_t directional_light_count; + float dual_paraboloid_side; + float z_far; + float z_near; + + uint32_t ssao_enabled; + float ssao_light_affect; + float ssao_ao_affect; + uint32_t roughness_limiter_enabled; + + float ao_color[4]; + }; + + UBO ubo; + + RID uniform_buffer; + + ReflectionData *reflections; + uint32_t max_reflections; + RID reflection_buffer; + uint32_t max_reflection_probes_per_instance; + + GIProbeData *gi_probes; + uint32_t max_gi_probes; + RID gi_probe_buffer; + uint32_t max_gi_probe_probes_per_instance; + + LightData *lights; + uint32_t max_lights; + RID light_buffer; + + DirectionalLightData *directional_lights; + uint32_t max_directional_lights; + RID directional_light_buffer; + + RID instance_buffer; + InstanceData *instances; + uint32_t max_instances; + + bool used_screen_texture = false; + bool used_normal_texture = false; + bool used_depth_texture = false; + bool used_sss = false; + uint32_t current_shader_index = 0; + uint32_t current_material_index = 0; + } scene_state; + + /* Render List */ + + struct RenderList { + + int max_elements; + + struct Element { + RasterizerScene::InstanceBase *instance; + MaterialData *material; + union { + struct { + //from least significant to most significant in sort, TODO: should be endian swapped on big endian + uint64_t geometry_index : 20; + uint64_t material_index : 15; + uint64_t shader_index : 12; + uint64_t uses_instancing : 1; + uint64_t uses_vct : 1; + uint64_t uses_lightmap : 1; + uint64_t depth_layer : 4; + uint64_t priority : 8; + }; + + uint64_t sort_key; + }; + uint32_t surface_index; + }; + + Element *base_elements; + Element **elements; + + int element_count; + int alpha_element_count; + + void clear() { + + element_count = 0; + alpha_element_count = 0; + } + + //should eventually be replaced by radix + + struct SortByKey { + + _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { + return A->sort_key < B->sort_key; + } + }; + + void sort_by_key(bool p_alpha) { + + SortArray sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); + } else { + sorter.sort(elements, element_count); + } + } + + struct SortByDepth { + + _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { + return A->instance->depth < B->instance->depth; + } + }; + + void sort_by_depth(bool p_alpha) { //used for shadows + + SortArray sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); + } else { + sorter.sort(elements, element_count); + } + } + + struct SortByReverseDepthAndPriority { + + _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { + uint32_t layer_A = uint32_t(A->priority); + uint32_t layer_B = uint32_t(B->priority); + if (layer_A == layer_B) { + return A->instance->depth > B->instance->depth; + } else { + return layer_A < layer_B; + } + } + }; + + void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha + + SortArray sorter; + if (p_alpha) { + sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); + } else { + sorter.sort(elements, element_count); + } + } + + _FORCE_INLINE_ Element *add_element() { + + if (element_count + alpha_element_count >= max_elements) + return NULL; + elements[element_count] = &base_elements[element_count]; + return elements[element_count++]; + } + + _FORCE_INLINE_ Element *add_alpha_element() { + + if (element_count + alpha_element_count >= max_elements) + return NULL; + int idx = max_elements - alpha_element_count - 1; + elements[idx] = &base_elements[idx]; + alpha_element_count++; + return elements[idx]; + } + + void init() { + + element_count = 0; + alpha_element_count = 0; + elements = memnew_arr(Element *, max_elements); + base_elements = memnew_arr(Element, max_elements); + for (int i = 0; i < max_elements; i++) + elements[i] = &base_elements[i]; // assign elements + } + + RenderList() { + + max_elements = 0; + } + + ~RenderList() { + memdelete_arr(elements); + memdelete_arr(base_elements); + } + }; + + RenderList render_list; + + static RasterizerSceneHighEndRD *singleton; + uint64_t render_pass; + double time; + RID default_shader; + RID default_material; + RID overdraw_material_shader; + RID overdraw_material; + RID wireframe_material_shader; + RID wireframe_material; + RID default_shader_rd; + RID default_radiance_uniform_set; + RID default_render_buffers_uniform_set; + + RID default_vec4_xform_buffer; + RID default_vec4_xform_uniform_set; + + LightClusterBuilder cluster_builder; + + enum PassMode { + PASS_MODE_COLOR, + PASS_MODE_COLOR_SPECULAR, + PASS_MODE_COLOR_TRANSPARENT, + PASS_MODE_SHADOW, + PASS_MODE_SHADOW_DP, + PASS_MODE_DEPTH, + PASS_MODE_DEPTH_NORMAL, + PASS_MODE_DEPTH_NORMAL_ROUGHNESS, + PASS_MODE_DEPTH_MATERIAL, + }; + + void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false); + void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows); + void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment); + void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform); + + void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth); + void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set); + _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index); + _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index); + + void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi); + +protected: + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color); + virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip); + virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); + +public: + virtual void set_time(double p_time, double p_step); + + virtual bool free(RID p_rid); + + RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage); + ~RasterizerSceneHighEndRD(); +}; +#endif // RASTERIZER_SCENE_HIGHEND_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp new file mode 100644 index 0000000000..842f7046c9 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.cpp @@ -0,0 +1,4039 @@ +/*************************************************************************/ +/* rasterizer_scene_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer_scene_rd.h" + +#include "core/os/os.h" +#include "core/project_settings.h" +#include "servers/rendering/rendering_server_raster.h" + +uint64_t RasterizerSceneRD::auto_exposure_counter = 2; + +void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) { + + rd.layers.clear(); + rd.radiance_base_cubemap = RID(); + if (rd.downsampled_radiance_cubemap.is_valid()) { + RD::get_singleton()->free(rd.downsampled_radiance_cubemap); + } + rd.downsampled_radiance_cubemap = RID(); + rd.downsampled_layer.mipmaps.clear(); + rd.coefficient_buffer = RID(); +} + +void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality) { + //recreate radiance and all data + + int mipmaps = p_mipmaps; + uint32_t w = p_size, h = p_size; + + if (p_use_array) { + int layers = p_low_quality ? 8 : roughness_layers; + + for (int i = 0; i < layers; i++) { + ReflectionData::Layer layer; + uint32_t mmw = w; + uint32_t mmh = h; + layer.mipmaps.resize(mipmaps); + layer.views.resize(mipmaps); + for (int j = 0; j < mipmaps; j++) { + ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j]; + mm.size.width = mmw; + mm.size.height = mmh; + for (int k = 0; k < 6; k++) { + mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6 + k, j); + Vector fbtex; + fbtex.push_back(mm.views[k]); + mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex); + } + + layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, RD::TEXTURE_SLICE_CUBEMAP); + + mmw = MAX(1, mmw >> 1); + mmh = MAX(1, mmh >> 1); + } + + rd.layers.push_back(layer); + } + + } else { + mipmaps = p_low_quality ? 8 : mipmaps; + //regular cubemap, lower quality (aliasing, less memory) + ReflectionData::Layer layer; + uint32_t mmw = w; + uint32_t mmh = h; + layer.mipmaps.resize(mipmaps); + layer.views.resize(mipmaps); + for (int j = 0; j < mipmaps; j++) { + ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j]; + mm.size.width = mmw; + mm.size.height = mmh; + for (int k = 0; k < 6; k++) { + mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + k, j); + Vector fbtex; + fbtex.push_back(mm.views[k]); + mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex); + } + + layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, RD::TEXTURE_SLICE_CUBEMAP); + + mmw = MAX(1, mmw >> 1); + mmh = MAX(1, mmh >> 1); + } + + rd.layers.push_back(layer); + } + + rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = 64; // Always 64x64 + tf.height = 64; + tf.type = RD::TEXTURE_TYPE_CUBE; + tf.array_layers = 6; + tf.mipmaps = 7; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rd.downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); + { + uint32_t mmw = 64; + uint32_t mmh = 64; + rd.downsampled_layer.mipmaps.resize(7); + for (int j = 0; j < rd.downsampled_layer.mipmaps.size(); j++) { + ReflectionData::DownsampleLayer::Mipmap &mm = rd.downsampled_layer.mipmaps.write[j]; + mm.size.width = mmw; + mm.size.height = mmh; + mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP); + + mmw = MAX(1, mmw >> 1); + mmh = MAX(1, mmh >> 1); + } + } +} + +void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) { + + storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size); + + for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) { + storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size); + } + + Vector views; + if (p_use_arrays) { + for (int i = 1; i < rd.layers.size(); i++) { + views.push_back(rd.layers[i].views[0]); + } + } else { + for (int i = 1; i < rd.layers[0].views.size(); i++) { + views.push_back(rd.layers[0].views[i]); + } + } + + storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, p_use_arrays); +} + +void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) { + + if (p_use_arrays) { + + //render directly to the layers + storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x); + } else { + + storage->get_effects()->cubemap_roughness(rd.layers[0].views[p_base_layer - 1], rd.layers[0].views[p_base_layer], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[p_base_layer].size.x); + } +} + +void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) { + + if (sky_use_cubemap_array) { + + for (int i = 0; i < rd.layers.size(); i++) { + for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) { + for (int k = 0; k < 6; k++) { + RID view = rd.layers[i].mipmaps[j].views[k]; + RID fb = rd.layers[i].mipmaps[j + 1].framebuffers[k]; + Vector2 size = rd.layers[i].mipmaps[j].size; + size = Vector2(1.0 / size.x, 1.0 / size.y); + storage->get_effects()->make_mipmap(view, fb, size); + } + } + } + } +} + +RID RasterizerSceneRD::sky_create() { + return sky_owner.make_rid(Sky()); +} + +void RasterizerSceneRD::_sky_invalidate(Sky *p_sky) { + if (!p_sky->dirty) { + p_sky->dirty = true; + p_sky->dirty_list = dirty_sky_list; + dirty_sky_list = p_sky; + } +} + +void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); + ERR_FAIL_COND(p_radiance_size < 32 || p_radiance_size > 2048); + if (sky->radiance_size == p_radiance_size) { + return; + } + sky->radiance_size = p_radiance_size; + + if (sky->mode == RS::SKY_MODE_REALTIME && sky->radiance_size != 256) { + WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally."); + sky->radiance_size = 256; + } + + _sky_invalidate(sky); + if (sky->radiance.is_valid()) { + RD::get_singleton()->free(sky->radiance); + sky->radiance = RID(); + } + _clear_reflection_data(sky->reflection); +} + +void RasterizerSceneRD::sky_set_mode(RID p_sky, RS::SkyMode p_mode) { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); + + if (sky->mode == p_mode) { + return; + } + + sky->mode = p_mode; + + if (sky->mode == RS::SKY_MODE_REALTIME && sky->radiance_size != 256) { + WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally."); + sky_set_radiance_size(p_sky, 256); + } + + _sky_invalidate(sky); + if (sky->radiance.is_valid()) { + RD::get_singleton()->free(sky->radiance); + sky->radiance = RID(); + } + _clear_reflection_data(sky->reflection); +} + +void RasterizerSceneRD::sky_set_material(RID p_sky, RID p_material) { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND(!sky); + sky->material = p_material; +} +void RasterizerSceneRD::_update_dirty_skys() { + + Sky *sky = dirty_sky_list; + + while (sky) { + + bool texture_set_dirty = false; + //update sky configuration if texture is missing + + if (sky->radiance.is_null()) { + int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1; + + uint32_t w = sky->radiance_size, h = sky->radiance_size; + int layers = roughness_layers; + if (sky->mode == RS::SKY_MODE_REALTIME) { + layers = 8; + if (roughness_layers != 8) { + WARN_PRINT("When using REALTIME skies, roughness_layers should be set to 8 in the project settings for best quality reflections"); + } + } + + if (sky_use_cubemap_array) { + //array (higher quality, 6 times more memory) + RD::TextureFormat tf; + tf.array_layers = layers * 6; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tf.mipmaps = mipmaps; + tf.width = w; + tf.height = h; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + _update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME); + + } else { + //regular cubemap, lower quality (aliasing, less memory) + RD::TextureFormat tf; + tf.array_layers = 6; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.type = RD::TEXTURE_TYPE_CUBE; + tf.mipmaps = MIN(mipmaps, layers); + tf.width = w; + tf.height = h; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + _update_reflection_data(sky->reflection, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == RS::SKY_MODE_REALTIME); + } + texture_set_dirty = true; + } + + // Create subpass buffers if they havent been created already + if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tformat.width = sky->screen_size.x / 2; + tformat.height = sky->screen_size.y / 2; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tformat.type = RD::TEXTURE_TYPE_2D; + + sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + Vector texs; + texs.push_back(sky->half_res_pass); + sky->half_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); + texture_set_dirty = true; + } + + if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tformat.width = sky->screen_size.x / 4; + tformat.height = sky->screen_size.y / 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + tformat.type = RD::TEXTURE_TYPE_2D; + + sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); + Vector texs; + texs.push_back(sky->quarter_res_pass); + sky->quarter_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); + texture_set_dirty = true; + } + + if (texture_set_dirty) { + for (int i = 0; i < SKY_TEXTURE_SET_MAX; i++) { + if (sky->texture_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(sky->texture_uniform_sets[i])) { + RD::get_singleton()->free(sky->texture_uniform_sets[i]); + sky->texture_uniform_sets[i] = RID(); + } + } + } + + sky->reflection.dirty = true; + + Sky *next = sky->dirty_list; + sky->dirty_list = nullptr; + sky->dirty = false; + sky = next; + } + + dirty_sky_list = nullptr; +} + +RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND_V(!sky, RID()); + + return sky->radiance; +} + +RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND_V(!sky, RID()); + + if (sky->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->uniform_set)) { + + sky->uniform_set = RID(); + if (sky->radiance.is_valid()) { + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(sky->radiance); + uniforms.push_back(u); + } + + sky->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + } + + return sky->uniform_set; +} + +RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) { + + if (p_sky->texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(p_sky->texture_uniform_sets[p_version])) { + return p_sky->texture_uniform_sets[p_version]; + } + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + if (p_sky->radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { + u.ids.push_back(p_sky->radiance); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1; // half res + if (p_sky->half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { + if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + u.ids.push_back(p_sky->reflection.layers[0].views[1]); + } else { + u.ids.push_back(p_sky->half_res_pass); + } + } else { + if (p_version < SKY_TEXTURE_SET_CUBEMAP) { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + } + } + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; // quarter res + if (p_sky->quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { + if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { + u.ids.push_back(p_sky->reflection.layers[0].views[2]); + } else { + u.ids.push_back(p_sky->quarter_res_pass); + } + } else { + if (p_version < SKY_TEXTURE_SET_CUBEMAP) { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); + } else { + u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); + } + } + uniforms.push_back(u); + } + + p_sky->texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES); + return p_sky->texture_uniform_sets[p_version]; +} + +RID RasterizerSceneRD::sky_get_material(RID p_sky) const { + Sky *sky = sky_owner.getornull(p_sky); + ERR_FAIL_COND_V(!sky, RID()); + + return sky->material; +} + +void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { + + ERR_FAIL_COND(!is_environment(p_environment)); + + Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); + ERR_FAIL_COND(!sky); + + RID sky_material = sky_get_material(environment_get_sky(p_environment)); + + SkyMaterialData *material = NULL; + + if (sky_material.is_valid()) { + material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + if (!material || !material->shader_data->valid) { + material = NULL; + } + } + + if (!material) { + sky_material = sky_shader.default_material; + material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + } + + ERR_FAIL_COND(!material); + + SkyShaderData *shader_data = material->shader_data; + + ERR_FAIL_COND(!shader_data); + + Basis sky_transform = environment_get_sky_orientation(p_environment); + sky_transform.invert(); + + float multiplier = environment_get_bg_energy(p_environment); + float custom_fov = environment_get_sky_custom_fov(p_environment); + // Camera + CameraMatrix camera; + + if (custom_fov) { + + float near_plane = p_projection.get_z_near(); + float far_plane = p_projection.get_z_far(); + float aspect = p_projection.get_aspect(); + + camera.set_perspective(custom_fov, aspect, near_plane, far_plane); + + } else { + camera = p_projection; + } + + sky_transform = p_transform.basis * sky_transform; + + if (shader_data->uses_quarter_res) { + RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES]; + + RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_QUARTER_RES); + + Vector clear_colors; + clear_colors.push_back(Color(0.0, 0.0, 0.0)); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + storage->get_effects()->render_sky(draw_list, time, sky->quarter_res_framebuffer, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin); + RD::get_singleton()->draw_list_end(); + } + + if (shader_data->uses_half_res) { + RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES]; + + RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_HALF_RES); + + Vector clear_colors; + clear_colors.push_back(Color(0.0, 0.0, 0.0)); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); + storage->get_effects()->render_sky(draw_list, time, sky->half_res_framebuffer, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin); + RD::get_singleton()->draw_list_end(); + } + + RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND]; + + RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_BACKGROUND); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); + storage->get_effects()->render_sky(draw_list, time, p_fb, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin); + RD::get_singleton()->draw_list_end(); +} + +void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size) { + + ERR_FAIL_COND(!is_environment(p_environment)); + + Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); + ERR_FAIL_COND(!sky); + + RID sky_material = sky_get_material(environment_get_sky(p_environment)); + + SkyMaterialData *material = NULL; + + if (sky_material.is_valid()) { + material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + if (!material || !material->shader_data->valid) { + material = NULL; + } + } + + if (!material) { + sky_material = sky_shader.default_material; + material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + } + + ERR_FAIL_COND(!material); + + SkyShaderData *shader_data = material->shader_data; + + ERR_FAIL_COND(!shader_data); + + // Invalidate supbass buffers if screen size changes + if (sky->screen_size != p_screen_size) { + sky->screen_size = p_screen_size; + sky->screen_size.x = sky->screen_size.x < 4 ? 4 : sky->screen_size.x; + sky->screen_size.y = sky->screen_size.y < 4 ? 4 : sky->screen_size.y; + if (shader_data->uses_half_res) { + if (sky->half_res_pass.is_valid()) { + RD::get_singleton()->free(sky->half_res_pass); + sky->half_res_pass = RID(); + } + _sky_invalidate(sky); + } + if (shader_data->uses_quarter_res) { + if (sky->quarter_res_pass.is_valid()) { + RD::get_singleton()->free(sky->quarter_res_pass); + sky->quarter_res_pass = RID(); + } + _sky_invalidate(sky); + } + } + + // Create new subpass buffers if necessary + if ((shader_data->uses_half_res && sky->half_res_pass.is_null()) || + (shader_data->uses_quarter_res && sky->quarter_res_pass.is_null()) || + sky->radiance.is_null()) { + _sky_invalidate(sky); + _update_dirty_skys(); + } + + if (shader_data->uses_time && time - sky->prev_time > 0.00001) { + + sky->prev_time = time; + sky->reflection.dirty = true; + RenderingServerRaster::redraw_request(); + } + + if (material != sky->prev_material) { + + sky->prev_material = material; + sky->reflection.dirty = true; + } + + if (material->uniform_set_updated) { + + material->uniform_set_updated = false; + sky->reflection.dirty = true; + } + + if (!p_position.is_equal_approx(sky->prev_position) && shader_data->uses_position) { + + sky->prev_position = p_position; + sky->reflection.dirty = true; + } + + if (shader_data->uses_light || sky_scene_state.light_uniform_set.is_null()) { + // Check whether the directional_light_buffer changes + bool light_data_dirty = false; + + if (sky_scene_state.directional_light_count != sky_scene_state.last_frame_directional_light_count) { + light_data_dirty = true; + for (uint32_t i = sky_scene_state.directional_light_count; i < sky_scene_state.max_directional_lights; i++) { + sky_scene_state.directional_lights[i].enabled = false; + } + } + if (!light_data_dirty) { + for (uint32_t i = 0; i < sky_scene_state.directional_light_count; i++) { + if (sky_scene_state.directional_lights[i].direction[0] != sky_scene_state.last_frame_directional_lights[i].direction[0] || + sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] || + sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] || + sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy || + sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] || + sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] || + sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] || + sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled) { + light_data_dirty = true; + break; + } + } + } + + if (light_data_dirty || sky_scene_state.light_uniform_set.is_null()) { + + RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights, true); + + if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) { + RD::get_singleton()->free(sky_scene_state.light_uniform_set); + } + + Vector uniforms; + { + RD::Uniform u; + u.binding = 0; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.ids.push_back(sky_scene_state.directional_light_buffer); + uniforms.push_back(u); + } + + sky_scene_state.light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_LIGHTS); + + RasterizerSceneRD::SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights; + sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights; + sky_scene_state.directional_lights = temp; + sky_scene_state.last_frame_directional_light_count = sky_scene_state.directional_light_count; + sky->reflection.dirty = true; + } + } +} + +void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { + + ERR_FAIL_COND(!is_environment(p_environment)); + + Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); + ERR_FAIL_COND(!sky); + + RID sky_material = sky_get_material(environment_get_sky(p_environment)); + + SkyMaterialData *material = NULL; + + if (sky_material.is_valid()) { + material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + if (!material || !material->shader_data->valid) { + material = NULL; + } + } + + if (!material) { + sky_material = sky_shader.default_material; + material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); + } + + ERR_FAIL_COND(!material); + + SkyShaderData *shader_data = material->shader_data; + + ERR_FAIL_COND(!shader_data); + + float multiplier = environment_get_bg_energy(p_environment); + + // Update radiance cubemap + if (sky->reflection.dirty) { + + static const Vector3 view_normals[6] = { + Vector3(+1, 0, 0), + Vector3(-1, 0, 0), + Vector3(0, +1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1) + }; + static const Vector3 view_up[6] = { + Vector3(0, -1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1), + Vector3(0, -1, 0), + Vector3(0, -1, 0) + }; + + CameraMatrix cm; + cm.set_perspective(90, 1, 0.01, 10.0); + CameraMatrix correction; + correction.set_depth_correction(true); + cm = correction * cm; + + if (shader_data->uses_quarter_res) { + RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; + + Vector clear_colors; + clear_colors.push_back(Color(0.0, 0.0, 0.0)); + RD::DrawListID cubemap_draw_list; + + for (int i = 0; i < 6; i++) { + Transform local_view; + local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]); + RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES); + + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin); + RD::get_singleton()->draw_list_end(); + } + } + + if (shader_data->uses_half_res) { + RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES]; + + Vector clear_colors; + clear_colors.push_back(Color(0.0, 0.0, 0.0)); + RD::DrawListID cubemap_draw_list; + + for (int i = 0; i < 6; i++) { + Transform local_view; + local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]); + RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP_HALF_RES); + + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin); + RD::get_singleton()->draw_list_end(); + } + } + + RD::DrawListID cubemap_draw_list; + RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP]; + + for (int i = 0; i < 6; i++) { + Transform local_view; + local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]); + RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP); + + cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); + storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin); + RD::get_singleton()->draw_list_end(); + } + if (sky_use_cubemap_array) { + if (sky->mode == RS::SKY_MODE_QUALITY) { + for (int i = 1; i < sky->reflection.layers.size(); i++) { + _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i); + } + } else { + _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array); + } + + _update_reflection_mipmaps(sky->reflection); + } else { + if (sky->mode == RS::SKY_MODE_QUALITY) { + for (int i = 1; i < sky->reflection.layers[0].mipmaps.size(); i++) { + _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i); + } + } else { + _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array); + } + } + + sky->reflection.dirty = false; + } +} + +/* SKY SHADER */ + +void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) { + //compile + + code = p_code; + valid = false; + ubo_size = 0; + uniforms.clear(); + + if (code == String()) { + return; //just invalid, but no error + } + + ShaderCompilerRD::GeneratedCode gen_code; + ShaderCompilerRD::IdentifierActions actions; + + uses_time = false; + uses_half_res = false; + uses_quarter_res = false; + uses_position = false; + uses_light = false; + + actions.render_mode_flags["use_half_res_pass"] = &uses_half_res; + actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res; + + actions.usage_flag_pointers["TIME"] = &uses_time; + actions.usage_flag_pointers["POSITION"] = &uses_position; + actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light; + actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light; + + actions.uniforms = &uniforms; + + RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; + + Error err = scene_singleton->sky_shader.compiler.compile(RS::SHADER_SKY, code, &actions, path, gen_code); + + ERR_FAIL_COND(err != OK); + + if (version.is_null()) { + version = scene_singleton->sky_shader.shader.version_create(); + } + +#if 0 + print_line("**compiling shader:"); + print_line("**defines:\n"); + for (int i = 0; i < gen_code.defines.size(); i++) { + print_line(gen_code.defines[i]); + } + print_line("\n**uniforms:\n" + gen_code.uniforms); + // print_line("\n**vertex_globals:\n" + gen_code.vertex_global); + // print_line("\n**vertex_code:\n" + gen_code.vertex); + print_line("\n**fragment_globals:\n" + gen_code.fragment_global); + print_line("\n**fragment_code:\n" + gen_code.fragment); + print_line("\n**light_code:\n" + gen_code.light); +#endif + + scene_singleton->sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); + ERR_FAIL_COND(!scene_singleton->sky_shader.shader.version_is_valid(version)); + + ubo_size = gen_code.uniform_total_size; + ubo_offsets = gen_code.uniform_offsets; + texture_uniforms = gen_code.texture_uniforms; + + //update pipelines + + for (int i = 0; i < SKY_VERSION_MAX; i++) { + + RD::PipelineDepthStencilState depth_stencil_state; + depth_stencil_state.enable_depth_test = true; + depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; + + RID shader_variant = scene_singleton->sky_shader.shader.version_get_shader(version, i); + pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0); + } + + valid = true; +} + +void RasterizerSceneRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { + if (!p_texture.is_valid()) { + default_texture_params.erase(p_name); + } else { + default_texture_params[p_name] = p_texture; + } +} + +void RasterizerSceneRD::SkyShaderData::get_param_list(List *p_param_list) const { + + Map order; + + for (Map::Element *E = uniforms.front(); E; E = E->next()) { + + if (E->get().texture_order >= 0) { + order[E->get().texture_order + 100000] = E->key(); + } else { + order[E->get().order] = E->key(); + } + } + + for (Map::Element *E = order.front(); E; E = E->next()) { + + PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); + pi.name = E->get(); + p_param_list->push_back(pi); + } +} + +bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const { + if (!uniforms.has(p_param)) { + return false; + } + + return uniforms[p_param].texture_order >= 0; +} + +bool RasterizerSceneRD::SkyShaderData::is_animated() const { + return false; +} + +bool RasterizerSceneRD::SkyShaderData::casts_shadows() const { + return false; +} + +Variant RasterizerSceneRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { + if (uniforms.has(p_parameter)) { + ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; + Vector default_value = uniform.default_value; + return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); + } + return Variant(); +} + +RasterizerSceneRD::SkyShaderData::SkyShaderData() { + valid = false; +} + +RasterizerSceneRD::SkyShaderData::~SkyShaderData() { + RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; + ERR_FAIL_COND(!scene_singleton); + //pipeline variants will clear themselves if shader is gone + if (version.is_valid()) { + scene_singleton->sky_shader.shader.version_free(version); + } +} + +RasterizerStorageRD::ShaderData *RasterizerSceneRD::_create_sky_shader_func() { + SkyShaderData *shader_data = memnew(SkyShaderData); + return shader_data; +} + +void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { + + RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; + + uniform_set_updated = true; + + if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { + p_uniform_dirty = true; + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + uniform_buffer = RID(); + } + + ubo_data.resize(shader_data->ubo_size); + if (ubo_data.size()) { + uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); + memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear + } + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + //check whether buffer changed + if (p_uniform_dirty && ubo_data.size()) { + + update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); + RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); + } + + uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); + + if ((uint32_t)texture_cache.size() != tex_uniform_count) { + texture_cache.resize(tex_uniform_count); + p_textures_dirty = true; + + //clear previous uniform set + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + uniform_set = RID(); + } + } + + if (p_textures_dirty && tex_uniform_count) { + + update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); + } + + if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { + // This material does not require an uniform set, so don't create it. + return; + } + + if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + //no reason to update uniform set, only UBO (or nothing) was needed to update + return; + } + + Vector uniforms; + + { + + if (shader_data->ubo_size) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 0; + u.ids.push_back(uniform_buffer); + uniforms.push_back(u); + } + + const RID *textures = texture_cache.ptrw(); + for (uint32_t i = 0; i < tex_uniform_count; i++) { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 1 + i; + u.ids.push_back(textures[i]); + uniforms.push_back(u); + } + } + + uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); +} + +RasterizerSceneRD::SkyMaterialData::~SkyMaterialData() { + if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { + RD::get_singleton()->free(uniform_set); + } + + if (uniform_buffer.is_valid()) { + RD::get_singleton()->free(uniform_buffer); + } +} + +RasterizerStorageRD::MaterialData *RasterizerSceneRD::_create_sky_material_func(SkyShaderData *p_shader) { + SkyMaterialData *material_data = memnew(SkyMaterialData); + material_data->shader_data = p_shader; + material_data->last_frame = false; + //update will happen later anyway so do nothing. + return material_data; +} + +RID RasterizerSceneRD::environment_create() { + + return environment_owner.make_rid(Environent()); +} + +void RasterizerSceneRD::environment_set_background(RID p_env, RS::EnvironmentBG p_bg) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->background = p_bg; +} +void RasterizerSceneRD::environment_set_sky(RID p_env, RID p_sky) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->sky = p_sky; +} +void RasterizerSceneRD::environment_set_sky_custom_fov(RID p_env, float p_scale) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->sky_custom_fov = p_scale; +} +void RasterizerSceneRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->sky_orientation = p_orientation; +} +void RasterizerSceneRD::environment_set_bg_color(RID p_env, const Color &p_color) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->bg_color = p_color; +} +void RasterizerSceneRD::environment_set_bg_energy(RID p_env, float p_energy) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->bg_energy = p_energy; +} +void RasterizerSceneRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->canvas_max_layer = p_max_layer; +} +void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, RS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->ambient_light = p_color; + env->ambient_source = p_ambient; + env->ambient_light_energy = p_energy; + env->ambient_sky_contribution = p_sky_contribution; + env->reflection_source = p_reflection_source; + env->ao_color = p_ao_color; +} + +RS::EnvironmentBG RasterizerSceneRD::environment_get_background(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_BG_MAX); + return env->background; +} +RID RasterizerSceneRD::environment_get_sky(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, RID()); + return env->sky; +} +float RasterizerSceneRD::environment_get_sky_custom_fov(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->sky_custom_fov; +} +Basis RasterizerSceneRD::environment_get_sky_orientation(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Basis()); + return env->sky_orientation; +} +Color RasterizerSceneRD::environment_get_bg_color(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->bg_color; +} +float RasterizerSceneRD::environment_get_bg_energy(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->bg_energy; +} +int RasterizerSceneRD::environment_get_canvas_max_layer(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->canvas_max_layer; +} +Color RasterizerSceneRD::environment_get_ambient_light_color(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->ambient_light; +} +RS::EnvironmentAmbientSource RasterizerSceneRD::environment_get_ambient_light_ambient_source(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_AMBIENT_SOURCE_BG); + return env->ambient_source; +} +float RasterizerSceneRD::environment_get_ambient_light_ambient_energy(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->ambient_light_energy; +} +float RasterizerSceneRD::environment_get_ambient_sky_contribution(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, 0); + return env->ambient_sky_contribution; +} +RS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_source(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, RS::ENV_REFLECTION_SOURCE_DISABLED); + return env->reflection_source; +} + +Color RasterizerSceneRD::environment_get_ao_color(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, Color()); + return env->ao_color; +} + +void RasterizerSceneRD::environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->exposure = p_exposure; + env->tone_mapper = p_tone_mapper; + if (!env->auto_exposure && p_auto_exposure) { + env->auto_exposure_version = ++auto_exposure_counter; + } + env->auto_exposure = p_auto_exposure; + env->white = p_white; + env->min_luminance = p_min_luminance; + env->max_luminance = p_max_luminance; + env->auto_exp_speed = p_auto_exp_speed; + env->auto_exp_scale = p_auto_exp_scale; +} + +void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + env->glow_enabled = p_enable; + env->glow_levels = p_level_flags; + env->glow_intensity = p_intensity; + env->glow_strength = p_strength; + env->glow_mix = p_mix; + env->glow_bloom = p_bloom_threshold; + env->glow_blend_mode = p_blend_mode; + env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; + env->glow_hdr_bleed_scale = p_hdr_bleed_scale; + env->glow_hdr_luminance_cap = p_hdr_luminance_cap; + env->glow_bicubic_upscale = p_bicubic_upscale; +} + +void RasterizerSceneRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND(!env); + + env->ssao_enabled = p_enable; + env->ssao_radius = p_radius; + env->ssao_intensity = p_intensity; + env->ssao_bias = p_bias; + env->ssao_direct_light_affect = p_light_affect; + env->ssao_ao_channel_affect = p_ao_channel_affect; + env->ssao_blur = p_blur; +} + +void RasterizerSceneRD::environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size) { + ssao_quality = p_quality; + ssao_half_size = p_half_size; +} + +bool RasterizerSceneRD::environment_is_ssao_enabled(RID p_env) const { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_enabled; +} + +float RasterizerSceneRD::environment_get_ssao_ao_affect(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_ao_channel_affect; +} +float RasterizerSceneRD::environment_get_ssao_light_affect(RID p_env) const { + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return env->ssao_direct_light_affect; +} + +bool RasterizerSceneRD::environment_is_ssr_enabled(RID p_env) const { + + Environent *env = environment_owner.getornull(p_env); + ERR_FAIL_COND_V(!env, false); + return false; +} + +bool RasterizerSceneRD::is_environment(RID p_env) const { + return environment_owner.owns(p_env); +} + +//////////////////////////////////////////////////////////// + +RID RasterizerSceneRD::reflection_atlas_create() { + + ReflectionAtlas ra; + ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count"); + ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size"); + + return reflection_atlas_owner.make_rid(ra); +} + +void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { + + ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas); + ERR_FAIL_COND(!ra); + + if (ra->size == p_reflection_size && ra->count == p_reflection_count) { + return; //no changes + } + + ra->size = p_reflection_size; + ra->count = p_reflection_count; + + if (ra->reflection.is_valid()) { + //clear and invalidate everything + RD::get_singleton()->free(ra->reflection); + ra->reflection = RID(); + RD::get_singleton()->free(ra->depth_buffer); + ra->depth_buffer = RID(); + + for (int i = 0; i < ra->reflections.size(); i++) { + _clear_reflection_data(ra->reflections.write[i].data); + if (ra->reflections[i].owner.is_null()) { + continue; + } + reflection_probe_release_atlas_index(ra->reflections[i].owner); + //rp->atlasindex clear + } + + ra->reflections.clear(); + } +} + +//////////////////////// +RID RasterizerSceneRD::reflection_probe_instance_create(RID p_probe) { + ReflectionProbeInstance rpi; + rpi.probe = p_probe; + return reflection_probe_instance_owner.make_rid(rpi); +} + +void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!rpi); + + rpi->transform = p_transform; + rpi->dirty = true; +} + +void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!rpi); + + if (rpi->atlas.is_null()) { + return; //nothing to release + } + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); + ERR_FAIL_COND(!atlas); + ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size()); + atlas->reflections.write[rpi->atlas_index].owner = RID(); + rpi->atlas_index = -1; + rpi->atlas = RID(); +} + +bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, false); + + if (rpi->rendering) { + return false; + } + + if (rpi->dirty) { + return true; + } + + if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { + return true; + } + + return rpi->atlas_index == -1; +} + +bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, false); + + return rpi->atlas.is_valid(); +} + +bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { + + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas); + + ERR_FAIL_COND_V(!atlas, false); + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, false); + + if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) { + WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings."); + reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count); + } + + if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) { + // Invalidate reflection atlas, need to regenerate + RD::get_singleton()->free(atlas->reflection); + atlas->reflection = RID(); + + for (int i = 0; i < atlas->reflections.size(); i++) { + if (atlas->reflections[i].owner.is_null()) { + continue; + } + reflection_probe_release_atlas_index(atlas->reflections[i].owner); + } + + atlas->reflections.clear(); + } + + if (atlas->reflection.is_null()) { + int mipmaps = MIN(roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1); + mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering + { + //reflection atlas was unused, create: + RD::TextureFormat tf; + tf.array_layers = 6 * atlas->count; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + tf.mipmaps = mipmaps; + tf.width = atlas->size; + tf.height = atlas->size; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + + atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + { + + RD::TextureFormat tf; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + tf.width = atlas->size; + tf.height = atlas->size; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + atlas->reflections.resize(atlas->count); + for (int i = 0; i < atlas->count; i++) { + _update_reflection_data(atlas->reflections.write[i].data, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS); + for (int j = 0; j < 6; j++) { + Vector fb; + fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]); + fb.push_back(atlas->depth_buffer); + atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb); + } + } + + Vector fb; + fb.push_back(atlas->depth_buffer); + atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb); + } + + if (rpi->atlas_index == -1) { + for (int i = 0; i < atlas->reflections.size(); i++) { + if (atlas->reflections[i].owner.is_null()) { + rpi->atlas_index = i; + break; + } + } + //find the one used last + if (rpi->atlas_index == -1) { + //everything is in use, find the one least used via LRU + uint64_t pass_min = 0; + + for (int i = 0; i < atlas->reflections.size(); i++) { + ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.getornull(atlas->reflections[i].owner); + if (rpi2->last_pass < pass_min) { + pass_min = rpi2->last_pass; + rpi->atlas_index = i; + } + } + } + } + + rpi->atlas = p_reflection_atlas; + rpi->rendering = true; + rpi->dirty = false; + rpi->processing_layer = 1; + rpi->processing_side = 0; + + return true; +} + +bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) { + + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, false); + ERR_FAIL_COND_V(!rpi->rendering, false); + ERR_FAIL_COND_V(rpi->atlas.is_null(), false); + + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); + if (!atlas || rpi->atlas_index == -1) { + //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering) + rpi->rendering = false; + return false; + } + + if (storage->reflection_probe_get_update_mode(rpi->probe) == RS::REFLECTION_PROBE_UPDATE_ALWAYS) { + // Using real time reflections, all roughness is done in one step + _create_reflection_fast_filter(atlas->reflections.write[rpi->atlas_index].data, false); + rpi->rendering = false; + rpi->processing_side = 0; + rpi->processing_layer = 1; + return true; + } + + if (rpi->processing_layer > 1) { + _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, 10, rpi->processing_layer); + rpi->processing_layer++; + if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { + rpi->rendering = false; + rpi->processing_side = 0; + rpi->processing_layer = 1; + return true; + } + return false; + + } else { + _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, rpi->processing_side, rpi->processing_layer); + } + + rpi->processing_side++; + if (rpi->processing_side == 6) { + rpi->processing_side = 0; + rpi->processing_layer++; + } + + return false; +} + +uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, 0); + + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); + ERR_FAIL_COND_V(!atlas, 0); + return atlas->size; +} + +RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_INDEX_V(p_index, 6, RID()); + + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->reflections[rpi->atlas_index].fbs[p_index]; +} + +RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, RID()); + ERR_FAIL_INDEX_V(p_index, 6, RID()); + + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->depth_fb; +} + +/////////////////////////////////////////////////////////// + +RID RasterizerSceneRD::shadow_atlas_create() { + + return shadow_atlas_owner.make_rid(ShadowAtlas()); +} + +void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) { + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_COND(p_size < 0); + p_size = next_power_of_2(p_size); + + if (p_size == shadow_atlas->size) + return; + + // erasing atlas + if (shadow_atlas->depth.is_valid()) { + RD::get_singleton()->free(shadow_atlas->depth); + shadow_atlas->depth = RID(); + shadow_atlas->fb = RID(); + } + for (int i = 0; i < 4; i++) { + //clear subdivisions + shadow_atlas->quadrants[i].shadows.resize(0); + shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision); + } + + //erase shadow atlas reference from lights + for (Map::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) { + LightInstance *li = light_instance_owner.getornull(E->key()); + ERR_CONTINUE(!li); + li->shadow_atlases.erase(p_atlas); + } + + //clear owners + shadow_atlas->shadow_owners.clear(); + + shadow_atlas->size = p_size; + + if (shadow_atlas->size) { + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = shadow_atlas->size; + tf.height = shadow_atlas->size; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + Vector fb; + fb.push_back(shadow_atlas->depth); + shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb); + } +} + +void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_INDEX(p_quadrant, 4); + ERR_FAIL_INDEX(p_subdivision, 16384); + + uint32_t subdiv = next_power_of_2(p_subdivision); + if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer + subdiv <<= 1; + } + + subdiv = int(Math::sqrt((float)subdiv)); + + //obtain the number that will be x*x + + if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) + return; + + //erase all data from quadrant + for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) { + + if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) { + shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); + LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); + ERR_CONTINUE(!li); + li->shadow_atlases.erase(p_atlas); + } + } + + shadow_atlas->quadrants[p_quadrant].shadows.resize(0); + shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv); + shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; + + //cache the smallest subdiv (for faster allocation in light update) + + shadow_atlas->smallest_subdiv = 1 << 30; + + for (int i = 0; i < 4; i++) { + if (shadow_atlas->quadrants[i].subdivision) { + shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision); + } + } + + if (shadow_atlas->smallest_subdiv == 1 << 30) { + shadow_atlas->smallest_subdiv = 0; + } + + //resort the size orders, simple bublesort for 4 elements.. + + int swaps = 0; + do { + swaps = 0; + + for (int i = 0; i < 3; i++) { + if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) { + SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]); + swaps++; + } + } + } while (swaps > 0); +} + +bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { + + for (int i = p_quadrant_count - 1; i >= 0; i--) { + + int qidx = p_in_quadrants[i]; + + if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { + return false; + } + + //look for an empty space + int sc = shadow_atlas->quadrants[qidx].shadows.size(); + ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw(); + + int found_free_idx = -1; //found a free one + int found_used_idx = -1; //found existing one, must steal it + uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion) + + for (int j = 0; j < sc; j++) { + if (!sarr[j].owner.is_valid()) { + found_free_idx = j; + break; + } + + LightInstance *sli = light_instance_owner.getornull(sarr[j].owner); + ERR_CONTINUE(!sli); + + if (sli->last_scene_pass != scene_pass) { + + //was just allocated, don't kill it so soon, wait a bit.. + if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) + continue; + + if (found_used_idx == -1 || sli->last_scene_pass < min_pass) { + found_used_idx = j; + min_pass = sli->last_scene_pass; + } + } + } + + if (found_free_idx == -1 && found_used_idx == -1) + continue; //nothing found + + if (found_free_idx == -1 && found_used_idx != -1) { + found_free_idx = found_used_idx; + } + + r_quadrant = qidx; + r_shadow = found_free_idx; + + return true; + } + + return false; +} + +bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND_V(!shadow_atlas, false); + + LightInstance *li = light_instance_owner.getornull(p_light_intance); + ERR_FAIL_COND_V(!li, false); + + if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { + return false; + } + + uint32_t quad_size = shadow_atlas->size >> 1; + int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage)); + + int valid_quadrants[4]; + int valid_quadrant_count = 0; + int best_size = -1; //best size found + int best_subdiv = -1; //subdiv for the best size + + //find the quadrants this fits into, and the best possible size it can fit into + for (int i = 0; i < 4; i++) { + int q = shadow_atlas->size_order[i]; + int sd = shadow_atlas->quadrants[q].subdivision; + if (sd == 0) + continue; //unused + + int max_fit = quad_size / sd; + + if (best_size != -1 && max_fit > best_size) + break; //too large + + valid_quadrants[valid_quadrant_count++] = q; + best_subdiv = sd; + + if (max_fit >= desired_fit) { + best_size = max_fit; + } + } + + ERR_FAIL_COND_V(valid_quadrant_count == 0, false); + + uint64_t tick = OS::get_singleton()->get_ticks_msec(); + + //see if it already exists + + if (shadow_atlas->shadow_owners.has(p_light_intance)) { + //it does! + uint32_t key = shadow_atlas->shadow_owners[p_light_intance]; + uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; + uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; + + bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); + bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version; + + if (!should_realloc) { + shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; + //already existing, see if it should redraw or it's just OK + return should_redraw; + } + + int new_quadrant, new_shadow; + + //find a better place + if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) { + //found a better place! + ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; + if (sh->owner.is_valid()) { + //is taken, but is invalid, erasing it + shadow_atlas->shadow_owners.erase(sh->owner); + LightInstance *sli = light_instance_owner.getornull(sh->owner); + sli->shadow_atlases.erase(p_atlas); + } + + //erase previous + shadow_atlas->quadrants[q].shadows.write[s].version = 0; + shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); + + sh->owner = p_light_intance; + sh->alloc_tick = tick; + sh->version = p_light_version; + li->shadow_atlases.insert(p_atlas); + + //make new key + key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; + key |= new_shadow; + //update it in map + shadow_atlas->shadow_owners[p_light_intance] = key; + //make it dirty, as it should redraw anyway + return true; + } + + //no better place for this shadow found, keep current + + //already existing, see if it should redraw or it's just OK + + shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; + + return should_redraw; + } + + int new_quadrant, new_shadow; + + //find a better place + if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) { + //found a better place! + ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; + if (sh->owner.is_valid()) { + //is taken, but is invalid, erasing it + shadow_atlas->shadow_owners.erase(sh->owner); + LightInstance *sli = light_instance_owner.getornull(sh->owner); + sli->shadow_atlases.erase(p_atlas); + } + + sh->owner = p_light_intance; + sh->alloc_tick = tick; + sh->version = p_light_version; + li->shadow_atlases.insert(p_atlas); + + //make new key + uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; + key |= new_shadow; + //update it in map + shadow_atlas->shadow_owners[p_light_intance] = key; + //make it dirty, as it should redraw anyway + + return true; + } + + //no place to allocate this light, apologies + + return false; +} + +void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) { + + p_size = nearest_power_of_2_templated(p_size); + + if (directional_shadow.size == p_size) { + return; + } + + directional_shadow.size = p_size; + + if (directional_shadow.depth.is_valid()) { + RD::get_singleton()->free(directional_shadow.depth); + directional_shadow.depth = RID(); + directional_shadow.fb = RID(); + } + + if (p_size > 0) { + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = p_size; + tf.height = p_size; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + Vector fb; + fb.push_back(directional_shadow.depth); + directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb); + } + + _base_uniforms_changed(); +} + +void RasterizerSceneRD::set_directional_shadow_count(int p_count) { + + directional_shadow.light_count = p_count; + directional_shadow.current_light = 0; +} + +static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) { + + int split_h = 1; + int split_v = 1; + + while (split_h * split_v < p_shadow_count) { + if (split_h == split_v) { + split_h <<= 1; + } else { + split_v <<= 1; + } + } + + Rect2i rect(0, 0, p_size, p_size); + rect.size.width /= split_h; + rect.size.height /= split_v; + + rect.position.x = rect.size.width * (p_shadow_index % split_h); + rect.position.y = rect.size.height * (p_shadow_index / split_h); + + return rect; +} + +int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) { + + ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0); + + Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0); + + LightInstance *light_instance = light_instance_owner.getornull(p_light_intance); + ERR_FAIL_COND_V(!light_instance, 0); + + switch (storage->light_directional_get_shadow_mode(light_instance->light)) { + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: + break; //none + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: r.size.height /= 2; break; + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: r.size /= 2; break; + } + + return MAX(r.size.width, r.size.height); +} + +////////////////////////////////////////////////// + +RID RasterizerSceneRD::camera_effects_create() { + + return camera_effects_owner.make_rid(CameraEffects()); +} + +void RasterizerSceneRD::camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter) { + + dof_blur_quality = p_quality; + dof_blur_use_jitter = p_use_jitter; +} + +void RasterizerSceneRD::camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape) { + + dof_blur_bokeh_shape = p_shape; +} + +void RasterizerSceneRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) { + CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); + ERR_FAIL_COND(!camfx); + + camfx->dof_blur_far_enabled = p_far_enable; + camfx->dof_blur_far_distance = p_far_distance; + camfx->dof_blur_far_transition = p_far_transition; + + camfx->dof_blur_near_enabled = p_near_enable; + camfx->dof_blur_near_distance = p_near_distance; + camfx->dof_blur_near_transition = p_near_transition; + + camfx->dof_blur_amount = p_amount; +} + +void RasterizerSceneRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) { + + CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); + ERR_FAIL_COND(!camfx); + + camfx->override_exposure_enabled = p_enable; + camfx->override_exposure = p_exposure; +} + +RID RasterizerSceneRD::light_instance_create(RID p_light) { + + RID li = light_instance_owner.make_rid(LightInstance()); + + LightInstance *light_instance = light_instance_owner.getornull(li); + + light_instance->self = li; + light_instance->light = p_light; + light_instance->light_type = storage->light_get_type(p_light); + + return li; +} + +void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { + + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->transform = p_transform; +} + +void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) { + + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + + if (storage->light_get_type(light_instance->light) != RS::LIGHT_DIRECTIONAL) { + p_pass = 0; + } + + ERR_FAIL_INDEX(p_pass, 4); + + light_instance->shadow_transform[p_pass].camera = p_projection; + light_instance->shadow_transform[p_pass].transform = p_transform; + light_instance->shadow_transform[p_pass].farplane = p_far; + light_instance->shadow_transform[p_pass].split = p_split; + light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale; +} + +void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) { + + LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); + ERR_FAIL_COND(!light_instance); + + light_instance->last_scene_pass = scene_pass; +} + +RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_size) { + + if (!shadow_cubemaps.has(p_size)) { + + ShadowCubemap sc; + { + RD::TextureFormat tf; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + tf.width = p_size; + tf.height = p_size; + tf.type = RD::TEXTURE_TYPE_CUBE; + tf.array_layers = 6; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + for (int i = 0; i < 6; i++) { + RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0); + Vector fbtex; + fbtex.push_back(side_texture); + sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex); + } + + shadow_cubemaps[p_size] = sc; + } + + return &shadow_cubemaps[p_size]; +} + +RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p_size) { + + if (!shadow_maps.has(p_size)) { + + ShadowMap sm; + { + RD::TextureFormat tf; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + tf.width = p_size.width; + tf.height = p_size.height; + tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; + + sm.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + Vector fbtex; + fbtex.push_back(sm.depth); + sm.fb = RD::get_singleton()->framebuffer_create(fbtex); + + shadow_maps[p_size] = sm; + } + + return &shadow_maps[p_size]; +} +///////////////////////////////// + +RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) { + //find a free slot + int index = -1; + for (int i = 0; i < gi_probe_slots.size(); i++) { + if (gi_probe_slots[i] == RID()) { + index = i; + break; + } + } + + ERR_FAIL_COND_V(index == -1, RID()); + + GIProbeInstance gi_probe; + gi_probe.slot = index; + gi_probe.probe = p_base; + RID rid = gi_probe_instance_owner.make_rid(gi_probe); + gi_probe_slots.write[index] = rid; + + return rid; +} + +void RasterizerSceneRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { + + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->transform = p_xform; +} + +bool RasterizerSceneRD::gi_probe_needs_update(RID p_probe) const { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + ERR_FAIL_COND_V(!gi_probe, false); + + //return true; + return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe); +} + +void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) { + + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + ERR_FAIL_COND(!gi_probe); + + uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe); + + // (RE)CREATE IF NEEDED + + if (gi_probe->last_probe_data_version != data_version) { + //need to re-create everything + if (gi_probe->texture.is_valid()) { + RD::get_singleton()->free(gi_probe->texture); + if (gi_probe_use_anisotropy) { + RD::get_singleton()->free(gi_probe->anisotropy_r16[0]); + RD::get_singleton()->free(gi_probe->anisotropy_r16[1]); + } + RD::get_singleton()->free(gi_probe->write_buffer); + gi_probe->mipmaps.clear(); + } + + for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) { + RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture); + RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth); + } + + gi_probe->dynamic_maps.clear(); + + Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); + + if (octree_size != Vector3i()) { + //can create a 3D texture + Vector levels = storage->gi_probe_get_level_counts(gi_probe->probe); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tf.width = octree_size.x; + tf.height = octree_size.y; + tf.depth = octree_size.z; + tf.type = RD::TEXTURE_TYPE_3D; + tf.mipmaps = levels.size(); + + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + + gi_probe->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); + + if (gi_probe_use_anisotropy) { + tf.format = RD::DATA_FORMAT_R16_UINT; + tf.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT); + tf.shareable_formats.push_back(RD::DATA_FORMAT_R5G6B5_UNORM_PACK16); + + //need to create R16 first, else driver does not like the storage bit for compute.. + gi_probe->anisotropy_r16[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + gi_probe->anisotropy_r16[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_R5G6B5_UNORM_PACK16; + gi_probe->anisotropy[0] = RD::get_singleton()->texture_create_shared(tv, gi_probe->anisotropy_r16[0]); + gi_probe->anisotropy[1] = RD::get_singleton()->texture_create_shared(tv, gi_probe->anisotropy_r16[1]); + + RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); + RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); + } + + { + int total_elements = 0; + for (int i = 0; i < levels.size(); i++) { + total_elements += levels[i]; + } + + if (gi_probe_use_anisotropy) { + total_elements *= 6; + } + + gi_probe->write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16); + } + + for (int i = 0; i < levels.size(); i++) { + GIProbeInstance::Mipmap mipmap; + mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), gi_probe->texture, 0, i, RD::TEXTURE_SLICE_3D); + if (gi_probe_use_anisotropy) { + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_R16_UINT; + mipmap.anisotropy[0] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[0], 0, i, RD::TEXTURE_SLICE_3D); + mipmap.anisotropy[1] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[1], 0, i, RD::TEXTURE_SLICE_3D); + } + + mipmap.level = levels.size() - i - 1; + mipmap.cell_offset = 0; + for (uint32_t j = 0; j < mipmap.level; j++) { + mipmap.cell_offset += levels[j]; + } + mipmap.cell_count = levels[mipmap.level]; + + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.ids.push_back(storage->gi_probe_get_octree_buffer(gi_probe->probe)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe)); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 4; + u.ids.push_back(gi_probe->write_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 9; + u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 10; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + { + Vector copy_uniforms = uniforms; + if (i == 0) { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 3; + u.ids.push_back(gi_probe_lights_uniform); + copy_uniforms.push_back(u); + } + + mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0); + + copy_uniforms = uniforms; //restore + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 5; + u.ids.push_back(gi_probe->texture); + copy_uniforms.push_back(u); + } + + if (gi_probe_use_anisotropy) { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 7; + u.ids.push_back(gi_probe->anisotropy[0]); + copy_uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 8; + u.ids.push_back(gi_probe->anisotropy[1]); + copy_uniforms.push_back(u); + } + } + + mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0); + } else { + mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0); + } + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(mipmap.texture); + uniforms.push_back(u); + } + + if (gi_probe_use_anisotropy) { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 6; + u.ids.push_back(mipmap.anisotropy[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 7; + u.ids.push_back(mipmap.anisotropy[1]); + uniforms.push_back(u); + } + } + + mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0); + + gi_probe->mipmaps.push_back(mipmap); + } + + { + uint32_t dynamic_map_size = MAX(MAX(octree_size.x, octree_size.y), octree_size.z); + uint32_t oversample = nearest_power_of_2_templated(4); + int mipmap_index = 0; + + while (mipmap_index < gi_probe->mipmaps.size()) { + GIProbeInstance::DynamicMap dmap; + + if (oversample > 0) { + dmap.size = dynamic_map_size * (1 << oversample); + dmap.mipmap = -1; + oversample--; + } else { + dmap.size = dynamic_map_size >> mipmap_index; + dmap.mipmap = mipmap_index; + mipmap_index++; + } + + RD::TextureFormat dtf; + dtf.width = dmap.size; + dtf.height = dmap.size; + dtf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + + if (gi_probe->dynamic_maps.size() == 0) { + dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + } + dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + + if (gi_probe->dynamic_maps.size() == 0) { + //render depth for first one + dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; + dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + } + + //just use depth as-is + dtf.format = RD::DATA_FORMAT_R32_SFLOAT; + dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + + if (gi_probe->dynamic_maps.size() == 0) { + + dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView()); + + Vector fb; + fb.push_back(dmap.albedo); + fb.push_back(dmap.normal); + fb.push_back(dmap.orm); + fb.push_back(dmap.texture); //emission + fb.push_back(dmap.depth); + fb.push_back(dmap.fb_depth); + + dmap.fb = RD::get_singleton()->framebuffer_create(fb); + + { + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; + u.binding = 3; + u.ids.push_back(gi_probe_lights_uniform); + uniforms.push_back(u); + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(dmap.albedo); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 6; + u.ids.push_back(dmap.normal); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 7; + u.ids.push_back(dmap.orm); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 8; + u.ids.push_back(dmap.fb_depth); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 9; + u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 10; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 11; + u.ids.push_back(dmap.texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 12; + u.ids.push_back(dmap.depth); + uniforms.push_back(u); + } + + dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0); + } + } else { + bool plot = dmap.mipmap >= 0; + bool write = dmap.mipmap < (gi_probe->mipmaps.size() - 1); + + Vector uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 5; + u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 6; + u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].depth); + uniforms.push_back(u); + } + + if (write) { + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 7; + u.ids.push_back(dmap.texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 8; + u.ids.push_back(dmap.depth); + uniforms.push_back(u); + } + } + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 9; + u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 10; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + if (plot) { + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 11; + u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].texture); + uniforms.push_back(u); + } + if (gi_probe_is_anisotropic()) { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 12; + u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].anisotropy[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 13; + u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].anisotropy[1]); + uniforms.push_back(u); + } + } + } + + dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT], 0); + } + + gi_probe->dynamic_maps.push_back(dmap); + } + } + } + + gi_probe->last_probe_data_version = data_version; + p_update_light_instances = true; //just in case + + _base_uniforms_changed(); + } + + // UDPDATE TIME + + if (gi_probe->has_dynamic_object_data) { + //if it has dynamic object data, it needs to be cleared + RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); + if (gi_probe_is_anisotropic()) { + RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); + RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); + } + } + + uint32_t light_count = 0; + + if (p_update_light_instances || p_dynamic_object_count > 0) { + + light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size()); + + { + Transform to_cell = storage->gi_probe_get_to_cell_xform(gi_probe->probe); + Transform to_probe_xform = (gi_probe->transform * to_cell.affine_inverse()).affine_inverse(); + //update lights + + for (uint32_t i = 0; i < light_count; i++) { + GIProbeLight &l = gi_probe_lights[i]; + RID light_instance = p_light_instances[i]; + RID light = light_instance_get_base_light(light_instance); + + l.type = storage->light_get_type(light); + l.attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_ATTENUATION); + l.energy = storage->light_get_param(light, RS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, RS::LIGHT_PARAM_INDIRECT_ENERGY); + l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, RS::LIGHT_PARAM_RANGE), 0, 0)).length(); + Color color = storage->light_get_color(light).to_linear(); + l.color[0] = color.r; + l.color[1] = color.g; + l.color[2] = color.b; + + l.spot_angle_radians = Math::deg2rad(storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ANGLE)); + l.spot_attenuation = storage->light_get_param(light, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + Transform xform = light_instance_get_base_transform(light_instance); + + Vector3 pos = to_probe_xform.xform(xform.origin); + Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized(); + + l.position[0] = pos.x; + l.position[1] = pos.y; + l.position[2] = pos.z; + + l.direction[0] = dir.x; + l.direction[1] = dir.y; + l.direction[2] = dir.z; + + l.has_shadow = storage->light_has_shadow(light); + } + + RD::get_singleton()->buffer_update(gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi_probe_lights, true); + } + } + + if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_object_count) { + // PROCESS MIPMAPS + if (gi_probe->mipmaps.size()) { + //can update mipmaps + + Vector3i probe_size = storage->gi_probe_get_octree_size(gi_probe->probe); + + GIProbePushConstant push_constant; + + push_constant.limits[0] = probe_size.x; + push_constant.limits[1] = probe_size.y; + push_constant.limits[2] = probe_size.z; + push_constant.stack_size = gi_probe->mipmaps.size(); + push_constant.emission_scale = 1.0; + push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe); + push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); + push_constant.light_count = light_count; + push_constant.aniso_strength = storage->gi_probe_get_anisotropy_strength(gi_probe->probe); + + /* print_line("probe update to version " + itos(gi_probe->last_probe_version)); + print_line("propagation " + rtos(push_constant.propagation)); + print_line("dynrange " + rtos(push_constant.dynamic_range)); + */ + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + + int passes; + if (p_update_light_instances) { + passes = storage->gi_probe_is_using_two_bounces(gi_probe->probe) ? 2 : 1; + } else { + passes = 1; //only re-blitting is necessary + } + int wg_size = 64; + int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X); + + for (int pass = 0; pass < passes; pass++) { + + if (p_update_light_instances) { + + for (int i = 0; i < gi_probe->mipmaps.size(); i++) { + if (i == 0) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]); + } else if (i == 1) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]); + } + + if (pass == 1 || i > 0) { + RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done + } + if (pass == 0 || i > 0) { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].uniform_set, 0); + } else { + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].second_bounce_uniform_set, 0); + } + + push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset; + push_constant.cell_count = gi_probe->mipmaps[i].cell_count; + + int wg_todo = (gi_probe->mipmaps[i].cell_count - 1) / wg_size + 1; + while (wg_todo) { + int wg_count = MIN(wg_todo, wg_limit_x); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); + wg_todo -= wg_count; + push_constant.cell_offset += wg_count * wg_size; + } + } + + RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done + } + + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]); + + for (int i = 0; i < gi_probe->mipmaps.size(); i++) { + + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].write_uniform_set, 0); + + push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset; + push_constant.cell_count = gi_probe->mipmaps[i].cell_count; + + int wg_todo = (gi_probe->mipmaps[i].cell_count - 1) / wg_size + 1; + while (wg_todo) { + int wg_count = MIN(wg_todo, wg_limit_x); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); + wg_todo -= wg_count; + push_constant.cell_offset += wg_count * wg_size; + } + } + } + + RD::get_singleton()->compute_list_end(); + } + } + + gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again + + if (p_dynamic_object_count && gi_probe->dynamic_maps.size()) { + + Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); + int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z); + + Transform oversample_scale; + oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier)); + + Transform to_cell = oversample_scale * storage->gi_probe_get_to_cell_xform(gi_probe->probe); + Transform to_world_xform = gi_probe->transform * to_cell.affine_inverse(); + Transform to_probe_xform = to_world_xform.affine_inverse(); + + AABB probe_aabb(Vector3(), octree_size); + + //this could probably be better parallelized in compute.. + for (int i = 0; i < p_dynamic_object_count; i++) { + + InstanceBase *instance = p_dynamic_objects[i]; + //not used, so clear + instance->depth_layer = 0; + instance->depth = 0; + + //transform aabb to giprobe + AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb); + + //this needs to wrap to grid resolution to avoid jitter + //also extend margin a bit just in case + Vector3i begin = aabb.position - Vector3i(1, 1, 1); + Vector3i end = aabb.position + aabb.size + Vector3i(1, 1, 1); + + for (int j = 0; j < 3; j++) { + if ((end[j] - begin[j]) & 1) { + end[j]++; //for half extents split, it needs to be even + } + begin[j] = MAX(begin[j], 0); + end[j] = MIN(end[j], octree_size[j] * multiplier); + } + + //aabb = aabb.intersection(probe_aabb); //intersect + aabb.position = begin; + aabb.size = end - begin; + + //print_line("aabb: " + aabb); + + for (int j = 0; j < 6; j++) { + + //if (j != 0 && j != 3) { + // continue; + //} + static const Vector3 render_z[6] = { + Vector3(1, 0, 0), + Vector3(0, 1, 0), + Vector3(0, 0, 1), + Vector3(-1, 0, 0), + Vector3(0, -1, 0), + Vector3(0, 0, -1), + }; + static const Vector3 render_up[6] = { + Vector3(0, 1, 0), + Vector3(0, 0, 1), + Vector3(0, 1, 0), + Vector3(0, 1, 0), + Vector3(0, 0, 1), + Vector3(0, 1, 0), + }; + + Vector3 render_dir = render_z[j]; + Vector3 up_dir = render_up[j]; + + Vector3 center = aabb.position + aabb.size * 0.5; + Transform xform; + xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir); + + Vector3 x_dir = xform.basis.get_axis(0).abs(); + int x_axis = int(Vector3(0, 1, 2).dot(x_dir)); + Vector3 y_dir = xform.basis.get_axis(1).abs(); + int y_axis = int(Vector3(0, 1, 2).dot(y_dir)); + Vector3 z_dir = -xform.basis.get_axis(2); + int z_axis = int(Vector3(0, 1, 2).dot(z_dir.abs())); + + Rect2i rect(aabb.position[x_axis], aabb.position[y_axis], aabb.size[x_axis], aabb.size[y_axis]); + bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(0)) < 0); + bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(1)) < 0); + bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(2)) > 0); + + CameraMatrix cm; + cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); + + _render_material(to_world_xform * xform, cm, true, &instance, 1, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); + + GIProbeDynamicPushConstant push_constant; + zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant)); + push_constant.limits[0] = octree_size.x; + push_constant.limits[1] = octree_size.y; + push_constant.limits[2] = octree_size.z; + push_constant.light_count = p_light_instances.size(); + push_constant.x_dir[0] = x_dir[0]; + push_constant.x_dir[1] = x_dir[1]; + push_constant.x_dir[2] = x_dir[2]; + push_constant.y_dir[0] = y_dir[0]; + push_constant.y_dir[1] = y_dir[1]; + push_constant.y_dir[2] = y_dir[2]; + push_constant.z_dir[0] = z_dir[0]; + push_constant.z_dir[1] = z_dir[1]; + push_constant.z_dir[2] = z_dir[2]; + push_constant.z_base = xform.origin[z_axis]; + push_constant.z_sign = (z_flip ? -1.0 : 1.0); + push_constant.pos_multiplier = float(1.0) / multiplier; + push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); + push_constant.flip_x = x_flip; + push_constant.flip_y = y_flip; + push_constant.rect_pos[0] = rect.position[0]; + push_constant.rect_pos[1] = rect.position[1]; + push_constant.rect_size[0] = rect.size[0]; + push_constant.rect_size[1] = rect.size[1]; + push_constant.prev_rect_ofs[0] = 0; + push_constant.prev_rect_ofs[1] = 0; + push_constant.prev_rect_size[0] = 0; + push_constant.prev_rect_size[1] = 0; + push_constant.on_mipmap = false; + push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe); + push_constant.pad[0] = 0; + push_constant.pad[1] = 0; + push_constant.pad[2] = 0; + + //process lighting + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->dynamic_maps[0].uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); + //print_line("rect: " + itos(i) + ": " + rect); + + for (int k = 1; k < gi_probe->dynamic_maps.size(); k++) { + + // enlarge the rect if needed so all pixels fit when downscaled, + // this ensures downsampling is smooth and optimal because no pixels are left behind + + //x + if (rect.position.x & 1) { + rect.size.x++; + push_constant.prev_rect_ofs[0] = 1; //this is used to ensure reading is also optimal + } else { + push_constant.prev_rect_ofs[0] = 0; + } + if (rect.size.x & 1) { + rect.size.x++; + } + + rect.position.x >>= 1; + rect.size.x = MAX(1, rect.size.x >> 1); + + //y + if (rect.position.y & 1) { + rect.size.y++; + push_constant.prev_rect_ofs[1] = 1; + } else { + push_constant.prev_rect_ofs[1] = 0; + } + if (rect.size.y & 1) { + rect.size.y++; + } + + rect.position.y >>= 1; + rect.size.y = MAX(1, rect.size.y >> 1); + + //shrink limits to ensure plot does not go outside map + if (gi_probe->dynamic_maps[k].mipmap > 0) { + for (int l = 0; l < 3; l++) { + push_constant.limits[l] = MAX(1, push_constant.limits[l] >> 1); + } + } + + //print_line("rect: " + itos(i) + ": " + rect); + push_constant.rect_pos[0] = rect.position[0]; + push_constant.rect_pos[1] = rect.position[1]; + push_constant.prev_rect_size[0] = push_constant.rect_size[0]; + push_constant.prev_rect_size[1] = push_constant.rect_size[1]; + push_constant.rect_size[0] = rect.size[0]; + push_constant.rect_size[1] = rect.size[1]; + push_constant.on_mipmap = gi_probe->dynamic_maps[k].mipmap > 0; + + RD::get_singleton()->compute_list_add_barrier(compute_list); + + if (gi_probe->dynamic_maps[k].mipmap < 0) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]); + } else if (k < gi_probe->dynamic_maps.size() - 1) { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]); + } else { + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]); + } + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->dynamic_maps[k].uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant)); + RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); + } + + RD::get_singleton()->compute_list_end(); + } + } + + gi_probe->has_dynamic_object_data = true; //clear until dynamic object data is used again + } + + gi_probe->last_probe_version = storage->gi_probe_get_version(gi_probe->probe); +} + +void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + if (gi_probe->mipmaps.size() == 0) { + return; + } + + CameraMatrix transform = (p_camera_with_transform * CameraMatrix(gi_probe->transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(gi_probe->probe).affine_inverse()); + + int level = 0; + Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); + + GIProbeDebugPushConstant push_constant; + push_constant.alpha = p_alpha; + push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); + push_constant.cell_offset = gi_probe->mipmaps[level].cell_offset; + push_constant.level = level; + + push_constant.bounds[0] = octree_size.x >> level; + push_constant.bounds[1] = octree_size.y >> level; + push_constant.bounds[2] = octree_size.z >> level; + push_constant.pad = 0; + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + + push_constant.projection[i * 4 + j] = transform.matrix[i][j]; + } + } + + if (giprobe_debug_uniform_set.is_valid()) { + RD::get_singleton()->free(giprobe_debug_uniform_set); + } + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe)); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 2; + u.ids.push_back(gi_probe->texture); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 3; + u.ids.push_back(storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); + uniforms.push_back(u); + } + + if (gi_probe_use_anisotropy) { + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 4; + u.ids.push_back(gi_probe->anisotropy[0]); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 5; + u.ids.push_back(gi_probe->anisotropy[1]); + uniforms.push_back(u); + } + } + + int cell_count; + if (!p_emission && p_lighting && gi_probe->has_dynamic_object_data) { + cell_count = push_constant.bounds[0] * push_constant.bounds[1] * push_constant.bounds[2]; + } else { + cell_count = gi_probe->mipmaps[level].cell_count; + } + + giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0); + RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, giprobe_debug_shader_version_pipelines[p_emission ? GI_PROBE_DEBUG_EMISSION : p_lighting ? (gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT) : GI_PROBE_DEBUG_COLOR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0); + RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant)); + RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36); +} + +const Vector &RasterizerSceneRD::gi_probe_get_slots() const { + + return gi_probe_slots; +} + +RasterizerSceneRD::GIProbeQuality RasterizerSceneRD::gi_probe_get_quality() const { + return gi_probe_quality; +} + +//////////////////////////////// +RID RasterizerSceneRD::render_buffers_create() { + RenderBuffers rb; + rb.data = _create_render_buffer_data(); + return render_buffers_owner.make_rid(rb); +} + +void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) { + ERR_FAIL_COND(!rb->blur[0].texture.is_null()); + + uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = rb->width; + tf.height = rb->height; + tf.type = RD::TEXTURE_TYPE_2D; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.mipmaps = mipmaps_required; + + rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + //the second one is smaller (only used for separatable part of blur) + tf.width >>= 1; + tf.height >>= 1; + tf.mipmaps--; + rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + int base_width = rb->width; + int base_height = rb->height; + + for (uint32_t i = 0; i < mipmaps_required; i++) { + + RenderBuffers::Blur::Mipmap mm; + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i); + { + Vector fbs; + fbs.push_back(mm.texture); + mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs); + } + + mm.width = base_width; + mm.height = base_height; + + rb->blur[0].mipmaps.push_back(mm); + + if (i > 0) { + + mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1); + { + Vector fbs; + fbs.push_back(mm.texture); + mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs); + } + + rb->blur[1].mipmaps.push_back(mm); + } + + base_width = MAX(1, base_width >> 1); + base_height = MAX(1, base_height >> 1); + } +} + +void RasterizerSceneRD::_allocate_luminance_textures(RenderBuffers *rb) { + ERR_FAIL_COND(!rb->luminance.current.is_null()); + + int w = rb->width; + int h = rb->height; + + while (true) { + w = MAX(w / 8, 1); + h = MAX(h / 8, 1); + + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = w; + tf.height = h; + tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; + + bool final = w == 1 && h == 1; + + if (final) { + tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT; + } + + RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + rb->luminance.reduce.push_back(texture); + + if (final) { + rb->luminance.current = RD::get_singleton()->texture_create(tf, RD::TextureView()); + break; + } + } +} + +void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { + + if (rb->texture.is_valid()) { + RD::get_singleton()->free(rb->texture); + rb->texture = RID(); + } + + if (rb->depth_texture.is_valid()) { + RD::get_singleton()->free(rb->depth_texture); + rb->depth_texture = RID(); + } + + for (int i = 0; i < 2; i++) { + if (rb->blur[i].texture.is_valid()) { + RD::get_singleton()->free(rb->blur[i].texture); + rb->blur[i].texture = RID(); + rb->blur[i].mipmaps.clear(); + } + } + + for (int i = 0; i < rb->luminance.reduce.size(); i++) { + RD::get_singleton()->free(rb->luminance.reduce[i]); + } + + for (int i = 0; i < rb->luminance.reduce.size(); i++) { + RD::get_singleton()->free(rb->luminance.reduce[i]); + } + rb->luminance.reduce.clear(); + + if (rb->luminance.current.is_valid()) { + RD::get_singleton()->free(rb->luminance.current); + rb->luminance.current = RID(); + } + + if (rb->ssao.ao[0].is_valid()) { + RD::get_singleton()->free(rb->ssao.depth); + RD::get_singleton()->free(rb->ssao.ao[0]); + if (rb->ssao.ao[1].is_valid()) { + RD::get_singleton()->free(rb->ssao.ao[1]); + } + if (rb->ssao.ao_full.is_valid()) { + RD::get_singleton()->free(rb->ssao.ao_full); + } + + rb->ssao.depth = RID(); + rb->ssao.ao[0] = RID(); + rb->ssao.ao[1] = RID(); + rb->ssao.ao_full = RID(); + rb->ssao.depth_slices.clear(); + } +} + +void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + Environent *env = environment_owner.getornull(p_environment); + ERR_FAIL_COND(!env); + + if (rb->ssao.ao[0].is_valid() && rb->ssao.ao_full.is_valid() != ssao_half_size) { + RD::get_singleton()->free(rb->ssao.depth); + RD::get_singleton()->free(rb->ssao.ao[0]); + if (rb->ssao.ao[1].is_valid()) { + RD::get_singleton()->free(rb->ssao.ao[1]); + } + if (rb->ssao.ao_full.is_valid()) { + RD::get_singleton()->free(rb->ssao.ao_full); + } + + rb->ssao.depth = RID(); + rb->ssao.ao[0] = RID(); + rb->ssao.ao[1] = RID(); + rb->ssao.ao_full = RID(); + rb->ssao.depth_slices.clear(); + } + + if (!rb->ssao.ao[0].is_valid()) { + //allocate depth slices + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R32_SFLOAT; + tf.width = rb->width / 2; + tf.height = rb->height / 2; + tf.mipmaps = Image::get_image_required_mipmaps(tf.width, tf.height, Image::FORMAT_RF) + 1; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); + for (uint32_t i = 0; i < tf.mipmaps; i++) { + RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i); + rb->ssao.depth_slices.push_back(slice); + } + } + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = ssao_half_size ? rb->width / 2 : rb->width; + tf.height = ssao_half_size ? rb->height / 2 : rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.ao[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + rb->ssao.ao[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + if (ssao_half_size) { + //upsample texture + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; + rb->ssao.ao_full = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + _render_buffers_uniform_set_changed(p_render_buffers); + } + + storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, Size2i(rb->width, rb->height), rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao[0], rb->ssao.ao_full.is_valid(), rb->ssao.ao[1], rb->ssao.ao_full, env->ssao_intensity, env->ssao_radius, env->ssao_bias, p_projection, ssao_quality, env->ssao_blur, env->ssao_blur_edge_sharpness); +} + +void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + Environent *env = environment_owner.getornull(p_environment); + //glow (if enabled) + CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); + + bool can_use_effects = rb->width >= 8 && rb->height >= 8; + + if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) { + + if (rb->blur[0].texture.is_null()) { + _allocate_blur_textures(rb); + _render_buffers_uniform_set_changed(p_render_buffers); + } + + float bokeh_size = camfx->dof_blur_amount * 64.0; + storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_projection.get_z_near(), p_projection.get_z_far(), p_projection.is_orthogonal()); + } + + if (can_use_effects && env && env->auto_exposure) { + + if (rb->luminance.current.is_null()) { + _allocate_luminance_textures(rb); + _render_buffers_uniform_set_changed(p_render_buffers); + } + + bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version; + rb->auto_exposure_version = env->auto_exposure_version; + + double step = env->auto_exp_speed * time_step; + storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); + + //swap final reduce with prev luminance + SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); + RenderingServerRaster::redraw_request(); //redraw all the time if auto exposure rendering is on + } + + int max_glow_level = -1; + int glow_mask = 0; + + if (can_use_effects && env && env->glow_enabled) { + + /* see that blur textures are allocated */ + + if (rb->blur[0].texture.is_null()) { + _allocate_blur_textures(rb); + _render_buffers_uniform_set_changed(p_render_buffers); + } + + for (int i = 0; i < RS::MAX_GLOW_LEVELS; i++) { + if (env->glow_levels & (1 << i)) { + + if (i >= rb->blur[1].mipmaps.size()) { + max_glow_level = rb->blur[1].mipmaps.size() - 1; + glow_mask |= 1 << max_glow_level; + + } else { + max_glow_level = i; + glow_mask |= (1 << i); + } + } + } + + for (int i = 0; i < (max_glow_level + 1); i++) { + + int vp_w = rb->blur[1].mipmaps[i].width; + int vp_h = rb->blur[1].mipmaps[i].height; + + if (i == 0) { + RID luminance_texture; + if (env->auto_exposure && rb->luminance.current.is_valid()) { + luminance_texture = rb->luminance.current; + } + storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); + } else { + storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength); + } + } + } + + { + //tonemap + RasterizerEffectsRD::TonemapSettings tonemap; + + tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); + + if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { + tonemap.use_auto_exposure = true; + tonemap.exposure_texture = rb->luminance.current; + tonemap.auto_exposure_grey = env->auto_exp_scale; + } else { + + tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); + } + + if (can_use_effects && env && env->glow_enabled) { + tonemap.use_glow = true; + tonemap.glow_mode = RasterizerEffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode); + tonemap.glow_intensity = env->glow_blend_mode == RS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity; + tonemap.glow_level_flags = glow_mask; + tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width; + tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; + tonemap.glow_use_bicubic_upscale = env->glow_bicubic_upscale; + tonemap.glow_texture = rb->blur[1].texture; + } else { + tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); + } + + if (env) { + tonemap.tonemap_mode = env->tone_mapper; + tonemap.white = env->white; + tonemap.exposure = env->exposure; + } + + storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); + } + + storage->render_target_disable_clear_request(rb->render_target); +} + +void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas) { + RasterizerEffectsRD *effects = storage->get_effects(); + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { + if (p_shadow_atlas.is_valid()) { + RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); + Size2 rtsize = storage->render_target_get_size(rb->render_target); + + effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true); + } + } + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) { + if (directional_shadow_get_texture().is_valid()) { + RID shadow_atlas_texture = directional_shadow_get_texture(); + Size2 rtsize = storage->render_target_get_size(rb->render_target); + + effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true); + } + } + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) { + if (rb->luminance.current.is_valid()) { + Size2 rtsize = storage->render_target_get_size(rb->render_target); + + effects->copy_to_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); + } + } + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao[0].is_valid()) { + Size2 rtsize = storage->render_target_get_size(rb->render_target); + RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; + effects->copy_to_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + } + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER && _render_buffers_get_roughness_texture(p_render_buffers).is_valid()) { + Size2 rtsize = storage->render_target_get_size(rb->render_target); + effects->copy_to_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); + } + + if (debug_draw == RS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { + Size2 rtsize = storage->render_target_get_size(rb->render_target); + effects->copy_to_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize)); + } +} + +RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + if (!rb->blur[0].texture.is_valid()) { + return RID(); //not valid at the moment + } + return rb->blur[0].texture; +} + +RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, RID()); + + return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; +} + +void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa) { + + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + rb->width = p_width; + rb->height = p_height; + rb->render_target = p_render_target; + rb->msaa = p_msaa; + _free_render_buffer_data(rb); + + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + tf.width = rb->width; + tf.height = rb->height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; + + rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + { + RD::TextureFormat tf; + tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; + tf.width = p_width; + tf.height = p_height; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + + rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + + rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa); + _render_buffers_uniform_set_changed(p_render_buffers); +} + +int RasterizerSceneRD::get_roughness_layers() const { + return roughness_layers; +} + +bool RasterizerSceneRD::is_using_radiance_cubemap_array() const { + return sky_use_cubemap_array; +} + +RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(RID p_render_buffers) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND_V(!rb, NULL); + return rb->data; +} + +void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { + + Color clear_color; + if (p_render_buffers.is_valid()) { + RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); + ERR_FAIL_COND(!rb); + clear_color = storage->render_target_get_clear_request_color(rb->render_target); + } else { + clear_color = storage->get_default_clear_color(); + } + + _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); + + if (p_render_buffers.is_valid()) { + RENDER_TIMESTAMP("Tonemap"); + + _render_buffers_post_process_and_tonemap(p_render_buffers, p_environment, p_camera_effects, p_cam_projection); + _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas); + } +} + +void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { + + LightInstance *light_instance = light_instance_owner.getornull(p_light); + ERR_FAIL_COND(!light_instance); + + Rect2i atlas_rect; + RID atlas_fb; + + bool using_dual_paraboloid = false; + bool using_dual_paraboloid_flip = false; + float zfar = 0; + RID render_fb; + RID render_texture; + float bias = 0; + float normal_bias = 0; + + bool render_cubemap = false; + bool finalize_cubemap = false; + + CameraMatrix light_projection; + Transform light_transform; + + if (storage->light_get_type(light_instance->light) == RS::LIGHT_DIRECTIONAL) { + //set pssm stuff + if (light_instance->last_scene_shadow_pass != scene_pass) { + light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light); + directional_shadow.current_light++; + light_instance->last_scene_shadow_pass = scene_pass; + } + + light_projection = light_instance->shadow_transform[p_pass].camera; + light_transform = light_instance->shadow_transform[p_pass].transform; + + atlas_rect.position.x = light_instance->directional_rect.position.x; + atlas_rect.position.y = light_instance->directional_rect.position.y; + atlas_rect.size.width = light_instance->directional_rect.size.x; + atlas_rect.size.height = light_instance->directional_rect.size.y; + + if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { + + atlas_rect.size.width /= 2; + atlas_rect.size.height /= 2; + + if (p_pass == 1) { + atlas_rect.position.x += atlas_rect.size.width; + } else if (p_pass == 2) { + atlas_rect.position.y += atlas_rect.size.height; + } else if (p_pass == 3) { + atlas_rect.position.x += atlas_rect.size.width; + atlas_rect.position.y += atlas_rect.size.height; + } + + } else if (storage->light_directional_get_shadow_mode(light_instance->light) == RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { + + atlas_rect.size.height /= 2; + + if (p_pass == 0) { + + } else { + atlas_rect.position.y += atlas_rect.size.height; + } + } + + light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect; + + light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size; + light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size; + + float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE)); + zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE); + bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult; + normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult; + + ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size); + render_fb = shadow_map->fb; + render_texture = shadow_map->depth; + atlas_fb = directional_shadow.fb; + + } else { + //set from shadow atlas + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + ERR_FAIL_COND(!shadow_atlas); + ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light)); + + uint32_t key = shadow_atlas->shadow_owners[p_light]; + + uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; + uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; + + ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size()); + + uint32_t quadrant_size = shadow_atlas->size >> 1; + + atlas_rect.position.x = (quadrant & 1) * quadrant_size; + atlas_rect.position.y = (quadrant >> 1) * quadrant_size; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + atlas_rect.position.x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + atlas_rect.position.y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + + atlas_rect.size.width = shadow_size; + atlas_rect.size.height = shadow_size; + atlas_fb = shadow_atlas->fb; + + zfar = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_RANGE); + bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_BIAS); + normal_bias = storage->light_get_param(light_instance->light, RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS); + + if (storage->light_get_type(light_instance->light) == RS::LIGHT_OMNI) { + + if (storage->light_omni_get_shadow_mode(light_instance->light) == RS::LIGHT_OMNI_SHADOW_CUBE) { + + ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2); + + render_fb = cubemap->side_fb[p_pass]; + render_texture = cubemap->cubemap; + + light_projection = light_instance->shadow_transform[0].camera; + light_transform = light_instance->shadow_transform[0].transform; + render_cubemap = true; + finalize_cubemap = p_pass == 5; + + } else { + + light_projection = light_instance->shadow_transform[0].camera; + light_transform = light_instance->shadow_transform[0].transform; + + atlas_rect.size.height /= 2; + atlas_rect.position.y += p_pass * atlas_rect.size.height; + + using_dual_paraboloid = true; + using_dual_paraboloid_flip = p_pass == 1; + + ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size); + render_fb = shadow_map->fb; + render_texture = shadow_map->depth; + } + + } else if (storage->light_get_type(light_instance->light) == RS::LIGHT_SPOT) { + + light_projection = light_instance->shadow_transform[0].camera; + light_transform = light_instance->shadow_transform[0].transform; + + ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size); + render_fb = shadow_map->fb; + render_texture = shadow_map->depth; + } + } + + if (render_cubemap) { + //rendering to cubemap + _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false); + if (finalize_cubemap) { + //reblit + atlas_rect.size.height /= 2; + storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, false); + atlas_rect.position.y += atlas_rect.size.height; + storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, true); + } + } else { + //render shadow + + _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip); + + //copy to atlas + storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true); + + //does not work from depth to color + //RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true); + } +} + +void RasterizerSceneRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { + + _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region); +} + +bool RasterizerSceneRD::free(RID p_rid) { + + if (render_buffers_owner.owns(p_rid)) { + RenderBuffers *rb = render_buffers_owner.getornull(p_rid); + _free_render_buffer_data(rb); + memdelete(rb->data); + render_buffers_owner.free(p_rid); + } else if (environment_owner.owns(p_rid)) { + //not much to delete, just free it + environment_owner.free(p_rid); + } else if (camera_effects_owner.owns(p_rid)) { + //not much to delete, just free it + camera_effects_owner.free(p_rid); + } else if (reflection_atlas_owner.owns(p_rid)) { + reflection_atlas_set_size(p_rid, 0, 0); + reflection_atlas_owner.free(p_rid); + } else if (reflection_probe_instance_owner.owns(p_rid)) { + //not much to delete, just free it + //ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid); + reflection_probe_release_atlas_index(p_rid); + reflection_probe_instance_owner.free(p_rid); + } else if (gi_probe_instance_owner.owns(p_rid)) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid); + if (gi_probe->texture.is_valid()) { + RD::get_singleton()->free(gi_probe->texture); + RD::get_singleton()->free(gi_probe->write_buffer); + } + if (gi_probe->anisotropy[0].is_valid()) { + RD::get_singleton()->free(gi_probe->anisotropy[0]); + RD::get_singleton()->free(gi_probe->anisotropy[1]); + } + + for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) { + RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture); + RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth); + } + + gi_probe_slots.write[gi_probe->slot] = RID(); + + gi_probe_instance_owner.free(p_rid); + } else if (sky_owner.owns(p_rid)) { + _update_dirty_skys(); + Sky *sky = sky_owner.getornull(p_rid); + + if (sky->radiance.is_valid()) { + RD::get_singleton()->free(sky->radiance); + sky->radiance = RID(); + } + _clear_reflection_data(sky->reflection); + + if (sky->uniform_buffer.is_valid()) { + RD::get_singleton()->free(sky->uniform_buffer); + sky->uniform_buffer = RID(); + } + + if (sky->half_res_pass.is_valid()) { + RD::get_singleton()->free(sky->half_res_pass); + sky->half_res_pass = RID(); + } + + if (sky->quarter_res_pass.is_valid()) { + RD::get_singleton()->free(sky->quarter_res_pass); + sky->quarter_res_pass = RID(); + } + + if (sky->material.is_valid()) { + storage->free(sky->material); + } + + sky_owner.free(p_rid); + } else if (light_instance_owner.owns(p_rid)) { + + LightInstance *light_instance = light_instance_owner.getornull(p_rid); + + //remove from shadow atlases.. + for (Set::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(E->get()); + ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); + uint32_t key = shadow_atlas->shadow_owners[p_rid]; + uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; + uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; + + shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); + shadow_atlas->shadow_owners.erase(p_rid); + } + + light_instance_owner.free(p_rid); + + } else if (shadow_atlas_owner.owns(p_rid)) { + + shadow_atlas_set_size(p_rid, 0); + shadow_atlas_owner.free(p_rid); + + } else { + return false; + } + + return true; +} + +void RasterizerSceneRD::set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw) { + debug_draw = p_debug_draw; +} + +void RasterizerSceneRD::update() { + _update_dirty_skys(); +} + +void RasterizerSceneRD::set_time(double p_time, double p_step) { + time = p_time; + time_step = p_step; +} + +void RasterizerSceneRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) { + screen_space_roughness_limiter = p_enable; + screen_space_roughness_limiter_curve = p_curve; +} + +bool RasterizerSceneRD::screen_space_roughness_limiter_is_active() const { + return screen_space_roughness_limiter; +} + +float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const { + return screen_space_roughness_limiter_curve; +} + +RasterizerSceneRD *RasterizerSceneRD::singleton = NULL; + +RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { + storage = p_storage; + singleton = this; + + roughness_layers = GLOBAL_GET("rendering/quality/reflections/roughness_layers"); + sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples"); + sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections"); + // sky_use_cubemap_array = false; + + uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); + + { + + //kinda complicated to compute the amount of slots, we try to use as many as we can + + gi_probe_max_lights = 32; + + gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights); + gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight)); + + gi_probe_use_anisotropy = GLOBAL_GET("rendering/quality/gi_probes/anisotropic"); + gi_probe_quality = GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/quality/gi_probes/quality")), 0, 2)); + + if (textures_per_stage <= 16) { + gi_probe_slots.resize(2); //thats all you can get + gi_probe_use_anisotropy = false; + } else if (textures_per_stage <= 31) { + gi_probe_slots.resize(4); //thats all you can get, iOS + gi_probe_use_anisotropy = false; + } else if (textures_per_stage <= 128) { + gi_probe_slots.resize(32); //old intel + gi_probe_use_anisotropy = false; + } else if (textures_per_stage <= 256) { + gi_probe_slots.resize(64); //old intel too + gi_probe_use_anisotropy = false; + } else { + if (gi_probe_use_anisotropy) { + gi_probe_slots.resize(1024 / 3); //needs 3 textures + } else { + gi_probe_slots.resize(1024); //modern intel, nvidia, 8192 or greater + } + } + + String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n"; + if (gi_probe_use_anisotropy) { + defines += "\n#define MODE_ANISOTROPIC\n"; + } + + Vector versions; + versions.push_back("\n#define MODE_COMPUTE_LIGHT\n"); + versions.push_back("\n#define MODE_SECOND_BOUNCE\n"); + versions.push_back("\n#define MODE_UPDATE_MIPMAPS\n"); + versions.push_back("\n#define MODE_WRITE_TEXTURE\n"); + versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_LIGHTING\n"); + versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_WRITE\n"); + versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n"); + versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n#define MODE_DYNAMIC_SHRINK_WRITE\n"); + + giprobe_shader.initialize(versions, defines); + giprobe_lighting_shader_version = giprobe_shader.version_create(); + for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) { + giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i); + giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]); + } + } + + { + + String defines; + if (gi_probe_use_anisotropy) { + defines += "\n#define USE_ANISOTROPY\n"; + } + Vector versions; + versions.push_back("\n#define MODE_DEBUG_COLOR\n"); + versions.push_back("\n#define MODE_DEBUG_LIGHT\n"); + versions.push_back("\n#define MODE_DEBUG_EMISSION\n"); + versions.push_back("\n#define MODE_DEBUG_LIGHT\n#define MODE_DEBUG_LIGHT_FULL\n"); + + giprobe_debug_shader.initialize(versions, defines); + giprobe_debug_shader_version = giprobe_debug_shader.version_create(); + for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) { + giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i); + + RD::PipelineRasterizationState rs; + rs.cull_mode = RD::POLYGON_CULL_FRONT; + RD::PipelineDepthStencilState ds; + ds.enable_depth_test = true; + ds.enable_depth_write = true; + ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; + + giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); + } + } + + /* SKY SHADER */ + + { + // Start with the directional lights for the sky + sky_scene_state.max_directional_lights = 4; + uint32_t directional_light_buffer_size = sky_scene_state.max_directional_lights * sizeof(SkyDirectionalLightData); + sky_scene_state.directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights); + sky_scene_state.last_frame_directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights); + sky_scene_state.last_frame_directional_light_count = sky_scene_state.max_directional_lights + 1; + sky_scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); + + String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_scene_state.max_directional_lights) + "\n"; + + // Initialize sky + Vector sky_modes; + sky_modes.push_back(""); // Full size + sky_modes.push_back("\n#define USE_HALF_RES_PASS\n"); // Half Res + sky_modes.push_back("\n#define USE_QUARTER_RES_PASS\n"); // Quarter res + sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n"); // Cubemap + sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_HALF_RES_PASS\n"); // Half Res Cubemap + sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_QUARTER_RES_PASS\n"); // Quarter res Cubemap + sky_shader.shader.initialize(sky_modes, defines); + } + + // register our shader funds + storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); + storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs); + + { + ShaderCompilerRD::DefaultIdentifierActions actions; + + actions.renames["COLOR"] = "color"; + actions.renames["ALPHA"] = "alpha"; + actions.renames["EYEDIR"] = "cube_normal"; + actions.renames["POSITION"] = "params.position_multiplier.xyz"; + actions.renames["SKY_COORDS"] = "panorama_coords"; + actions.renames["SCREEN_UV"] = "uv"; + actions.renames["TIME"] = "params.time"; + actions.renames["HALF_RES_COLOR"] = "half_res_color"; + actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color"; + actions.renames["RADIANCE"] = "radiance"; + actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled"; + actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction"; + actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].energy"; + actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color"; + actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled"; + actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction"; + actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].energy"; + actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color"; + actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled"; + actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction"; + actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].energy"; + actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color"; + actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled"; + actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction"; + actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].energy"; + actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color"; + actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS"; + actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS"; + actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS"; + actions.custom_samplers["RADIANCE"] = "material_samplers[3]"; + actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; + actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; + + actions.sampler_array_name = "material_samplers"; + actions.base_texture_binding_index = 1; + actions.texture_layout_set = 1; + actions.base_uniform_string = "material."; + actions.base_varying_index = 10; + + actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; + actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; + + sky_shader.compiler.initialize(actions); + } + + { + // default material and shader for sky shader + sky_shader.default_shader = storage->shader_create(); + storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = mix(vec3(0.3), vec3(0.2, 0.4, 0.9), smoothstep(0.0, 0.05, EYEDIR.y)); } \n"); + sky_shader.default_material = storage->material_create(); + storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); + + SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); + sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); + + Vector uniforms; + + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_SAMPLER; + u.binding = 0; + u.ids.resize(12); + RID *ids_ptr = u.ids.ptrw(); + ids_ptr[0] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[1] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[2] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[3] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[4] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[5] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + ids_ptr[6] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[7] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[8] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[9] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[10] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + ids_ptr[11] = storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + uniforms.push_back(u); + } + + sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS); + } + + camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape")))); + camera_effects_set_dof_blur_quality(RS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter")); + environment_set_ssao_quality(RS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); + screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter"); + screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve"); +} + +RasterizerSceneRD::~RasterizerSceneRD() { + for (Map::Element *E = shadow_maps.front(); E; E = E->next()) { + RD::get_singleton()->free(E->get().depth); + } + for (Map::Element *E = shadow_cubemaps.front(); E; E = E->next()) { + RD::get_singleton()->free(E->get().cubemap); + } + + if (sky_scene_state.sampler_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.sampler_uniform_set)) { + RD::get_singleton()->free(sky_scene_state.sampler_uniform_set); + } + if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) { + RD::get_singleton()->free(sky_scene_state.light_uniform_set); + } + + RD::get_singleton()->free(gi_probe_lights_uniform); + giprobe_debug_shader.version_free(giprobe_debug_shader_version); + giprobe_shader.version_free(giprobe_lighting_shader_version); + memdelete_arr(gi_probe_lights); + SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); + sky_shader.shader.version_free(md->shader_data->version); + RD::get_singleton()->free(sky_scene_state.directional_light_buffer); + memdelete_arr(sky_scene_state.directional_lights); + memdelete_arr(sky_scene_state.last_frame_directional_lights); + storage->free(sky_shader.default_shader); + storage->free(sky_shader.default_material); +} diff --git a/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h new file mode 100644 index 0000000000..0a1cc8ebd7 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_scene_rd.h @@ -0,0 +1,1109 @@ +/*************************************************************************/ +/* rasterizer_scene_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_SCENE_RD_H +#define RASTERIZER_SCENE_RD_H + +#include "core/rid_owner.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering/rasterizer_rd/rasterizer_storage_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/giprobe.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h" +#include "servers/rendering/rasterizer_rd/shaders/sky.glsl.gen.h" +#include "servers/rendering/rendering_device.h" + +class RasterizerSceneRD : public RasterizerScene { +public: + enum GIProbeQuality { + GIPROBE_QUALITY_ULTRA_LOW, + GIPROBE_QUALITY_MEDIUM, + GIPROBE_QUALITY_HIGH, + }; + +protected: + double time; + + // Skys need less info from Directional Lights than the normal shaders + struct SkyDirectionalLightData { + + float direction[3]; + float energy; + float color[3]; + uint32_t enabled; + }; + + struct SkySceneState { + + SkyDirectionalLightData *directional_lights; + SkyDirectionalLightData *last_frame_directional_lights; + uint32_t max_directional_lights; + uint32_t directional_light_count; + uint32_t last_frame_directional_light_count; + RID directional_light_buffer; + RID sampler_uniform_set; + RID light_uniform_set; + } sky_scene_state; + + struct RenderBufferData { + + virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, RS::ViewportMSAA p_msaa) = 0; + virtual ~RenderBufferData() {} + }; + virtual RenderBufferData *_create_render_buffer_data() = 0; + + virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0; + virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0; + virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; + + virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); + + RenderBufferData *render_buffers_get_data(RID p_render_buffers); + + virtual void _base_uniforms_changed() = 0; + virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0; + virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers) = 0; + virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; + + void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); + + void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size); + void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); + void _draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); + +private: + RS::ViewportDebugDraw debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; + double time_step = 0; + static RasterizerSceneRD *singleton; + + int roughness_layers; + + RasterizerStorageRD *storage; + + struct ReflectionData { + + struct Layer { + struct Mipmap { + RID framebuffers[6]; + RID views[6]; + Size2i size; + }; + Vector mipmaps; //per-face view + Vector views; // per-cubemap view + }; + + struct DownsampleLayer { + struct Mipmap { + RID view; + Size2i size; + }; + Vector mipmaps; + }; + + RID radiance_base_cubemap; //cubemap for first layer, first cubemap + RID downsampled_radiance_cubemap; + DownsampleLayer downsampled_layer; + RID coefficient_buffer; + + bool dirty = true; + + Vector layers; + }; + + void _clear_reflection_data(ReflectionData &rd); + void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality); + void _create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays); + void _create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer); + void _update_reflection_mipmaps(ReflectionData &rd); + + /* Sky shader */ + + enum SkyVersion { + SKY_VERSION_BACKGROUND, + SKY_VERSION_HALF_RES, + SKY_VERSION_QUARTER_RES, + SKY_VERSION_CUBEMAP, + SKY_VERSION_CUBEMAP_HALF_RES, + SKY_VERSION_CUBEMAP_QUARTER_RES, + SKY_VERSION_MAX + }; + + struct SkyShader { + SkyShaderRD shader; + ShaderCompilerRD compiler; + + RID default_shader; + RID default_material; + RID default_shader_rd; + } sky_shader; + + struct SkyShaderData : public RasterizerStorageRD::ShaderData { + bool valid; + RID version; + + RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX]; + Map uniforms; + Vector texture_uniforms; + + Vector ubo_offsets; + uint32_t ubo_size; + + String path; + String code; + Map default_texture_params; + + bool uses_time; + bool uses_position; + bool uses_half_res; + bool uses_quarter_res; + bool uses_light; + + virtual void set_code(const String &p_Code); + virtual void set_default_texture_param(const StringName &p_name, RID p_texture); + virtual void get_param_list(List *p_param_list) const; + virtual bool is_param_texture(const StringName &p_param) const; + virtual bool is_animated() const; + virtual bool casts_shadows() const; + virtual Variant get_default_parameter(const StringName &p_parameter) const; + SkyShaderData(); + virtual ~SkyShaderData(); + }; + + RasterizerStorageRD::ShaderData *_create_sky_shader_func(); + static RasterizerStorageRD::ShaderData *_create_sky_shader_funcs() { + return static_cast(singleton)->_create_sky_shader_func(); + }; + + struct SkyMaterialData : public RasterizerStorageRD::MaterialData { + uint64_t last_frame; + SkyShaderData *shader_data; + RID uniform_buffer; + RID uniform_set; + Vector texture_cache; + Vector ubo_data; + bool uniform_set_updated; + + virtual void set_render_priority(int p_priority) {} + virtual void set_next_pass(RID p_pass) {} + virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); + virtual ~SkyMaterialData(); + }; + + RasterizerStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); + static RasterizerStorageRD::MaterialData *_create_sky_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { + return static_cast(singleton)->_create_sky_material_func(static_cast(p_shader)); + }; + + enum SkyTextureSetVersion { + SKY_TEXTURE_SET_BACKGROUND, + SKY_TEXTURE_SET_HALF_RES, + SKY_TEXTURE_SET_QUARTER_RES, + SKY_TEXTURE_SET_CUBEMAP, + SKY_TEXTURE_SET_CUBEMAP_HALF_RES, + SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, + SKY_TEXTURE_SET_MAX + }; + + enum SkySet { + SKY_SET_SAMPLERS, + SKY_SET_MATERIAL, + SKY_SET_TEXTURES, + SKY_SET_LIGHTS, + SKY_SET_MAX + }; + + /* SKY */ + struct Sky { + RID radiance; + RID half_res_pass; + RID half_res_framebuffer; + RID quarter_res_pass; + RID quarter_res_framebuffer; + Size2i screen_size; + + RID texture_uniform_sets[SKY_TEXTURE_SET_MAX]; + RID uniform_set; + + RID material; + RID uniform_buffer; + + int radiance_size = 256; + + RS::SkyMode mode = RS::SKY_MODE_QUALITY; + + ReflectionData reflection; + bool dirty = false; + Sky *dirty_list = nullptr; + + //State to track when radiance cubemap needs updating + SkyMaterialData *prev_material; + Vector3 prev_position; + float prev_time; + }; + + Sky *dirty_sky_list = nullptr; + + void _sky_invalidate(Sky *p_sky); + void _update_dirty_skys(); + RID _get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version); + + uint32_t sky_ggx_samples_quality; + bool sky_use_cubemap_array; + + mutable RID_Owner sky_owner; + + /* REFLECTION ATLAS */ + + struct ReflectionAtlas { + + int count = 0; + int size = 0; + + RID reflection; + RID depth_buffer; + RID depth_fb; + + struct Reflection { + RID owner; + ReflectionData data; + RID fbs[6]; + }; + + Vector reflections; + }; + + RID_Owner reflection_atlas_owner; + + /* REFLECTION PROBE INSTANCE */ + + struct ReflectionProbeInstance { + + RID probe; + int atlas_index = -1; + RID atlas; + + bool dirty = true; + bool rendering = false; + int processing_layer = 1; + int processing_side = 0; + + uint32_t render_step = 0; + uint64_t last_pass = 0; + uint32_t render_index = 0; + + Transform transform; + }; + + mutable RID_Owner reflection_probe_instance_owner; + + /* GIPROBE INSTANCE */ + + struct GIProbeLight { + + uint32_t type; + float energy; + float radius; + float attenuation; + + float color[3]; + float spot_angle_radians; + + float position[3]; + float spot_attenuation; + + float direction[3]; + uint32_t has_shadow; + }; + + struct GIProbePushConstant { + + int32_t limits[3]; + uint32_t stack_size; + + float emission_scale; + float propagation; + float dynamic_range; + uint32_t light_count; + + uint32_t cell_offset; + uint32_t cell_count; + float aniso_strength; + uint32_t pad; + }; + + struct GIProbeDynamicPushConstant { + + int32_t limits[3]; + uint32_t light_count; + int32_t x_dir[3]; + float z_base; + int32_t y_dir[3]; + float z_sign; + int32_t z_dir[3]; + float pos_multiplier; + uint32_t rect_pos[2]; + uint32_t rect_size[2]; + uint32_t prev_rect_ofs[2]; + uint32_t prev_rect_size[2]; + uint32_t flip_x; + uint32_t flip_y; + float dynamic_range; + uint32_t on_mipmap; + float propagation; + float pad[3]; + }; + + struct GIProbeInstance { + + RID probe; + RID texture; + RID anisotropy[2]; //only if anisotropy is used + RID anisotropy_r16[2]; //only if anisotropy is used + RID write_buffer; + + struct Mipmap { + RID texture; + RID anisotropy[2]; //only if anisotropy is used + RID uniform_set; + RID second_bounce_uniform_set; + RID write_uniform_set; + uint32_t level; + uint32_t cell_offset; + uint32_t cell_count; + }; + Vector mipmaps; + + struct DynamicMap { + RID texture; //color normally, or emission on first pass + RID fb_depth; //actual depth buffer for the first pass, float depth for later passes + RID depth; //actual depth buffer for the first pass, float depth for later passes + RID normal; //normal buffer for the first pass + RID albedo; //emission buffer for the first pass + RID orm; //orm buffer for the first pass + RID fb; //used for rendering, only valid on first map + RID uniform_set; + uint32_t size; + int mipmap; // mipmap to write to, -1 if no mipmap assigned + }; + + Vector dynamic_maps; + + int slot = -1; + uint32_t last_probe_version = 0; + uint32_t last_probe_data_version = 0; + + uint64_t last_pass = 0; + uint32_t render_index = 0; + + bool has_dynamic_object_data = false; + + Transform transform; + }; + + GIProbeLight *gi_probe_lights; + uint32_t gi_probe_max_lights; + RID gi_probe_lights_uniform; + + bool gi_probe_use_anisotropy = false; + GIProbeQuality gi_probe_quality = GIPROBE_QUALITY_MEDIUM; + + Vector gi_probe_slots; + + enum { + GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT, + GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE, + GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP, + GI_PROBE_SHADER_VERSION_WRITE_TEXTURE, + GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING, + GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE, + GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT, + GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT, + GI_PROBE_SHADER_VERSION_MAX + }; + GiprobeShaderRD giprobe_shader; + RID giprobe_lighting_shader_version; + RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX]; + RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX]; + + mutable RID_Owner gi_probe_instance_owner; + + enum { + GI_PROBE_DEBUG_COLOR, + GI_PROBE_DEBUG_LIGHT, + GI_PROBE_DEBUG_EMISSION, + GI_PROBE_DEBUG_LIGHT_FULL, + GI_PROBE_DEBUG_MAX + }; + + struct GIProbeDebugPushConstant { + float projection[16]; + uint32_t cell_offset; + float dynamic_range; + float alpha; + uint32_t level; + int32_t bounds[3]; + uint32_t pad; + }; + + GiprobeDebugShaderRD giprobe_debug_shader; + RID giprobe_debug_shader_version; + RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX]; + RenderPipelineVertexFormatCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX]; + RID giprobe_debug_uniform_set; + + /* SHADOW ATLAS */ + + struct ShadowAtlas { + + enum { + QUADRANT_SHIFT = 27, + SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1, + SHADOW_INVALID = 0xFFFFFFFF + }; + + struct Quadrant { + + uint32_t subdivision; + + struct Shadow { + RID owner; + uint64_t version; + uint64_t alloc_tick; + + Shadow() { + version = 0; + alloc_tick = 0; + } + }; + + Vector shadows; + + Quadrant() { + subdivision = 0; //not in use + } + + } quadrants[4]; + + int size_order[4] = { 0, 1, 2, 3 }; + uint32_t smallest_subdiv = 0; + + int size = 0; + + RID depth; + RID fb; //for copying + + Map shadow_owners; + }; + + RID_Owner shadow_atlas_owner; + + bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); + + /* DIRECTIONAL SHADOW */ + + struct DirectionalShadow { + RID depth; + RID fb; //for copying + + int light_count = 0; + int size = 0; + int current_light = 0; + } directional_shadow; + + /* SHADOW CUBEMAPS */ + + struct ShadowCubemap { + + RID cubemap; + RID side_fb[6]; + }; + + Map shadow_cubemaps; + ShadowCubemap *_get_shadow_cubemap(int p_size); + + struct ShadowMap { + RID depth; + RID fb; + }; + + Map shadow_maps; + ShadowMap *_get_shadow_map(const Size2i &p_size); + + void _create_shadow_cubemaps(); + + /* LIGHT INSTANCE */ + + struct LightInstance { + + struct ShadowTransform { + + CameraMatrix camera; + Transform transform; + float farplane; + float split; + float bias_scale; + Rect2 atlas_rect; + }; + + RS::LightType light_type; + + ShadowTransform shadow_transform[4]; + + RID self; + RID light; + Transform transform; + + Vector3 light_vector; + Vector3 spot_vector; + float linear_att; + + uint64_t shadow_pass = 0; + uint64_t last_scene_pass = 0; + uint64_t last_scene_shadow_pass = 0; + uint64_t last_pass = 0; + uint32_t light_index = 0; + uint32_t light_directional_index = 0; + + uint32_t current_shadow_atlas_key; + + Vector2 dp; + + Rect2 directional_rect; + + Set shadow_atlases; //shadow atlases where this light is registered + + LightInstance() {} + }; + + mutable RID_Owner light_instance_owner; + + /* ENVIRONMENT */ + + struct Environent { + + // BG + RS::EnvironmentBG background = RS::ENV_BG_CLEAR_COLOR; + RID sky; + float sky_custom_fov = 0.0; + Basis sky_orientation; + Color bg_color; + float bg_energy = 1.0; + int canvas_max_layer = 0; + RS::EnvironmentAmbientSource ambient_source = RS::ENV_AMBIENT_SOURCE_BG; + Color ambient_light; + float ambient_light_energy = 1.0; + float ambient_sky_contribution = 1.0; + RS::EnvironmentReflectionSource reflection_source = RS::ENV_REFLECTION_SOURCE_BG; + Color ao_color; + + /// Tonemap + + RS::EnvironmentToneMapper tone_mapper; + float exposure = 1.0; + float white = 1.0; + bool auto_exposure = false; + float min_luminance = 0.2; + float max_luminance = 8.0; + float auto_exp_speed = 0.2; + float auto_exp_scale = 0.5; + uint64_t auto_exposure_version = 0; + + /// Glow + + bool glow_enabled = false; + int glow_levels = (1 << 2) | (1 << 4); + float glow_intensity = 0.8; + float glow_strength = 1.0; + float glow_bloom = 0.0; + float glow_mix = 0.01; + RS::EnvironmentGlowBlendMode glow_blend_mode = RS::ENV_GLOW_BLEND_MODE_SOFTLIGHT; + float glow_hdr_bleed_threshold = 1.0; + float glow_hdr_luminance_cap = 12.0; + float glow_hdr_bleed_scale = 2.0; + bool glow_bicubic_upscale = false; + + /// SSAO + + bool ssao_enabled = false; + float ssao_radius = 1; + float ssao_intensity = 1; + float ssao_bias = 0.01; + float ssao_direct_light_affect = 0.0; + float ssao_ao_channel_affect = 0.0; + float ssao_blur_edge_sharpness = 4.0; + RS::EnvironmentSSAOBlur ssao_blur = RS::ENV_SSAO_BLUR_3x3; + }; + + RS::EnvironmentSSAOQuality ssao_quality = RS::ENV_SSAO_QUALITY_MEDIUM; + bool ssao_half_size = false; + + static uint64_t auto_exposure_counter; + + mutable RID_Owner environment_owner; + + /* CAMERA EFFECTS */ + + struct CameraEffects { + + bool dof_blur_far_enabled = false; + float dof_blur_far_distance = 10; + float dof_blur_far_transition = 5; + + bool dof_blur_near_enabled = false; + float dof_blur_near_distance = 2; + float dof_blur_near_transition = 1; + + float dof_blur_amount = 0.1; + + bool override_exposure_enabled = false; + float override_exposure = 1; + }; + + RS::DOFBlurQuality dof_blur_quality = RS::DOF_BLUR_QUALITY_MEDIUM; + RS::DOFBokehShape dof_blur_bokeh_shape = RS::DOF_BOKEH_HEXAGON; + bool dof_blur_use_jitter = false; + + mutable RID_Owner camera_effects_owner; + + /* RENDER BUFFERS */ + + struct RenderBuffers { + + RenderBufferData *data = nullptr; + int width = 0, height = 0; + RS::ViewportMSAA msaa = RS::VIEWPORT_MSAA_DISABLED; + RID render_target; + + uint64_t auto_exposure_version = 1; + + RID texture; //main texture for rendering to, must be filled after done rendering + RID depth_texture; //main depth texture + + //built-in textures used for ping pong image processing and blurring + struct Blur { + RID texture; + + struct Mipmap { + RID texture; + RID framebuffer; + int width; + int height; + }; + + Vector mipmaps; + }; + + Blur blur[2]; //the second one starts from the first mipmap + + struct Luminance { + + Vector reduce; + RID current; + } luminance; + + struct SSAO { + RID depth; + Vector depth_slices; + RID ao[2]; + RID ao_full; //when using half-size + } ssao; + }; + + bool screen_space_roughness_limiter = false; + float screen_space_roughness_limiter_curve = 1.0; + + mutable RID_Owner render_buffers_owner; + + void _free_render_buffer_data(RenderBuffers *rb); + void _allocate_blur_textures(RenderBuffers *rb); + void _allocate_luminance_textures(RenderBuffers *rb); + + void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas); + void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection); + + uint64_t scene_pass = 0; + uint64_t shadow_atlas_realloc_tolerance_msec = 500; + +public: + /* SHADOW ATLAS API */ + + RID shadow_atlas_create(); + void shadow_atlas_set_size(RID p_atlas, int p_size); + void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision); + bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version); + _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { + ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND_V(!atlas, false); + return atlas->shadow_owners.has(p_light_intance); + } + + _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) { + ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->depth; + } + + _FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) { + ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas); + ERR_FAIL_COND_V(!atlas, Size2i()); + return Size2(atlas->size, atlas->size); + } + + void directional_shadow_atlas_set_size(int p_size); + int get_directional_light_shadow_size(RID p_light_intance); + void set_directional_shadow_count(int p_count); + + _FORCE_INLINE_ RID directional_shadow_get_texture() { + return directional_shadow.depth; + } + + _FORCE_INLINE_ Size2i directional_shadow_get_size() { + return Size2i(directional_shadow.size, directional_shadow.size); + } + + /* SKY API */ + + RID sky_create(); + void sky_set_radiance_size(RID p_sky, int p_radiance_size); + void sky_set_mode(RID p_sky, RS::SkyMode p_mode); + void sky_set_material(RID p_sky, RID p_material); + + RID sky_get_radiance_texture_rd(RID p_sky) const; + RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const; + RID sky_get_material(RID p_sky) const; + + /* ENVIRONMENT API */ + + RID environment_create(); + + void environment_set_background(RID p_env, RS::EnvironmentBG p_bg); + void environment_set_sky(RID p_env, RID p_sky); + void environment_set_sky_custom_fov(RID p_env, float p_scale); + void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); + void environment_set_bg_color(RID p_env, const Color &p_color); + void environment_set_bg_energy(RID p_env, float p_energy); + void environment_set_canvas_max_layer(RID p_env, int p_max_layer); + void environment_set_ambient_light(RID p_env, const Color &p_color, RS::EnvironmentAmbientSource p_ambient = RS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, RS::EnvironmentReflectionSource p_reflection_source = RS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()); + + RS::EnvironmentBG environment_get_background(RID p_env) const; + RID environment_get_sky(RID p_env) const; + float environment_get_sky_custom_fov(RID p_env) const; + Basis environment_get_sky_orientation(RID p_env) const; + Color environment_get_bg_color(RID p_env) const; + float environment_get_bg_energy(RID p_env) const; + int environment_get_canvas_max_layer(RID p_env) const; + Color environment_get_ambient_light_color(RID p_env) const; + RS::EnvironmentAmbientSource environment_get_ambient_light_ambient_source(RID p_env) const; + float environment_get_ambient_light_ambient_energy(RID p_env) const; + float environment_get_ambient_sky_contribution(RID p_env) const; + RS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; + Color environment_get_ao_color(RID p_env) const; + + bool is_environment(RID p_env) const; + + void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, RS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); + + void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {} + + void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {} + void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, RS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); + void environment_set_ssao_quality(RS::EnvironmentSSAOQuality p_quality, bool p_half_size); + bool environment_is_ssao_enabled(RID p_env) const; + float environment_get_ssao_ao_affect(RID p_env) const; + float environment_get_ssao_light_affect(RID p_env) const; + bool environment_is_ssr_enabled(RID p_env) const; + + void environment_set_tonemap(RID p_env, RS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); + void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} + + void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {} + void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {} + void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {} + + virtual RID camera_effects_create(); + + virtual void camera_effects_set_dof_blur_quality(RS::DOFBlurQuality p_quality, bool p_use_jitter); + virtual void camera_effects_set_dof_blur_bokeh_shape(RS::DOFBokehShape p_shape); + + virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount); + virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure); + + RID light_instance_create(RID p_light); + void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); + void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0); + void light_instance_mark_visible(RID p_light_instance); + + _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->light; + } + + _FORCE_INLINE_ Transform light_instance_get_base_transform(RID p_light_instance) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->transform; + } + + _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) { + + ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); + LightInstance *li = light_instance_owner.getornull(p_light_instance); + uint32_t key = shadow_atlas->shadow_owners[li->self]; + + uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; + uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; + + ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2()); + + uint32_t atlas_size = shadow_atlas->size; + uint32_t quadrant_size = atlas_size >> 1; + + uint32_t x = (quadrant & 1) * quadrant_size; + uint32_t y = (quadrant >> 1) * quadrant_size; + + uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); + x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; + + uint32_t width = shadow_size; + uint32_t height = shadow_size; + + return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size)); + } + + _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) { + + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->shadow_transform[p_index].camera; + } + + _FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) { + + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->shadow_transform[p_index].transform; + } + + _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) { + + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->shadow_transform[p_index].atlas_rect; + } + + _FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) { + + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->shadow_transform[p_index].split; + } + + _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + li->last_pass = p_pass; + } + + _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->last_pass; + } + + _FORCE_INLINE_ void light_instance_set_index(RID p_light_instance, uint32_t p_index) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + li->light_index = p_index; + } + + _FORCE_INLINE_ uint32_t light_instance_get_index(RID p_light_instance) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->light_index; + } + + _FORCE_INLINE_ RS::LightType light_instance_get_type(RID p_light_instance) { + LightInstance *li = light_instance_owner.getornull(p_light_instance); + return li->light_type; + } + + virtual RID reflection_atlas_create(); + virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count); + _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) { + ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas); + ERR_FAIL_COND_V(!atlas, RID()); + return atlas->reflection; + } + + virtual RID reflection_probe_instance_create(RID p_probe); + virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform); + virtual void reflection_probe_release_atlas_index(RID p_instance); + virtual bool reflection_probe_instance_needs_redraw(RID p_instance); + virtual bool reflection_probe_instance_has_reflection(RID p_instance); + virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas); + virtual bool reflection_probe_instance_postprocess_step(RID p_instance); + + uint32_t reflection_probe_instance_get_resolution(RID p_instance); + RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index); + RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index); + + _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, RID()); + + return rpi->probe; + } + + _FORCE_INLINE_ void reflection_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!rpi); + rpi->render_index = p_render_index; + } + + _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_index(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, 0); + + return rpi->render_index; + } + + _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!rpi); + rpi->last_pass = p_render_pass; + } + + _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, 0); + + return rpi->last_pass; + } + + _FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, Transform()); + + return rpi->transform; + } + + _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) { + ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!rpi, -1); + + return rpi->atlas_index; + } + + RID gi_probe_instance_create(RID p_base); + void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform); + bool gi_probe_needs_update(RID p_probe) const; + void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects); + + _FORCE_INLINE_ uint32_t gi_probe_instance_get_slot(RID p_probe) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + return gi_probe->slot; + } + _FORCE_INLINE_ RID gi_probe_instance_get_base_probe(RID p_probe) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + return gi_probe->probe; + } + _FORCE_INLINE_ Transform gi_probe_instance_get_transform_to_cell(RID p_probe) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + return storage->gi_probe_get_to_cell_xform(gi_probe->probe) * gi_probe->transform.affine_inverse(); + } + + _FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + return gi_probe->texture; + } + _FORCE_INLINE_ RID gi_probe_instance_get_aniso_texture(RID p_probe, int p_index) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); + return gi_probe->anisotropy[p_index]; + } + + _FORCE_INLINE_ void gi_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!gi_probe); + gi_probe->render_index = p_render_index; + } + + _FORCE_INLINE_ uint32_t gi_probe_instance_get_render_index(RID p_instance) { + GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!gi_probe, 0); + + return gi_probe->render_index; + } + + _FORCE_INLINE_ void gi_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { + GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND(!g_probe); + g_probe->last_pass = p_render_pass; + } + + _FORCE_INLINE_ uint32_t gi_probe_instance_get_render_pass(RID p_instance) { + GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance); + ERR_FAIL_COND_V(!g_probe, 0); + + return g_probe->last_pass; + } + + const Vector &gi_probe_get_slots() const; + _FORCE_INLINE_ bool gi_probe_is_anisotropic() const { + return gi_probe_use_anisotropy; + } + GIProbeQuality gi_probe_get_quality() const; + + RID render_buffers_create(); + void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, RS::ViewportMSAA p_msaa); + + RID render_buffers_get_ao_texture(RID p_render_buffers); + RID render_buffers_get_back_buffer_texture(RID p_render_buffers); + + void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + + void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); + + void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); + + virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; } + _FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; } + + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve); + virtual bool screen_space_roughness_limiter_is_active() const; + virtual float screen_space_roughness_limiter_get_curve() const; + + int get_roughness_layers() const; + bool is_using_radiance_cubemap_array() const; + + virtual bool free(RID p_rid); + + virtual void update(); + + virtual void set_debug_draw_mode(RS::ViewportDebugDraw p_debug_draw); + _FORCE_INLINE_ RS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; } + + virtual void set_time(double p_time, double p_step); + + RasterizerSceneRD(RasterizerStorageRD *p_storage); + ~RasterizerSceneRD(); +}; + +#endif // RASTERIZER_SCENE_RD_H diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp new file mode 100644 index 0000000000..83af15602c --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.cpp @@ -0,0 +1,4822 @@ +/*************************************************************************/ +/* rasterizer_storage_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rasterizer_storage_rd.h" +#include "core/engine.h" +#include "core/project_settings.h" +#include "servers/rendering/shader_language.h" + +Ref RasterizerStorageRD::_validate_texture_format(const Ref &p_image, TextureToRDFormat &r_format) { + + Ref image = p_image->duplicate(); + + switch (p_image->get_format()) { + case Image::FORMAT_L8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //luminance + case Image::FORMAT_LA8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; + } break; //luminance-alpha + case Image::FORMAT_R8: { + r_format.format = RD::DATA_FORMAT_R8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RG8: { + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGB8: { + //this format is not mandatory for specification, check if supported first + if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBA8: { + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGBA4444: { + r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RGB565: { + r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_RF: { + r_format.format = RD::DATA_FORMAT_R32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float + case Image::FORMAT_RGF: { + r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBF: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + image->convert(Image::FORMAT_RGBAF); + } + + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAF: { + r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RH: { + r_format.format = RD::DATA_FORMAT_R16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //half float + case Image::FORMAT_RGH: { + r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGBH: { + //this format is not mandatory for specification, check if supported first + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->convert(Image::FORMAT_RGBAH); + } + + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_RGBAH: { + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; + case Image::FORMAT_RGBE9995: { + r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; +#ifndef _MSC_VER +#warning TODO need to make a function in Image to swap bits for this +#endif + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; + } break; + case Image::FORMAT_DXT1: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //s3tc bc1 + case Image::FORMAT_DXT3: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //bc2 + case Image::FORMAT_DXT5: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; //bc3 + case Image::FORMAT_RGTC_R: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_RGTC_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_BPTC_RGBA: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + + } break; //btpc bc7 + case Image::FORMAT_BPTC_RGBF: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //float bc6h + case Image::FORMAT_BPTC_RGBFU: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; + image->decompress(); + image->convert(Image::FORMAT_RGBAH); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //unsigned float bc6hu + case Image::FORMAT_PVRTC2: { + //this is not properly supported by MoltekVK it seems, so best to use ETC2 + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //pvrtc + case Image::FORMAT_PVRTC2A: { + //this is not properly supported by MoltekVK it seems, so best to use ETC2 + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; + r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_PVRTC4: { + //this is not properly supported by MoltekVK it seems, so best to use ETC2 + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_PVRTC4A: { + //this is not properly supported by MoltekVK it seems, so best to use ETC2 + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; + r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_R11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; //etc2 + case Image::FORMAT_ETC2_R11S: { + + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_R8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; //signed: {} break; NOT srgb. + case Image::FORMAT_ETC2_RG11: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_UNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC2_RG11S: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8_SNORM; + image->decompress(); + image->convert(Image::FORMAT_RG8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_ETC: + case Image::FORMAT_ETC2_RGB8: { + //ETC2 is backwards compatible with ETC1, and all modern platforms support it + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + + } break; + case Image::FORMAT_ETC2_RGBA8: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RGB8A1: { + + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; + } break; + case Image::FORMAT_ETC2_RA_AS_RG: { + + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + case Image::FORMAT_DXT5_RA_AS_RG: { + if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { + r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; + r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; + } else { + //not supported, reconvert + r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + image->decompress(); + image->convert(Image::FORMAT_RGBA8); + } + r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; + r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; + r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; + r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } break; + + default: { + } + } + + return image; +} + +RID RasterizerStorageRD::texture_2d_create(const Ref &p_image) { + ERR_FAIL_COND_V(p_image.is_null(), RID()); + ERR_FAIL_COND_V(p_image->empty(), RID()); + + TextureToRDFormat ret_format; + Ref image = _validate_texture_format(p_image, ret_format); + + Texture texture; + + texture.type = Texture::TYPE_2D; + + texture.width = p_image->get_width(); + texture.height = p_image->get_height(); + texture.layers = 1; + texture.mipmaps = p_image->get_mipmap_count() + 1; + texture.depth = 1; + texture.format = p_image->get_format(); + texture.validated_format = image->get_format(); + + texture.rd_type = RD::TEXTURE_TYPE_2D; + texture.rd_format = ret_format.format; + texture.rd_format_srgb = ret_format.format_srgb; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = texture.rd_format; + rd_format.width = texture.width; + rd_format.height = texture.height; + rd_format.depth = 1; + rd_format.array_layers = 1; + rd_format.mipmaps = texture.mipmaps; + rd_format.type = texture.rd_type; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_format.shareable_formats.push_back(texture.rd_format); + rd_format.shareable_formats.push_back(texture.rd_format_srgb); + } + } + { + rd_view.swizzle_r = ret_format.swizzle_r; + rd_view.swizzle_g = ret_format.swizzle_g; + rd_view.swizzle_b = ret_format.swizzle_b; + rd_view.swizzle_a = ret_format.swizzle_a; + } + Vector data = image->get_data(); //use image data + Vector> data_slices; + data_slices.push_back(data); + texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); + ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID()); + if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { + rd_view.format_override = texture.rd_format_srgb; + texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); + if (texture.rd_texture_srgb.is_null()) { + RD::get_singleton()->free(texture.rd_texture); + ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID()); + } + } + + //used for 2D, overridable + texture.width_2d = texture.width; + texture.height_2d = texture.height; + texture.is_render_target = false; + texture.rd_view = rd_view; + texture.is_proxy = false; + + return texture_owner.make_rid(texture); +} + +RID RasterizerStorageRD::texture_2d_layered_create(const Vector> &p_layers, RS::TextureLayeredType p_layered_type) { + + return RID(); +} +RID RasterizerStorageRD::texture_3d_create(const Vector> &p_slices) { + + return RID(); +} + +RID RasterizerStorageRD::texture_proxy_create(RID p_base) { + Texture *tex = texture_owner.getornull(p_base); + ERR_FAIL_COND_V(!tex, RID()); + Texture proxy_tex = *tex; + + proxy_tex.rd_view.format_override = tex->rd_format; + proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + if (proxy_tex.rd_texture_srgb.is_valid()) { + proxy_tex.rd_view.format_override = tex->rd_format_srgb; + proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); + } + proxy_tex.proxy_to = p_base; + proxy_tex.is_render_target = false; + proxy_tex.is_proxy = true; + proxy_tex.proxies.clear(); + + RID rid = texture_owner.make_rid(proxy_tex); + + tex->proxies.push_back(rid); + + return rid; +} + +void RasterizerStorageRD::_texture_2d_update(RID p_texture, const Ref &p_image, int p_layer, bool p_immediate) { + + ERR_FAIL_COND(p_image.is_null() || p_image->empty()); + + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->is_render_target); + ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); + ERR_FAIL_COND(p_image->get_format() != tex->format); + + if (tex->type == Texture::TYPE_LAYERED) { + ERR_FAIL_INDEX(p_layer, tex->layers); + } + +#ifdef TOOLS_ENABLED + tex->image_cache_2d.unref(); +#endif + TextureToRDFormat f; + Ref validated = _validate_texture_format(p_image, f); + + RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data(), !p_immediate); +} + +void RasterizerStorageRD::texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer) { + _texture_2d_update(p_texture, p_image, p_layer, true); +} +void RasterizerStorageRD::texture_2d_update(RID p_texture, const Ref &p_image, int p_layer) { + _texture_2d_update(p_texture, p_image, p_layer, false); +} +void RasterizerStorageRD::texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap) { +} + +void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { + + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(!tex->is_proxy); + Texture *proxy_to = texture_owner.getornull(p_proxy_to); + ERR_FAIL_COND(!proxy_to); + ERR_FAIL_COND(proxy_to->is_proxy); + + if (tex->proxy_to.is_valid()) { + //unlink proxy + if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { + RD::get_singleton()->free(tex->rd_texture); + tex->rd_texture = RID(); + } + if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { + RD::get_singleton()->free(tex->rd_texture_srgb); + tex->rd_texture_srgb = RID(); + } + Texture *prev_tex = texture_owner.getornull(tex->proxy_to); + ERR_FAIL_COND(!prev_tex); + prev_tex->proxies.erase(p_texture); + } + + *tex = *proxy_to; + + tex->proxy_to = p_proxy_to; + tex->is_render_target = false; + tex->is_proxy = true; + tex->proxies.clear(); + proxy_to->proxies.push_back(p_texture); + + tex->rd_view.format_override = tex->rd_format; + tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + if (tex->rd_texture_srgb.is_valid()) { + tex->rd_view.format_override = tex->rd_format_srgb; + tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); + } +} + +//these two APIs can be used together or in combination with the others. +RID RasterizerStorageRD::texture_2d_placeholder_create() { + + //this could be better optimized to reuse an existing image , done this way + //for now to get it working + Ref image; + image.instance(); + image->create(4, 4, false, Image::FORMAT_RGBA8); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + image->set_pixel(i, j, Color(1, 0, 1, 1)); + } + } + + return texture_2d_create(image); +} +RID RasterizerStorageRD::texture_2d_layered_placeholder_create() { + + return RID(); +} +RID RasterizerStorageRD::texture_3d_placeholder_create() { + + return RID(); +} + +Ref RasterizerStorageRD::texture_2d_get(RID p_texture) const { + + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND_V(!tex, Ref()); + +#ifdef TOOLS_ENABLED + if (tex->image_cache_2d.is_valid()) { + return tex->image_cache_2d; + } +#endif + Vector data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); + ERR_FAIL_COND_V(data.size() == 0, Ref()); + Ref image; + image.instance(); + image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); + ERR_FAIL_COND_V(image->empty(), Ref()); + if (tex->format != tex->validated_format) { + image->convert(tex->format); + } + +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + tex->image_cache_2d = image; + } +#endif + + return image; +} +Ref RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { + + return Ref(); +} +Ref RasterizerStorageRD::texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const { + + return Ref(); +} + +void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { + + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->proxy_to.is_valid()); //cant replace proxy + Texture *by_tex = texture_owner.getornull(p_by_texture); + ERR_FAIL_COND(!by_tex); + ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //cant replace proxy + + if (tex == by_tex) { + return; + } + + if (tex->rd_texture_srgb.is_valid()) { + RD::get_singleton()->free(tex->rd_texture_srgb); + } + RD::get_singleton()->free(tex->rd_texture); + + Vector proxies_to_update = tex->proxies; + Vector proxies_to_redirect = by_tex->proxies; + + *tex = *by_tex; + + tex->proxies = proxies_to_update; //restore proxies, so they can be updated + + for (int i = 0; i < proxies_to_update.size(); i++) { + texture_proxy_update(proxies_to_update[i], p_texture); + } + for (int i = 0; i < proxies_to_redirect.size(); i++) { + texture_proxy_update(proxies_to_redirect[i], p_texture); + } + //delete last, so proxies can be updated + texture_owner.free(p_by_texture); +} +void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + ERR_FAIL_COND(tex->type != Texture::TYPE_2D); + tex->width_2d = p_width; + tex->height_2d = p_height; +} + +void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->path = p_path; +} +String RasterizerStorageRD::texture_get_path(RID p_texture) const { + return String(); +} + +void RasterizerStorageRD::texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->detect_3d_callback_ud = p_userdata; + tex->detect_3d_callback = p_callback; +} +void RasterizerStorageRD::texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->detect_normal_callback_ud = p_userdata; + tex->detect_normal_callback = p_callback; +} +void RasterizerStorageRD::texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { + Texture *tex = texture_owner.getornull(p_texture); + ERR_FAIL_COND(!tex); + tex->detect_roughness_callback_ud = p_userdata; + tex->detect_roughness_callback = p_callback; +} +void RasterizerStorageRD::texture_debug_usage(List *r_info) { +} + +void RasterizerStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { +} +void RasterizerStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { +} + +Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) { + return texture_2d_get_size(p_proxy); +} + +/* SHADER API */ + +RID RasterizerStorageRD::shader_create() { + + Shader shader; + shader.data = NULL; + shader.type = SHADER_TYPE_MAX; + + return shader_owner.make_rid(shader); +} + +void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) { + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND(!shader); + + shader->code = p_code; + String mode_string = ShaderLanguage::get_shader_type(p_code); + + ShaderType new_type; + if (mode_string == "canvas_item") + new_type = SHADER_TYPE_2D; + else if (mode_string == "particles") + new_type = SHADER_TYPE_PARTICLES; + else if (mode_string == "spatial") + new_type = SHADER_TYPE_3D; + else if (mode_string == "sky") + new_type = SHADER_TYPE_SKY; + else + new_type = SHADER_TYPE_MAX; + + if (new_type != shader->type) { + if (shader->data) { + memdelete(shader->data); + shader->data = NULL; + } + + for (Set::Element *E = shader->owners.front(); E; E = E->next()) { + + Material *material = E->get(); + material->shader_type = new_type; + if (material->data) { + memdelete(material->data); + material->data = NULL; + } + } + + shader->type = new_type; + + if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) { + shader->data = shader_data_request_func[new_type](); + } else { + shader->type = SHADER_TYPE_MAX; //invalid + } + + for (Set::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + if (shader->data) { + material->data = material_data_request_func[new_type](shader->data); + material->data->set_next_pass(material->next_pass); + material->data->set_render_priority(material->priority); + } + material->shader_type = new_type; + } + } + + if (shader->data) { + shader->data->set_code(p_code); + } + + for (Set::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + material->instance_dependency.instance_notify_changed(false, true); + _material_queue_update(material, true, true); + } +} + +String RasterizerStorageRD::shader_get_code(RID p_shader) const { + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND_V(!shader, String()); + return shader->code; +} +void RasterizerStorageRD::shader_get_param_list(RID p_shader, List *p_param_list) const { + + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND(!shader); + if (shader->data) { + return shader->data->get_param_list(p_param_list); + } +} + +void RasterizerStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { + + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND(!shader); + + if (p_texture.is_valid() && texture_owner.owns(p_texture)) { + shader->default_texture_parameter[p_name] = p_texture; + } else { + shader->default_texture_parameter.erase(p_name); + } + + for (Set::Element *E = shader->owners.front(); E; E = E->next()) { + Material *material = E->get(); + _material_queue_update(material, false, true); + } +} + +RID RasterizerStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND_V(!shader, RID()); + if (shader->default_texture_parameter.has(p_name)) { + return shader->default_texture_parameter[p_name]; + } + + return RID(); +} +Variant RasterizerStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const { + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND_V(!shader, Variant()); + if (shader->data) { + return shader->data->get_default_parameter(p_param); + } + return Variant(); +} +void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { + ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); + shader_data_request_func[p_shader_type] = p_function; +} + +/* COMMON MATERIAL API */ + +RID RasterizerStorageRD::material_create() { + + Material material; + material.data = NULL; + material.shader = NULL; + material.shader_type = SHADER_TYPE_MAX; + material.update_next = NULL; + material.update_requested = false; + material.uniform_dirty = false; + material.texture_dirty = false; + material.priority = 0; + RID id = material_owner.make_rid(material); + { + Material *material_ptr = material_owner.getornull(id); + material_ptr->self = id; + } + return id; +} + +void RasterizerStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { + if (material->update_requested) { + return; + } + + material->update_next = material_update_list; + material_update_list = material; + material->update_requested = true; + material->uniform_dirty = p_uniform; + material->texture_dirty = p_texture; +} + +void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) { + + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + + if (material->data) { + memdelete(material->data); + material->data = NULL; + } + + if (material->shader) { + material->shader->owners.erase(material); + material->shader = NULL; + material->shader_type = SHADER_TYPE_MAX; + } + + if (p_shader.is_null()) { + material->instance_dependency.instance_notify_changed(false, true); + return; + } + + Shader *shader = shader_owner.getornull(p_shader); + ERR_FAIL_COND(!shader); + material->shader = shader; + material->shader_type = shader->type; + shader->owners.insert(material); + + if (shader->type == SHADER_TYPE_MAX) { + return; + } + + ERR_FAIL_COND(shader->data == NULL); + + material->data = material_data_request_func[shader->type](shader->data); + material->data->set_next_pass(material->next_pass); + material->data->set_render_priority(material->priority); + //updating happens later + material->instance_dependency.instance_notify_changed(false, true); + _material_queue_update(material, true, true); +} + +void RasterizerStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { + + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + + if (p_value.get_type() == Variant::NIL) { + material->params.erase(p_param); + } else { + material->params[p_param] = p_value; + } + + if (material->shader && material->shader->data) { //shader is valid + bool is_texture = material->shader->data->is_param_texture(p_param); + _material_queue_update(material, !is_texture, is_texture); + } else { + _material_queue_update(material, true, true); + } +} + +Variant RasterizerStorageRD::material_get_param(RID p_material, const StringName &p_param) const { + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND_V(!material, Variant()); + if (material->params.has(p_param)) { + return material->params[p_param]; + } else { + return Variant(); + } +} + +void RasterizerStorageRD::material_set_next_pass(RID p_material, RID p_next_material) { + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + + if (material->next_pass == p_next_material) { + return; + } + + material->next_pass = p_next_material; + if (material->data) { + material->data->set_next_pass(p_next_material); + } + + material->instance_dependency.instance_notify_changed(false, true); +} +void RasterizerStorageRD::material_set_render_priority(RID p_material, int priority) { + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + material->priority = priority; + if (material->data) { + material->data->set_render_priority(priority); + } +} + +bool RasterizerStorageRD::material_is_animated(RID p_material) { + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND_V(!material, false); + if (material->shader && material->shader->data) { + if (material->shader->data->is_animated()) { + return true; + } else if (material->next_pass.is_valid()) { + return material_is_animated(material->next_pass); + } + } + return false; //by default nothing is animated +} +bool RasterizerStorageRD::material_casts_shadows(RID p_material) { + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND_V(!material, true); + if (material->shader && material->shader->data) { + if (material->shader->data->casts_shadows()) { + return true; + } else if (material->next_pass.is_valid()) { + return material_casts_shadows(material->next_pass); + } + } + return true; //by default everything casts shadows +} + +void RasterizerStorageRD::material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) { + Material *material = material_owner.getornull(p_material); + ERR_FAIL_COND(!material); + p_instance->update_dependency(&material->instance_dependency); + if (material->next_pass.is_valid()) { + material_update_dependency(material->next_pass, p_instance); + } +} + +void RasterizerStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { + ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); + material_data_request_func[p_shader_type] = p_function; +} + +_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant &value, uint8_t *data, bool p_linear_color) { + switch (type) { + case ShaderLanguage::TYPE_BOOL: { + + bool v = value; + + uint32_t *gui = (uint32_t *)data; + *gui = v ? 1 : 0; + } break; + case ShaderLanguage::TYPE_BVEC2: { + + int v = value; + uint32_t *gui = (uint32_t *)data; + gui[0] = v & 1 ? 1 : 0; + gui[1] = v & 2 ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + + int v = value; + uint32_t *gui = (uint32_t *)data; + gui[0] = (v & 1) ? 1 : 0; + gui[1] = (v & 2) ? 1 : 0; + gui[2] = (v & 4) ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + + int v = value; + uint32_t *gui = (uint32_t *)data; + gui[0] = (v & 1) ? 1 : 0; + gui[1] = (v & 2) ? 1 : 0; + gui[2] = (v & 4) ? 1 : 0; + gui[3] = (v & 8) ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_INT: { + + int v = value; + int32_t *gui = (int32_t *)data; + gui[0] = v; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + + Vector iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + const int *r = iv.ptr(); + + for (int i = 0; i < 2; i++) { + if (i < s) + gui[i] = r[i]; + else + gui[i] = 0; + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + + Vector iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + const int *r = iv.ptr(); + + for (int i = 0; i < 3; i++) { + if (i < s) + gui[i] = r[i]; + else + gui[i] = 0; + } + } break; + case ShaderLanguage::TYPE_IVEC4: { + + Vector iv = value; + int s = iv.size(); + int32_t *gui = (int32_t *)data; + + const int *r = iv.ptr(); + + for (int i = 0; i < 4; i++) { + if (i < s) + gui[i] = r[i]; + else + gui[i] = 0; + } + } break; + case ShaderLanguage::TYPE_UINT: { + + int v = value; + uint32_t *gui = (uint32_t *)data; + gui[0] = v; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + + Vector iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + const int *r = iv.ptr(); + + for (int i = 0; i < 2; i++) { + if (i < s) + gui[i] = r[i]; + else + gui[i] = 0; + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + Vector iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + const int *r = iv.ptr(); + + for (int i = 0; i < 3; i++) { + if (i < s) + gui[i] = r[i]; + else + gui[i] = 0; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + Vector iv = value; + int s = iv.size(); + uint32_t *gui = (uint32_t *)data; + + const int *r = iv.ptr(); + + for (int i = 0; i < 4; i++) { + if (i < s) + gui[i] = r[i]; + else + gui[i] = 0; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + float v = value; + float *gui = (float *)data; + gui[0] = v; + + } break; + case ShaderLanguage::TYPE_VEC2: { + Vector2 v = value; + float *gui = (float *)data; + gui[0] = v.x; + gui[1] = v.y; + + } break; + case ShaderLanguage::TYPE_VEC3: { + Vector3 v = value; + float *gui = (float *)data; + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + + } break; + case ShaderLanguage::TYPE_VEC4: { + + float *gui = (float *)data; + + if (value.get_type() == Variant::COLOR) { + Color v = value; + + if (p_linear_color) { + v = v.to_linear(); + } + + gui[0] = v.r; + gui[1] = v.g; + gui[2] = v.b; + gui[3] = v.a; + } else if (value.get_type() == Variant::RECT2) { + Rect2 v = value; + + gui[0] = v.position.x; + gui[1] = v.position.y; + gui[2] = v.size.x; + gui[3] = v.size.y; + } else if (value.get_type() == Variant::QUAT) { + Quat v = value; + + gui[0] = v.x; + gui[1] = v.y; + gui[2] = v.z; + gui[3] = v.w; + } else { + Plane v = value; + + gui[0] = v.normal.x; + gui[1] = v.normal.y; + gui[2] = v.normal.z; + gui[3] = v.d; + } + } break; + case ShaderLanguage::TYPE_MAT2: { + Transform2D v = value; + float *gui = (float *)data; + + //in std140 members of mat2 are treated as vec4s + gui[0] = v.elements[0][0]; + gui[1] = v.elements[0][1]; + gui[2] = 0; + gui[3] = 0; + gui[4] = v.elements[1][0]; + gui[5] = v.elements[1][1]; + gui[6] = 0; + gui[7] = 0; + } break; + case ShaderLanguage::TYPE_MAT3: { + + Basis v = value; + float *gui = (float *)data; + + gui[0] = v.elements[0][0]; + gui[1] = v.elements[1][0]; + gui[2] = v.elements[2][0]; + gui[3] = 0; + gui[4] = v.elements[0][1]; + gui[5] = v.elements[1][1]; + gui[6] = v.elements[2][1]; + gui[7] = 0; + gui[8] = v.elements[0][2]; + gui[9] = v.elements[1][2]; + gui[10] = v.elements[2][2]; + gui[11] = 0; + } break; + case ShaderLanguage::TYPE_MAT4: { + + Transform v = value; + float *gui = (float *)data; + + gui[0] = v.basis.elements[0][0]; + gui[1] = v.basis.elements[1][0]; + gui[2] = v.basis.elements[2][0]; + gui[3] = 0; + gui[4] = v.basis.elements[0][1]; + gui[5] = v.basis.elements[1][1]; + gui[6] = v.basis.elements[2][1]; + gui[7] = 0; + gui[8] = v.basis.elements[0][2]; + gui[9] = v.basis.elements[1][2]; + gui[10] = v.basis.elements[2][2]; + gui[11] = 0; + gui[12] = v.origin.x; + gui[13] = v.origin.y; + gui[14] = v.origin.z; + gui[15] = 1; + } break; + default: { + } + } +} + +_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector &value, uint8_t *data) { + + switch (type) { + case ShaderLanguage::TYPE_BOOL: { + + uint32_t *gui = (uint32_t *)data; + *gui = value[0].boolean ? 1 : 0; + } break; + case ShaderLanguage::TYPE_BVEC2: { + + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC3: { + + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + gui[2] = value[2].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_BVEC4: { + + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].boolean ? 1 : 0; + gui[1] = value[1].boolean ? 1 : 0; + gui[2] = value[2].boolean ? 1 : 0; + gui[3] = value[3].boolean ? 1 : 0; + + } break; + case ShaderLanguage::TYPE_INT: { + + int32_t *gui = (int32_t *)data; + gui[0] = value[0].sint; + + } break; + case ShaderLanguage::TYPE_IVEC2: { + + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_IVEC3: { + + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_IVEC4: { + + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].sint; + } + + } break; + case ShaderLanguage::TYPE_UINT: { + + uint32_t *gui = (uint32_t *)data; + gui[0] = value[0].uint; + + } break; + case ShaderLanguage::TYPE_UVEC2: { + + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].uint; + } + } break; + case ShaderLanguage::TYPE_UVEC3: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].uint; + } + + } break; + case ShaderLanguage::TYPE_UVEC4: { + int32_t *gui = (int32_t *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].uint; + } + } break; + case ShaderLanguage::TYPE_FLOAT: { + + float *gui = (float *)data; + gui[0] = value[0].real; + + } break; + case ShaderLanguage::TYPE_VEC2: { + + float *gui = (float *)data; + + for (int i = 0; i < 2; i++) { + gui[i] = value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC3: { + + float *gui = (float *)data; + + for (int i = 0; i < 3; i++) { + gui[i] = value[i].real; + } + + } break; + case ShaderLanguage::TYPE_VEC4: { + + float *gui = (float *)data; + + for (int i = 0; i < 4; i++) { + gui[i] = value[i].real; + } + } break; + case ShaderLanguage::TYPE_MAT2: { + float *gui = (float *)data; + + //in std140 members of mat2 are treated as vec4s + gui[0] = value[0].real; + gui[1] = value[1].real; + gui[2] = 0; + gui[3] = 0; + gui[4] = value[2].real; + gui[5] = value[3].real; + gui[6] = 0; + gui[7] = 0; + } break; + case ShaderLanguage::TYPE_MAT3: { + + float *gui = (float *)data; + + gui[0] = value[0].real; + gui[1] = value[1].real; + gui[2] = value[2].real; + gui[3] = 0; + gui[4] = value[3].real; + gui[5] = value[4].real; + gui[6] = value[5].real; + gui[7] = 0; + gui[8] = value[6].real; + gui[9] = value[7].real; + gui[10] = value[8].real; + gui[11] = 0; + } break; + case ShaderLanguage::TYPE_MAT4: { + + float *gui = (float *)data; + + for (int i = 0; i < 16; i++) { + gui[i] = value[i].real; + } + } break; + default: { + } + } +} + +_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) { + + switch (type) { + + case ShaderLanguage::TYPE_BOOL: + case ShaderLanguage::TYPE_INT: + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_FLOAT: { + zeromem(data, 4); + } break; + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_VEC2: { + zeromem(data, 8); + } break; + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_VEC3: + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC4: + case ShaderLanguage::TYPE_VEC4: { + + zeromem(data, 16); + } break; + case ShaderLanguage::TYPE_MAT2: { + + zeromem(data, 32); + } break; + case ShaderLanguage::TYPE_MAT3: { + + zeromem(data, 48); + } break; + case ShaderLanguage::TYPE_MAT4: { + zeromem(data, 64); + } break; + + default: { + } + } +} + +void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Map &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { + + for (Map::Element *E = p_uniforms.front(); E; E = E->next()) { + + if (E->get().order < 0) + continue; // texture, does not go here + + //regular uniform + uint32_t offset = p_uniform_offsets[E->get().order]; +#ifdef DEBUG_ENABLED + uint32_t size = ShaderLanguage::get_type_size(E->get().type); + ERR_CONTINUE(offset + size > p_buffer_size); +#endif + uint8_t *data = &p_buffer[offset]; + const Map::Element *V = p_parameters.find(E->key()); + + if (V) { + //user provided + _fill_std140_variant_ubo_value(E->get().type, V->get(), data, p_use_linear_color); + + } else if (E->get().default_value.size()) { + //default value + _fill_std140_ubo_value(E->get().type, E->get().default_value, data); + //value=E->get().default_value; + } else { + //zero because it was not provided + if (E->get().type == ShaderLanguage::TYPE_VEC4 && E->get().hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + //colors must be set as black, with alpha as 1.0 + _fill_std140_variant_ubo_value(E->get().type, Color(0, 0, 0, 1), data, p_use_linear_color); + } else { + //else just zero it out + _fill_std140_ubo_empty(E->get().type, data); + } + } + } +} + +void RasterizerStorageRD::MaterialData::update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { + + RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton; +#ifdef TOOLS_ENABLED + Texture *roughness_detect_texture = nullptr; + RS::TextureDetectRoughnessChannel roughness_channel; + Texture *normal_detect_texture = nullptr; +#endif + + for (int i = 0; i < p_texture_uniforms.size(); i++) { + + const StringName &uniform_name = p_texture_uniforms[i].name; + + RID texture; + + const Map::Element *V = p_parameters.find(uniform_name); + if (V) { + texture = V->get(); + } + + if (!texture.is_valid()) { + const Map::Element *W = p_default_textures.find(uniform_name); + if (W) { + + texture = W->get(); + } + } + + RID rd_texture; + + if (texture.is_null()) { + //check default usage + switch (p_texture_uniforms[i].hint) { + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: + case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: { + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); + } break; + case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); + } break; + default: { + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + } break; + } + } else { + bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); + + Texture *tex = singleton->texture_owner.getornull(texture); + + if (tex) { + + rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; +#ifdef TOOLS_ENABLED + if (tex->detect_3d_callback && p_use_linear_color) { + tex->detect_3d_callback(tex->detect_3d_callback_ud); + } + if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { + if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { + normal_detect_texture = tex; + } + tex->detect_normal_callback(tex->detect_normal_callback_ud); + } + if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { + //find the normal texture + roughness_detect_texture = tex; + roughness_channel = RS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); + } + +#endif + } + + if (rd_texture.is_null()) { + //wtf + rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); + } + } + + p_textures[i] = rd_texture; + } +#ifdef TOOLS_ENABLED + if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) { + roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); + } +#endif +} + +void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { + Material *material = material_owner.getornull(p_material); + if (material->shader_type != p_shader_type) { + return; + } + if (material->data) { + material->data->update_parameters(material->params, false, true); + } +} + +void RasterizerStorageRD::_update_queued_materials() { + Material *material = material_update_list; + while (material) { + Material *next = material->update_next; + + if (material->data) { + material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); + } + material->update_requested = false; + material->texture_dirty = false; + material->uniform_dirty = false; + material->update_next = NULL; + material = next; + } + material_update_list = NULL; +} +/* MESH API */ + +RID RasterizerStorageRD::mesh_create() { + + return mesh_owner.make_rid(Mesh()); +} + +/// Returns stride +void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface) { + + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + + //ensure blend shape consistency + ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shapes.size() != (int)mesh->blend_shape_count); + ERR_FAIL_COND(mesh->blend_shape_count && p_surface.bone_aabbs.size() != mesh->bone_aabbs.size()); + +#ifdef DEBUG_ENABLED + //do a validation, to catch errors first + { + + uint32_t stride = 0; + + for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { + + if ((p_surface.format & (1 << i))) { + + switch (i) { + + case RS::ARRAY_VERTEX: { + + if (p_surface.format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + stride += sizeof(float) * 2; + } else { + stride += sizeof(float) * 3; + } + + } break; + case RS::ARRAY_NORMAL: { + + if (p_surface.format & RS::ARRAY_COMPRESS_NORMAL) { + stride += sizeof(int8_t) * 4; + } else { + stride += sizeof(float) * 4; + } + + } break; + case RS::ARRAY_TANGENT: { + + if (p_surface.format & RS::ARRAY_COMPRESS_TANGENT) { + stride += sizeof(int8_t) * 4; + } else { + stride += sizeof(float) * 4; + } + + } break; + case RS::ARRAY_COLOR: { + + if (p_surface.format & RS::ARRAY_COMPRESS_COLOR) { + stride += sizeof(int8_t) * 4; + } else { + stride += sizeof(float) * 4; + } + + } break; + case RS::ARRAY_TEX_UV: { + + if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV) { + stride += sizeof(int16_t) * 2; + } else { + stride += sizeof(float) * 2; + } + + } break; + case RS::ARRAY_TEX_UV2: { + + if (p_surface.format & RS::ARRAY_COMPRESS_TEX_UV2) { + stride += sizeof(int16_t) * 2; + } else { + stride += sizeof(float) * 2; + } + + } break; + case RS::ARRAY_BONES: { + //assumed weights too + + //unique format, internally 16 bits, exposed as single array for 32 + + stride += sizeof(int32_t) * 4; + + } break; + } + } + } + + int expected_size = stride * p_surface.vertex_count; + ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); + } + +#endif + + Mesh::Surface *s = memnew(Mesh::Surface); + + s->format = p_surface.format; + s->primitive = p_surface.primitive; + + s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data); + s->vertex_count = p_surface.vertex_count; + + if (p_surface.index_count) { + bool is_index_16 = p_surface.vertex_count <= 65536; + + s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); + s->index_count = p_surface.index_count; + s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); + if (p_surface.lods.size()) { + s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); + s->lod_count = p_surface.lods.size(); + + for (int i = 0; i < p_surface.lods.size(); i++) { + + uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); + s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); + s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); + s->lods[i].edge_length = p_surface.lods[i].edge_length; + } + } + } + + s->aabb = p_surface.aabb; + s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. + + for (int i = 0; i < p_surface.blend_shapes.size(); i++) { + + if (p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()) { + memdelete(s); + ERR_FAIL_COND(p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()); + } + RID vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.blend_shapes[i].size(), p_surface.blend_shapes[i]); + s->blend_shapes.push_back(vertex_buffer); + } + + mesh->blend_shape_count = p_surface.blend_shapes.size(); + + if (mesh->surface_count == 0) { + mesh->bone_aabbs = p_surface.bone_aabbs; + mesh->aabb = p_surface.aabb; + } else { + for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { + mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); + } + mesh->aabb.merge_with(p_surface.aabb); + } + + s->material = p_surface.material; + + mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); + mesh->surfaces[mesh->surface_count] = s; + mesh->surface_count++; + + mesh->instance_dependency.instance_notify_changed(true, true); + + mesh->material_cache.clear(); +} + +int RasterizerStorageRD::mesh_get_blend_shape_count(RID p_mesh) const { + const Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, -1); + return mesh->blend_shape_count; +} + +void RasterizerStorageRD::mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_INDEX((int)p_mode, 2); + + mesh->blend_shape_mode = p_mode; +} +RS::BlendShapeMode RasterizerStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::BLEND_SHAPE_MODE_NORMALIZED); + return mesh->blend_shape_mode; +} + +void RasterizerStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + ERR_FAIL_COND(p_data.size() == 0); + uint64_t data_size = p_data.size(); + const uint8_t *r = p_data.ptr(); + + RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); +} + +void RasterizerStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); + mesh->surfaces[p_surface]->material = p_material; + + mesh->instance_dependency.instance_notify_changed(false, true); + mesh->material_cache.clear(); +} +RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, RID()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); + + return mesh->surfaces[p_surface]->material; +} + +RS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const { + + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::SurfaceData()); + ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RS::SurfaceData()); + + Mesh::Surface &s = *mesh->surfaces[p_surface]; + + RS::SurfaceData sd; + sd.format = s.format; + sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); + sd.vertex_count = s.vertex_count; + sd.index_count = s.index_count; + sd.primitive = s.primitive; + + if (sd.index_count) { + sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); + } + sd.aabb = s.aabb; + for (uint32_t i = 0; i < s.lod_count; i++) { + RS::SurfaceData::LOD lod; + lod.edge_length = s.lods[i].edge_length; + lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); + sd.lods.push_back(lod); + } + + sd.bone_aabbs = s.bone_aabbs; + + for (int i = 0; i < s.blend_shapes.size(); i++) { + Vector bs = RD::get_singleton()->buffer_get_data(s.blend_shapes[i]); + sd.blend_shapes.push_back(bs); + } + + return sd; +} + +int RasterizerStorageRD::mesh_get_surface_count(RID p_mesh) const { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, 0); + return mesh->surface_count; +} + +void RasterizerStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + mesh->custom_aabb = p_aabb; +} +AABB RasterizerStorageRD::mesh_get_custom_aabb(RID p_mesh) const { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, AABB()); + return mesh->custom_aabb; +} + +AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, AABB()); + + if (mesh->custom_aabb != AABB()) { + return mesh->custom_aabb; + } + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + if (!skeleton || skeleton->size == 0) { + return mesh->aabb; + } + + AABB aabb; + + for (uint32_t i = 0; i < mesh->surface_count; i++) { + + AABB laabb; + if ((mesh->surfaces[i]->format & RS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { + + int bs = mesh->surfaces[i]->bone_aabbs.size(); + const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr(); + + int sbs = skeleton->size; + ERR_CONTINUE(bs > sbs); + const float *baseptr = skeleton->data.ptr(); + + bool first = true; + + if (skeleton->use_2d) { + for (int j = 0; j < bs; j++) { + + if (skbones[0].size == Vector3()) + continue; //bone is unused + + const float *dataptr = baseptr + j * 8; + + Transform mtx; + + mtx.basis.elements[0].x = dataptr[0]; + mtx.basis.elements[1].x = dataptr[1]; + mtx.origin.x = dataptr[3]; + + mtx.basis.elements[0].y = dataptr[4]; + mtx.basis.elements[1].y = dataptr[5]; + mtx.origin.y = dataptr[7]; + + AABB baabb = mtx.xform(skbones[j]); + + if (first) { + laabb = baabb; + first = false; + } else { + laabb.merge_with(baabb); + } + } + } else { + for (int j = 0; j < bs; j++) { + + if (skbones[0].size == Vector3()) + continue; //bone is unused + + const float *dataptr = baseptr + j * 12; + + Transform mtx; + + mtx.basis.elements[0][0] = dataptr[0]; + mtx.basis.elements[0][1] = dataptr[1]; + mtx.basis.elements[0][2] = dataptr[2]; + mtx.origin.x = dataptr[3]; + mtx.basis.elements[1][0] = dataptr[4]; + mtx.basis.elements[1][1] = dataptr[5]; + mtx.basis.elements[1][2] = dataptr[6]; + mtx.origin.y = dataptr[7]; + mtx.basis.elements[2][0] = dataptr[8]; + mtx.basis.elements[2][1] = dataptr[9]; + mtx.basis.elements[2][2] = dataptr[10]; + mtx.origin.z = dataptr[11]; + + AABB baabb = mtx.xform(skbones[j]); + if (first) { + laabb = baabb; + first = false; + } else { + laabb.merge_with(baabb); + } + } + } + + if (laabb.size == Vector3()) { + laabb = mesh->surfaces[i]->aabb; + } + } else { + + laabb = mesh->surfaces[i]->aabb; + } + + if (i == 0) { + aabb = laabb; + } else { + aabb.merge_with(laabb); + } + } + + return aabb; +} + +void RasterizerStorageRD::mesh_clear(RID p_mesh) { + + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + for (uint32_t i = 0; i < mesh->surface_count; i++) { + Mesh::Surface &s = *mesh->surfaces[i]; + RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions + if (s.versions) { + memfree(s.versions); //reallocs, so free with memfree. + } + + if (s.index_buffer.is_valid()) { + RD::get_singleton()->free(s.index_buffer); + } + + if (s.lod_count) { + for (uint32_t j = 0; j < s.lod_count; j++) { + RD::get_singleton()->free(s.lods[j].index_buffer); + } + memdelete_arr(s.lods); + } + + for (int32_t j = 0; j < s.blend_shapes.size(); j++) { + RD::get_singleton()->free(s.blend_shapes[j]); + } + + if (s.blend_shape_base_buffer.is_valid()) { + RD::get_singleton()->free(s.blend_shape_base_buffer); + } + + memdelete(mesh->surfaces[i]); + } + if (mesh->surfaces) { + memfree(mesh->surfaces); + } + + mesh->surfaces = nullptr; + mesh->surface_count = 0; + mesh->material_cache.clear(); + mesh->instance_dependency.instance_notify_changed(true, true); +} + +void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask) { + uint32_t version = s->version_count; + s->version_count++; + s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); + + Mesh::Surface::Version &v = s->versions[version]; + + Vector attributes; + Vector buffers; + + uint32_t stride = 0; + + for (int i = 0; i < RS::ARRAY_WEIGHTS; i++) { + + RD::VertexDescription vd; + RID buffer; + vd.location = i; + + if (!(s->format & (1 << i))) { + // Not supplied by surface, use default value + buffer = mesh_default_rd_buffers[i]; + switch (i) { + + case RS::ARRAY_VERTEX: { + + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + + } break; + case RS::ARRAY_NORMAL: { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + } break; + case RS::ARRAY_TANGENT: { + + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + } break; + case RS::ARRAY_COLOR: { + + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + + } break; + case RS::ARRAY_TEX_UV: { + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + + } break; + case RS::ARRAY_TEX_UV2: { + + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + } break; + case RS::ARRAY_BONES: { + + //assumed weights too + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + } break; + } + } else { + //Supplied, use it + + vd.offset = stride; + vd.stride = 1; //mark that it needs a stride set + buffer = s->vertex_buffer; + + switch (i) { + + case RS::ARRAY_VERTEX: { + + if (s->format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + stride += sizeof(float) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; + stride += sizeof(float) * 3; + } + + } break; + case RS::ARRAY_NORMAL: { + + if (s->format & RS::ARRAY_COMPRESS_NORMAL) { + vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM; + stride += sizeof(int8_t) * 4; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + stride += sizeof(float) * 4; + } + + } break; + case RS::ARRAY_TANGENT: { + + if (s->format & RS::ARRAY_COMPRESS_TANGENT) { + vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM; + stride += sizeof(int8_t) * 4; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + stride += sizeof(float) * 4; + } + + } break; + case RS::ARRAY_COLOR: { + + if (s->format & RS::ARRAY_COMPRESS_COLOR) { + vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + stride += sizeof(int8_t) * 4; + } else { + vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; + stride += sizeof(float) * 4; + } + + } break; + case RS::ARRAY_TEX_UV: { + + if (s->format & RS::ARRAY_COMPRESS_TEX_UV) { + vd.format = RD::DATA_FORMAT_R16G16_SFLOAT; + stride += sizeof(int16_t) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + stride += sizeof(float) * 2; + } + + } break; + case RS::ARRAY_TEX_UV2: { + + if (s->format & RS::ARRAY_COMPRESS_TEX_UV2) { + vd.format = RD::DATA_FORMAT_R16G16_SFLOAT; + stride += sizeof(int16_t) * 2; + } else { + vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; + stride += sizeof(float) * 2; + } + + } break; + case RS::ARRAY_BONES: { + //assumed weights too + + //unique format, internally 16 bits, exposed as single array for 32 + + vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; + stride += sizeof(int32_t) * 4; + + } break; + } + } + + if (!(p_input_mask & (1 << i))) { + continue; // Shader does not need this, skip it + } + + attributes.push_back(vd); + buffers.push_back(buffer); + } + + //update final stride + for (int i = 0; i < attributes.size(); i++) { + if (attributes[i].stride == 1) { + attributes.write[i].stride = stride; + } + } + + v.input_mask = p_input_mask; + v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); + v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); +} + +////////////////// MULTIMESH + +RID RasterizerStorageRD::multimesh_create() { + + return multimesh_owner.make_rid(MultiMesh()); +} + +void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + + if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { + return; + } + + if (multimesh->buffer.is_valid()) { + RD::get_singleton()->free(multimesh->buffer); + multimesh->buffer = RID(); + multimesh->uniform_set_3d = RID(); //cleared by dependency + } + + if (multimesh->data_cache_dirty_regions) { + memdelete_arr(multimesh->data_cache_dirty_regions); + multimesh->data_cache_dirty_regions = nullptr; + multimesh->data_cache_used_dirty_regions = 0; + } + + multimesh->instances = p_instances; + multimesh->xform_format = p_transform_format; + multimesh->uses_colors = p_use_colors; + multimesh->color_offset_cache = p_transform_format == RS::MULTIMESH_TRANSFORM_2D ? 8 : 12; + multimesh->uses_custom_data = p_use_custom_data; + multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); + multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); + multimesh->buffer_set = false; + + //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == RS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); + multimesh->data_cache = Vector(); + multimesh->aabb = AABB(); + multimesh->aabb_dirty = false; + multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); + + if (multimesh->instances) { + + multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); + } +} + +int RasterizerStorageRD::multimesh_get_instance_count(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->instances; +} + +void RasterizerStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + if (multimesh->mesh == p_mesh) { + return; + } + multimesh->mesh = p_mesh; + + if (multimesh->instances == 0) { + return; + } + + if (multimesh->data_cache.size()) { + //we have a data cache, just mark it dirt + _multimesh_mark_all_dirty(multimesh, false, true); + } else if (multimesh->instances) { + //need to re-create AABB unfortunately, calling this has a penalty + if (multimesh->buffer_set) { + Vector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + const uint8_t *r = buffer.ptr(); + const float *data = (const float *)r; + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + } + } + + multimesh->instance_dependency.instance_notify_changed(true, true); +} + +#define MULTIMESH_DIRTY_REGION_SIZE 512 + +void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { + if (multimesh->data_cache.size() > 0) { + return; //already local + } + ERR_FAIL_COND(multimesh->data_cache.size() > 0); + // this means that the user wants to load/save individual elements, + // for this, the data must reside on CPU, so just copy it there. + multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); + { + float *w = multimesh->data_cache.ptrw(); + + if (multimesh->buffer_set) { + Vector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + { + + const uint8_t *r = buffer.ptr(); + copymem(w, r, buffer.size()); + } + } else { + zeromem(w, multimesh->instances * multimesh->stride_cache * sizeof(float)); + } + } + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = 0; + } + multimesh->data_cache_used_dirty_regions = 0; +} + +void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { + + uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; +#ifdef DEBUG_ENABLED + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug +#endif + if (!multimesh->data_cache_dirty_regions[region_index]) { + multimesh->data_cache_dirty_regions[region_index] = true; + multimesh->data_cache_used_dirty_regions++; + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { + if (p_data) { + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + if (!multimesh->data_cache_dirty_regions[i]) { + multimesh->data_cache_dirty_regions[i] = true; + multimesh->data_cache_used_dirty_regions++; + } + } + } + + if (p_aabb) { + multimesh->aabb_dirty = true; + } + + if (!multimesh->dirty) { + multimesh->dirty_list = multimesh_dirty_list; + multimesh_dirty_list = multimesh; + multimesh->dirty = true; + } +} + +void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { + + ERR_FAIL_COND(multimesh->mesh.is_null()); + AABB aabb; + AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); + for (int i = 0; i < p_instances; i++) { + const float *data = p_data + multimesh->stride_cache * i; + Transform t; + + if (multimesh->xform_format == RS::MULTIMESH_TRANSFORM_3D) { + + t.basis.elements[0][0] = data[0]; + t.basis.elements[0][1] = data[1]; + t.basis.elements[0][2] = data[2]; + t.origin.x = data[3]; + t.basis.elements[1][0] = data[4]; + t.basis.elements[1][1] = data[5]; + t.basis.elements[1][2] = data[6]; + t.origin.y = data[7]; + t.basis.elements[2][0] = data[8]; + t.basis.elements[2][1] = data[9]; + t.basis.elements[2][2] = data[10]; + t.origin.z = data[11]; + + } else { + + t.basis.elements[0].x = data[0]; + t.basis.elements[1].x = data[1]; + t.origin.x = data[3]; + + t.basis.elements[0].y = data[4]; + t.basis.elements[1].y = data[5]; + t.origin.y = data[7]; + } + + if (i == 0) { + aabb = t.xform(mesh_aabb); + } else { + aabb.merge_with(t.xform(mesh_aabb)); + } + } + + multimesh->aabb = aabb; +} + +void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.basis.elements[0][0]; + dataptr[1] = p_transform.basis.elements[0][1]; + dataptr[2] = p_transform.basis.elements[0][2]; + dataptr[3] = p_transform.origin.x; + dataptr[4] = p_transform.basis.elements[1][0]; + dataptr[5] = p_transform.basis.elements[1][1]; + dataptr[6] = p_transform.basis.elements[1][2]; + dataptr[7] = p_transform.origin.y; + dataptr[8] = p_transform.basis.elements[2][0]; + dataptr[9] = p_transform.basis.elements[2][1]; + dataptr[10] = p_transform.basis.elements[2][2]; + dataptr[11] = p_transform.origin.z; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} + +void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache; + + dataptr[0] = p_transform.elements[0][0]; + dataptr[1] = p_transform.elements[1][0]; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2][0]; + dataptr[4] = p_transform.elements[0][1]; + dataptr[5] = p_transform.elements[1][1]; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2][1]; + } + + _multimesh_mark_dirty(multimesh, p_index, true); +} +void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(!multimesh->uses_colors); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} +void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_INDEX(p_index, multimesh->instances); + ERR_FAIL_COND(!multimesh->uses_custom_data); + + _multimesh_make_local(multimesh); + + { + float *w = multimesh->data_cache.ptrw(); + + float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + dataptr[0] = p_color.r; + dataptr[1] = p_color.g; + dataptr[2] = p_color.b; + dataptr[3] = p_color.a; + } + + _multimesh_mark_dirty(multimesh, p_index, false); +} + +RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, RID()); + + return multimesh->mesh; +} + +Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform()); + ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_3D, Transform()); + + _multimesh_make_local(multimesh); + + Transform t; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache; + + t.basis.elements[0][0] = dataptr[0]; + t.basis.elements[0][1] = dataptr[1]; + t.basis.elements[0][2] = dataptr[2]; + t.origin.x = dataptr[3]; + t.basis.elements[1][0] = dataptr[4]; + t.basis.elements[1][1] = dataptr[5]; + t.basis.elements[1][2] = dataptr[6]; + t.origin.y = dataptr[7]; + t.basis.elements[2][0] = dataptr[8]; + t.basis.elements[2][1] = dataptr[9]; + t.basis.elements[2][2] = dataptr[10]; + t.origin.z = dataptr[11]; + } + + return t; +} +Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Transform2D()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); + ERR_FAIL_COND_V(multimesh->xform_format != RS::MULTIMESH_TRANSFORM_2D, Transform2D()); + + _multimesh_make_local(multimesh); + + Transform2D t; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache; + + t.elements[0][0] = dataptr[0]; + t.elements[1][0] = dataptr[1]; + t.elements[2][0] = dataptr[3]; + t.elements[0][1] = dataptr[4]; + t.elements[1][1] = dataptr[5]; + t.elements[2][1] = dataptr[7]; + } + + return t; +} +Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} +Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Color()); + ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); + ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); + + _multimesh_make_local(multimesh); + + Color c; + { + const float *r = multimesh->data_cache.ptr(); + + const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; + + c.r = dataptr[0]; + c.g = dataptr[1]; + c.b = dataptr[2]; + c.a = dataptr[3]; + } + + return c; +} + +void RasterizerStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); + + { + const float *r = p_buffer.ptr(); + RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r, false); + multimesh->buffer_set = true; + } + + if (multimesh->data_cache.size()) { + //if we have a data cache, just update it + multimesh->data_cache = p_buffer; + { + //clear dirty since nothing will be dirty anymore + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + multimesh->data_cache_used_dirty_regions = 0; + } + + _multimesh_mark_all_dirty(multimesh, false, true); //update AABB + } else if (multimesh->mesh.is_valid()) { + //if we have a mesh set, we need to re-generate the AABB from the new data + const float *data = p_buffer.ptr(); + + _multimesh_re_create_aabb(multimesh, data, multimesh->instances); + multimesh->instance_dependency.instance_notify_changed(true, false); + } +} + +Vector RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, Vector()); + if (multimesh->buffer.is_null()) { + return Vector(); + } else if (multimesh->data_cache.size()) { + return multimesh->data_cache; + } else { + //get from memory + + Vector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); + Vector ret; + ret.resize(multimesh->instances); + { + float *w = multimesh->data_cache.ptrw(); + const uint8_t *r = buffer.ptr(); + copymem(w, r, buffer.size()); + } + + return ret; + } +} + +void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND(!multimesh); + ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); + if (multimesh->visible_instances == p_visible) { + return; + } + + if (multimesh->data_cache.size()) { + //there is a data cache.. + _multimesh_mark_all_dirty(multimesh, false, true); + } + + multimesh->visible_instances = p_visible; +} +int RasterizerStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, 0); + return multimesh->visible_instances; +} + +AABB RasterizerStorageRD::multimesh_get_aabb(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + ERR_FAIL_COND_V(!multimesh, AABB()); + if (multimesh->aabb_dirty) { + const_cast(this)->_update_dirty_multimeshes(); + } + return multimesh->aabb; +} + +void RasterizerStorageRD::_update_dirty_multimeshes() { + + while (multimesh_dirty_list) { + + MultiMesh *multimesh = multimesh_dirty_list; + + if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists + const float *data = multimesh->data_cache.ptr(); + + uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; + + if (multimesh->data_cache_used_dirty_regions) { + + uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; + + uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); + + if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { + //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much + RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache * sizeof(float)), data, false); + } else { + //not that many regions? update them all + for (uint32_t i = 0; i < visible_region_count; i++) { + if (multimesh->data_cache_dirty_regions[i]) { + uint64_t offset = i * region_size; + uint64_t size = multimesh->stride_cache * multimesh->instances * sizeof(float); + RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size], false); + } + } + } + + for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { + multimesh->data_cache_dirty_regions[i] = false; + } + + multimesh->data_cache_used_dirty_regions = 0; + } + + if (multimesh->aabb_dirty) { + //aabb is dirty.. + _multimesh_re_create_aabb(multimesh, data, visible_instances); + multimesh->aabb_dirty = false; + multimesh->instance_dependency.instance_notify_changed(true, false); + } + } + + multimesh_dirty_list = multimesh->dirty_list; + + multimesh->dirty_list = nullptr; + multimesh->dirty = false; + } + + multimesh_dirty_list = nullptr; +} + +/* SKELETON */ + +/* SKELETON API */ + +RID RasterizerStorageRD::skeleton_create() { + + return skeleton_owner.make_rid(Skeleton()); +} + +void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { + + if (!skeleton->dirty) { + skeleton->dirty = true; + skeleton->dirty_list = skeleton_dirty_list; + skeleton_dirty_list = skeleton; + } +} + +void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + ERR_FAIL_COND(p_bones < 0); + + if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) + return; + + skeleton->size = p_bones; + skeleton->use_2d = p_2d_skeleton; + skeleton->uniform_set_3d = RID(); + + if (skeleton->buffer.is_valid()) { + RD::get_singleton()->free(skeleton->buffer); + skeleton->buffer = RID(); + skeleton->data.resize(0); + } + + if (skeleton->size) { + + skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12)); + skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float)); + zeromem(skeleton->data.ptrw(), skeleton->data.size() * sizeof(float)); + + _skeleton_make_dirty(skeleton); + } +} +int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND_V(!skeleton, 0); + + return skeleton->size; +} + +void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone, skeleton->size); + ERR_FAIL_COND(skeleton->use_2d); + + float *dataptr = skeleton->data.ptrw() + p_bone * 12; + + dataptr[0] = p_transform.basis.elements[0][0]; + dataptr[1] = p_transform.basis.elements[0][1]; + dataptr[2] = p_transform.basis.elements[0][2]; + dataptr[3] = p_transform.origin.x; + dataptr[4] = p_transform.basis.elements[1][0]; + dataptr[5] = p_transform.basis.elements[1][1]; + dataptr[6] = p_transform.basis.elements[1][2]; + dataptr[7] = p_transform.origin.y; + dataptr[8] = p_transform.basis.elements[2][0]; + dataptr[9] = p_transform.basis.elements[2][1]; + dataptr[10] = p_transform.basis.elements[2][2]; + dataptr[11] = p_transform.origin.z; + + _skeleton_make_dirty(skeleton); +} + +Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND_V(!skeleton, Transform()); + ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform()); + ERR_FAIL_COND_V(skeleton->use_2d, Transform()); + + const float *dataptr = skeleton->data.ptr() + p_bone * 12; + + Transform t; + + t.basis.elements[0][0] = dataptr[0]; + t.basis.elements[0][1] = dataptr[1]; + t.basis.elements[0][2] = dataptr[2]; + t.origin.x = dataptr[3]; + t.basis.elements[1][0] = dataptr[4]; + t.basis.elements[1][1] = dataptr[5]; + t.basis.elements[1][2] = dataptr[6]; + t.origin.y = dataptr[7]; + t.basis.elements[2][0] = dataptr[8]; + t.basis.elements[2][1] = dataptr[9]; + t.basis.elements[2][2] = dataptr[10]; + t.origin.z = dataptr[11]; + + return t; +} +void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND(!skeleton); + ERR_FAIL_INDEX(p_bone, skeleton->size); + ERR_FAIL_COND(!skeleton->use_2d); + + float *dataptr = skeleton->data.ptrw() + p_bone * 8; + + dataptr[0] = p_transform.elements[0][0]; + dataptr[1] = p_transform.elements[1][0]; + dataptr[2] = 0; + dataptr[3] = p_transform.elements[2][0]; + dataptr[4] = p_transform.elements[0][1]; + dataptr[5] = p_transform.elements[1][1]; + dataptr[6] = 0; + dataptr[7] = p_transform.elements[2][1]; + + _skeleton_make_dirty(skeleton); +} +Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND_V(!skeleton, Transform2D()); + ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); + ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); + + const float *dataptr = skeleton->data.ptr() + p_bone * 8; + + Transform2D t; + t.elements[0][0] = dataptr[0]; + t.elements[1][0] = dataptr[1]; + t.elements[2][0] = dataptr[3]; + t.elements[0][1] = dataptr[4]; + t.elements[1][1] = dataptr[5]; + t.elements[2][1] = dataptr[7]; + + return t; +} + +void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + + ERR_FAIL_COND(!skeleton->use_2d); + + skeleton->base_transform_2d = p_base_transform; +} + +void RasterizerStorageRD::_update_dirty_skeletons() { + + while (skeleton_dirty_list) { + + Skeleton *skeleton = skeleton_dirty_list; + + if (skeleton->size) { + + RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr(), false); + } + + skeleton_dirty_list = skeleton->dirty_list; + + skeleton->instance_dependency.instance_notify_changed(true, false); + + skeleton->dirty = false; + skeleton->dirty_list = nullptr; + } + + skeleton_dirty_list = nullptr; +} + +/* LIGHT */ + +RID RasterizerStorageRD::light_create(RS::LightType p_type) { + + Light light; + light.type = p_type; + + light.param[RS::LIGHT_PARAM_ENERGY] = 1.0; + light.param[RS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0; + light.param[RS::LIGHT_PARAM_SPECULAR] = 0.5; + light.param[RS::LIGHT_PARAM_RANGE] = 1.0; + light.param[RS::LIGHT_PARAM_SPOT_ANGLE] = 45; + light.param[RS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45; + light.param[RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; + light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; + light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; + light.param[RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; + light.param[RS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; + light.param[RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1; + light.param[RS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1; + + return light_owner.make_rid(light); +} + +void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->color = p_color; +} +void RasterizerStorageRD::light_set_param(RID p_light, RS::LightParam p_param, float p_value) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + ERR_FAIL_INDEX(p_param, RS::LIGHT_PARAM_MAX); + + switch (p_param) { + case RS::LIGHT_PARAM_RANGE: + case RS::LIGHT_PARAM_SPOT_ANGLE: + case RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: + case RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: + case RS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: + case RS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: + case RS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: + case RS::LIGHT_PARAM_SHADOW_BIAS: { + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); + } break; + default: { + } + } + + light->param[p_param] = p_value; +} +void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->shadow = p_enabled; + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + light->shadow_color = p_color; +} + +void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->projector = p_texture; +} + +void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->negative = p_enable; +} +void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->cull_mask = p_mask; + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->reverse_cull = p_enabled; + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->use_gi = p_enabled; + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} +void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->omni_shadow_mode = p_mode; + + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +RS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_OMNI_SHADOW_CUBE); + + return light->omni_shadow_mode; +} + +void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_shadow_mode = p_mode; + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_blend_splits = p_enable; + light->version++; + light->instance_dependency.instance_notify_changed(true, false); +} + +bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, false); + + return light->directional_blend_splits; +} + +RS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); + + return light->directional_shadow_mode; +} + +void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode) { + + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND(!light); + + light->directional_range_mode = p_range_mode; +} + +RS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); + + return light->directional_range_mode; +} + +bool RasterizerStorageRD::light_get_use_gi(RID p_light) { + Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, false); + + return light->use_gi; +} + +uint64_t RasterizerStorageRD::light_get_version(RID p_light) const { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->version; +} + +AABB RasterizerStorageRD::light_get_aabb(RID p_light) const { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, AABB()); + + switch (light->type) { + + case RS::LIGHT_SPOT: { + + float len = light->param[RS::LIGHT_PARAM_RANGE]; + float size = Math::tan(Math::deg2rad(light->param[RS::LIGHT_PARAM_SPOT_ANGLE])) * len; + return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); + }; + case RS::LIGHT_OMNI: { + + float r = light->param[RS::LIGHT_PARAM_RANGE]; + return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); + }; + case RS::LIGHT_DIRECTIONAL: { + + return AABB(); + }; + } + + ERR_FAIL_V(AABB()); +} + +/* REFLECTION PROBE */ + +RID RasterizerStorageRD::reflection_probe_create() { + + return reflection_probe_owner.make_rid(ReflectionProbe()); +} + +void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->update_mode = p_mode; + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->intensity = p_intensity; +} + +void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior_ambient = p_ambient; +} + +void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior_ambient_energy = p_energy; +} + +void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior_ambient_probe_contrib = p_contrib; +} + +void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->max_distance = p_distance; + + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} +void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->extents = p_extents; + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} +void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->origin_offset = p_offset; + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->interior = p_enable; + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} +void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->box_projection = p_enable; +} + +void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->enable_shadows = p_enable; + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} +void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + + reflection_probe->cull_mask = p_layers; + reflection_probe->instance_dependency.instance_notify_changed(true, false); +} + +void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) { + + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND(!reflection_probe); + ERR_FAIL_COND(p_resolution < 32); + + reflection_probe->resolution = p_resolution; +} + +AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const { + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, AABB()); + + AABB aabb; + aabb.position = -reflection_probe->extents; + aabb.size = reflection_probe->extents * 2.0; + + return aabb; +} +RS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, RS::REFLECTION_PROBE_UPDATE_ALWAYS); + + return reflection_probe->update_mode; +} + +uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->cull_mask; +} + +Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, Vector3()); + + return reflection_probe->extents; +} +Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, Vector3()); + + return reflection_probe->origin_offset; +} + +bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, false); + + return reflection_probe->enable_shadows; +} + +float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->max_distance; +} + +int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->resolution; +} + +float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->intensity; +} +bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, false); + + return reflection_probe->interior; +} +bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, false); + + return reflection_probe->box_projection; +} + +Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, Color()); + + return reflection_probe->interior_ambient; +} +float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->interior_ambient_energy; +} +float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const { + + const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); + ERR_FAIL_COND_V(!reflection_probe, 0); + + return reflection_probe->interior_ambient_probe_contrib; +} + +RID RasterizerStorageRD::gi_probe_create() { + + return gi_probe_owner.make_rid(GIProbe()); +} + +void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + if (gi_probe->octree_buffer.is_valid()) { + RD::get_singleton()->free(gi_probe->octree_buffer); + RD::get_singleton()->free(gi_probe->data_buffer); + if (gi_probe->sdf_texture.is_valid()) { + RD::get_singleton()->free(gi_probe->sdf_texture); + } + + gi_probe->sdf_texture = RID(); + gi_probe->octree_buffer = RID(); + gi_probe->data_buffer = RID(); + gi_probe->octree_buffer_size = 0; + gi_probe->data_buffer_size = 0; + gi_probe->cell_count = 0; + } + + gi_probe->to_cell_xform = p_to_cell_xform; + gi_probe->bounds = p_aabb; + gi_probe->octree_size = p_octree_size; + gi_probe->level_counts = p_level_counts; + + if (p_octree_cells.size()) { + ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32 + + uint32_t cell_count = p_octree_cells.size() / 32; + + ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches + + gi_probe->cell_count = cell_count; + gi_probe->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells); + gi_probe->octree_buffer_size = p_octree_cells.size(); + gi_probe->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells); + gi_probe->data_buffer_size = p_data_cells.size(); + + if (p_distance_field.size()) { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = gi_probe->octree_size.x; + tf.height = gi_probe->octree_size.y; + tf.depth = gi_probe->octree_size.z; + tf.type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + Vector> s; + s.push_back(p_distance_field); + gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); + } +#if 0 + { + RD::TextureFormat tf; + tf.format = RD::DATA_FORMAT_R8_UNORM; + tf.width = gi_probe->octree_size.x; + tf.height = gi_probe->octree_size.y; + tf.depth = gi_probe->octree_size.z; + tf.type = RD::TEXTURE_TYPE_3D; + tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); + tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); + gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); + } + RID shared_tex; + { + + RD::TextureView tv; + tv.format_override = RD::DATA_FORMAT_R8_UINT; + shared_tex = RD::get_singleton()->texture_create_shared(tv, gi_probe->sdf_texture); + } + //update SDF texture + Vector uniforms; + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 1; + u.ids.push_back(gi_probe->octree_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 2; + u.ids.push_back(gi_probe->data_buffer); + uniforms.push_back(u); + } + { + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_IMAGE; + u.binding = 3; + u.ids.push_back(shared_tex); + uniforms.push_back(u); + } + + RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_sdf_shader_version_shader, 0); + + { + uint32_t push_constant[4] = { 0, 0, 0, 0 }; + + for (int i = 0; i < gi_probe->level_counts.size() - 1; i++) { + push_constant[0] += gi_probe->level_counts[i]; + } + push_constant[1] = push_constant[0] + gi_probe->level_counts[gi_probe->level_counts.size() - 1]; + + print_line("offset: " + itos(push_constant[0])); + print_line("size: " + itos(push_constant[1])); + //create SDF + RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); + RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_sdf_shader_pipeline); + RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0); + RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4); + RD::get_singleton()->compute_list_dispatch(compute_list, gi_probe->octree_size.x / 4, gi_probe->octree_size.y / 4, gi_probe->octree_size.z / 4); + RD::get_singleton()->compute_list_end(); + } + + RD::get_singleton()->free(uniform_set); + RD::get_singleton()->free(shared_tex); + } +#endif + } + + gi_probe->version++; + gi_probe->data_version++; + + gi_probe->instance_dependency.instance_notify_changed(true, false); +} + +AABB RasterizerStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, AABB()); + + return gi_probe->bounds; +} + +Vector3i RasterizerStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, Vector3i()); + return gi_probe->octree_size; +} +Vector RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, Vector()); + + if (gi_probe->octree_buffer.is_valid()) { + return RD::get_singleton()->buffer_get_data(gi_probe->octree_buffer); + } + return Vector(); +} +Vector RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, Vector()); + + if (gi_probe->data_buffer.is_valid()) { + return RD::get_singleton()->buffer_get_data(gi_probe->data_buffer); + } + return Vector(); +} +Vector RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, Vector()); + + if (gi_probe->data_buffer.is_valid()) { + return RD::get_singleton()->texture_get_data(gi_probe->sdf_texture, 0); + } + return Vector(); +} +Vector RasterizerStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, Vector()); + + return gi_probe->level_counts; +} +Transform RasterizerStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, Transform()); + + return gi_probe->to_cell_xform; +} + +void RasterizerStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->dynamic_range = p_range; + gi_probe->version++; +} +float RasterizerStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + + return gi_probe->dynamic_range; +} + +void RasterizerStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->propagation = p_range; + gi_probe->version++; +} +float RasterizerStorageRD::gi_probe_get_propagation(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->propagation; +} + +void RasterizerStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->energy = p_energy; +} +float RasterizerStorageRD::gi_probe_get_energy(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->energy; +} + +void RasterizerStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->ao = p_ao; +} +float RasterizerStorageRD::gi_probe_get_ao(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->ao; +} + +void RasterizerStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) { + + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->ao_size = p_strength; +} + +float RasterizerStorageRD::gi_probe_get_ao_size(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->ao_size; +} + +void RasterizerStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->bias = p_bias; +} +float RasterizerStorageRD::gi_probe_get_bias(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->bias; +} + +void RasterizerStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->normal_bias = p_normal_bias; +} +float RasterizerStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->normal_bias; +} + +void RasterizerStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) { + + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->anisotropy_strength = p_strength; +} + +float RasterizerStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->anisotropy_strength; +} + +void RasterizerStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->interior = p_enable; +} + +void RasterizerStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND(!gi_probe); + + gi_probe->use_two_bounces = p_enable; + gi_probe->version++; +} + +bool RasterizerStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, false); + return gi_probe->use_two_bounces; +} + +bool RasterizerStorageRD::gi_probe_is_interior(RID p_gi_probe) const { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->interior; +} + +uint32_t RasterizerStorageRD::gi_probe_get_version(RID p_gi_probe) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->version; +} + +uint32_t RasterizerStorageRD::gi_probe_get_data_version(RID p_gi_probe) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, 0); + return gi_probe->data_version; +} + +RID RasterizerStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const { + + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, RID()); + return gi_probe->octree_buffer; +} +RID RasterizerStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const { + + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, RID()); + return gi_probe->data_buffer; +} + +RID RasterizerStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { + GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); + ERR_FAIL_COND_V(!gi_probe, RID()); + + return gi_probe->sdf_texture; +} + +/* RENDER TARGET API */ + +void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { + + //free in reverse dependency order + if (rt->framebuffer.is_valid()) { + RD::get_singleton()->free(rt->framebuffer); + } + + if (rt->color.is_valid()) { + RD::get_singleton()->free(rt->color); + } + + if (rt->backbuffer.is_valid()) { + RD::get_singleton()->free(rt->backbuffer); + rt->backbuffer = RID(); + rt->backbuffer_fb = RID(); + for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { + //just erase copies, since the rest are erased by dependency + RD::get_singleton()->free(rt->backbuffer_mipmaps[i].mipmap_copy); + } + rt->backbuffer_mipmaps.clear(); + if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) { + RD::get_singleton()->free(rt->backbuffer_uniform_set); + } + rt->backbuffer_uniform_set = RID(); + } + + rt->framebuffer = RID(); + rt->color = RID(); +} + +void RasterizerStorageRD::_update_render_target(RenderTarget *rt) { + + if (rt->texture.is_null()) { + //create a placeholder until updated + rt->texture = texture_2d_placeholder_create(); + Texture *tex = texture_owner.getornull(rt->texture); + tex->is_render_target = true; + } + + _clear_render_target(rt); + + if (rt->size.width == 0 || rt->size.height == 0) { + return; + } + //until we implement support for HDR monitors (and render target is attached to screen), this is enough. + rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; + rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8; + + RD::TextureFormat rd_format; + RD::TextureView rd_view; + { //attempt register + rd_format.format = rt->color_format; + rd_format.width = rt->size.width; + rd_format.height = rt->size.height; + rd_format.depth = 1; + rd_format.array_layers = 1; + rd_format.mipmaps = 1; + rd_format.type = RD::TEXTURE_TYPE_2D; + rd_format.samples = RD::TEXTURE_SAMPLES_1; + rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; + rd_format.shareable_formats.push_back(rt->color_format); + rd_format.shareable_formats.push_back(rt->color_format_srgb); + } + + rt->color = RD::get_singleton()->texture_create(rd_format, rd_view); + ERR_FAIL_COND(rt->color.is_null()); + + Vector fb_textures; + fb_textures.push_back(rt->color); + rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures); + if (rt->framebuffer.is_null()) { + _clear_render_target(rt); + ERR_FAIL_COND(rt->framebuffer.is_null()); + } + + { //update texture + + Texture *tex = texture_owner.getornull(rt->texture); + + //free existing textures + if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { + RD::get_singleton()->free(tex->rd_texture); + } + if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { + RD::get_singleton()->free(tex->rd_texture_srgb); + } + + tex->rd_texture = RID(); + tex->rd_texture_srgb = RID(); + + //create shared textures to the color buffer, + //so transparent can be supported + RD::TextureView view; + view.format_override = rt->color_format; + if (!rt->flags[RENDER_TARGET_TRANSPARENT]) { + view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; + } + tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color); + if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) { + view.format_override = rt->color_format_srgb; + tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color); + } + tex->rd_view = view; + tex->width = rt->size.width; + tex->height = rt->size.height; + tex->width_2d = rt->size.width; + tex->height_2d = rt->size.height; + tex->rd_format = rt->color_format; + tex->rd_format_srgb = rt->color_format_srgb; + tex->format = rt->image_format; + + Vector proxies = tex->proxies; //make a copy, since update may change it + for (int i = 0; i < proxies.size(); i++) { + texture_proxy_update(proxies[i], rt->texture); + } + } +} + +void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { + ERR_FAIL_COND(rt->backbuffer.is_valid()); + + uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8); + RD::TextureFormat tf; + tf.format = rt->color_format; + tf.width = rt->size.width; + tf.height = rt->size.height; + tf.type = RD::TEXTURE_TYPE_2D; + tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; + tf.mipmaps = mipmaps_required; + + rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); + + { + Vector backbuffer_att; + RID backbuffer_fb_tex = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0); + backbuffer_att.push_back(backbuffer_fb_tex); + rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(backbuffer_att); + } + + //create mipmaps + for (uint32_t i = 1; i < mipmaps_required; i++) { + + RenderTarget::BackbufferMipmap mm; + { + mm.mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i); + Vector mm_fb_at; + mm_fb_at.push_back(mm.mipmap); + mm.mipmap_fb = RD::get_singleton()->framebuffer_create(mm_fb_at); + } + + { + Size2 mm_size = Image::get_image_mipmap_size(tf.width, tf.height, Image::FORMAT_RGBA8, i); + + RD::TextureFormat mmtf = tf; + mmtf.width = mm_size.width; + mmtf.height = mm_size.height; + mmtf.mipmaps = 1; + + mm.mipmap_copy = RD::get_singleton()->texture_create(mmtf, RD::TextureView()); + Vector mm_fb_at; + mm_fb_at.push_back(mm.mipmap_copy); + mm.mipmap_copy_fb = RD::get_singleton()->framebuffer_create(mm_fb_at); + } + + rt->backbuffer_mipmaps.push_back(mm); + } +} + +RID RasterizerStorageRD::render_target_create() { + RenderTarget render_target; + + render_target.was_used = false; + render_target.clear_requested = false; + + for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { + render_target.flags[i] = false; + } + _update_render_target(&render_target); + return render_target_owner.make_rid(render_target); +} + +void RasterizerStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) { + //unused for this render target +} + +void RasterizerStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->size.x = p_width; + rt->size.y = p_height; + _update_render_target(rt); +} + +RID RasterizerStorageRD::render_target_get_texture(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->texture; +} + +void RasterizerStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { +} + +void RasterizerStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->flags[p_flag] = p_value; + _update_render_target(rt); +} + +bool RasterizerStorageRD::render_target_was_used(RID p_render_target) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, false); + return rt->was_used; +} + +void RasterizerStorageRD::render_target_set_as_unused(RID p_render_target) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->was_used = false; +} + +Size2 RasterizerStorageRD::render_target_get_size(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, Size2()); + + return rt->size; +} + +RID RasterizerStorageRD::render_target_get_rd_framebuffer(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + return rt->framebuffer; +} + +void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->clear_requested = true; + rt->clear_color = p_clear_color; +} + +bool RasterizerStorageRD::render_target_is_clear_requested(RID p_render_target) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, false); + return rt->clear_requested; +} + +Color RasterizerStorageRD::render_target_get_clear_request_color(RID p_render_target) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, Color()); + return rt->clear_color; +} + +void RasterizerStorageRD::render_target_disable_clear_request(RID p_render_target) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + rt->clear_requested = false; +} + +void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) { + + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + if (!rt->clear_requested) { + return; + } + Vector clear_colors; + clear_colors.push_back(rt->clear_color); + RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); + RD::get_singleton()->draw_list_end(); + rt->clear_requested = false; +} + +void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND(!rt); + if (!rt->backbuffer.is_valid()) { + _create_render_target_backbuffer(rt); + } + + Rect2i region = p_region; + Rect2 blur_region; + if (region == Rect2i()) { + region.size = rt->size; + } else { + blur_region = region; + blur_region.position /= rt->size; + blur_region.size /= rt->size; + } + + //single texture copy for backbuffer + RD::get_singleton()->texture_copy(rt->color, rt->backbuffer, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); + //effects.copy(rt->color, rt->backbuffer_fb, blur_region); + + //then mipmap blur + RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps. + Vector2 pixel_size = Vector2(1.0 / rt->size.width, 1.0 / rt->size.height); + + for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { + pixel_size *= 2.0; //go halfway + const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i]; + effects.gaussian_blur(prev_texture, mm.mipmap_copy_fb, mm.mipmap_copy, mm.mipmap_fb, pixel_size, blur_region); + prev_texture = mm.mipmap; + } +} + +RID RasterizerStorageRD::render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader) { + RenderTarget *rt = render_target_owner.getornull(p_render_target); + ERR_FAIL_COND_V(!rt, RID()); + + if (!rt->backbuffer.is_valid()) { + _create_render_target_backbuffer(rt); + } + + if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) { + return rt->backbuffer_uniform_set; //if still valid, return/reuse it. + } + + //create otherwise + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_TEXTURE; + u.binding = 0; + u.ids.push_back(rt->backbuffer); + uniforms.push_back(u); + + rt->backbuffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, 3); + ERR_FAIL_COND_V(!rt->backbuffer_uniform_set.is_valid(), RID()); + + return rt->backbuffer_uniform_set; +} + +void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { + if (mesh_owner.owns(p_base)) { + Mesh *mesh = mesh_owner.getornull(p_base); + p_instance->update_dependency(&mesh->instance_dependency); + } else if (multimesh_owner.owns(p_base)) { + + MultiMesh *multimesh = multimesh_owner.getornull(p_base); + p_instance->update_dependency(&multimesh->instance_dependency); + if (multimesh->mesh.is_valid()) { + base_update_dependency(multimesh->mesh, p_instance); + } + } else if (reflection_probe_owner.owns(p_base)) { + ReflectionProbe *rp = reflection_probe_owner.getornull(p_base); + p_instance->update_dependency(&rp->instance_dependency); + } else if (gi_probe_owner.owns(p_base)) { + GIProbe *gip = gi_probe_owner.getornull(p_base); + p_instance->update_dependency(&gip->instance_dependency); + } else if (light_owner.owns(p_base)) { + Light *l = light_owner.getornull(p_base); + p_instance->update_dependency(&l->instance_dependency); + } +} + +void RasterizerStorageRD::skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { + + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND(!skeleton); + + p_instance->update_dependency(&skeleton->instance_dependency); +} + +RS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { + + if (mesh_owner.owns(p_rid)) { + return RS::INSTANCE_MESH; + } + if (multimesh_owner.owns(p_rid)) { + return RS::INSTANCE_MULTIMESH; + } + if (reflection_probe_owner.owns(p_rid)) { + return RS::INSTANCE_REFLECTION_PROBE; + } + if (gi_probe_owner.owns(p_rid)) { + return RS::INSTANCE_GI_PROBE; + } + if (light_owner.owns(p_rid)) { + return RS::INSTANCE_LIGHT; + } + + return RS::INSTANCE_NONE; +} +void RasterizerStorageRD::update_dirty_resources() { + _update_queued_materials(); + _update_dirty_multimeshes(); + _update_dirty_skeletons(); +} + +bool RasterizerStorageRD::has_os_feature(const String &p_feature) const { + + if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + if (p_feature == "pvrtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT)) { + return true; + } + + return false; +} +bool RasterizerStorageRD::free(RID p_rid) { + + if (texture_owner.owns(p_rid)) { + Texture *t = texture_owner.getornull(p_rid); + + ERR_FAIL_COND_V(t->is_render_target, false); + + if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) { + //erase this first, as it's a dependency of the one below + RD::get_singleton()->free(t->rd_texture_srgb); + } + if (RD::get_singleton()->texture_is_valid(t->rd_texture)) { + RD::get_singleton()->free(t->rd_texture); + } + + if (t->is_proxy && t->proxy_to.is_valid()) { + Texture *proxy_to = texture_owner.getornull(t->proxy_to); + if (proxy_to) { + proxy_to->proxies.erase(p_rid); + } + } + + for (int i = 0; i < t->proxies.size(); i++) { + Texture *p = texture_owner.getornull(t->proxies[i]); + ERR_CONTINUE(!p); + p->proxy_to = RID(); + p->rd_texture = RID(); + p->rd_texture_srgb = RID(); + } + texture_owner.free(p_rid); + + } else if (shader_owner.owns(p_rid)) { + Shader *shader = shader_owner.getornull(p_rid); + //make material unreference this + while (shader->owners.size()) { + material_set_shader(shader->owners.front()->get()->self, RID()); + } + //clear data if exists + if (shader->data) { + memdelete(shader->data); + } + shader_owner.free(p_rid); + + } else if (material_owner.owns(p_rid)) { + Material *material = material_owner.getornull(p_rid); + if (material->update_requested) { + _update_queued_materials(); + } + material_set_shader(p_rid, RID()); //clean up shader + material->instance_dependency.instance_notify_deleted(p_rid); + material_owner.free(p_rid); + } else if (mesh_owner.owns(p_rid)) { + mesh_clear(p_rid); + Mesh *mesh = mesh_owner.getornull(p_rid); + mesh->instance_dependency.instance_notify_deleted(p_rid); + mesh_owner.free(p_rid); + } else if (multimesh_owner.owns(p_rid)) { + _update_dirty_multimeshes(); + multimesh_allocate(p_rid, 0, RS::MULTIMESH_TRANSFORM_2D); + MultiMesh *multimesh = multimesh_owner.getornull(p_rid); + multimesh->instance_dependency.instance_notify_deleted(p_rid); + multimesh_owner.free(p_rid); + } else if (skeleton_owner.owns(p_rid)) { + _update_dirty_skeletons(); + skeleton_allocate(p_rid, 0); + Skeleton *skeleton = skeleton_owner.getornull(p_rid); + skeleton->instance_dependency.instance_notify_deleted(p_rid); + skeleton_owner.free(p_rid); + } else if (reflection_probe_owner.owns(p_rid)) { + ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); + reflection_probe->instance_dependency.instance_notify_deleted(p_rid); + reflection_probe_owner.free(p_rid); + } else if (gi_probe_owner.owns(p_rid)) { + gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector(), Vector(), Vector(), Vector()); //deallocate + GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); + gi_probe->instance_dependency.instance_notify_deleted(p_rid); + gi_probe_owner.free(p_rid); + + } else if (light_owner.owns(p_rid)) { + + // delete the texture + Light *light = light_owner.getornull(p_rid); + light->instance_dependency.instance_notify_deleted(p_rid); + light_owner.free(p_rid); + + } else if (render_target_owner.owns(p_rid)) { + RenderTarget *rt = render_target_owner.getornull(p_rid); + + _clear_render_target(rt); + + if (rt->texture.is_valid()) { + Texture *tex = texture_owner.getornull(rt->texture); + tex->is_render_target = false; + free(rt->texture); + } + + render_target_owner.free(p_rid); + } else { + return false; + } + + return true; +} + +RasterizerEffectsRD *RasterizerStorageRD::get_effects() { + return &effects; +} + +void RasterizerStorageRD::capture_timestamps_begin() { + RD::get_singleton()->capture_timestamp("Frame Begin", false); +} + +void RasterizerStorageRD::capture_timestamp(const String &p_name) { + RD::get_singleton()->capture_timestamp(p_name, true); +} + +uint32_t RasterizerStorageRD::get_captured_timestamps_count() const { + return RD::get_singleton()->get_captured_timestamps_count(); +} +uint64_t RasterizerStorageRD::get_captured_timestamps_frame() const { + return RD::get_singleton()->get_captured_timestamps_frame(); +} + +uint64_t RasterizerStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const { + return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index); +} +uint64_t RasterizerStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const { + return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index); +} +String RasterizerStorageRD::get_captured_timestamp_name(uint32_t p_index) const { + return RD::get_singleton()->get_captured_timestamp_name(p_index); +} + +RasterizerStorageRD::RasterizerStorageRD() { + + for (int i = 0; i < SHADER_TYPE_MAX; i++) { + shader_data_request_func[i] = NULL; + } + + material_update_list = NULL; + { //create default textures + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_2D; + + Vector pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 255); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 255); + } + + { + Vector> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 128); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 255); + pv.set(i * 4 + 1, 128); + pv.set(i * 4 + 2, 255); + pv.set(i * 4 + 3, 255); + } + + { + Vector> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); + } + + { //create default cubemap + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY; + + Vector pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default cubemap array + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.array_layers = 6; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_CUBE; + + Vector pv; + pv.resize(16 * 4); + for (int i = 0; i < 16; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector> vpv; + for (int i = 0; i < 6; i++) { + vpv.push_back(pv); + } + default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + { //create default 3D + + RD::TextureFormat tformat; + tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; + tformat.width = 4; + tformat.height = 4; + tformat.depth = 4; + tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; + tformat.type = RD::TEXTURE_TYPE_3D; + + Vector pv; + pv.resize(64 * 4); + for (int i = 0; i < 64; i++) { + pv.set(i * 4 + 0, 0); + pv.set(i * 4 + 1, 0); + pv.set(i * 4 + 2, 0); + pv.set(i * 4 + 3, 0); + } + + { + Vector> vpv; + vpv.push_back(pv); + default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); + } + } + + //default samplers + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + RD::SamplerState sampler_state; + switch (i) { + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.max_lod = 0; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { + + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.max_lod = 0; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.use_anisotropy = true; + sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy"); + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.use_anisotropy = true; + sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy"); + + } break; + default: { + } + } + switch (j) { + case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { + + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + } break; + default: { + } + } + + default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); + } + } + + //default rd buffers + { + + { //vertex + + Vector buffer; + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} + +{ //normal + Vector buffer; + buffer.resize(sizeof(float) * 3); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} + +{ //tangent + Vector buffer; + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} + +{ //color + Vector buffer; + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 1.0; + fptr[1] = 1.0; + fptr[2] = 1.0; + fptr[3] = 1.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} + +{ //tex uv 1 + Vector buffer; + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} +{ //tex uv 2 + Vector buffer; + buffer.resize(sizeof(float) * 2); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} + +{ //bones + Vector buffer; + buffer.resize(sizeof(uint32_t) * 4); + { + uint8_t *w = buffer.ptrw(); + uint32_t *fptr = (uint32_t *)w; + fptr[0] = 0; + fptr[1] = 0; + fptr[2] = 0; + fptr[3] = 0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} + +{ //weights + Vector buffer; + buffer.resize(sizeof(float) * 4); + { + uint8_t *w = buffer.ptrw(); + float *fptr = (float *)w; + fptr[0] = 0.0; + fptr[1] = 0.0; + fptr[2] = 0.0; + fptr[3] = 0.0; + } + mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); +} +} + +{ + Vector sdf_versions; + sdf_versions.push_back(""); //one only + giprobe_sdf_shader.initialize(sdf_versions); + giprobe_sdf_shader_version = giprobe_sdf_shader.version_create(); + giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector()); + giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0); + giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader); +} +} + +RasterizerStorageRD::~RasterizerStorageRD() { + + //def textures + for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { + RD::get_singleton()->free(default_rd_textures[i]); + } + + //def samplers + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + RD::get_singleton()->free(default_rd_samplers[i][j]); + } + } + + //def buffers + for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { + RD::get_singleton()->free(mesh_default_rd_buffers[i]); + } + giprobe_sdf_shader.version_free(giprobe_sdf_shader_version); +} diff --git a/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h new file mode 100644 index 0000000000..e69be644d7 --- /dev/null +++ b/servers/rendering/rasterizer_rd/rasterizer_storage_rd.h @@ -0,0 +1,1135 @@ +/*************************************************************************/ +/* rasterizer_storage_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RASTERIZER_STORAGE_RD_H +#define RASTERIZER_STORAGE_RD_H + +#include "core/rid_owner.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering/rasterizer_rd/rasterizer_effects_rd.h" +#include "servers/rendering/rasterizer_rd/shader_compiler_rd.h" +#include "servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl.gen.h" +#include "servers/rendering/rendering_device.h" + +class RasterizerStorageRD : public RasterizerStorage { +public: + enum ShaderType { + SHADER_TYPE_2D, + SHADER_TYPE_3D, + SHADER_TYPE_PARTICLES, + SHADER_TYPE_SKY, + SHADER_TYPE_MAX + }; + + struct ShaderData { + virtual void set_code(const String &p_Code) = 0; + virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0; + virtual void get_param_list(List *p_param_list) const = 0; + virtual bool is_param_texture(const StringName &p_param) const = 0; + virtual bool is_animated() const = 0; + virtual bool casts_shadows() const = 0; + virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; + virtual ~ShaderData() {} + }; + + typedef ShaderData *(*ShaderDataRequestFunction)(); + + struct MaterialData { + + void update_uniform_buffer(const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Map &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); + void update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); + + virtual void set_render_priority(int p_priority) = 0; + virtual void set_next_pass(RID p_pass) = 0; + virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; + virtual ~MaterialData() {} + }; + typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); + + enum DefaultRDTexture { + DEFAULT_RD_TEXTURE_WHITE, + DEFAULT_RD_TEXTURE_BLACK, + DEFAULT_RD_TEXTURE_NORMAL, + DEFAULT_RD_TEXTURE_ANISO, + DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, + DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, + DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, + DEFAULT_RD_TEXTURE_3D_WHITE, + DEFAULT_RD_TEXTURE_MAX + }; + + enum DefaultRDBuffer { + DEFAULT_RD_BUFFER_VERTEX, + DEFAULT_RD_BUFFER_NORMAL, + DEFAULT_RD_BUFFER_TANGENT, + DEFAULT_RD_BUFFER_COLOR, + DEFAULT_RD_BUFFER_TEX_UV, + DEFAULT_RD_BUFFER_TEX_UV2, + DEFAULT_RD_BUFFER_BONES, + DEFAULT_RD_BUFFER_WEIGHTS, + DEFAULT_RD_BUFFER_MAX, + }; + +private: + /* TEXTURE API */ + struct Texture { + + enum Type { + TYPE_2D, + TYPE_LAYERED, + TYPE_3D + }; + + Type type; + + RenderingDevice::TextureType rd_type; + RID rd_texture; + RID rd_texture_srgb; + RenderingDevice::DataFormat rd_format; + RenderingDevice::DataFormat rd_format_srgb; + + RD::TextureView rd_view; + + Image::Format format; + Image::Format validated_format; + + int width; + int height; + int depth; + int layers; + int mipmaps; + + int height_2d; + int width_2d; + + bool is_render_target; + bool is_proxy; + + Ref image_cache_2d; + String path; + + RID proxy_to; + Vector proxies; + + RS::TextureDetectCallback detect_3d_callback = nullptr; + void *detect_3d_callback_ud = nullptr; + + RS::TextureDetectCallback detect_normal_callback = nullptr; + void *detect_normal_callback_ud = nullptr; + + RS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; + void *detect_roughness_callback_ud = nullptr; + }; + + struct TextureToRDFormat { + RD::DataFormat format; + RD::DataFormat format_srgb; + RD::TextureSwizzle swizzle_r; + RD::TextureSwizzle swizzle_g; + RD::TextureSwizzle swizzle_b; + RD::TextureSwizzle swizzle_a; + TextureToRDFormat() { + format = RD::DATA_FORMAT_MAX; + format_srgb = RD::DATA_FORMAT_MAX; + swizzle_r = RD::TEXTURE_SWIZZLE_R; + swizzle_g = RD::TEXTURE_SWIZZLE_G; + swizzle_b = RD::TEXTURE_SWIZZLE_B; + swizzle_a = RD::TEXTURE_SWIZZLE_A; + } + }; + + //textures can be created from threads, so this RID_Owner is thread safe + mutable RID_Owner texture_owner; + + Ref _validate_texture_format(const Ref &p_image, TextureToRDFormat &r_format); + + RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; + RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + + /* SHADER */ + + struct Material; + + struct Shader { + ShaderData *data; + String code; + ShaderType type; + Map default_texture_parameter; + Set owners; + }; + + ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner shader_owner; + + /* Material */ + + struct Material { + RID self; + MaterialData *data; + Shader *shader; + //shortcut to shader data and type + ShaderType shader_type; + bool update_requested; + bool uniform_dirty; + bool texture_dirty; + Material *update_next; + Map params; + int32_t priority; + RID next_pass; + RasterizerScene::InstanceDependency instance_dependency; + }; + + MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; + mutable RID_Owner material_owner; + + Material *material_update_list; + void _material_queue_update(Material *material, bool p_uniform, bool p_texture); + void _update_queued_materials(); + + /* Mesh */ + + struct Mesh { + + struct Surface { + RS::PrimitiveType primitive; + uint32_t format = 0; + + RID vertex_buffer; + uint32_t vertex_count = 0; + + // A different pipeline needs to be allocated + // depending on the inputs available in the + // material. + // There are never that many geometry/material + // combinations, so a simple array is the most + // cache-efficient structure. + + struct Version { + uint32_t input_mask; + RD::VertexFormatID vertex_format; + RID vertex_array; + }; + + SpinLock version_lock; //needed to access versions + Version *versions = nullptr; //allocated on demand + uint32_t version_count = 0; + + RID index_buffer; + RID index_array; + uint32_t index_count = 0; + + struct LOD { + float edge_length; + RID index_buffer; + RID index_array; + }; + + LOD *lods = nullptr; + uint32_t lod_count = 0; + + AABB aabb; + + Vector bone_aabbs; + + Vector blend_shapes; + RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed + + RID material; + + uint32_t render_index = 0; + uint64_t render_pass = 0; + + uint32_t multimesh_render_index = 0; + uint64_t multimesh_render_pass = 0; + }; + + uint32_t blend_shape_count = 0; + RS::BlendShapeMode blend_shape_mode = RS::BLEND_SHAPE_MODE_NORMALIZED; + + Surface **surfaces = nullptr; + uint32_t surface_count = 0; + + Vector bone_aabbs; + + AABB aabb; + AABB custom_aabb; + + Vector material_cache; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + mutable RID_Owner mesh_owner; + + void _mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask); + + RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; + + /* MultiMesh */ + struct MultiMesh { + RID mesh; + int instances = 0; + RS::MultimeshTransformFormat xform_format = RS::MULTIMESH_TRANSFORM_3D; + bool uses_colors = false; + bool uses_custom_data = false; + int visible_instances = -1; + AABB aabb; + bool aabb_dirty = false; + bool buffer_set = false; + uint32_t stride_cache = 0; + uint32_t color_offset_cache = 0; + uint32_t custom_data_offset_cache = 0; + + Vector data_cache; //used if individual setting is used + bool *data_cache_dirty_regions = nullptr; + uint32_t data_cache_used_dirty_regions = 0; + + RID buffer; //storage buffer + RID uniform_set_3d; + + bool dirty = false; + MultiMesh *dirty_list = nullptr; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + mutable RID_Owner multimesh_owner; + + MultiMesh *multimesh_dirty_list = nullptr; + + _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; + _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); + _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); + _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); + void _update_dirty_multimeshes(); + + /* Skeleton */ + + struct Skeleton { + bool use_2d = false; + int size = 0; + Vector data; + RID buffer; + + bool dirty = false; + Skeleton *dirty_list = nullptr; + Transform2D base_transform_2d; + + RID uniform_set_3d; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + mutable RID_Owner skeleton_owner; + + _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton); + + Skeleton *skeleton_dirty_list = nullptr; + + void _update_dirty_skeletons(); + + /* LIGHT */ + + struct Light { + + RS::LightType type; + float param[RS::LIGHT_PARAM_MAX]; + Color color = Color(1, 1, 1, 1); + Color shadow_color; + RID projector; + bool shadow = false; + bool negative = false; + bool reverse_cull = false; + bool use_gi = true; + uint32_t cull_mask = 0xFFFFFFFF; + RS::LightOmniShadowMode omni_shadow_mode = RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; + RS::LightDirectionalShadowMode directional_shadow_mode = RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; + RS::LightDirectionalShadowDepthRangeMode directional_range_mode = RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; + bool directional_blend_splits = false; + uint64_t version = 0; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + mutable RID_Owner light_owner; + + /* REFLECTION PROBE */ + + struct ReflectionProbe { + + RS::ReflectionProbeUpdateMode update_mode = RS::REFLECTION_PROBE_UPDATE_ONCE; + int resolution = 256; + float intensity = 1.0; + Color interior_ambient; + float interior_ambient_energy = 1.0; + float interior_ambient_probe_contrib = 0.0; + float max_distance = 0; + Vector3 extents = Vector3(1, 1, 1); + Vector3 origin_offset; + bool interior = false; + bool box_projection = false; + bool enable_shadows = false; + uint32_t cull_mask = (1 << 20) - 1; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + mutable RID_Owner reflection_probe_owner; + + /* GI PROBE */ + + struct GIProbe { + + RID octree_buffer; + RID data_buffer; + RID sdf_texture; + + uint32_t octree_buffer_size = 0; + uint32_t data_buffer_size = 0; + + Vector level_counts; + + int cell_count = 0; + + Transform to_cell_xform; + AABB bounds; + Vector3i octree_size; + + float dynamic_range = 4.0; + float energy = 1.0; + float ao = 0.0; + float ao_size = 0.5; + float bias = 1.4; + float normal_bias = 0.0; + float propagation = 0.7; + bool interior = false; + bool use_two_bounces = false; + + float anisotropy_strength = 0.5; + + uint32_t version = 1; + uint32_t data_version = 1; + + RasterizerScene::InstanceDependency instance_dependency; + }; + + GiprobeSdfShaderRD giprobe_sdf_shader; + RID giprobe_sdf_shader_version; + RID giprobe_sdf_shader_version_shader; + RID giprobe_sdf_shader_pipeline; + + mutable RID_Owner gi_probe_owner; + + /* RENDER TARGET */ + + struct RenderTarget { + + Size2i size; + RID framebuffer; + RID color; + + //used for retrieving from CPU + RD::DataFormat color_format; + RD::DataFormat color_format_srgb; + Image::Format image_format; + + bool flags[RENDER_TARGET_FLAG_MAX]; + + RID backbuffer; //used for effects + RID backbuffer_fb; + + struct BackbufferMipmap { + RID mipmap; + RID mipmap_fb; + RID mipmap_copy; + RID mipmap_copy_fb; + }; + + Vector backbuffer_mipmaps; + RID backbuffer_uniform_set; + + //texture generated for this owner (nor RD). + RID texture; + bool was_used; + + //clear request + bool clear_requested; + Color clear_color; + }; + + RID_Owner render_target_owner; + + void _clear_render_target(RenderTarget *rt); + void _update_render_target(RenderTarget *rt); + void _create_render_target_backbuffer(RenderTarget *rt); + + /* EFFECTS */ + + RasterizerEffectsRD effects; + +public: + /* TEXTURE API */ + + virtual RID texture_2d_create(const Ref &p_image); + virtual RID texture_2d_layered_create(const Vector> &p_layers, RS::TextureLayeredType p_layered_type); + virtual RID texture_3d_create(const Vector> &p_slices); //all slices, then all the mipmaps, must be coherent + virtual RID texture_proxy_create(RID p_base); + + virtual void _texture_2d_update(RID p_texture, const Ref &p_image, int p_layer, bool p_immediate); + + virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0); //mostly used for video and streaming + virtual void texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0); + virtual void texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap); + virtual void texture_proxy_update(RID p_texture, RID p_proxy_to); + + //these two APIs can be used together or in combination with the others. + virtual RID texture_2d_placeholder_create(); + virtual RID texture_2d_layered_placeholder_create(); + virtual RID texture_3d_placeholder_create(); + + virtual Ref texture_2d_get(RID p_texture) const; + virtual Ref texture_2d_layer_get(RID p_texture, int p_layer) const; + virtual Ref texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const; + + virtual void texture_replace(RID p_texture, RID p_by_texture); + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); + + virtual void texture_set_path(RID p_texture, const String &p_path); + virtual String texture_get_path(RID p_texture) const; + + virtual void texture_set_detect_3d_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_normal_callback(RID p_texture, RS::TextureDetectCallback p_callback, void *p_userdata); + virtual void texture_set_detect_roughness_callback(RID p_texture, RS::TextureDetectRoughnessCallback p_callback, void *p_userdata); + + virtual void texture_debug_usage(List *r_info); + + virtual void texture_set_proxy(RID p_proxy, RID p_base); + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); + + virtual Size2 texture_size_with_proxy(RID p_proxy); + + //internal usage + + _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { + if (p_texture.is_null()) { + return RID(); + } + Texture *tex = texture_owner.getornull(p_texture); + + if (!tex) { + return RID(); + } + return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; + } + + _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { + if (p_texture.is_null()) { + return Size2i(); + } + Texture *tex = texture_owner.getornull(p_texture); + + if (!tex) { + return Size2i(); + } + return Size2i(tex->width_2d, tex->height_2d); + } + + _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { + return default_rd_textures[p_texture]; + } + _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { + return default_rd_samplers[p_filter][p_repeat]; + } + + /* SHADER API */ + + RID shader_create(); + + void shader_set_code(RID p_shader, const String &p_code); + String shader_get_code(RID p_shader) const; + void shader_get_param_list(RID p_shader, List *p_param_list) const; + + void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture); + RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const; + Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; + void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); + + /* COMMON MATERIAL API */ + + RID material_create(); + + void material_set_shader(RID p_material, RID p_shader); + + void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value); + Variant material_get_param(RID p_material, const StringName &p_param) const; + + void material_set_next_pass(RID p_material, RID p_next_material); + void material_set_render_priority(RID p_material, int priority); + + bool material_is_animated(RID p_material); + bool material_casts_shadows(RID p_material); + + void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance); + void material_force_update_textures(RID p_material, ShaderType p_shader_type); + + void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); + + _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { + Material *material = material_owner.getornull(p_material); + if (!material || material->shader_type != p_shader_type) { + return NULL; + } else { + return material->data; + } + } + + /* MESH API */ + + virtual RID mesh_create(); + + /// Return stride + virtual void mesh_add_surface(RID p_mesh, const RS::SurfaceData &p_surface); + + virtual int mesh_get_blend_shape_count(RID p_mesh) const; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, RS::BlendShapeMode p_mode); + virtual RS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; + + virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data); + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; + + virtual RS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const; + + virtual int mesh_get_surface_count(RID p_mesh) const; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); + virtual AABB mesh_get_custom_aabb(RID p_mesh) const; + + virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()); + + virtual void mesh_clear(RID p_mesh); + + _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, NULL); + r_surface_count = mesh->surface_count; + if (r_surface_count == 0) { + return NULL; + } + if (mesh->material_cache.empty()) { + mesh->material_cache.resize(mesh->surface_count); + for (uint32_t i = 0; i < r_surface_count; i++) { + mesh->material_cache.write[i] = mesh->surfaces[i]->material; + } + } + + return mesh->material_cache.ptr(); + } + + _FORCE_INLINE_ RS::PrimitiveType mesh_surface_get_primitive(RID p_mesh, uint32_t p_surface_index) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND_V(!mesh, RS::PRIMITIVE_MAX); + ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, RS::PRIMITIVE_MAX); + + return mesh->surfaces[p_surface_index]->primitive; + } + + _FORCE_INLINE_ void mesh_surface_get_arrays_and_format(RID p_mesh, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RID &r_index_array_rd, RD::VertexFormatID &r_vertex_format) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + ERR_FAIL_COND(!mesh); + ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); + + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + r_index_array_rd = s->index_array; + + s->version_lock.lock(); + + //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way + + for (uint32_t i = 0; i < s->version_count; i++) { + if (s->versions[i].input_mask != p_input_mask) { + continue; + } + //we have this version, hooray + r_vertex_format = s->versions[i].vertex_format; + r_vertex_array_rd = s->versions[i].vertex_array; + s->version_lock.unlock(); + return; + } + + uint32_t version = s->version_count; //gets added at the end + + _mesh_surface_generate_version_for_input_mask(s, p_input_mask); + + r_vertex_format = s->versions[version].vertex_format; + r_vertex_array_rd = s->versions[version].vertex_array; + + s->version_lock.unlock(); + } + + _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { + ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); + return mesh_default_rd_buffers[p_buffer]; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->render_pass != p_render_pass) { + (*r_index)++; + s->render_pass = p_render_pass; + s->render_index = *r_index; + } + + return s->render_index; + } + + _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { + Mesh *mesh = mesh_owner.getornull(p_mesh); + Mesh::Surface *s = mesh->surfaces[p_surface_index]; + + if (s->multimesh_render_pass != p_render_pass) { + (*r_index)++; + s->multimesh_render_pass = p_render_pass; + s->multimesh_render_index = *r_index; + } + + return s->multimesh_render_index; + } + + /* MULTIMESH API */ + + RID multimesh_create(); + + void multimesh_allocate(RID p_multimesh, int p_instances, RS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false); + int multimesh_get_instance_count(RID p_multimesh) const; + + void multimesh_set_mesh(RID p_multimesh, RID p_mesh); + void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform); + void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); + void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); + void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color); + + RID multimesh_get_mesh(RID p_multimesh) const; + + Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const; + Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; + Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; + Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; + + void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer); + Vector multimesh_get_buffer(RID p_multimesh) const; + + void multimesh_set_visible_instances(RID p_multimesh, int p_visible); + int multimesh_get_visible_instances(RID p_multimesh) const; + + AABB multimesh_get_aabb(RID p_multimesh) const; + + _FORCE_INLINE_ RS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + return multimesh->xform_format; + } + + _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + return multimesh->uses_colors; + } + + _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + return multimesh->uses_custom_data; + } + + _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + if (multimesh->visible_instances >= 0) { + return multimesh->visible_instances; + } + return multimesh->instances; + } + + _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { + MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); + if (!multimesh->uniform_set_3d.is_valid()) { + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(multimesh->buffer); + uniforms.push_back(u); + multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return multimesh->uniform_set_3d; + } + + /* IMMEDIATE API */ + + RID immediate_create() { return RID(); } + void immediate_begin(RID p_immediate, RS::PrimitiveType p_rimitive, RID p_texture = RID()) {} + void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {} + void immediate_normal(RID p_immediate, const Vector3 &p_normal) {} + void immediate_tangent(RID p_immediate, const Plane &p_tangent) {} + void immediate_color(RID p_immediate, const Color &p_color) {} + void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {} + void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {} + void immediate_end(RID p_immediate) {} + void immediate_clear(RID p_immediate) {} + void immediate_set_material(RID p_immediate, RID p_material) {} + RID immediate_get_material(RID p_immediate) const { return RID(); } + AABB immediate_get_aabb(RID p_immediate) const { return AABB(); } + + /* SKELETON API */ + + RID skeleton_create(); + void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false); + void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); + void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform); + int skeleton_get_bone_count(RID p_skeleton) const; + void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform); + Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; + void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); + Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; + + _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { + Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); + ERR_FAIL_COND_V(!skeleton, RID()); + ERR_FAIL_COND_V(skeleton->size == 0, RID()); + if (skeleton->use_2d) { + return RID(); + } + if (!skeleton->uniform_set_3d.is_valid()) { + Vector uniforms; + RD::Uniform u; + u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; + u.binding = 0; + u.ids.push_back(skeleton->buffer); + uniforms.push_back(u); + skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); + } + + return skeleton->uniform_set_3d; + } + /* Light API */ + + RID light_create(RS::LightType p_type); + + RID directional_light_create() { return light_create(RS::LIGHT_DIRECTIONAL); } + RID omni_light_create() { return light_create(RS::LIGHT_OMNI); } + RID spot_light_create() { return light_create(RS::LIGHT_SPOT); } + + void light_set_color(RID p_light, const Color &p_color); + void light_set_param(RID p_light, RS::LightParam p_param, float p_value); + void light_set_shadow(RID p_light, bool p_enabled); + void light_set_shadow_color(RID p_light, const Color &p_color); + void light_set_projector(RID p_light, RID p_texture); + void light_set_negative(RID p_light, bool p_enable); + void light_set_cull_mask(RID p_light, uint32_t p_mask); + void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); + void light_set_use_gi(RID p_light, bool p_enabled); + + void light_omni_set_shadow_mode(RID p_light, RS::LightOmniShadowMode p_mode); + + void light_directional_set_shadow_mode(RID p_light, RS::LightDirectionalShadowMode p_mode); + void light_directional_set_blend_splits(RID p_light, bool p_enable); + bool light_directional_get_blend_splits(RID p_light) const; + void light_directional_set_shadow_depth_range_mode(RID p_light, RS::LightDirectionalShadowDepthRangeMode p_range_mode); + RS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; + + RS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); + RS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); + + _FORCE_INLINE_ RS::LightType light_get_type(RID p_light) const { + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + + return light->type; + } + AABB light_get_aabb(RID p_light) const; + + _FORCE_INLINE_ float light_get_param(RID p_light, RS::LightParam p_param) { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->param[p_param]; + } + + _FORCE_INLINE_ Color light_get_color(RID p_light) { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, Color()); + + return light->color; + } + + _FORCE_INLINE_ Color light_get_shadow_color(RID p_light) { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, Color()); + + return light->shadow_color; + } + + _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, 0); + + return light->cull_mask; + } + + _FORCE_INLINE_ bool light_has_shadow(RID p_light) const { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + + return light->shadow; + } + + _FORCE_INLINE_ bool light_is_negative(RID p_light) const { + + const Light *light = light_owner.getornull(p_light); + ERR_FAIL_COND_V(!light, RS::LIGHT_DIRECTIONAL); + + return light->negative; + } + + bool light_get_use_gi(RID p_light); + uint64_t light_get_version(RID p_light) const; + + /* PROBE API */ + + RID reflection_probe_create(); + + void reflection_probe_set_update_mode(RID p_probe, RS::ReflectionProbeUpdateMode p_mode); + void reflection_probe_set_intensity(RID p_probe, float p_intensity); + void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient); + void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); + void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib); + void reflection_probe_set_max_distance(RID p_probe, float p_distance); + void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents); + void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset); + void reflection_probe_set_as_interior(RID p_probe, bool p_enable); + void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable); + void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable); + void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); + void reflection_probe_set_resolution(RID p_probe, int p_resolution); + + AABB reflection_probe_get_aabb(RID p_probe) const; + RS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; + uint32_t reflection_probe_get_cull_mask(RID p_probe) const; + Vector3 reflection_probe_get_extents(RID p_probe) const; + Vector3 reflection_probe_get_origin_offset(RID p_probe) const; + float reflection_probe_get_origin_max_distance(RID p_probe) const; + int reflection_probe_get_resolution(RID p_probe) const; + bool reflection_probe_renders_shadows(RID p_probe) const; + + float reflection_probe_get_intensity(RID p_probe) const; + bool reflection_probe_is_interior(RID p_probe) const; + bool reflection_probe_is_box_projection(RID p_probe) const; + Color reflection_probe_get_interior_ambient(RID p_probe) const; + float reflection_probe_get_interior_ambient_energy(RID p_probe) const; + float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const; + + void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); + void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); + + /* GI PROBE API */ + + RID gi_probe_create(); + + void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts); + + AABB gi_probe_get_bounds(RID p_gi_probe) const; + Vector3i gi_probe_get_octree_size(RID p_gi_probe) const; + Vector gi_probe_get_octree_cells(RID p_gi_probe) const; + Vector gi_probe_get_data_cells(RID p_gi_probe) const; + Vector gi_probe_get_distance_field(RID p_gi_probe) const; + + Vector gi_probe_get_level_counts(RID p_gi_probe) const; + Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const; + + void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range); + float gi_probe_get_dynamic_range(RID p_gi_probe) const; + + void gi_probe_set_propagation(RID p_gi_probe, float p_range); + float gi_probe_get_propagation(RID p_gi_probe) const; + + void gi_probe_set_energy(RID p_gi_probe, float p_energy); + float gi_probe_get_energy(RID p_gi_probe) const; + + void gi_probe_set_ao(RID p_gi_probe, float p_ao); + float gi_probe_get_ao(RID p_gi_probe) const; + + void gi_probe_set_ao_size(RID p_gi_probe, float p_strength); + float gi_probe_get_ao_size(RID p_gi_probe) const; + + void gi_probe_set_bias(RID p_gi_probe, float p_bias); + float gi_probe_get_bias(RID p_gi_probe) const; + + void gi_probe_set_normal_bias(RID p_gi_probe, float p_range); + float gi_probe_get_normal_bias(RID p_gi_probe) const; + + void gi_probe_set_interior(RID p_gi_probe, bool p_enable); + bool gi_probe_is_interior(RID p_gi_probe) const; + + void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable); + bool gi_probe_is_using_two_bounces(RID p_gi_probe) const; + + void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength); + float gi_probe_get_anisotropy_strength(RID p_gi_probe) const; + + uint32_t gi_probe_get_version(RID p_probe); + uint32_t gi_probe_get_data_version(RID p_probe); + + RID gi_probe_get_octree_buffer(RID p_gi_probe) const; + RID gi_probe_get_data_buffer(RID p_gi_probe) const; + + RID gi_probe_get_sdf_texture(RID p_gi_probe); + + /* LIGHTMAP CAPTURE */ + + void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {} + AABB lightmap_capture_get_bounds(RID p_capture) const { return AABB(); } + void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) {} + RID lightmap_capture_create() { + return RID(); + } + Vector lightmap_capture_get_octree(RID p_capture) const { + return Vector(); + } + void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {} + Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const { return Transform(); } + void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {} + int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { return 0; } + void lightmap_capture_set_energy(RID p_capture, float p_energy) {} + float lightmap_capture_get_energy(RID p_capture) const { return 0.0; } + const Vector *lightmap_capture_get_octree_ptr(RID p_capture) const { + return NULL; + } + + /* PARTICLES */ + + RID particles_create() { return RID(); } + + void particles_set_emitting(RID p_particles, bool p_emitting) {} + void particles_set_amount(RID p_particles, int p_amount) {} + void particles_set_lifetime(RID p_particles, float p_lifetime) {} + void particles_set_one_shot(RID p_particles, bool p_one_shot) {} + void particles_set_pre_process_time(RID p_particles, float p_time) {} + void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) {} + void particles_set_randomness_ratio(RID p_particles, float p_ratio) {} + void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {} + void particles_set_speed_scale(RID p_particles, float p_scale) {} + void particles_set_use_local_coordinates(RID p_particles, bool p_enable) {} + void particles_set_process_material(RID p_particles, RID p_material) {} + void particles_set_fixed_fps(RID p_particles, int p_fps) {} + void particles_set_fractional_delta(RID p_particles, bool p_enable) {} + void particles_restart(RID p_particles) {} + + void particles_set_draw_order(RID p_particles, RS::ParticlesDrawOrder p_order) {} + + void particles_set_draw_passes(RID p_particles, int p_count) {} + void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {} + + void particles_request_process(RID p_particles) {} + AABB particles_get_current_aabb(RID p_particles) { return AABB(); } + AABB particles_get_aabb(RID p_particles) const { return AABB(); } + + void particles_set_emission_transform(RID p_particles, const Transform &p_transform) {} + + bool particles_get_emitting(RID p_particles) { return false; } + int particles_get_draw_passes(RID p_particles) const { return 0; } + RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { return RID(); } + + virtual bool particles_is_inactive(RID p_particles) const { return false; } + + /* RENDER TARGET API */ + + RID render_target_create(); + void render_target_set_position(RID p_render_target, int p_x, int p_y); + void render_target_set_size(RID p_render_target, int p_width, int p_height); + RID render_target_get_texture(RID p_render_target); + void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id); + void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); + bool render_target_was_used(RID p_render_target); + void render_target_set_as_unused(RID p_render_target); + void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region); + RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader); + + virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color); + virtual bool render_target_is_clear_requested(RID p_render_target); + virtual Color render_target_get_clear_request_color(RID p_render_target); + virtual void render_target_disable_clear_request(RID p_render_target); + virtual void render_target_do_clear_request(RID p_render_target); + + Size2 render_target_get_size(RID p_render_target); + RID render_target_get_rd_framebuffer(RID p_render_target); + + RS::InstanceType get_base_type(RID p_rid) const; + + bool free(RID p_rid); + + bool has_os_feature(const String &p_feature) const; + + void update_dirty_resources(); + + void set_debug_generate_wireframes(bool p_generate) {} + + void render_info_begin_capture() {} + void render_info_end_capture() {} + int get_captured_render_info(RS::RenderInfo p_info) { return 0; } + + int get_render_info(RS::RenderInfo p_info) { return 0; } + String get_video_adapter_name() const { return String(); } + String get_video_adapter_vendor() const { return String(); } + + virtual void capture_timestamps_begin(); + virtual void capture_timestamp(const String &p_name); + virtual uint32_t get_captured_timestamps_count() const; + virtual uint64_t get_captured_timestamps_frame() const; + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const; + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; + virtual String get_captured_timestamp_name(uint32_t p_index) const; + + static RasterizerStorage *base_singleton; + + RasterizerEffectsRD *get_effects(); + + RasterizerStorageRD(); + ~RasterizerStorageRD(); +}; + +#endif // RASTERIZER_STORAGE_RD_H diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp new file mode 100644 index 0000000000..4ee020aa69 --- /dev/null +++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp @@ -0,0 +1,97 @@ +/*************************************************************************/ +/* render_pipeline_vertex_format_cache_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "render_pipeline_vertex_format_cache_rd.h" +#include "core/os/memory.h" + +RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { + + RD::PipelineMultisampleState multisample_state_version = multisample_state; + multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id); + + RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, rasterization_state, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags); + ERR_FAIL_COND_V(pipeline.is_null(), RID()); + versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); + versions[version_count].framebuffer_id = p_framebuffer_format_id; + versions[version_count].vertex_id = p_vertex_format_id; + versions[version_count].pipeline = pipeline; + version_count++; + return pipeline; +} + +void RenderPipelineVertexFormatCacheRD::_clear() { + + if (versions) { + for (uint32_t i = 0; i < version_count; i++) { + //shader may be gone, so this may not be valid + if (RD::get_singleton()->render_pipeline_is_valid(versions[i].pipeline)) { + RD::get_singleton()->free(versions[i].pipeline); + } + } + version_count = 0; + memfree(versions); + versions = NULL; + } +} + +void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) { + ERR_FAIL_COND(p_shader.is_null()); + _clear(); + shader = p_shader; + input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(p_shader); + render_primitive = p_primitive; + rasterization_state = p_rasterization_state; + multisample_state = p_multisample; + depth_stencil_state = p_depth_stencil_state; + blend_state = p_blend_state; + dynamic_state_flags = p_dynamic_state_flags; +} + +void RenderPipelineVertexFormatCacheRD::update_shader(RID p_shader) { + ERR_FAIL_COND(p_shader.is_null()); + _clear(); + setup(p_shader, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags); +} + +void RenderPipelineVertexFormatCacheRD::clear() { + _clear(); + shader = RID(); //clear shader + input_mask = 0; +} + +RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() { + version_count = 0; + versions = NULL; + input_mask = 0; +} + +RenderPipelineVertexFormatCacheRD::~RenderPipelineVertexFormatCacheRD() { + _clear(); +} diff --git a/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h new file mode 100644 index 0000000000..ecb1b42b06 --- /dev/null +++ b/servers/rendering/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h @@ -0,0 +1,96 @@ +/*************************************************************************/ +/* render_pipeline_vertex_format_cache_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDER_PIPELINE_CACHE_RD_H +#define RENDER_PIPELINE_CACHE_RD_H + +#include "core/spin_lock.h" +#include "servers/rendering/rendering_device.h" + +class RenderPipelineVertexFormatCacheRD { + + SpinLock spin_lock; + + RID shader; + uint32_t input_mask; + + RD::RenderPrimitive render_primitive; + RD::PipelineRasterizationState rasterization_state; + RD::PipelineMultisampleState multisample_state; + RD::PipelineDepthStencilState depth_stencil_state; + RD::PipelineColorBlendState blend_state; + int dynamic_state_flags; + + struct Version { + RD::VertexFormatID vertex_id; + RD::FramebufferFormatID framebuffer_id; + RID pipeline; + }; + + Version *versions; + uint32_t version_count; + + RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id); + + void _clear(); + +public: + void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0); + void update_shader(RID p_shader); + + _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { +#ifdef DEBUG_ENABLED + ERR_FAIL_COND_V_MSG(shader.is_null(), RID(), + "Attempted to use an unused shader variant (shader is null),"); +#endif + + spin_lock.lock(); + RID result; + for (uint32_t i = 0; i < version_count; i++) { + if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) { + result = versions[i].pipeline; + spin_lock.unlock(); + return result; + } + } + result = _generate_version(p_vertex_format_id, p_framebuffer_format_id); + spin_lock.unlock(); + return result; + } + + _FORCE_INLINE_ uint32_t get_vertex_input_mask() const { + return input_mask; + } + void clear(); + RenderPipelineVertexFormatCacheRD(); + ~RenderPipelineVertexFormatCacheRD(); +}; + +#endif // RENDER_PIPELINE_CACHE_RD_H diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp new file mode 100644 index 0000000000..b3a4b0ede8 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.cpp @@ -0,0 +1,1243 @@ +/*************************************************************************/ +/* shader_compiler_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shader_compiler_rd.h" + +#include "core/os/os.h" +#include "core/project_settings.h" + +#define SL ShaderLanguage + +static String _mktab(int p_level) { + + String tb; + for (int i = 0; i < p_level; i++) { + tb += "\t"; + } + + return tb; +} + +static String _typestr(SL::DataType p_type) { + + String type = ShaderLanguage::get_datatype_name(p_type); + if (ShaderLanguage::is_sampler_type(p_type)) { + type = type.replace("sampler", "texture"); //we use textures instead of samplers + } + return type; +} + +static int _get_datatype_size(SL::DataType p_type) { + + switch (p_type) { + + case SL::TYPE_VOID: return 0; + case SL::TYPE_BOOL: return 4; + case SL::TYPE_BVEC2: return 8; + case SL::TYPE_BVEC3: return 12; + case SL::TYPE_BVEC4: return 16; + case SL::TYPE_INT: return 4; + case SL::TYPE_IVEC2: return 8; + case SL::TYPE_IVEC3: return 12; + case SL::TYPE_IVEC4: return 16; + case SL::TYPE_UINT: return 4; + case SL::TYPE_UVEC2: return 8; + case SL::TYPE_UVEC3: return 12; + case SL::TYPE_UVEC4: return 16; + case SL::TYPE_FLOAT: return 4; + case SL::TYPE_VEC2: return 8; + case SL::TYPE_VEC3: return 12; + case SL::TYPE_VEC4: return 16; + case SL::TYPE_MAT2: + return 32; //4 * 4 + 4 * 4 + case SL::TYPE_MAT3: + return 48; // 4 * 4 + 4 * 4 + 4 * 4 + case SL::TYPE_MAT4: return 64; + case SL::TYPE_SAMPLER2D: return 16; + case SL::TYPE_ISAMPLER2D: return 16; + case SL::TYPE_USAMPLER2D: return 16; + case SL::TYPE_SAMPLER2DARRAY: return 16; + case SL::TYPE_ISAMPLER2DARRAY: return 16; + case SL::TYPE_USAMPLER2DARRAY: return 16; + case SL::TYPE_SAMPLER3D: return 16; + case SL::TYPE_ISAMPLER3D: return 16; + case SL::TYPE_USAMPLER3D: return 16; + case SL::TYPE_SAMPLERCUBE: return 16; + case SL::TYPE_STRUCT: return 0; + } + + ERR_FAIL_V(0); +} + +static int _get_datatype_alignment(SL::DataType p_type) { + + switch (p_type) { + + case SL::TYPE_VOID: return 0; + case SL::TYPE_BOOL: return 4; + case SL::TYPE_BVEC2: return 8; + case SL::TYPE_BVEC3: return 16; + case SL::TYPE_BVEC4: return 16; + case SL::TYPE_INT: return 4; + case SL::TYPE_IVEC2: return 8; + case SL::TYPE_IVEC3: return 16; + case SL::TYPE_IVEC4: return 16; + case SL::TYPE_UINT: return 4; + case SL::TYPE_UVEC2: return 8; + case SL::TYPE_UVEC3: return 16; + case SL::TYPE_UVEC4: return 16; + case SL::TYPE_FLOAT: return 4; + case SL::TYPE_VEC2: return 8; + case SL::TYPE_VEC3: return 16; + case SL::TYPE_VEC4: return 16; + case SL::TYPE_MAT2: return 16; + case SL::TYPE_MAT3: return 16; + case SL::TYPE_MAT4: return 16; + case SL::TYPE_SAMPLER2D: return 16; + case SL::TYPE_ISAMPLER2D: return 16; + case SL::TYPE_USAMPLER2D: return 16; + case SL::TYPE_SAMPLER2DARRAY: return 16; + case SL::TYPE_ISAMPLER2DARRAY: return 16; + case SL::TYPE_USAMPLER2DARRAY: return 16; + case SL::TYPE_SAMPLER3D: return 16; + case SL::TYPE_ISAMPLER3D: return 16; + case SL::TYPE_USAMPLER3D: return 16; + case SL::TYPE_SAMPLERCUBE: return 16; + case SL::TYPE_STRUCT: return 0; + } + + ERR_FAIL_V(0); +} +static String _interpstr(SL::DataInterpolation p_interp) { + + switch (p_interp) { + case SL::INTERPOLATION_FLAT: return "flat "; + case SL::INTERPOLATION_SMOOTH: return ""; + } + return ""; +} + +static String _prestr(SL::DataPrecision p_pres) { + + switch (p_pres) { + case SL::PRECISION_LOWP: return "lowp "; + case SL::PRECISION_MEDIUMP: return "mediump "; + case SL::PRECISION_HIGHP: return "highp "; + case SL::PRECISION_DEFAULT: return ""; + } + return ""; +} + +static String _qualstr(SL::ArgumentQualifier p_qual) { + + switch (p_qual) { + case SL::ARGUMENT_QUALIFIER_IN: return ""; + case SL::ARGUMENT_QUALIFIER_OUT: return "out "; + case SL::ARGUMENT_QUALIFIER_INOUT: return "inout "; + } + return ""; +} + +static String _opstr(SL::Operator p_op) { + + return SL::get_operator_text(p_op); +} + +static String _mkid(const String &p_id) { + + String id = "m_" + p_id.replace("__", "_dus_"); + return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl +} + +static String f2sp0(float p_float) { + + String num = rtoss(p_float); + if (num.find(".") == -1 && num.find("e") == -1) { + num += ".0"; + } + return num; +} + +static String get_constant_text(SL::DataType p_type, const Vector &p_values) { + + switch (p_type) { + case SL::TYPE_BOOL: return p_values[0].boolean ? "true" : "false"; + case SL::TYPE_BVEC2: + case SL::TYPE_BVEC3: + case SL::TYPE_BVEC4: { + + String text = "bvec" + itos(p_type - SL::TYPE_BOOL + 1) + "("; + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += p_values[i].boolean ? "true" : "false"; + } + text += ")"; + return text; + } + + case SL::TYPE_INT: return itos(p_values[0].sint); + case SL::TYPE_IVEC2: + case SL::TYPE_IVEC3: + case SL::TYPE_IVEC4: { + + String text = "ivec" + itos(p_type - SL::TYPE_INT + 1) + "("; + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += itos(p_values[i].sint); + } + text += ")"; + return text; + + } break; + case SL::TYPE_UINT: return itos(p_values[0].uint) + "u"; + case SL::TYPE_UVEC2: + case SL::TYPE_UVEC3: + case SL::TYPE_UVEC4: { + + String text = "uvec" + itos(p_type - SL::TYPE_UINT + 1) + "("; + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += itos(p_values[i].uint) + "u"; + } + text += ")"; + return text; + } break; + case SL::TYPE_FLOAT: return f2sp0(p_values[0].real); + case SL::TYPE_VEC2: + case SL::TYPE_VEC3: + case SL::TYPE_VEC4: { + + String text = "vec" + itos(p_type - SL::TYPE_FLOAT + 1) + "("; + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += f2sp0(p_values[i].real); + } + text += ")"; + return text; + + } break; + case SL::TYPE_MAT2: + case SL::TYPE_MAT3: + case SL::TYPE_MAT4: { + + String text = "mat" + itos(p_type - SL::TYPE_MAT2 + 2) + "("; + for (int i = 0; i < p_values.size(); i++) { + if (i > 0) + text += ","; + + text += f2sp0(p_values[i].real); + } + text += ")"; + return text; + + } break; + default: ERR_FAIL_V(String()); + } +} + +String ShaderCompilerRD::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat) { + if (p_filter == ShaderLanguage::FILTER_DEFAULT) { + ERR_FAIL_COND_V(actions.default_filter == ShaderLanguage::FILTER_DEFAULT, String()); + p_filter = actions.default_filter; + } + if (p_repeat == ShaderLanguage::REPEAT_DEFAULT) { + ERR_FAIL_COND_V(actions.default_repeat == ShaderLanguage::REPEAT_DEFAULT, String()); + p_repeat = actions.default_repeat; + } + return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]"; +} + +void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map &p_func_code, String &r_to_add, Set &added) { + + int fidx = -1; + + for (int i = 0; i < p_node->functions.size(); i++) { + if (p_node->functions[i].name == p_for_func) { + fidx = i; + break; + } + } + + ERR_FAIL_COND(fidx == -1); + + for (Set::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { + + if (added.has(E->get())) { + continue; //was added already + } + + _dump_function_deps(p_node, E->get(), p_func_code, r_to_add, added); + + SL::FunctionNode *fnode = NULL; + + for (int i = 0; i < p_node->functions.size(); i++) { + if (p_node->functions[i].name == E->get()) { + fnode = p_node->functions[i].function; + break; + } + } + + ERR_FAIL_COND(!fnode); + + r_to_add += "\n"; + + String header; + if (fnode->return_type == SL::TYPE_STRUCT) { + header = _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "("; + } else { + header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "("; + } + for (int i = 0; i < fnode->arguments.size(); i++) { + + if (i > 0) + header += ", "; + if (fnode->arguments[i].type == SL::TYPE_STRUCT) { + header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name); + } else { + header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name); + } + } + + header += ")\n"; + r_to_add += header; + r_to_add += p_func_code[E->get()]; + + added.insert(E->get()); + } +} + +String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) { + + String code; + + switch (p_node->type) { + + case SL::Node::TYPE_SHADER: { + + SL::ShaderNode *pnode = (SL::ShaderNode *)p_node; + + for (int i = 0; i < pnode->render_modes.size(); i++) { + + if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) { + + r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]]); + used_rmode_defines.insert(pnode->render_modes[i]); + } + + if (p_actions.render_mode_flags.has(pnode->render_modes[i])) { + *p_actions.render_mode_flags[pnode->render_modes[i]] = true; + } + + if (p_actions.render_mode_values.has(pnode->render_modes[i])) { + Pair &p = p_actions.render_mode_values[pnode->render_modes[i]]; + *p.first = p.second; + } + } + + // structs + + for (int i = 0; i < pnode->vstructs.size(); i++) { + + SL::StructNode *st = pnode->vstructs[i].shader_struct; + String struct_code; + + struct_code += "struct "; + struct_code += _mkid(pnode->vstructs[i].name); + struct_code += " "; + struct_code += "{\n"; + for (int j = 0; j < st->members.size(); j++) { + SL::MemberNode *m = st->members[j]; + if (m->datatype == SL::TYPE_STRUCT) { + struct_code += _mkid(m->struct_name); + } else { + struct_code += _prestr(m->precision); + struct_code += _typestr(m->datatype); + } + struct_code += " "; + struct_code += m->name; + if (m->array_size > 0) { + struct_code += "["; + struct_code += itos(m->array_size); + struct_code += "]"; + } + struct_code += ";\n"; + } + struct_code += "}"; + struct_code += ";\n"; + + r_gen_code.vertex_global += struct_code; + r_gen_code.fragment_global += struct_code; + } + + int max_texture_uniforms = 0; + int max_uniforms = 0; + + for (Map::Element *E = pnode->uniforms.front(); E; E = E->next()) { + if (SL::is_sampler_type(E->get().type)) + max_texture_uniforms++; + else + max_uniforms++; + } + + r_gen_code.texture_uniforms.resize(max_texture_uniforms); + + Vector uniform_sizes; + Vector uniform_alignments; + Vector uniform_defines; + uniform_sizes.resize(max_uniforms); + uniform_alignments.resize(max_uniforms); + uniform_defines.resize(max_uniforms); + bool uses_uniforms = false; + + for (Map::Element *E = pnode->uniforms.front(); E; E = E->next()) { + + String ucode; + + if (SL::is_sampler_type(E->get().type)) { + ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + E->get().texture_order) + ") uniform "; + } + + ucode += _prestr(E->get().precision); + ucode += _typestr(E->get().type); + ucode += " " + _mkid(E->key()); + ucode += ";\n"; + if (SL::is_sampler_type(E->get().type)) { + r_gen_code.vertex_global += ucode; + r_gen_code.fragment_global += ucode; + + GeneratedCode::Texture texture; + texture.name = E->key(); + texture.hint = E->get().hint; + texture.type = E->get().type; + texture.filter = E->get().filter; + texture.repeat = E->get().repeat; + + r_gen_code.texture_uniforms.write[E->get().texture_order] = texture; + } else { + if (!uses_uniforms) { + + r_gen_code.defines.push_back(String("#define USE_MATERIAL_UNIFORMS\n")); + uses_uniforms = true; + } + uniform_defines.write[E->get().order] = ucode; + uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type); + uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type); + } + + p_actions.uniforms->insert(E->key(), E->get()); + } + + for (int i = 0; i < max_uniforms; i++) { + r_gen_code.uniforms += uniform_defines[i]; + } + +#if 1 + // add up + int offset = 0; + for (int i = 0; i < uniform_sizes.size(); i++) { + + int align = offset % uniform_alignments[i]; + + if (align != 0) { + offset += uniform_alignments[i] - align; + } + + r_gen_code.uniform_offsets.push_back(offset); + + offset += uniform_sizes[i]; + } + + r_gen_code.uniform_total_size = offset; + + if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16 + r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16); + } +#else + // add up + for (int i = 0; i < uniform_sizes.size(); i++) { + + if (i > 0) { + + int align = uniform_sizes[i - 1] % uniform_alignments[i]; + if (align != 0) { + uniform_sizes[i - 1] += uniform_alignments[i] - align; + } + + uniform_sizes[i] = uniform_sizes[i] + uniform_sizes[i - 1]; + } + } + //offset + r_gen_code.uniform_offsets.resize(uniform_sizes.size()); + for (int i = 0; i < uniform_sizes.size(); i++) { + + if (i > 0) + r_gen_code.uniform_offsets[i] = uniform_sizes[i - 1]; + else + r_gen_code.uniform_offsets[i] = 0; + } + /* + for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { + + if (SL::is_sampler_type(E->get().type)) { + continue; + } + + } + +*/ + if (uniform_sizes.size()) { + r_gen_code.uniform_total_size = uniform_sizes[uniform_sizes.size() - 1]; + } else { + r_gen_code.uniform_total_size = 0; + } +#endif + + uint32_t index = p_default_actions.base_varying_index; + + for (Map::Element *E = pnode->varyings.front(); E; E = E->next()) { + + String vcode; + String interp_mode = _interpstr(E->get().interpolation); + vcode += _prestr(E->get().precision); + vcode += _typestr(E->get().type); + vcode += " " + _mkid(E->key()); + if (E->get().array_size > 0) { + vcode += "["; + vcode += itos(E->get().array_size); + vcode += "]"; + } + vcode += ";\n"; + r_gen_code.vertex_global += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; + r_gen_code.fragment_global += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; + index++; + } + + for (Map::Element *E = pnode->constants.front(); E; E = E->next()) { + String gcode; + gcode += "const "; + gcode += _prestr(E->get().precision); + if (E->get().type == SL::TYPE_STRUCT) { + gcode += _mkid(E->get().type_str); + } else { + gcode += _typestr(E->get().type); + } + gcode += " " + _mkid(E->key()); + gcode += "="; + gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + gcode += ";\n"; + r_gen_code.vertex_global += gcode; + r_gen_code.fragment_global += gcode; + } + + Map function_code; + + //code for functions + for (int i = 0; i < pnode->functions.size(); i++) { + SL::FunctionNode *fnode = pnode->functions[i].function; + function = fnode; + current_func_name = fnode->name; + function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + function = NULL; + } + + //place functions in actual code + + Set added_vtx; + Set added_fragment; //share for light + + for (int i = 0; i < pnode->functions.size(); i++) { + + SL::FunctionNode *fnode = pnode->functions[i].function; + + function = fnode; + + current_func_name = fnode->name; + + if (fnode->name == vertex_name) { + + _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx); + r_gen_code.vertex = function_code[vertex_name]; + } + + if (fnode->name == fragment_name) { + + _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); + r_gen_code.fragment = function_code[fragment_name]; + } + + if (fnode->name == light_name) { + + _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); + r_gen_code.light = function_code[light_name]; + } + function = NULL; + } + + //code+=dump_node_code(pnode->body,p_level); + } break; + case SL::Node::TYPE_STRUCT: { + + } break; + case SL::Node::TYPE_FUNCTION: { + + } break; + case SL::Node::TYPE_BLOCK: { + SL::BlockNode *bnode = (SL::BlockNode *)p_node; + + //variables + if (!bnode->single_statement) { + code += _mktab(p_level - 1) + "{\n"; + } + + for (int i = 0; i < bnode->statements.size(); i++) { + + String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + + if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) { + code += scode; //use directly + } else { + code += _mktab(p_level) + scode + ";\n"; + } + } + if (!bnode->single_statement) { + code += _mktab(p_level - 1) + "}\n"; + } + + } break; + case SL::Node::TYPE_VARIABLE_DECLARATION: { + SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node; + + String declaration; + if (vdnode->is_const) { + declaration += "const "; + } + if (vdnode->datatype == SL::TYPE_STRUCT) { + declaration += _mkid(vdnode->struct_name); + } else { + declaration += _prestr(vdnode->precision) + _typestr(vdnode->datatype); + } + for (int i = 0; i < vdnode->declarations.size(); i++) { + if (i > 0) { + declaration += ","; + } else { + declaration += " "; + } + declaration += _mkid(vdnode->declarations[i].name); + if (vdnode->declarations[i].initializer) { + declaration += "="; + declaration += _dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + } + + code += declaration; + } break; + case SL::Node::TYPE_VARIABLE: { + SL::VariableNode *vnode = (SL::VariableNode *)p_node; + + if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) { + *p_actions.write_flag_pointers[vnode->name] = true; + } + + if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) { + String define = p_default_actions.usage_defines[vnode->name]; + if (define.begins_with("@")) { + define = p_default_actions.usage_defines[define.substr(1, define.length())]; + } + r_gen_code.defines.push_back(define); + used_name_defines.insert(vnode->name); + } + + if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) { + *p_actions.usage_flag_pointers[vnode->name] = true; + used_flag_pointers.insert(vnode->name); + } + + if (p_default_actions.renames.has(vnode->name)) + code = p_default_actions.renames[vnode->name]; + else { + code = _mkid(vnode->name); + if (actions.base_uniform_string != String() && shader->uniforms.has(vnode->name) && shader->uniforms[vnode->name].texture_order < 0) { + code = actions.base_uniform_string + code; + } + } + + if (vnode->name == time_name) { + if (current_func_name == vertex_name) { + r_gen_code.uses_vertex_time = true; + } + if (current_func_name == fragment_name || current_func_name == light_name) { + r_gen_code.uses_fragment_time = true; + } + } + + } break; + case SL::Node::TYPE_ARRAY_CONSTRUCT: { + SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node; + int sz = acnode->initializer.size(); + if (acnode->datatype == SL::TYPE_STRUCT) { + code += _mkid(acnode->struct_name); + } else { + code += _typestr(acnode->datatype); + } + code += "["; + code += itos(acnode->initializer.size()); + code += "]"; + code += "("; + for (int i = 0; i < sz; i++) { + code += _dump_node_code(acnode->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (i != sz - 1) { + code += ", "; + } + } + code += ")"; + } break; + case SL::Node::TYPE_ARRAY_DECLARATION: { + + SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node; + String declaration; + if (adnode->is_const) { + declaration += "const "; + } + if (adnode->datatype == SL::TYPE_STRUCT) { + declaration += _mkid(adnode->struct_name); + } else { + declaration = _prestr(adnode->precision) + _typestr(adnode->datatype); + } + for (int i = 0; i < adnode->declarations.size(); i++) { + if (i > 0) { + declaration += ","; + } else { + declaration += " "; + } + declaration += _mkid(adnode->declarations[i].name); + declaration += "["; + declaration += itos(adnode->declarations[i].size); + declaration += "]"; + int sz = adnode->declarations[i].initializer.size(); + if (sz > 0) { + declaration += "="; + if (adnode->datatype == SL::TYPE_STRUCT) { + declaration += _mkid(adnode->struct_name); + } else { + declaration += _typestr(adnode->datatype); + } + declaration += "["; + declaration += itos(sz); + declaration += "]"; + declaration += "("; + for (int j = 0; j < sz; j++) { + declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (j != sz - 1) { + declaration += ", "; + } + } + declaration += ")"; + } + } + + code += declaration; + } break; + case SL::Node::TYPE_ARRAY: { + SL::ArrayNode *anode = (SL::ArrayNode *)p_node; + + if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) { + *p_actions.write_flag_pointers[anode->name] = true; + } + + if (p_default_actions.usage_defines.has(anode->name) && !used_name_defines.has(anode->name)) { + String define = p_default_actions.usage_defines[anode->name]; + if (define.begins_with("@")) { + define = p_default_actions.usage_defines[define.substr(1, define.length())]; + } + r_gen_code.defines.push_back(define); + used_name_defines.insert(anode->name); + } + + if (p_actions.usage_flag_pointers.has(anode->name) && !used_flag_pointers.has(anode->name)) { + *p_actions.usage_flag_pointers[anode->name] = true; + used_flag_pointers.insert(anode->name); + } + + if (p_default_actions.renames.has(anode->name)) + code = p_default_actions.renames[anode->name]; + else + code = _mkid(anode->name); + + if (anode->call_expression != NULL) { + code += "."; + code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + } + + if (anode->index_expression != NULL) { + code += "["; + code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + } + + if (anode->name == time_name) { + if (current_func_name == vertex_name) { + r_gen_code.uses_vertex_time = true; + } + if (current_func_name == fragment_name || current_func_name == light_name) { + r_gen_code.uses_fragment_time = true; + } + } + + } break; + case SL::Node::TYPE_CONSTANT: { + SL::ConstantNode *cnode = (SL::ConstantNode *)p_node; + return get_constant_text(cnode->datatype, cnode->values); + + } break; + case SL::Node::TYPE_OPERATOR: { + SL::OperatorNode *onode = (SL::OperatorNode *)p_node; + + switch (onode->op) { + + case SL::OP_ASSIGN: + case SL::OP_ASSIGN_ADD: + case SL::OP_ASSIGN_SUB: + case SL::OP_ASSIGN_MUL: + case SL::OP_ASSIGN_DIV: + case SL::OP_ASSIGN_SHIFT_LEFT: + case SL::OP_ASSIGN_SHIFT_RIGHT: + case SL::OP_ASSIGN_MOD: + case SL::OP_ASSIGN_BIT_AND: + case SL::OP_ASSIGN_BIT_OR: + case SL::OP_ASSIGN_BIT_XOR: + code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + break; + case SL::OP_BIT_INVERT: + case SL::OP_NEGATE: + case SL::OP_NOT: + case SL::OP_DECREMENT: + case SL::OP_INCREMENT: + code = _opstr(onode->op) + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + break; + case SL::OP_POST_DECREMENT: + case SL::OP_POST_INCREMENT: + code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op); + break; + case SL::OP_CALL: + case SL::OP_STRUCT: + case SL::OP_CONSTRUCT: { + + ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String()); + + SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0]; + + bool is_texture_func = false; + if (onode->op == SL::OP_STRUCT) { + code += _mkid(vnode->name); + } else if (onode->op == SL::OP_CONSTRUCT) { + code += String(vnode->name); + } else { + + if (internal_functions.has(vnode->name)) { + code += vnode->name; + is_texture_func = texture_functions.has(vnode->name); + } else if (p_default_actions.renames.has(vnode->name)) { + code += p_default_actions.renames[vnode->name]; + } else { + code += _mkid(vnode->name); + } + } + + code += "("; + + for (int i = 1; i < onode->arguments.size(); i++) { + if (i > 1) + code += ", "; + String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + if (is_texture_func && i == 1 && onode->arguments[i]->type == SL::Node::TYPE_VARIABLE) { + + //need to map from texture to sampler in order to sample + const SL::VariableNode *varnode = static_cast(onode->arguments[i]); + + StringName texture_uniform = varnode->name; + + String sampler_name; + + if (actions.custom_samplers.has(texture_uniform)) { + sampler_name = actions.custom_samplers[texture_uniform]; + } else { + if (shader->uniforms.has(texture_uniform)) { + sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat); + } else { + bool found = false; + + for (int j = 0; j < function->arguments.size(); j++) { + if (function->arguments[j].name == texture_uniform) { + if (function->arguments[j].tex_builtin_check) { + ERR_CONTINUE(!actions.custom_samplers.has(function->arguments[j].tex_builtin)); + sampler_name = actions.custom_samplers[function->arguments[j].tex_builtin]; + found = true; + break; + } + if (function->arguments[j].tex_argument_check) { + sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat); + found = true; + break; + } + } + } + if (!found) { + //function was most likely unused, so use anything (compiler will remove it anyway) + sampler_name = _get_sampler_name(ShaderLanguage::FILTER_DEFAULT, ShaderLanguage::REPEAT_DEFAULT); + } + } + } + + code += ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype()) + "(" + node_code + ", " + sampler_name + ")"; + } else { + code += node_code; + } + } + code += ")"; + } break; + case SL::OP_INDEX: { + + code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "["; + code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + + } break; + case SL::OP_SELECT_IF: { + + code += "("; + code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "?"; + code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ":"; + code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += ")"; + + } break; + + default: { + + code = "(" + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")"; + break; + } + } + + } break; + case SL::Node::TYPE_CONTROL_FLOW: { + SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node; + if (cfnode->flow_op == SL::FLOW_OP_IF) { + + code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + if (cfnode->blocks.size() == 2) { + + code += _mktab(p_level) + "else\n"; + code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } + } else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) { + + code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_CASE) { + + code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) { + + code += _mktab(p_level) + "default:\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_DO) { + + code += _mktab(p_level) + "do"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");"; + } else if (cfnode->flow_op == SL::FLOW_OP_WHILE) { + + code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; + code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + } else if (cfnode->flow_op == SL::FLOW_OP_FOR) { + + String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n"; + code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); + + } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { + + if (cfnode->expressions.size()) { + code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ";"; + } else { + code = "return;"; + } + } else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) { + + if (p_actions.usage_flag_pointers.has("DISCARD") && !used_flag_pointers.has("DISCARD")) { + *p_actions.usage_flag_pointers["DISCARD"] = true; + used_flag_pointers.insert("DISCARD"); + } + + code = "discard;"; + } else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) { + + code = "continue;"; + } else if (cfnode->flow_op == SL::FLOW_OP_BREAK) { + + code = "break;"; + } + + } break; + case SL::Node::TYPE_MEMBER: { + SL::MemberNode *mnode = (SL::MemberNode *)p_node; + code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name; + if (mnode->index_expression != NULL) { + code += "["; + code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); + code += "]"; + } + + } break; + } + + return code; +} + +Error ShaderCompilerRD::compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { + + Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types()); + + if (err != OK) { + + Vector shader = p_code.split("\n"); + for (int i = 0; i < shader.size(); i++) { + print_line(itos(i + 1) + " " + shader[i]); + } + + _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); + return err; + } + + r_gen_code.defines.clear(); + r_gen_code.vertex = String(); + r_gen_code.vertex_global = String(); + r_gen_code.fragment = String(); + r_gen_code.fragment_global = String(); + r_gen_code.light = String(); + r_gen_code.uses_fragment_time = false; + r_gen_code.uses_vertex_time = false; + + used_name_defines.clear(); + used_rmode_defines.clear(); + used_flag_pointers.clear(); + + shader = parser.get_shader(); + function = NULL; + _dump_node_code(shader, 1, r_gen_code, *p_actions, actions, false); + + return OK; +} + +void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) { + actions = p_actions; + + vertex_name = "vertex"; + fragment_name = "fragment"; + light_name = "light"; + time_name = "TIME"; + + List func_list; + + ShaderLanguage::get_builtin_funcs(&func_list); + + for (List::Element *E = func_list.front(); E; E = E->next()) { + internal_functions.insert(E->get()); + } + texture_functions.insert("texture"); + texture_functions.insert("textureProj"); + texture_functions.insert("textureLod"); + texture_functions.insert("textureProjLod"); + texture_functions.insert("textureGrad"); +} + +ShaderCompilerRD::ShaderCompilerRD() { +#if 0 + + /** SPATIAL SHADER **/ + + actions[RS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; + actions[RS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; + actions[RS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; + actions[RS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; + actions[RS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; + actions[RS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; + + actions[RS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; + actions[RS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; + actions[RS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; + actions[RS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; + actions[RS::SHADER_SPATIAL].renames["POSITION"] = "position"; + actions[RS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; + actions[RS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; + actions[RS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; + actions[RS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize"; + actions[RS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID"; + + //builtins + + actions[RS::SHADER_SPATIAL].renames["TIME"] = "time"; + actions[RS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; + + actions[RS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; + actions[RS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; + actions[RS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; + actions[RS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; + actions[RS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; + actions[RS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; + actions[RS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; + actions[RS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; + actions[RS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; + actions[RS::SHADER_SPATIAL].renames["RIM"] = "rim"; + actions[RS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; + actions[RS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; + actions[RS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; + actions[RS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; + actions[RS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; + actions[RS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; + actions[RS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; + actions[RS::SHADER_SPATIAL].renames["AO"] = "ao"; + actions[RS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; + actions[RS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; + actions[RS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; + actions[RS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; + actions[RS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; + actions[RS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; + actions[RS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; + actions[RS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; + actions[RS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; + actions[RS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; + + //for light + actions[RS::SHADER_SPATIAL].renames["VIEW"] = "view"; + actions[RS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; + actions[RS::SHADER_SPATIAL].renames["LIGHT"] = "light"; + actions[RS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; + actions[RS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; + actions[RS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; + + actions[RS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; + actions[RS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; + actions[RS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; + actions[RS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; + actions[RS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; + actions[RS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; + actions[RS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; + actions[RS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; + actions[RS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; + actions[RS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; + actions[RS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; + actions[RS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; + actions[RS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; + + actions[RS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; + actions[RS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; + actions[RS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; + + actions[RS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + actions[RS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; + + actions[RS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; + + bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); + + if (!force_lambert) { + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; + } + + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; + + bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx"); + + if (!force_blinn) { + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; + } else { + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; + } + + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; + actions[RS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; + + /* PARTICLES SHADER */ + + actions[RS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; + actions[RS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; + actions[RS::SHADER_PARTICLES].renames["MASS"] = "mass"; + actions[RS::SHADER_PARTICLES].renames["ACTIVE"] = "shader_active"; + actions[RS::SHADER_PARTICLES].renames["RESTART"] = "restart"; + actions[RS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; + actions[RS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; + actions[RS::SHADER_PARTICLES].renames["TIME"] = "time"; + actions[RS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; + actions[RS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; + actions[RS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; + actions[RS::SHADER_PARTICLES].renames["INDEX"] = "index"; + actions[RS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; + actions[RS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; + actions[RS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; + + actions[RS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; + actions[RS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; + actions[RS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; +#endif +} diff --git a/servers/rendering/rasterizer_rd/shader_compiler_rd.h b/servers/rendering/rasterizer_rd/shader_compiler_rd.h new file mode 100644 index 0000000000..7d78469e9c --- /dev/null +++ b/servers/rendering/rasterizer_rd/shader_compiler_rd.h @@ -0,0 +1,123 @@ +/*************************************************************************/ +/* shader_compiler_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHADER_COMPILER_RD_H +#define SHADER_COMPILER_RD_H + +#include "core/pair.h" +#include "servers/rendering/shader_language.h" +#include "servers/rendering/shader_types.h" +#include "servers/rendering_server.h" + +class ShaderCompilerRD { +public: + struct IdentifierActions { + + Map> render_mode_values; + Map render_mode_flags; + Map usage_flag_pointers; + Map write_flag_pointers; + + Map *uniforms; + }; + + struct GeneratedCode { + + Vector defines; + struct Texture { + StringName name; + ShaderLanguage::DataType type; + ShaderLanguage::ShaderNode::Uniform::Hint hint; + ShaderLanguage::TextureFilter filter; + ShaderLanguage::TextureRepeat repeat; + }; + + Vector texture_uniforms; + + Vector uniform_offsets; + uint32_t uniform_total_size; + String uniforms; + String vertex_global; + String vertex; + String fragment_global; + String fragment; + String light; + + bool uses_fragment_time; + bool uses_vertex_time; + }; + + struct DefaultIdentifierActions { + + Map renames; + Map render_mode_defines; + Map usage_defines; + Map custom_samplers; + ShaderLanguage::TextureFilter default_filter; + ShaderLanguage::TextureRepeat default_repeat; + String sampler_array_name; + int base_texture_binding_index = 0; + int texture_layout_set = 0; + String base_uniform_string; + uint32_t base_varying_index = 0; + }; + +private: + ShaderLanguage parser; + + String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat); + + void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map &p_func_code, String &r_to_add, Set &added); + String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning); + + const ShaderLanguage::ShaderNode *shader; + const ShaderLanguage::FunctionNode *function; + StringName current_func_name; + StringName vertex_name; + StringName fragment_name; + StringName light_name; + StringName time_name; + Set texture_functions; + + Set used_name_defines; + Set used_flag_pointers; + Set used_rmode_defines; + Set internal_functions; + + DefaultIdentifierActions actions; + +public: + Error compile(RS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); + + void initialize(DefaultIdentifierActions p_actions); + ShaderCompilerRD(); +}; + +#endif // SHADERCOMPILERRD_H diff --git a/servers/rendering/rasterizer_rd/shader_rd.cpp b/servers/rendering/rasterizer_rd/shader_rd.cpp new file mode 100644 index 0000000000..3dcfd0faf9 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shader_rd.cpp @@ -0,0 +1,495 @@ +/*************************************************************************/ +/* shader_rd.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shader_rd.h" + +#include "core/string_builder.h" +#include "rasterizer_rd.h" +#include "servers/rendering/rendering_device.h" + +void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) { + + name = p_name; + //split vertex and shader code (thank you, shader compiler programmers from you know what company). + if (p_vertex_code) { + String defines_tag = "\nVERSION_DEFINES"; + String globals_tag = "\nVERTEX_SHADER_GLOBALS"; + String material_tag = "\nMATERIAL_UNIFORMS"; + String code_tag = "\nVERTEX_SHADER_CODE"; + String code = p_vertex_code; + + int cpos = code.find(defines_tag); + if (cpos != -1) { + vertex_codev = code.substr(0, cpos).ascii(); + code = code.substr(cpos + defines_tag.length(), code.length()); + } + + cpos = code.find(material_tag); + + if (cpos == -1) { + vertex_code0 = code.ascii(); + } else { + vertex_code0 = code.substr(0, cpos).ascii(); + code = code.substr(cpos + material_tag.length(), code.length()); + + cpos = code.find(globals_tag); + + if (cpos == -1) { + vertex_code1 = code.ascii(); + } else { + + vertex_code1 = code.substr(0, cpos).ascii(); + String code2 = code.substr(cpos + globals_tag.length(), code.length()); + + cpos = code2.find(code_tag); + if (cpos == -1) { + vertex_code2 = code2.ascii(); + } else { + + vertex_code2 = code2.substr(0, cpos).ascii(); + vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); + } + } + } + } + + if (p_fragment_code) { + String defines_tag = "\nVERSION_DEFINES"; + String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; + String material_tag = "\nMATERIAL_UNIFORMS"; + String code_tag = "\nFRAGMENT_SHADER_CODE"; + String light_code_tag = "\nLIGHT_SHADER_CODE"; + String code = p_fragment_code; + + int cpos = code.find(defines_tag); + if (cpos != -1) { + fragment_codev = code.substr(0, cpos).ascii(); + code = code.substr(cpos + defines_tag.length(), code.length()); + } + + cpos = code.find(material_tag); + if (cpos == -1) { + fragment_code0 = code.ascii(); + } else { + fragment_code0 = code.substr(0, cpos).ascii(); + //print_line("CODE0:\n"+String(fragment_code0.get_data())); + code = code.substr(cpos + material_tag.length(), code.length()); + cpos = code.find(globals_tag); + + if (cpos == -1) { + fragment_code1 = code.ascii(); + } else { + + fragment_code1 = code.substr(0, cpos).ascii(); + //print_line("CODE1:\n"+String(fragment_code1.get_data())); + + String code2 = code.substr(cpos + globals_tag.length(), code.length()); + cpos = code2.find(light_code_tag); + + if (cpos == -1) { + fragment_code2 = code2.ascii(); + } else { + + fragment_code2 = code2.substr(0, cpos).ascii(); + //print_line("CODE2:\n"+String(fragment_code2.get_data())); + + String code3 = code2.substr(cpos + light_code_tag.length(), code2.length()); + + cpos = code3.find(code_tag); + if (cpos == -1) { + fragment_code3 = code3.ascii(); + } else { + + fragment_code3 = code3.substr(0, cpos).ascii(); + //print_line("CODE3:\n"+String(fragment_code3.get_data())); + fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii(); + //print_line("CODE4:\n"+String(fragment_code4.get_data())); + } + } + } + } + } + + if (p_compute_code) { + is_compute = true; + + String defines_tag = "\nVERSION_DEFINES"; + String globals_tag = "\nCOMPUTE_SHADER_GLOBALS"; + String material_tag = "\nMATERIAL_UNIFORMS"; + String code_tag = "\nCOMPUTE_SHADER_CODE"; + String code = p_compute_code; + + int cpos = code.find(defines_tag); + if (cpos != -1) { + compute_codev = code.substr(0, cpos).ascii(); + code = code.substr(cpos + defines_tag.length(), code.length()); + } + + cpos = code.find(material_tag); + + if (cpos == -1) { + compute_code0 = code.ascii(); + } else { + compute_code0 = code.substr(0, cpos).ascii(); + code = code.substr(cpos + material_tag.length(), code.length()); + + cpos = code.find(globals_tag); + + if (cpos == -1) { + compute_code1 = code.ascii(); + } else { + + compute_code1 = code.substr(0, cpos).ascii(); + String code2 = code.substr(cpos + globals_tag.length(), code.length()); + + cpos = code2.find(code_tag); + if (cpos == -1) { + compute_code2 = code2.ascii(); + } else { + + compute_code2 = code2.substr(0, cpos).ascii(); + compute_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); + } + } + } + } +} + +RID ShaderRD::version_create() { + + //initialize() was never called + ERR_FAIL_COND_V(variant_defines.size() == 0, RID()); + + Version version; + version.dirty = true; + version.valid = false; + version.initialize_needed = true; + version.variants = NULL; + return version_owner.make_rid(version); +} + +void ShaderRD::_clear_version(Version *p_version) { + //clear versions if they exist + if (p_version->variants) { + for (int i = 0; i < variant_defines.size(); i++) { + RD::get_singleton()->free(p_version->variants[i]); + } + + memdelete_arr(p_version->variants); + p_version->variants = NULL; + } +} + +void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { + + Vector stages; + + String error; + String current_source; + RD::ShaderStage current_stage = RD::SHADER_STAGE_VERTEX; + bool build_ok = true; + + if (!is_compute) { + //vertex stage + + StringBuilder builder; + + builder.append(vertex_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); + builder.append(variant_defines[p_variant].get_data()); + + for (int j = 0; j < p_version->custom_defines.size(); j++) { + builder.append(p_version->custom_defines[j].get_data()); + } + + builder.append(vertex_code0.get_data()); //first part of vertex + + builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) + + builder.append(vertex_code1.get_data()); //second part of vertex + + builder.append(p_version->vertex_globals.get_data()); // vertex globals + + builder.append(vertex_code2.get_data()); //third part of vertex + + builder.append(p_version->vertex_code.get_data()); // code + + builder.append(vertex_code3.get_data()); //fourth of vertex + + current_source = builder.as_string(); + RD::ShaderStageData stage; + stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_VERTEX, current_source, RD::SHADER_LANGUAGE_GLSL, &error); + if (stage.spir_v.size() == 0) { + build_ok = false; + } else { + + stage.shader_stage = RD::SHADER_STAGE_VERTEX; + stages.push_back(stage); + } + } + + if (!is_compute && build_ok) { + //fragment stage + current_stage = RD::SHADER_STAGE_FRAGMENT; + + StringBuilder builder; + + builder.append(fragment_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + + builder.append(general_defines.get_data()); + builder.append(variant_defines[p_variant].get_data()); + for (int j = 0; j < p_version->custom_defines.size(); j++) { + builder.append(p_version->custom_defines[j].get_data()); + } + + builder.append(fragment_code0.get_data()); //first part of fragment + + builder.append(p_version->uniforms.get_data()); //uniforms (same for fragment and fragment) + + builder.append(fragment_code1.get_data()); //first part of fragment + + builder.append(p_version->fragment_globals.get_data()); // fragment globals + + builder.append(fragment_code2.get_data()); //third part of fragment + + builder.append(p_version->fragment_light.get_data()); // fragment light + + builder.append(fragment_code3.get_data()); //fourth part of fragment + + builder.append(p_version->fragment_code.get_data()); // fragment code + + builder.append(fragment_code4.get_data()); //fourth part of fragment + + current_source = builder.as_string(); + RD::ShaderStageData stage; + stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_FRAGMENT, current_source, RD::SHADER_LANGUAGE_GLSL, &error); + if (stage.spir_v.size() == 0) { + build_ok = false; + } else { + + stage.shader_stage = RD::SHADER_STAGE_FRAGMENT; + stages.push_back(stage); + } + } + + if (is_compute) { + //compute stage + current_stage = RD::SHADER_STAGE_COMPUTE; + + StringBuilder builder; + + builder.append(compute_codev.get_data()); // version info (if exists) + builder.append("\n"); //make sure defines begin at newline + builder.append(general_defines.get_data()); + builder.append(variant_defines[p_variant].get_data()); + + for (int j = 0; j < p_version->custom_defines.size(); j++) { + builder.append(p_version->custom_defines[j].get_data()); + } + + builder.append(compute_code0.get_data()); //first part of compute + + builder.append(p_version->uniforms.get_data()); //uniforms (same for compute and fragment) + + builder.append(compute_code1.get_data()); //second part of compute + + builder.append(p_version->compute_globals.get_data()); // compute globals + + builder.append(compute_code2.get_data()); //third part of compute + + builder.append(p_version->compute_code.get_data()); // code + + builder.append(compute_code3.get_data()); //fourth of compute + + current_source = builder.as_string(); + RD::ShaderStageData stage; + stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_COMPUTE, current_source, RD::SHADER_LANGUAGE_GLSL, &error); + if (stage.spir_v.size() == 0) { + build_ok = false; + } else { + + stage.shader_stage = RD::SHADER_STAGE_COMPUTE; + stages.push_back(stage); + } + } + + if (!build_ok) { + MutexLock lock(variant_set_mutex); //properly print the errors + ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_COMPUTE ? "Compute " : (current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment")) + " shader, variant #" + itos(p_variant) + " (" + variant_defines[p_variant].get_data() + ")."); + ERR_PRINT(error); + +#ifdef DEBUG_ENABLED + ERR_PRINT("code:\n" + current_source.get_with_code_lines()); +#endif + return; + } + + RID shader = RD::get_singleton()->shader_create(stages); + { + MutexLock lock(variant_set_mutex); + p_version->variants[p_variant] = shader; + } +} + +void ShaderRD::_compile_version(Version *p_version) { + + _clear_version(p_version); + + p_version->valid = false; + p_version->dirty = false; + + p_version->variants = memnew_arr(RID, variant_defines.size()); +#if 1 + + RasterizerRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); +#else + for (int i = 0; i < variant_defines.size(); i++) { + + _compile_variant(i, p_version); + } +#endif + + bool all_valid = true; + for (int i = 0; i < variant_defines.size(); i++) { + if (p_version->variants[i].is_null()) { + all_valid = false; + break; + } + } + + if (!all_valid) { + //clear versions if they exist + for (int i = 0; i < variant_defines.size(); i++) { + if (!p_version->variants[i].is_null()) { + RD::get_singleton()->free(p_version->variants[i]); + } + } + memdelete_arr(p_version->variants); + p_version->variants = NULL; + return; + } + + p_version->valid = true; +} + +void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector &p_custom_defines) { + + ERR_FAIL_COND(is_compute); + + Version *version = version_owner.getornull(p_version); + ERR_FAIL_COND(!version); + version->vertex_globals = p_vertex_globals.utf8(); + version->vertex_code = p_vertex_code.utf8(); + version->fragment_light = p_fragment_light.utf8(); + version->fragment_globals = p_fragment_globals.utf8(); + version->fragment_code = p_fragment_code.utf8(); + version->uniforms = p_uniforms.utf8(); + + version->custom_defines.clear(); + for (int i = 0; i < p_custom_defines.size(); i++) { + version->custom_defines.push_back(p_custom_defines[i].utf8()); + } + + version->dirty = true; + if (version->initialize_needed) { + _compile_version(version); + version->initialize_needed = false; + } +} + +void ShaderRD::version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector &p_custom_defines) { + + ERR_FAIL_COND(!is_compute); + + Version *version = version_owner.getornull(p_version); + ERR_FAIL_COND(!version); + version->compute_globals = p_compute_globals.utf8(); + version->compute_code = p_compute_code.utf8(); + version->uniforms = p_uniforms.utf8(); + + version->custom_defines.clear(); + for (int i = 0; i < p_custom_defines.size(); i++) { + version->custom_defines.push_back(p_custom_defines[i].utf8()); + } + + version->dirty = true; + if (version->initialize_needed) { + _compile_version(version); + version->initialize_needed = false; + } +} + +bool ShaderRD::version_is_valid(RID p_version) { + Version *version = version_owner.getornull(p_version); + ERR_FAIL_COND_V(!version, false); + + if (version->dirty) { + _compile_version(version); + } + + return version->valid; +} + +bool ShaderRD::version_free(RID p_version) { + + if (version_owner.owns(p_version)) { + Version *version = version_owner.getornull(p_version); + _clear_version(version); + version_owner.free(p_version); + } else { + return false; + } + + return true; +} + +void ShaderRD::initialize(const Vector &p_variant_defines, const String &p_general_defines) { + ERR_FAIL_COND(variant_defines.size()); + ERR_FAIL_COND(p_variant_defines.size() == 0); + general_defines = p_general_defines.utf8(); + for (int i = 0; i < p_variant_defines.size(); i++) { + + variant_defines.push_back(p_variant_defines[i].utf8()); + } +} + +ShaderRD::~ShaderRD() { + List remaining; + version_owner.get_owned_list(&remaining); + if (remaining.size()) { + ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed"); + while (remaining.size()) { + version_free(remaining.front()->get()); + remaining.pop_front(); + } + } +} diff --git a/servers/rendering/rasterizer_rd/shader_rd.h b/servers/rendering/rasterizer_rd/shader_rd.h new file mode 100644 index 0000000000..6635b08cc8 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shader_rd.h @@ -0,0 +1,136 @@ +/*************************************************************************/ +/* shader_rd.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHADER_RD_H +#define SHADER_RD_H + +#include "core/hash_map.h" +#include "core/map.h" +#include "core/os/mutex.h" +#include "core/rid_owner.h" +#include "core/variant.h" + +#include +/** + @author Juan Linietsky +*/ + +class ShaderRD { + + //versions + CharString general_defines; + Vector variant_defines; + + struct Version { + CharString uniforms; + CharString vertex_globals; + CharString vertex_code; + CharString compute_globals; + CharString compute_code; + CharString fragment_light; + CharString fragment_globals; + CharString fragment_code; + Vector custom_defines; + + RID *variants; //same size as version defines + + bool valid; + bool dirty; + bool initialize_needed; + }; + + Mutex variant_set_mutex; + + void _compile_variant(uint32_t p_variant, Version *p_version); + + void _clear_version(Version *p_version); + void _compile_version(Version *p_version); + + RID_Owner version_owner; + + CharString fragment_codev; //for version and extensions + CharString fragment_code0; + CharString fragment_code1; + CharString fragment_code2; + CharString fragment_code3; + CharString fragment_code4; + + CharString vertex_codev; //for version and extensions + CharString vertex_code0; + CharString vertex_code1; + CharString vertex_code2; + CharString vertex_code3; + + bool is_compute = false; + + CharString compute_codev; //for version and extensions + CharString compute_code0; + CharString compute_code1; + CharString compute_code2; + CharString compute_code3; + + const char *name; + +protected: + ShaderRD() {} + void setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name); + +public: + RID version_create(); + + void version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector &p_custom_defines); + void version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector &p_custom_defines); + + _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { + ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); + + Version *version = version_owner.getornull(p_version); + ERR_FAIL_COND_V(!version, RID()); + + if (version->dirty) { + _compile_version(version); + } + + if (!version->valid) { + return RID(); + } + + return version->variants[p_variant]; + } + + bool version_is_valid(RID p_version); + + bool version_free(RID p_version); + + void initialize(const Vector &p_variant_defines, const String &p_general_defines = ""); + virtual ~ShaderRD(); +}; + +#endif diff --git a/servers/rendering/rasterizer_rd/shaders/SCsub b/servers/rendering/rasterizer_rd/shaders/SCsub new file mode 100644 index 0000000000..2dcb2a703f --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/SCsub @@ -0,0 +1,24 @@ +#!/usr/bin/env python + +Import('env') + +if 'RD_GLSL' in env['BUILDERS']: + env.RD_GLSL('canvas.glsl'); + env.RD_GLSL('canvas_occlusion.glsl'); + env.RD_GLSL('blur.glsl'); + env.RD_GLSL('cubemap_roughness.glsl'); + env.RD_GLSL('cubemap_downsampler.glsl'); + env.RD_GLSL('cubemap_filter.glsl'); + env.RD_GLSL('scene_high_end.glsl'); + env.RD_GLSL('sky.glsl'); + env.RD_GLSL('tonemap.glsl'); + env.RD_GLSL('copy.glsl'); + env.RD_GLSL('giprobe.glsl'); + env.RD_GLSL('giprobe_debug.glsl'); + env.RD_GLSL('giprobe_sdf.glsl'); + env.RD_GLSL('luminance_reduce.glsl'); + env.RD_GLSL('bokeh_dof.glsl'); + env.RD_GLSL('ssao.glsl'); + env.RD_GLSL('ssao_minify.glsl'); + env.RD_GLSL('ssao_blur.glsl'); + env.RD_GLSL('roughness_limiter.glsl'); diff --git a/servers/rendering/rasterizer_rd/shaders/blur.glsl b/servers/rendering/rasterizer_rd/shaders/blur.glsl new file mode 100644 index 0000000000..87c20ebaef --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/blur.glsl @@ -0,0 +1,294 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +#include "blur_inc.glsl" + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +void main() { + + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + uv_interp = base_arr[gl_VertexIndex]; + + if (bool(blur.flags & FLAG_USE_BLUR_SECTION)) { + uv_interp = blur.section.xy + uv_interp * blur.section.zw; + } + + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); + + if (bool(blur.flags & FLAG_FLIP_Y)) { + uv_interp.y = 1.0 - uv_interp.y; + } +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +#include "blur_inc.glsl" + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform sampler2D source_color; + +#ifdef MODE_SSAO_MERGE +layout(set = 1, binding = 0) uniform sampler2D source_ssao; +#endif + +#ifdef GLOW_USE_AUTO_EXPOSURE +layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; +#endif + +layout(location = 0) out vec4 frag_color; + +//DOF +#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR) + +layout(set = 1, binding = 0) uniform sampler2D dof_source_depth; + +#ifdef DOF_NEAR_BLUR_MERGE +layout(set = 2, binding = 0) uniform sampler2D source_dof_original; +#endif + +#ifdef DOF_QUALITY_LOW +const int dof_kernel_size = 5; +const int dof_kernel_from = 2; +const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388); +#endif + +#ifdef DOF_QUALITY_MEDIUM +const int dof_kernel_size = 11; +const int dof_kernel_from = 5; +const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037); + +#endif + +#ifdef DOF_QUALITY_HIGH +const int dof_kernel_size = 21; +const int dof_kernel_from = 10; +const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174); +#endif + +#endif + +void main() { + +#ifdef MODE_MIPMAP + + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size); + color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size); + frag_color = color / 4.0; + +#endif + +#ifdef MODE_GAUSSIAN_BLUR + + //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect + + if (bool(blur.flags & FLAG_HORIZONTAL)) { + + vec2 pix_size = blur.pixel_size; + pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607; + color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879; + color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514; + color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303; + color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879; + color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514; + color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303; + frag_color = color; + } else { + + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774; + color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477; + color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136; + color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477; + color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136; + frag_color = color; + } +#endif + +#ifdef MODE_GAUSSIAN_GLOW + + //Glow uses larger sigma 1 for a more rounded blur effect + +#define GLOW_ADD(m_ofs, m_mult) \ + { \ + vec2 ofs = uv_interp + m_ofs * pix_size; \ + vec4 c = texture(source_color, ofs) * m_mult; \ + if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \ + c *= 0.0; \ + } \ + color += c; \ + } + + if (bool(blur.flags & FLAG_HORIZONTAL)) { + + vec2 pix_size = blur.pixel_size; + pix_size *= 0.5; //reading from larger buffer, so use more samples + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938; + GLOW_ADD(vec2(1.0, 0.0), 0.165569); + GLOW_ADD(vec2(2.0, 0.0), 0.140367); + GLOW_ADD(vec2(3.0, 0.0), 0.106595); + GLOW_ADD(vec2(-1.0, 0.0), 0.165569); + GLOW_ADD(vec2(-2.0, 0.0), 0.140367); + GLOW_ADD(vec2(-3.0, 0.0), 0.106595); + color *= blur.glow_strength; + frag_color = color; + } else { + + vec2 pix_size = blur.pixel_size; + vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713; + GLOW_ADD(vec2(0.0, 1.0), 0.233062); + GLOW_ADD(vec2(0.0, 2.0), 0.122581); + GLOW_ADD(vec2(0.0, -1.0), 0.233062); + GLOW_ADD(vec2(0.0, -2.0), 0.122581); + color *= blur.glow_strength; + frag_color = color; + } + +#undef GLOW_ADD + + if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) { +#ifdef GLOW_USE_AUTO_EXPOSURE + + frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey; +#endif + frag_color *= blur.glow_exposure; + + float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); + float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom); + + frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)); + } + +#endif + +#ifdef MODE_DOF_FAR_BLUR + + vec4 color_accum = vec4(0.0); + + float depth = texture(dof_source_depth, uv_interp, 0.0).r; + depth = depth * 2.0 - 1.0; + + if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { + depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; + } else { + depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near)); + } + + float amount = smoothstep(blur.dof_begin, blur.dof_end, depth); + float k_accum = 0.0; + + for (int i = 0; i < dof_kernel_size; i++) { + + int int_ofs = i - dof_kernel_from; + vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius; + + float tap_k = dof_kernel[i]; + + float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; + tap_depth = tap_depth * 2.0 - 1.0; + + if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { + + tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; + } else { + tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near)); + } + + float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0); + tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect + + vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k; + + k_accum += tap_k * tap_amount; + color_accum += tap_color * tap_amount; + } + + if (k_accum > 0.0) { + color_accum /= k_accum; + } + + frag_color = color_accum; ///k_accum; + +#endif + +#ifdef MODE_DOF_NEAR_BLUR + + vec4 color_accum = vec4(0.0); + + float max_accum = 0.0; + + for (int i = 0; i < dof_kernel_size; i++) { + + int int_ofs = i - dof_kernel_from; + vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * blur.dof_radius; + float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from)); + + float tap_k = dof_kernel[i]; + + vec4 tap_color = texture(source_color, tap_uv, 0.0); + + float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; + tap_depth = tap_depth * 2.0 - 1.0; + if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { + + tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; + } else { + tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near)); + } + float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth); + tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect + + if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) { + tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth); + } + + max_accum = max(max_accum, tap_amount * ofs_influence); + + color_accum += tap_color * tap_k; + } + + color_accum.a = max(color_accum.a, sqrt(max_accum)); + +#ifdef DOF_NEAR_BLUR_MERGE + { + vec4 original = texture(source_dof_original, uv_interp, 0.0); + color_accum = mix(original, color_accum, color_accum.a); + } +#endif + + if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) { + frag_color = color_accum; + } +#endif + +#ifdef MODE_SIMPLE_COPY + vec4 color = texture(source_color, uv_interp, 0.0); + if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) { + color.rgb = vec3(max(max(color.r, color.g), color.b)); + } + frag_color = color; +#endif + +#ifdef MODE_SSAO_MERGE + vec4 color = texture(source_color, uv_interp, 0.0); + float ssao = texture(source_ssao, uv_interp, 0.0).r; + frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0); + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl b/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl new file mode 100644 index 0000000000..33ba9de7bb --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/blur_inc.glsl @@ -0,0 +1,35 @@ +#define FLAG_HORIZONTAL (1 << 0) +#define FLAG_USE_BLUR_SECTION (1 << 1) +#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2) +#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3) +#define FLAG_GLOW_FIRST_PASS (1 << 4) +#define FLAG_FLIP_Y (1 << 5) +#define FLAG_COPY_FORCE_LUMINANCE (1 << 6) + +layout(push_constant, binding = 1, std430) uniform Blur { + vec4 section; + vec2 pixel_size; + uint flags; + uint pad; + // Glow. + float glow_strength; + float glow_bloom; + float glow_hdr_threshold; + float glow_hdr_scale; + float glow_exposure; + float glow_white; + float glow_luminance_cap; + float glow_auto_exposure_grey; + // DOF. + float dof_begin; + float dof_end; + float dof_radius; + float dof_pad; + + vec2 dof_dir; + float camera_z_far; + float camera_z_near; + + vec4 ssao_color; +} +blur; diff --git a/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl new file mode 100644 index 0000000000..7153fe6b17 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/bokeh_dof.glsl @@ -0,0 +1,258 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +#define BLOCK_SIZE 8 + +layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; +/* clang-format on */ + +#ifdef MODE_GEN_BLUR_SIZE +layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image; +layout(set = 1, binding = 0) uniform sampler2D source_depth; +#endif + +#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL) || defined(MODE_BOKEH_CIRCULAR) +layout(set = 1, binding = 0) uniform sampler2D color_texture; +layout(rgba16f, set = 0, binding = 0) uniform restrict writeonly image2D bokeh_image; +#endif + +#ifdef MODE_COMPOSITE_BOKEH +layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image; +layout(set = 1, binding = 0) uniform sampler2D source_bokeh; +#endif + +// based on https://www.shadertoy.com/view/Xd3GDl + +layout(push_constant, binding = 1, std430) uniform Params { + ivec2 size; + float z_far; + float z_near; + + bool orthogonal; + float blur_size; + float blur_scale; + int blur_steps; + + bool blur_near_active; + float blur_near_begin; + float blur_near_end; + bool blur_far_active; + + float blur_far_begin; + float blur_far_end; + bool second_pass; + bool half_size; + + bool use_jitter; + float jitter_seed; + uint pad[2]; +} +params; + +//used to work around downsampling filter +#define DEPTH_GAP 0.0 + +#ifdef MODE_GEN_BLUR_SIZE + +float get_depth_at_pos(vec2 uv) { + float depth = textureLod(source_depth, uv, 0.0).x; + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } + return depth; +} + +float get_blur_size(float depth) { + + if (params.blur_near_active && depth < params.blur_near_begin) { + return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative + } + + if (params.blur_far_active && depth > params.blur_far_begin) { + return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP; + } + + return 0.0; +} + +#endif + +const float GOLDEN_ANGLE = 2.39996323; + +//note: uniform pdf rand [0;1[ +float hash12n(vec2 p) { + p = fract(p * vec2(5.3987, 5.4421)); + p += dot(p.yx, p.xy + vec2(21.5351, 14.3137)); + return fract(p.x * p.y * 95.4307); +} + +#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL) + +vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) { + + dir *= pixel_size; + vec4 color = texture(color_texture, uv); + + vec4 accum = color; + float total = 1.0; + + float blur_scale = params.blur_size / float(params.blur_steps); + + if (params.use_jitter) { + uv += dir * (hash12n(uv + params.jitter_seed) - 0.5); + } + + for (int i = -params.blur_steps; i <= params.blur_steps; i++) { + + if (i == 0) { + continue; + } + float radius = float(i) * blur_scale; + vec2 suv = uv + dir * radius; + radius = abs(radius); + + vec4 sample_color = texture(color_texture, suv); + float limit; + + if (sample_color.a < color.a) { + limit = abs(sample_color.a); + } else { + limit = abs(color.a); + } + + limit -= DEPTH_GAP; + + float m = smoothstep(radius - 0.5, radius + 0.5, limit); + + accum += mix(color, sample_color, m); + + total += 1.0; + } + + return accum / total; +} + +#endif + +void main() { + + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + if (any(greaterThan(pos, params.size))) { //too large, do nothing + return; + } + + vec2 pixel_size = 1.0 / vec2(params.size); + vec2 uv = vec2(pos) / vec2(params.size); + +#ifdef MODE_GEN_BLUR_SIZE + uv += pixel_size * 0.5; + //precompute size in alpha channel + float depth = get_depth_at_pos(uv); + float size = get_blur_size(depth); + + vec4 color = imageLoad(color_image, pos); + color.a = size; + imageStore(color_image, pos, color); +#endif + +#ifdef MODE_BOKEH_BOX + + //pixel_size*=0.5; //resolution is doubled + if (params.second_pass || !params.half_size) { + uv += pixel_size * 0.5; //half pixel to read centers + } else { + uv += pixel_size * 0.25; //half pixel to read centers from full res + } + + vec2 dir = (params.second_pass ? vec2(0.0, 1.0) : vec2(1.0, 0.0)); + + vec4 color = weighted_filter_dir(dir, uv, pixel_size); + + imageStore(bokeh_image, pos, color); + +#endif + +#ifdef MODE_BOKEH_HEXAGONAL + + //pixel_size*=0.5; //resolution is doubled + if (params.second_pass || !params.half_size) { + uv += pixel_size * 0.5; //half pixel to read centers + } else { + uv += pixel_size * 0.25; //half pixel to read centers from full res + } + + vec2 dir = (params.second_pass ? normalize(vec2(1.0, 0.577350269189626)) : vec2(0.0, 1.0)); + + vec4 color = weighted_filter_dir(dir, uv, pixel_size); + + if (params.second_pass) { + dir = normalize(vec2(-1.0, 0.577350269189626)); + + vec4 color2 = weighted_filter_dir(dir, uv, pixel_size); + + color.rgb = min(color.rgb, color2.rgb); + color.a = (color.a + color2.a) * 0.5; + } + + imageStore(bokeh_image, pos, color); + +#endif + +#ifdef MODE_BOKEH_CIRCULAR + + if (params.half_size) { + pixel_size *= 0.5; //resolution is doubled + } + + uv += pixel_size * 0.5; //half pixel to read centers + + vec4 color = texture(color_texture, uv); + float accum = 1.0; + float radius = params.blur_scale; + + for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) { + + vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius; + vec4 sample_color = texture(color_texture, suv); + float sample_size = abs(sample_color.a); + if (sample_color.a > color.a) { + sample_size = clamp(sample_size, 0.0, abs(color.a) * 2.0); + } + + float m = smoothstep(radius - 0.5, radius + 0.5, sample_size); + color += mix(color / accum, sample_color, m); + accum += 1.0; + radius += params.blur_scale / radius; + } + + color /= accum; + + imageStore(bokeh_image, pos, color); +#endif + +#ifdef MODE_COMPOSITE_BOKEH + + uv += pixel_size * 0.5; + vec4 color = imageLoad(color_image, pos); + vec4 bokeh = texture(source_bokeh, uv); + + float mix_amount; + if (bokeh.a < color.a) { + mix_amount = min(1.0, max(0.0, max(abs(color.a), abs(bokeh.a)) - DEPTH_GAP)); + } else { + mix_amount = min(1.0, max(0.0, abs(color.a) - DEPTH_GAP)); + } + + color.rgb = mix(color.rgb, bokeh.rgb, mix_amount); //blend between hires and lowres + + color.a = 0; //reset alpha + imageStore(color_image, pos, color); +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/canvas.glsl b/servers/rendering/rasterizer_rd/shaders/canvas.glsl new file mode 100644 index 0000000000..28135fce31 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/canvas.glsl @@ -0,0 +1,584 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +#ifdef USE_ATTRIBUTES +layout(location = 0) in vec2 vertex_attrib; +/* clang-format on */ +layout(location = 3) in vec4 color_attrib; +layout(location = 4) in vec2 uv_attrib; + +layout(location = 6) in uvec4 bones_attrib; + +#endif + +#include "canvas_uniforms_inc.glsl" + +layout(location = 0) out vec2 uv_interp; +layout(location = 1) out vec4 color_interp; +layout(location = 2) out vec2 vertex_interp; + +#ifdef USE_NINEPATCH + +layout(location = 3) out vec2 pixel_size_interp; + +#endif + +#ifdef USE_MATERIAL_UNIFORMS +layout(set = 1, binding = 1, std140) uniform MaterialUniforms{ + /* clang-format off */ +MATERIAL_UNIFORMS + /* clang-format on */ +} material; +#endif + +/* clang-format off */ +VERTEX_SHADER_GLOBALS +/* clang-format on */ + +void main() { + + vec4 instance_custom = vec4(0.0); +#ifdef USE_PRIMITIVE + + //weird bug, + //this works + vec2 vertex; + vec2 uv; + vec4 color; + + if (gl_VertexIndex == 0) { + vertex = draw_data.points[0]; + uv = draw_data.uvs[0]; + color = vec4(unpackHalf2x16(draw_data.colors[0]), unpackHalf2x16(draw_data.colors[1])); + } else if (gl_VertexIndex == 1) { + vertex = draw_data.points[1]; + uv = draw_data.uvs[1]; + color = vec4(unpackHalf2x16(draw_data.colors[2]), unpackHalf2x16(draw_data.colors[3])); + } else { + vertex = draw_data.points[2]; + uv = draw_data.uvs[2]; + color = vec4(unpackHalf2x16(draw_data.colors[4]), unpackHalf2x16(draw_data.colors[5])); + } + uvec4 bones = uvec4(0, 0, 0, 0); + +#elif defined(USE_ATTRIBUTES) + + vec2 vertex = vertex_attrib; + vec4 color = color_attrib; + vec2 uv = uv_attrib; + + uvec4 bones = bones_attrib; +#else + + vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + vec2 vertex_base = vertex_base_arr[gl_VertexIndex]; + + vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy); + vec4 color = draw_data.modulation; + vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0))); + uvec4 bones = uvec4(0, 0, 0, 0); + +#endif + + mat4 world_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0)); + +#if 0 + if (draw_data.flags & FLAGS_INSTANCING_ENABLED) { + + uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK; + offset *= gl_InstanceIndex; + mat4 instance_xform = mat4( + vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), 0.0, texelFetch(instancing_buffer, offset + 3)), + vec4(texelFetch(instancing_buffer, offset + 4), texelFetch(instancing_buffer, offset + 5), 0.0, texelFetch(instancing_buffer, offset + 7)), + vec4(0.0, 0.0, 1.0, 0.0), + vec4(0.0, 0.0, 0.0, 1.0)); + offset += 8; + if (draw_data.flags & FLAGS_INSTANCING_HAS_COLORS) { + vec4 instance_color; + if (draw_data.flags & FLAGS_INSTANCING_COLOR_8_BIT) { + uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset)); + instance_color = unpackUnorm4x8(bits); + offset += 1; + } else { + instance_color = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); + offser += 4; + } + + color *= instance_color; + } + if (draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA) { + if (draw_data.flags & FLAGS_INSTANCING_CUSTOM_DATA_8_BIT) { + uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset)); + instance_custom = unpackUnorm4x8(bits); + } else { + instance_custom = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); + } + } + } + +#endif + +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + if (bool(draw_data.flags & FLAGS_USING_PARTICLES)) { + //scale by texture size + vertex /= draw_data.color_texture_pixel_size; + } +#endif + +#ifdef USE_POINT_SIZE + float point_size = 1.0; +#endif + { + /* clang-format off */ +VERTEX_SHADER_CODE + /* clang-format on */ + } + +#ifdef USE_NINEPATCH + pixel_size_interp = abs(draw_data.dst_rect.zw) * vertex_base; +#endif + +#if !defined(SKIP_TRANSFORM_USED) + vertex = (world_matrix * vec4(vertex, 0.0, 1.0)).xy; +#endif + + color_interp = color; + + if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) { + + vertex = floor(vertex + 0.5); + // precision issue on some hardware creates artifacts within texture + // offset uv by a small amount to avoid + uv += 1e-5; + } + +#ifdef USE_ATTRIBUTES +#if 0 + if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone + //skeleton transform + + ivec4 bone_indicesi = ivec4(bone_indices); + + uvec2 tex_ofs = bone_indicesi.x * 2; + + mat2x4 m; + m = mat2x4( + texelFetch(skeleton_buffer, tex_ofs + 0), + texelFetch(skeleton_buffer, tex_ofs + 1)) * + bone_weights.x; + + tex_ofs = bone_indicesi.y * 2; + + m += mat2x4( + texelFetch(skeleton_buffer, tex_ofs + 0), + texelFetch(skeleton_buffer, tex_ofs + 1)) * + bone_weights.y; + + tex_ofs = bone_indicesi.z * 2; + + m += mat2x4( + texelFetch(skeleton_buffer, tex_ofs + 0), + texelFetch(skeleton_buffer, tex_ofs + 1)) * + bone_weights.z; + + tex_ofs = bone_indicesi.w * 2; + + m += mat2x4( + texelFetch(skeleton_buffer, tex_ofs + 0), + texelFetch(skeleton_buffer, tex_ofs + 1)) * + bone_weights.w; + + mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse; + + //outvec = bone_matrix * outvec; + } +#endif +#endif + + vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy; + + vertex_interp = vertex; + uv_interp = uv; + + gl_Position = canvas_data.screen_transform * vec4(vertex, 0.0, 1.0); + +#ifdef USE_POINT_SIZE + gl_PointSize = point_size; +#endif +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +#include "canvas_uniforms_inc.glsl" + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ +layout(location = 1) in vec4 color_interp; +layout(location = 2) in vec2 vertex_interp; + +#ifdef USE_NINEPATCH + +layout(location = 3) in vec2 pixel_size_interp; + +#endif + +layout(location = 0) out vec4 frag_color; + +#ifdef USE_MATERIAL_UNIFORMS +layout(set = 1, binding = 1, std140) uniform MaterialUniforms{ + /* clang-format off */ +MATERIAL_UNIFORMS + /* clang-format on */ +} material; +#endif + +/* clang-format off */ +FRAGMENT_SHADER_GLOBALS +/* clang-format on */ + +#ifdef LIGHT_SHADER_CODE_USED + +vec4 light_compute( + vec3 light_vertex, + vec3 light_position, + vec3 normal, + vec4 light_color, + float light_energy, + vec4 specular_shininess, + inout vec4 shadow_modulate, + vec2 screen_uv, + vec2 uv, + vec4 color) { + + vec4 light = vec4(0.0); + /* clang-format off */ +LIGHT_SHADER_CODE + /* clang-format on */ + return light; +} + +#endif + +#ifdef USE_NINEPATCH + +float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { + + float tex_size = 1.0 / tex_pixel_size; + + if (pixel < margin_begin) { + return pixel * tex_pixel_size; + } else if (pixel >= draw_size - margin_end) { + return (tex_size - (draw_size - pixel)) * tex_pixel_size; + } else { + if (!bool(draw_data.flags & FLAGS_NINEPACH_DRAW_CENTER)) { + draw_center--; + } + + // np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum. + if (np_repeat == 0) { // Stretch. + // Convert to ratio. + float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end); + // Scale to source texture. + return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size; + } else if (np_repeat == 1) { // Tile. + // Convert to offset. + float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end); + // Scale to source texture. + return (margin_begin + ofs) * tex_pixel_size; + } else if (np_repeat == 2) { // Tile Fit. + // Calculate scale. + float src_area = draw_size - margin_begin - margin_end; + float dst_area = tex_size - margin_begin - margin_end; + float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5)); + // Convert to ratio. + float ratio = (pixel - margin_begin) / src_area; + ratio = mod(ratio * scale, 1.0); + // Scale to source texture. + return (margin_begin + ratio * dst_area) * tex_pixel_size; + } else { // Shouldn't happen, but silences compiler warning. + return 0.0; + } + } +} + +#endif + +void main() { + + vec4 color = color_interp; + vec2 uv = uv_interp; + vec2 vertex = vertex_interp; + +#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) + +#ifdef USE_NINEPATCH + + int draw_center = 2; + uv = vec2( + map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(draw_data.flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center), + map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(draw_data.flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center)); + + if (draw_center == 0) { + color.a = 0.0; + } + + uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed + +#endif + if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) { + + uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw)); + } + +#endif + + color *= texture(sampler2D(color_texture, texture_sampler), uv); + + uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights + + vec3 normal; + +#if defined(NORMAL_USED) + + bool normal_used = true; +#else + bool normal_used = false; +#endif + + if (normal_used || (light_count > 0 && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { + normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); + normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); + normal_used = true; + } else { + normal = vec3(0.0, 0.0, 1.0); + } + + vec4 specular_shininess; + +#if defined(SPECULAR_SHININESS_USED) + + bool specular_shininess_used = true; +#else + bool specular_shininess_used = false; +#endif + + if (specular_shininess_used || (light_count > 0 && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { + specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); + specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); + specular_shininess_used = true; + } else { + specular_shininess = vec4(1.0); + } + +#if defined(SCREEN_UV_USED) + vec2 screen_uv = gl_FragCoord.xy * canvas_data.screen_pixel_size; +#else + vec2 screen_uv = vec2(0.0); +#endif + + vec3 light_vertex = vec3(vertex, 0.0); + vec2 shadow_vertex = vertex; + + { + float normal_depth = 1.0; + +#if defined(NORMALMAP_USED) + vec3 normal_map = vec3(0.0, 0.0, 1.0); + normal_used = true; +#endif + + /* clang-format off */ + +FRAGMENT_SHADER_CODE + + /* clang-format on */ + +#if defined(NORMALMAP_USED) + normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth); +#endif + } + + if (normal_used) { + //convert by item transform + normal.xy = mat2(normalize(draw_data.world_x), normalize(draw_data.world_y)) * normal.xy; + //convert by canvas transform + normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz); + } + + vec4 base_color = color; + if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) { + color = vec4(0.0); //invisible by default due to using light mask + } + + color *= canvas_data.canvas_modulation; +#ifdef USE_LIGHTING + for (uint i = 0; i < MAX_LIGHT_TEXTURES; i++) { + if (i >= light_count) { + break; + } + uint light_base; + if (i < 8) { + if (i < 4) { + light_base = draw_data.lights[0]; + } else { + light_base = draw_data.lights[1]; + } + } else { + if (i < 12) { + light_base = draw_data.lights[2]; + } else { + light_base = draw_data.lights[3]; + } + } + light_base >>= (i & 3) * 8; + light_base &= 0xFF; + + vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. + vec4 light_color = texture(sampler2D(light_textures[i], texture_sampler), tex_uv); + vec4 light_base_color = light_array.data[light_base].color; + +#ifdef LIGHT_SHADER_CODE_USED + + vec4 shadow_modulate = vec4(1.0); + vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height); + + light_color.rgb *= light_base_color.rgb; + light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv); +#else + + light_color.rgb *= light_base_color.rgb * light_base_color.a; + + if (normal_used) { + + vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height); + vec3 pos = light_vertex; + vec3 light_vec = normalize(light_pos - pos); + float cNdotL = max(0.0, dot(normal, light_vec)); + + if (specular_shininess_used) { + //blinn + vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough + vec3 half_vec = normalize(view + light_vec); + + float cNdotV = max(dot(normal, view), 0.0); + float cNdotH = max(dot(normal, half_vec), 0.0); + float cVdotH = max(dot(view, half_vec), 0.0); + float cLdotH = max(dot(light_vec, half_vec), 0.0); + float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess); + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); + + light_color.rgb = specular_shininess.rgb * light_base_color.rgb * s + light_color.rgb * cNdotL; + } else { + light_color.rgb *= cNdotL; + } + } +#endif + if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) { + //if outside the light texture, light color is zero + light_color.a = 0.0; + } + + if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { + + vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. + + vec2 pos_norm = normalize(shadow_pos); + vec2 pos_abs = abs(pos_norm); + vec2 pos_box = pos_norm / max(pos_abs.x, pos_abs.y); + vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot? + float tex_ofs; + float distance; + if (pos_rot.y > 0) { + if (pos_rot.x > 0) { + tex_ofs = pos_box.y * 0.125 + 0.125; + distance = shadow_pos.x; + } else { + tex_ofs = pos_box.x * -0.125 + (0.25 + 0.125); + distance = shadow_pos.y; + } + } else { + if (pos_rot.x < 0) { + tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125); + distance = -shadow_pos.x; + } else { + tex_ofs = pos_box.x * 0.125 + (0.75 + 0.125); + distance = -shadow_pos.y; + } + } + + //float distance = length(shadow_pos); + float shadow; + uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK; + + vec4 shadow_uv = vec4(tex_ofs, 0.0, distance, 1.0); + + if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) { + shadow = textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; + } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) { + vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); + shadow = 0.0; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x; + shadow /= 5.0; + } else { //PCF13 + vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); + shadow = 0.0; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 6.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 5.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 4.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 3.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 3.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 4.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 5.0).x; + shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 6.0).x; + shadow /= 13.0; + } + + vec4 shadow_color = light_array.data[light_base].shadow_color; +#ifdef LIGHT_SHADER_CODE_USED + shadow_color *= shadow_modulate; +#endif + light_color = mix(light_color, shadow_color, shadow); + } + + uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK; + + switch (blend_mode) { + case LIGHT_FLAGS_BLEND_MODE_ADD: { + color.rgb += light_color.rgb * light_color.a; + } break; + case LIGHT_FLAGS_BLEND_MODE_SUB: { + color.rgb -= light_color.rgb * light_color.a; + } break; + case LIGHT_FLAGS_BLEND_MODE_MIX: { + color.rgb = mix(color.rgb, light_color.rgb, light_color.a); + } break; + case LIGHT_FLAGS_BLEND_MODE_MASK: { + light_color.a *= base_color.a; + color.rgb = mix(color.rgb, light_color.rgb, light_color.a); + } break; + } + } +#endif + + frag_color = color; +} diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl new file mode 100644 index 0000000000..7b30cc8fe9 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/canvas_occlusion.glsl @@ -0,0 +1,40 @@ +/* clang-format off */ +[vertex] + +#version 450 + +layout(location = 0) in highp vec3 vertex; +/* clang-format on */ + +layout(push_constant, binding = 0, std430) uniform Constants { + + mat4 projection; + mat2x4 modelview; + vec2 direction; + vec2 pad; +} +constants; + +layout(location = 0) out highp float depth; + +void main() { + + highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); + depth = dot(constants.direction, vtx.xy); + + gl_Position = constants.projection * vtx; +} + +/* clang-format off */ +[fragment] + +#version 450 + +layout(location = 0) in highp float depth; +/* clang-format on */ +layout(location = 0) out highp float distance_buf; + +void main() { + + distance_buf = depth; +} diff --git a/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl new file mode 100644 index 0000000000..1ac43480cd --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/canvas_uniforms_inc.glsl @@ -0,0 +1,141 @@ +#define M_PI 3.14159265359 + +#define FLAGS_INSTANCING_STRIDE_MASK 0xF +#define FLAGS_INSTANCING_ENABLED (1 << 4) +#define FLAGS_INSTANCING_HAS_COLORS (1 << 5) +#define FLAGS_INSTANCING_COLOR_8BIT (1 << 6) +#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 7) +#define FLAGS_INSTANCING_CUSTOM_DATA_8_BIT (1 << 8) + +#define FLAGS_CLIP_RECT_UV (1 << 9) +#define FLAGS_TRANSPOSE_RECT (1 << 10) +#define FLAGS_USING_LIGHT_MASK (1 << 11) +#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12) +#define FLAGS_USING_PARTICLES (1 << 13) +#define FLAGS_USE_PIXEL_SNAP (1 << 14) + +#define FLAGS_NINEPATCH_H_MODE_SHIFT 16 +#define FLAGS_NINEPATCH_V_MODE_SHIFT 18 + +#define FLAGS_LIGHT_COUNT_SHIFT 20 + +#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) +#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) + +// In vulkan, sets should always be ordered using the following logic: +// Lower Sets: Sets that change format and layout less often +// Higher sets: Sets that change format and layout very often +// This is because changing a set for another with a different layout or format, +// invalidates all the upper ones. + +/* SET0: Draw Primitive */ + +layout(push_constant, binding = 0, std430) uniform DrawData { + vec2 world_x; + vec2 world_y; + vec2 world_ofs; + uint flags; + uint specular_shininess; +#ifdef USE_PRIMITIVE + vec2 points[3]; + vec2 uvs[3]; + uint colors[6]; +#else + vec4 modulation; + vec4 ninepatch_margins; + vec4 dst_rect; //for built-in rect and UV + vec4 src_rect; + vec2 pad; + +#endif + vec2 color_texture_pixel_size; + uint lights[4]; +} +draw_data; + +// The values passed per draw primitives are cached within it + +layout(set = 0, binding = 1) uniform texture2D color_texture; +layout(set = 0, binding = 2) uniform texture2D normal_texture; +layout(set = 0, binding = 3) uniform texture2D specular_texture; +layout(set = 0, binding = 4) uniform sampler texture_sampler; + +layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer; + +/* SET1: Is reserved for the material */ + +#ifdef USE_MATERIAL_SAMPLERS + +layout(set = 1, binding = 0) uniform sampler material_samplers[12]; + +#endif + +/* SET2: Canvas Item State (including lighting) */ + +layout(set = 2, binding = 0, std140) uniform CanvasData { + mat4 canvas_transform; + mat4 screen_transform; + mat4 canvas_normal_transform; + vec4 canvas_modulation; + vec2 screen_pixel_size; + float time; + float time_pad; + //uint light_count; +} +canvas_data; + +layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer; + +layout(set = 2, binding = 2, std140) uniform SkeletonData { + mat4 skeleton_transform; //in world coordinates + mat4 skeleton_transform_inverse; +} +skeleton_data; + +#ifdef USE_LIGHTING + +#define LIGHT_FLAGS_BLEND_MASK (3 << 16) +#define LIGHT_FLAGS_BLEND_MODE_ADD (0 << 16) +#define LIGHT_FLAGS_BLEND_MODE_SUB (1 << 16) +#define LIGHT_FLAGS_BLEND_MODE_MIX (2 << 16) +#define LIGHT_FLAGS_BLEND_MODE_MASK (3 << 16) +#define LIGHT_FLAGS_HAS_SHADOW (1 << 20) +#define LIGHT_FLAGS_FILTER_SHIFT 22 +#define LIGHT_FLAGS_FILTER_MASK (3 << 22) +#define LIGHT_FLAGS_SHADOW_NEAREST (0 << 22) +#define LIGHT_FLAGS_SHADOW_PCF5 (1 << 22) +#define LIGHT_FLAGS_SHADOW_PCF13 (2 << 22) + +struct Light { + mat2x4 texture_matrix; //light to texture coordinate matrix (transposed) + mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed) + vec4 color; + vec4 shadow_color; + vec2 position; + uint flags; //index to light texture + float height; + float shadow_pixel_size; + float pad0; + float pad1; + float pad2; +}; + +layout(set = 2, binding = 3, std140) uniform LightData { + Light data[MAX_LIGHTS]; +} +light_array; + +layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES]; +layout(set = 2, binding = 5) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES]; + +layout(set = 2, binding = 6) uniform sampler shadow_sampler; + +#endif + +/* SET3: Render Target Data */ + +#ifdef SCREEN_TEXTURE_USED + +layout(set = 3, binding = 0) uniform texture2D screen_texture; + +#endif diff --git a/servers/rendering/rasterizer_rd/shaders/copy.glsl b/servers/rendering/rasterizer_rd/shaders/copy.glsl new file mode 100644 index 0000000000..cbb9b546a3 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/copy.glsl @@ -0,0 +1,86 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +void main() { + + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + uv_interp = base_arr[gl_VertexIndex]; + + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ + +#ifdef MODE_CUBE_TO_DP + +layout(set = 0, binding = 0) uniform samplerCube source_cube; + +layout(push_constant, binding = 0, std430) uniform Params { + float bias; + float z_far; + float z_near; + bool z_flip; +} +params; + +layout(location = 0) out float depth_buffer; + +#endif + +void main() { + +#ifdef MODE_CUBE_TO_DP + + vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0); + + normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); + normal = normalize(normal); + + normal.y = -normal.y; //needs to be flipped to match projection matrix + if (!params.z_flip) { + normal.z = -normal.z; + } + + float depth = texture(source_cube, normal).r; + + // absolute values for direction cosines, bigger value equals closer to basis axis + vec3 unorm = abs(normal); + + if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { + // x code + unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); + } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { + // y code + unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); + } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { + // z code + unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + } else { + // oh-no we messed up code + // has to be + unorm = vec3(1.0, 0.0, 0.0); + } + + float depth_fix = 1.0 / dot(normal, unorm); + + depth = 2.0 * depth - 1.0; + float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far; + +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl new file mode 100644 index 0000000000..9f3ecf6053 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/cubemap_downsampler.glsl @@ -0,0 +1,188 @@ +// Copyright 2016 Activision Publishing, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +#define BLOCK_SIZE 8 + +layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform samplerCube source_cubemap; + +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap; + +layout(push_constant, binding = 1, std430) uniform Params { + uint face_size; +} +params; + +#define M_PI 3.14159265359 + +void get_dir_0(out vec3 dir, in float u, in float v) { + dir[0] = 1.0; + dir[1] = v; + dir[2] = -u; +} +void get_dir_1(out vec3 dir, in float u, in float v) { + dir[0] = -1.0; + dir[1] = v; + dir[2] = u; +} +void get_dir_2(out vec3 dir, in float u, in float v) { + dir[0] = u; + dir[1] = 1.0; + dir[2] = -v; +} +void get_dir_3(out vec3 dir, in float u, in float v) { + dir[0] = u; + dir[1] = -1.0; + dir[2] = v; +} +void get_dir_4(out vec3 dir, in float u, in float v) { + dir[0] = u; + dir[1] = v; + dir[2] = 1.0; +} +void get_dir_5(out vec3 dir, in float u, in float v) { + dir[0] = -u; + dir[1] = v; + dir[2] = -1.0; +} + +float calcWeight(float u, float v) { + float val = u * u + v * v + 1.0; + return val * sqrt(val); +} + +void main() { + uvec3 id = gl_GlobalInvocationID; + uint face_size = params.face_size; + + if (id.x < face_size && id.y < face_size) { + float inv_face_size = 1.0 / float(face_size); + + float u0 = (float(id.x) * 2.0 + 1.0 - 0.75) * inv_face_size - 1.0; + float u1 = (float(id.x) * 2.0 + 1.0 + 0.75) * inv_face_size - 1.0; + + float v0 = (float(id.y) * 2.0 + 1.0 - 0.75) * -inv_face_size + 1.0; + float v1 = (float(id.y) * 2.0 + 1.0 + 0.75) * -inv_face_size + 1.0; + + float weights[4]; + weights[0] = calcWeight(u0, v0); + weights[1] = calcWeight(u1, v0); + weights[2] = calcWeight(u0, v1); + weights[3] = calcWeight(u1, v1); + + const float wsum = 0.5 / (weights[0] + weights[1] + weights[2] + weights[3]); + for (int i = 0; i < 4; i++) { + weights[i] = weights[i] * wsum + .125; + } + + vec3 dir; + vec4 color; + switch (id.z) { + case 0: + get_dir_0(dir, u0, v0); + color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; + + get_dir_0(dir, u1, v0); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; + + get_dir_0(dir, u0, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; + + get_dir_0(dir, u1, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; + break; + case 1: + get_dir_1(dir, u0, v0); + color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; + + get_dir_1(dir, u1, v0); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; + + get_dir_1(dir, u0, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; + + get_dir_1(dir, u1, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; + break; + case 2: + get_dir_2(dir, u0, v0); + color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; + + get_dir_2(dir, u1, v0); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; + + get_dir_2(dir, u0, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; + + get_dir_2(dir, u1, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; + break; + case 3: + get_dir_3(dir, u0, v0); + color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; + + get_dir_3(dir, u1, v0); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; + + get_dir_3(dir, u0, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; + + get_dir_3(dir, u1, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; + break; + case 4: + get_dir_4(dir, u0, v0); + color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; + + get_dir_4(dir, u1, v0); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; + + get_dir_4(dir, u0, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; + + get_dir_4(dir, u1, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; + break; + default: + get_dir_5(dir, u0, v0); + color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; + + get_dir_5(dir, u1, v0); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; + + get_dir_5(dir, u0, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; + + get_dir_5(dir, u1, v1); + color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; + break; + } + imageStore(dest_cubemap, ivec3(id), color); + } +} diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl new file mode 100644 index 0000000000..193d0a8a3c --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/cubemap_filter.glsl @@ -0,0 +1,328 @@ +// Copyright 2016 Activision Publishing, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the Software +// is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +#define GROUP_SIZE 64 + +layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform samplerCube source_cubemap; +layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly imageCube dest_cubemap0; +layout(rgba16f, set = 2, binding = 1) uniform restrict writeonly imageCube dest_cubemap1; +layout(rgba16f, set = 2, binding = 2) uniform restrict writeonly imageCube dest_cubemap2; +layout(rgba16f, set = 2, binding = 3) uniform restrict writeonly imageCube dest_cubemap3; +layout(rgba16f, set = 2, binding = 4) uniform restrict writeonly imageCube dest_cubemap4; +layout(rgba16f, set = 2, binding = 5) uniform restrict writeonly imageCube dest_cubemap5; +layout(rgba16f, set = 2, binding = 6) uniform restrict writeonly imageCube dest_cubemap6; + +#ifdef USE_HIGH_QUALITY +#define NUM_TAPS 32 +#else +#define NUM_TAPS 8 +#endif + +#define BASE_RESOLUTION 128 + +#ifdef USE_HIGH_QUALITY +layout(set = 1, binding = 0, std430) buffer restrict readonly Data { + vec4[7][5][3][24] coeffs; +} +data; +#else +layout(set = 1, binding = 0, std430) buffer restrict readonly Data { + vec4[7][5][6] coeffs; +} +data; +#endif + +void get_dir(out vec3 dir, in vec2 uv, in uint face) { + switch (face) { + case 0: + dir = vec3(1.0, uv[1], -uv[0]); + break; + case 1: + dir = vec3(-1.0, uv[1], uv[0]); + break; + case 2: + dir = vec3(uv[0], 1.0, -uv[1]); + break; + case 3: + dir = vec3(uv[0], -1.0, uv[1]); + break; + case 4: + dir = vec3(uv[0], uv[1], 1.0); + break; + default: + dir = vec3(-uv[0], uv[1], -1.0); + break; + } +} + +void main() { + // INPUT: + // id.x = the linear address of the texel (ignoring face) + // id.y = the face + // -> use to index output texture + // id.x = texel x + // id.y = texel y + // id.z = face + uvec3 id = gl_GlobalInvocationID; + + // determine which texel this is +#ifndef USE_TEXTURE_ARRAY + // NOTE (macOS/MoltenVK): Do not rename, "level" variable name conflicts with the Metal "level(float lod)" mipmap sampling function name. + int mip_level = 0; + if (id.x < (128 * 128)) { + mip_level = 0; + } else if (id.x < (128 * 128 + 64 * 64)) { + mip_level = 1; + id.x -= (128 * 128); + } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32)) { + mip_level = 2; + id.x -= (128 * 128 + 64 * 64); + } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16)) { + mip_level = 3; + id.x -= (128 * 128 + 64 * 64 + 32 * 32); + } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8)) { + mip_level = 4; + id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16); + } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4)) { + mip_level = 5; + id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8); + } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2)) { + mip_level = 6; + id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4); + } else { + return; + } + int res = BASE_RESOLUTION >> mip_level; +#else // Using Texture Arrays so all levels are the same resolution + int res = BASE_RESOLUTION; + int mip_level = int(id.x / (BASE_RESOLUTION * BASE_RESOLUTION)); + id.x -= mip_level * BASE_RESOLUTION * BASE_RESOLUTION; +#endif + + // determine dir / pos for the texel + vec3 dir, adir, frameZ; + { + id.z = id.y; + id.y = id.x / res; + id.x -= id.y * res; + + vec2 uv; + uv.x = (float(id.x) * 2.0 + 1.0) / float(res) - 1.0; + uv.y = -(float(id.y) * 2.0 + 1.0) / float(res) + 1.0; + + get_dir(dir, uv, id.z); + frameZ = normalize(dir); + + adir = abs(dir); + } + + // GGX gather colors + vec4 color = vec4(0.0); + for (int axis = 0; axis < 3; axis++) { + const int otherAxis0 = 1 - (axis & 1) - (axis >> 1); + const int otherAxis1 = 2 - (axis >> 1); + + float frameweight = (max(adir[otherAxis0], adir[otherAxis1]) - .75) / .25; + if (frameweight > 0.0) { + // determine frame + vec3 UpVector; + switch (axis) { + case 0: + UpVector = vec3(1, 0, 0); + break; + case 1: + UpVector = vec3(0, 1, 0); + break; + default: + UpVector = vec3(0, 0, 1); + break; + } + + vec3 frameX = normalize(cross(UpVector, frameZ)); + vec3 frameY = cross(frameZ, frameX); + + // calculate parametrization for polynomial + float Nx = dir[otherAxis0]; + float Ny = dir[otherAxis1]; + float Nz = adir[axis]; + + float NmaxXY = max(abs(Ny), abs(Nx)); + Nx /= NmaxXY; + Ny /= NmaxXY; + + float theta; + if (Ny < Nx) { + if (Ny <= -0.999) + theta = Nx; + else + theta = Ny; + } else { + if (Ny >= 0.999) + theta = -Nx; + else + theta = -Ny; + } + + float phi; + if (Nz <= -0.999) + phi = -NmaxXY; + else if (Nz >= 0.999) + phi = NmaxXY; + else + phi = Nz; + + float theta2 = theta * theta; + float phi2 = phi * phi; + + // sample + for (int iSuperTap = 0; iSuperTap < NUM_TAPS / 4; iSuperTap++) { + const int index = (NUM_TAPS / 4) * axis + iSuperTap; + +#ifdef USE_HIGH_QUALITY + vec4 coeffsDir0[3]; + vec4 coeffsDir1[3]; + vec4 coeffsDir2[3]; + vec4 coeffsLevel[3]; + vec4 coeffsWeight[3]; + + for (int iCoeff = 0; iCoeff < 3; iCoeff++) { + coeffsDir0[iCoeff] = data.coeffs[mip_level][0][iCoeff][index]; + coeffsDir1[iCoeff] = data.coeffs[mip_level][1][iCoeff][index]; + coeffsDir2[iCoeff] = data.coeffs[mip_level][2][iCoeff][index]; + coeffsLevel[iCoeff] = data.coeffs[mip_level][3][iCoeff][index]; + coeffsWeight[iCoeff] = data.coeffs[mip_level][4][iCoeff][index]; + } + + for (int iSubTap = 0; iSubTap < 4; iSubTap++) { + // determine sample attributes (dir, weight, mip_level) + vec3 sample_dir = frameX * (coeffsDir0[0][iSubTap] + coeffsDir0[1][iSubTap] * theta2 + coeffsDir0[2][iSubTap] * phi2) + frameY * (coeffsDir1[0][iSubTap] + coeffsDir1[1][iSubTap] * theta2 + coeffsDir1[2][iSubTap] * phi2) + frameZ * (coeffsDir2[0][iSubTap] + coeffsDir2[1][iSubTap] * theta2 + coeffsDir2[2][iSubTap] * phi2); + + float sample_level = coeffsLevel[0][iSubTap] + coeffsLevel[1][iSubTap] * theta2 + coeffsLevel[2][iSubTap] * phi2; + + float sample_weight = coeffsWeight[0][iSubTap] + coeffsWeight[1][iSubTap] * theta2 + coeffsWeight[2][iSubTap] * phi2; +#else + vec4 coeffsDir0 = data.coeffs[mip_level][0][index]; + vec4 coeffsDir1 = data.coeffs[mip_level][1][index]; + vec4 coeffsDir2 = data.coeffs[mip_level][2][index]; + vec4 coeffsLevel = data.coeffs[mip_level][3][index]; + vec4 coeffsWeight = data.coeffs[mip_level][4][index]; + + for (int iSubTap = 0; iSubTap < 4; iSubTap++) { + // determine sample attributes (dir, weight, mip_level) + vec3 sample_dir = frameX * coeffsDir0[iSubTap] + frameY * coeffsDir1[iSubTap] + frameZ * coeffsDir2[iSubTap]; + + float sample_level = coeffsLevel[iSubTap]; + + float sample_weight = coeffsWeight[iSubTap]; +#endif + + sample_weight *= frameweight; + + // adjust for jacobian + sample_dir /= max(abs(sample_dir[0]), max(abs(sample_dir[1]), abs(sample_dir[2]))); + sample_level += 0.75 * log2(dot(sample_dir, sample_dir)); +#ifndef USE_TEXTURE_ARRAY + sample_level += float(mip_level) / 6.0; // Hack to increase the perceived roughness and reduce upscaling artifacts +#endif + // sample cubemap + color.xyz += textureLod(source_cubemap, normalize(sample_dir), sample_level).xyz * sample_weight; + color.w += sample_weight; + } + } + } + } + color /= color.w; + + // write color + color.xyz = max(vec3(0.0), color.xyz); + color.w = 1.0; +#ifdef USE_TEXTURE_ARRAY + id.xy *= uvec2(2, 2); +#endif + + switch (mip_level) { + case 0: + imageStore(dest_cubemap0, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap0, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + case 1: + imageStore(dest_cubemap1, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap1, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + case 2: + imageStore(dest_cubemap2, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap2, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + case 3: + imageStore(dest_cubemap3, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap3, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + case 4: + imageStore(dest_cubemap4, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap4, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + case 5: + imageStore(dest_cubemap5, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap5, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + default: + imageStore(dest_cubemap6, ivec3(id), color); +#ifdef USE_TEXTURE_ARRAY + imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); + imageStore(dest_cubemap6, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); + imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); +#endif + break; + } +} diff --git a/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl new file mode 100644 index 0000000000..e85996fa1a --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/cubemap_roughness.glsl @@ -0,0 +1,147 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +#define GROUP_SIZE 8 + +layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform samplerCube source_cube; + +layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap; + +layout(push_constant, binding = 1, std430) uniform Params { + uint face_id; + uint sample_count; + float roughness; + bool use_direct_write; + float face_size; +} +params; + +#define M_PI 3.14159265359 + +vec3 texelCoordToVec(vec2 uv, uint faceID) { + mat3 faceUvVectors[6]; + + // -x + faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z + faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face + + // +x + faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z + faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face + + // -y + faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z + faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face + + // +y + faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z + faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face + + // -z + faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x + faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face + + // +z + faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x + faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y + faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face + + // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. + vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; + return normalize(result); +} + +vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { + float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] + + // Compute distribution direction + float Phi = 2.0 * M_PI * Xi.x; + float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); + float SinTheta = sqrt(1.0 - CosTheta * CosTheta); + + // Convert to spherical direction + vec3 H; + H.x = SinTheta * cos(Phi); + H.y = SinTheta * sin(Phi); + H.z = CosTheta; + + vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); + vec3 TangentX = normalize(cross(UpVector, N)); + vec3 TangentY = cross(N, TangentX); + + // Tangent to world space + return TangentX * H.x + TangentY * H.y + N * H.z; +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float GGX(float NdotV, float a) { + float k = a / 2.0; + return NdotV / (NdotV * (1.0 - k) + k); +} + +// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html +float G_Smith(float a, float nDotV, float nDotL) { + return GGX(nDotL, a * a) * GGX(nDotV, a * a); +} + +float radicalInverse_VdC(uint bits) { + bits = (bits << 16u) | (bits >> 16u); + bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); + bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); + bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); + bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); + return float(bits) * 2.3283064365386963e-10; // / 0x100000000 +} + +vec2 Hammersley(uint i, uint N) { + return vec2(float(i) / float(N), radicalInverse_VdC(i)); +} + +void main() { + uvec3 id = gl_GlobalInvocationID; + id.z += params.face_id; + + vec2 uv = ((vec2(id.xy) * 2.0 + 1.0) / (params.face_size) - 1.0); + vec3 N = texelCoordToVec(uv, id.z); + + //vec4 color = color_interp; + + if (params.use_direct_write) { + + imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0)); + } else { + + vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); + + for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) { + vec2 xi = Hammersley(sampleNum, params.sample_count); + + vec3 H = ImportanceSampleGGX(xi, params.roughness, N); + vec3 V = N; + vec3 L = (2.0 * dot(V, H) * H - V); + + float ndotl = clamp(dot(N, L), 0.0, 1.0); + + if (ndotl > 0.0) { + + sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl; + sum.a += ndotl; + } + } + sum /= sum.a; + + imageStore(dest_cubemap, ivec3(id), vec4(sum.rgb, 1.0)); + } +} diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl new file mode 100644 index 0000000000..fd09f96a57 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/giprobe.glsl @@ -0,0 +1,788 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +#ifdef MODE_DYNAMIC +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +#else +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; +#endif +/* clang-format on */ + +#ifndef MODE_DYNAMIC + +#define NO_CHILDREN 0xFFFFFFFF +#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) + +struct CellChildren { + uint children[8]; +}; + +layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { + CellChildren data[]; +} +cell_children; + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; + +layout(set = 0, binding = 2, std430) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +#endif // MODE DYNAMIC + +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_OMNI 1 +#define LIGHT_TYPE_SPOT 2 + +#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) + +struct Light { + + uint type; + float energy; + float radius; + float attenuation; + + vec3 color; + float spot_angle_radians; + + vec3 position; + float spot_attenuation; + + vec3 direction; + bool has_shadow; +}; + +layout(set = 0, binding = 3, std140) uniform Lights { + Light data[MAX_LIGHTS]; +} +lights; + +#endif // MODE COMPUTE LIGHT + +#ifdef MODE_SECOND_BOUNCE + +layout(set = 0, binding = 5) uniform texture3D color_texture; + +#ifdef MODE_ANISOTROPIC +layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture; +layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture; +#endif // MODE ANISOTROPIC + +#endif // MODE_SECOND_BOUNCE + +#ifndef MODE_DYNAMIC + +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 limits; + uint stack_size; + + float emission_scale; + float propagation; + float dynamic_range; + + uint light_count; + uint cell_offset; + uint cell_count; + float aniso_strength; + uint pad; +} +params; + +layout(set = 0, binding = 4, std430) buffer Outputs { + vec4 data[]; +} +outputs; + +#endif // MODE DYNAMIC + +layout(set = 0, binding = 9) uniform texture3D texture_sdf; +layout(set = 0, binding = 10) uniform sampler texture_sampler; + +#ifdef MODE_WRITE_TEXTURE + +layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex; + +#ifdef MODE_ANISOTROPIC + +layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex; +layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex; + +#endif + +#endif + +#ifdef MODE_DYNAMIC + +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 limits; + uint light_count; //when not lighting + ivec3 x_dir; + float z_base; + ivec3 y_dir; + float z_sign; + ivec3 z_dir; + float pos_multiplier; + ivec2 rect_pos; + ivec2 rect_size; + ivec2 prev_rect_ofs; + ivec2 prev_rect_size; + bool flip_x; + bool flip_y; + float dynamic_range; + bool on_mipmap; + float propagation; + float pad[3]; +} +params; + +#ifdef MODE_DYNAMIC_LIGHTING + +layout(rgba8, set = 0, binding = 5) uniform restrict readonly image2D source_albedo; +layout(rgba8, set = 0, binding = 6) uniform restrict readonly image2D source_normal; +layout(rgba8, set = 0, binding = 7) uniform restrict readonly image2D source_orm; +//layout (set=0,binding=8) uniform texture2D source_depth; +layout(rgba16f, set = 0, binding = 11) uniform restrict image2D emission; +layout(r32f, set = 0, binding = 12) uniform restrict image2D depth; + +#endif + +#ifdef MODE_DYNAMIC_SHRINK + +layout(rgba16f, set = 0, binding = 5) uniform restrict readonly image2D source_light; +layout(r32f, set = 0, binding = 6) uniform restrict readonly image2D source_depth; + +#ifdef MODE_DYNAMIC_SHRINK_WRITE + +layout(rgba16f, set = 0, binding = 7) uniform restrict writeonly image2D light; +layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth; + +#endif // MODE_DYNAMIC_SHRINK_WRITE + +#ifdef MODE_DYNAMIC_SHRINK_PLOT + +layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture; + +#ifdef MODE_ANISOTROPIC + +layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture; +layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture; + +#endif // MODE ANISOTROPIC + +#endif //MODE_DYNAMIC_SHRINK_PLOT + +#endif // MODE_DYNAMIC_SHRINK + +//layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex; + +#endif // MODE DYNAMIC + +#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) + +float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { + + vec3 cell_size = 1.0 / vec3(params.limits); + float occlusion = 1.0; + while (distance > 0.5) { //use this to avoid precision errors + float advance = texture(sampler3D(texture_sdf, texture_sampler), from * cell_size).r * 255.0 - 1.0; + if (advance < 0.0) { + occlusion = 0.0; + break; + } + + occlusion = min(advance, occlusion); + + advance = max(distance_adv, advance - mod(advance, distance_adv)); //should always advance in multiples of distance_adv + + from += direction * advance; + distance -= advance; + } + + return occlusion; //max(0.0,distance); +} + +bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) { + + if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { + + light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); + attenuation = 1.0; + + } else { + + light_pos = lights.data[light].position; + float distance = length(pos - light_pos); + if (distance >= lights.data[light].radius) { + return false; + } + + attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation); + + if (lights.data[light].type == LIGHT_TYPE_SPOT) { + + vec3 rel = normalize(pos - light_pos); + float angle = acos(dot(rel, lights.data[light].direction)); + if (angle > lights.data[light].spot_angle_radians) { + return false; + } + + float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1); + attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation); + } + } + + return true; +} + +float get_normal_advance(vec3 p_normal) { + + vec3 normal = p_normal; + vec3 unorm = abs(normal); + + if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { + // x code + unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); + } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { + // y code + unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); + } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { + // z code + unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + } else { + // oh-no we messed up code + // has to be + unorm = vec3(1.0, 0.0, 0.0); + } + + return 1.0 / dot(normal, unorm); +} + +void clip_segment(vec4 plane, vec3 begin, inout vec3 end) { + + vec3 segment = begin - end; + float den = dot(plane.xyz, segment); + + //printf("den is %i\n",den); + if (den < 0.0001) { + return; + } + + float dist = (dot(plane.xyz, begin) - plane.w) / den; + + if (dist < 0.0001 || dist > 1.0001) { + return; + } + + end = begin + segment * -dist; +} + +bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, inout vec3 light_dir) { + float attenuation; + vec3 light_pos; + + if (!compute_light_vector(index, pos, attenuation, light_pos)) { + return false; + } + + light_dir = normalize(pos - light_pos); + + if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal, light_dir) >= 0)) { + return false; //not facing the light, or attenuation is near zero + } + + if (lights.data[index].has_shadow) { + + float distance_adv = get_normal_advance(light_dir); + + vec3 to = pos; + if (length(normal) > 0.2) { + to += normal * distance_adv * 0.51; + } else { + to -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion + } + + //clip + clip_segment(mix(vec4(-1.0, 0.0, 0.0, 0.0), vec4(1.0, 0.0, 0.0, float(params.limits.x - 1)), bvec4(light_dir.x < 0.0)), to, light_pos); + clip_segment(mix(vec4(0.0, -1.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, float(params.limits.y - 1)), bvec4(light_dir.y < 0.0)), to, light_pos); + clip_segment(mix(vec4(0.0, 0.0, -1.0, 0.0), vec4(0.0, 0.0, 1.0, float(params.limits.z - 1)), bvec4(light_dir.z < 0.0)), to, light_pos); + + float distance = length(to - light_pos); + if (distance < 0.1) { + return false; // hit + } + + distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always + light_pos = to - light_dir * distance; + + //from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion + + /*float dist = raymarch(distance,distance_adv,light_pos,light_dir); + + if (dist > distance_adv) { + return false; + } + + attenuation *= 1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); + */ + + float occlusion = raymarch(distance, distance_adv, light_pos, light_dir); + + if (occlusion == 0.0) { + return false; + } + + attenuation *= occlusion; //1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); + } + + light = lights.data[index].color * attenuation * lights.data[index].energy; + return true; +} + +#endif // MODE COMPUTE LIGHT + +void main() { + +#ifndef MODE_DYNAMIC + + uint cell_index = gl_GlobalInvocationID.x; + if (cell_index >= params.cell_count) { + return; + } + cell_index += params.cell_offset; + + uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); + vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo); + +#endif + + /////////////////COMPUTE LIGHT/////////////////////////////// + +#ifdef MODE_COMPUTE_LIGHT + + vec3 pos = vec3(posu) + vec3(0.5); + + vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); + vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz; + +#ifdef MODE_ANISOTROPIC + vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); +#else + vec3 accum = vec3(0.0); +#endif + + for (uint i = 0; i < params.light_count; i++) { + + vec3 light; + vec3 light_dir; + if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) { + continue; + } + + light *= albedo.rgb; + +#ifdef MODE_ANISOTROPIC + for (uint j = 0; j < 6; j++) { + + accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light; + } +#else + if (length(normal) > 0.2) { + accum += max(0.0, dot(normal, -light_dir)) * light; + } else { + //all directions + accum += light; + } +#endif + } + +#ifdef MODE_ANISOTROPIC + + for (uint i = 0; i < 6; i++) { + vec3 light = accum[i]; + if (length(normal) > 0.2) { + light += max(0.0, dot(accum_dirs[i], -normal)) * emission; + } else { + light += emission; + } + + outputs.data[cell_index * 6 + i] = vec4(light, 0.0); + } + +#else + outputs.data[cell_index] = vec4(accum + emission, 0.0); + +#endif + +#endif //MODE_COMPUTE_LIGHT + + /////////////////SECOND BOUNCE/////////////////////////////// + +#ifdef MODE_SECOND_BOUNCE + vec3 pos = vec3(posu) + vec3(0.5); + ivec3 ipos = ivec3(posu); + vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); + +#ifdef MODE_ANISOTROPIC + vec3 accum[6]; + const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); + + /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range; + vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb; + vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb; + accum[0]=src_col * src_aniso_pos.x; + accum[1]=src_col * src_aniso_neg.x; + accum[2]=src_col * src_aniso_pos.y; + accum[3]=src_col * src_aniso_neg.y; + accum[4]=src_col * src_aniso_pos.z; + accum[5]=src_col * src_aniso_neg.z;*/ + + accum[0] = outputs.data[cell_index * 6 + 0].rgb; + accum[1] = outputs.data[cell_index * 6 + 1].rgb; + accum[2] = outputs.data[cell_index * 6 + 2].rgb; + accum[3] = outputs.data[cell_index * 6 + 3].rgb; + accum[4] = outputs.data[cell_index * 6 + 4].rgb; + accum[5] = outputs.data[cell_index * 6 + 5].rgb; + +#else + vec3 accum = outputs.data[cell_index].rgb; + +#endif + + if (length(normal.xyz) > 0.2) { + + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal.xyz)); + vec3 bitangent = normalize(cross(tangent, normal.xyz)); + mat3 normal_mat = mat3(tangent, bitangent, normal.xyz); + +#define MAX_CONE_DIRS 6 + + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5)); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + float tan_half_angle = 0.577; + + for (int i = 0; i < MAX_CONE_DIRS; i++) { + + vec3 direction = normal_mat * cone_dirs[i]; + vec4 color = vec4(0.0); + { + + float dist = 1.5; + float max_distance = length(vec3(params.limits)); + vec3 cell_size = 1.0 / vec3(params.limits); + +#ifdef MODE_ANISOTROPIC + vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength); +#endif + while (dist < max_distance && color.a < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec3 uvw_pos = (pos + dist * direction) * cell_size; + float half_diameter = diameter * 0.5; + //check if outside, then break + //if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) { + // break; + //} + + float log2_diameter = log2(diameter); + vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter); +#ifdef MODE_ANISOTROPIC + + vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb; + vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb; + + scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0)); +#endif + float a = (1.0 - color.a); + color += a * scolor; + dist += half_diameter; + } + } + color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range +#ifdef MODE_ANISOTROPIC + for (uint j = 0; j < 6; j++) { + + accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb; + } +#else + accum += color.rgb; +#endif + } + } + +#ifdef MODE_ANISOTROPIC + + outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); + outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); + outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); + outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); + outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); + outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); +#else + outputs.data[cell_index] = vec4(accum, 0.0); + +#endif + +#endif // MODE_SECOND_BOUNCE + + /////////////////UPDATE MIPMAPS/////////////////////////////// + +#ifdef MODE_UPDATE_MIPMAPS + + { +#ifdef MODE_ANISOTROPIC + vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); +#else + vec3 light_accum = vec3(0.0); +#endif + float count = 0.0; + for (uint i = 0; i < 8; i++) { + uint child_index = cell_children.data[cell_index].children[i]; + if (child_index == NO_CHILDREN) { + continue; + } +#ifdef MODE_ANISOTROPIC + light_accum[0] += outputs.data[child_index * 6 + 0].rgb; + light_accum[1] += outputs.data[child_index * 6 + 1].rgb; + light_accum[2] += outputs.data[child_index * 6 + 2].rgb; + light_accum[3] += outputs.data[child_index * 6 + 3].rgb; + light_accum[4] += outputs.data[child_index * 6 + 4].rgb; + light_accum[5] += outputs.data[child_index * 6 + 5].rgb; + +#else + light_accum += outputs.data[child_index].rgb; + +#endif + + count += 1.0; + } + + float divisor = mix(8.0, count, params.propagation); +#ifdef MODE_ANISOTROPIC + outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); + outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); + outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); + outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); + outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); + outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); + +#else + outputs.data[cell_index] = vec4(light_accum / divisor, 0.0); +#endif + } +#endif + + ///////////////////WRITE TEXTURE///////////////////////////// + +#ifdef MODE_WRITE_TEXTURE + { + +#ifdef MODE_ANISOTROPIC + vec3 accum_total = vec3(0.0); + accum_total += outputs.data[cell_index * 6 + 0].rgb; + accum_total += outputs.data[cell_index * 6 + 1].rgb; + accum_total += outputs.data[cell_index * 6 + 2].rgb; + accum_total += outputs.data[cell_index * 6 + 3].rgb; + accum_total += outputs.data[cell_index * 6 + 4].rgb; + accum_total += outputs.data[cell_index * 6 + 5].rgb; + + float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001); + vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy); + vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy); + + { + uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0)); + aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5; + aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11; + imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos)); + } + + { + uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0)); + aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5; + aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11; + imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg)); + } + + imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a)); + +#else + + imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a)); + +#endif + } +#endif + + ///////////////////DYNAMIC LIGHTING///////////////////////////// + +#ifdef MODE_DYNAMIC + + ivec2 pos_xy = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThanEqual(pos_xy, params.rect_size))) { + return; //out of bounds + } + + ivec2 uv_xy = pos_xy; + if (params.flip_x) { + uv_xy.x = params.rect_size.x - pos_xy.x - 1; + } + if (params.flip_y) { + uv_xy.y = params.rect_size.y - pos_xy.y - 1; + } + +#ifdef MODE_DYNAMIC_LIGHTING + + { + float z = params.z_base + imageLoad(depth, uv_xy).x * params.z_sign; + + ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z); + + vec3 normal = imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0; + normal = vec3(params.x_dir) * normal.x * mix(1.0, -1.0, params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0, -1.0, params.flip_y) - vec3(params.z_dir) * normal.z; + + vec4 albedo = imageLoad(source_albedo, uv_xy); + + //determine the position in space + + vec3 accum = vec3(0.0); + for (uint i = 0; i < params.light_count; i++) { + + vec3 light; + vec3 light_dir; + if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) { + continue; + } + + light *= albedo.rgb; + + accum += max(0.0, dot(normal, -light_dir)) * light; + } + + accum += imageLoad(emission, uv_xy).xyz; + + imageStore(emission, uv_xy, vec4(accum, albedo.a)); + imageStore(depth, uv_xy, vec4(z)); + } + +#endif // MODE DYNAMIC LIGHTING + +#ifdef MODE_DYNAMIC_SHRINK + + { + vec4 accum = vec4(0.0); + float accum_z = 0.0; + float count = 0.0; + + for (int i = 0; i < 4; i++) { + ivec2 ofs = pos_xy * 2 + ivec2(i & 1, i >> 1) - params.prev_rect_ofs; + if (any(lessThan(ofs, ivec2(0))) || any(greaterThanEqual(ofs, params.prev_rect_size))) { + continue; + } + if (params.flip_x) { + ofs.x = params.prev_rect_size.x - ofs.x - 1; + } + if (params.flip_y) { + ofs.y = params.prev_rect_size.y - ofs.y - 1; + } + + vec4 light = imageLoad(source_light, ofs); + if (light.a == 0.0) { //ignore empty + continue; + } + accum += light; + float z = imageLoad(source_depth, ofs).x; + accum_z += z * 0.5; //shrink half too + count += 1.0; + } + + if (params.on_mipmap) { + accum.rgb /= mix(8.0, count, params.propagation); + accum.a /= 8.0; + } else { + accum /= 4.0; + } + + if (count == 0.0) { + accum_z = 0.0; //avoid nan + } else { + accum_z /= count; + } + +#ifdef MODE_DYNAMIC_SHRINK_WRITE + + imageStore(light, uv_xy, accum); + imageStore(depth, uv_xy, vec4(accum_z)); +#endif + +#ifdef MODE_DYNAMIC_SHRINK_PLOT + + if (accum.a < 0.001) { + return; //do not blit if alpha is too low + } + + ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(accum_z); + + float z_frac = fract(accum_z); + + for (int i = 0; i < 2; i++) { + ivec3 pos3d = pos + abs(params.z_dir) * i; + if (any(lessThan(pos3d, ivec3(0))) || any(greaterThanEqual(pos3d, params.limits))) { + //skip if offlimits + continue; + } + vec4 color_blit = accum * (i == 0 ? 1.0 - z_frac : z_frac); + vec4 color = imageLoad(color_texture, pos3d); + color.rgb *= params.dynamic_range; + +#if 0 + color.rgb = mix(color.rgb,color_blit.rgb,color_blit.a); + color.a+=color_blit.a; +#else + + float sa = 1.0 - color_blit.a; + vec4 result; + result.a = color.a * sa + color_blit.a; + if (result.a == 0.0) { + result = vec4(0.0); + } else { + result.rgb = (color.rgb * color.a * sa + color_blit.rgb * color_blit.a) / result.a; + color = result; + } + +#endif + color.rgb /= params.dynamic_range; + imageStore(color_texture, pos3d, color); + //imageStore(color_texture,pos3d,vec4(1,1,1,1)); + +#ifdef MODE_ANISOTROPIC + //do not care about anisotropy for dynamic objects, just store full lit in all directions + imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF)); + imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF)); + +#endif // ANISOTROPIC + } +#endif // MODE_DYNAMIC_SHRINK_PLOT + } +#endif + +#endif // MODE DYNAMIC +} diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl new file mode 100644 index 0000000000..b1784e7eee --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/giprobe_debug.glsl @@ -0,0 +1,208 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; +/* clang-format on */ + +layout(set = 0, binding = 1, std140) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +layout(set = 0, binding = 2) uniform texture3D color_tex; + +layout(set = 0, binding = 3) uniform sampler tex_sampler; + +#ifdef USE_ANISOTROPY +layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex; +layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex; +#endif + +layout(push_constant, binding = 0, std430) uniform Params { + + mat4 projection; + uint cell_offset; + float dynamic_range; + float alpha; + uint level; + ivec3 bounds; + uint pad; +} +params; + +layout(location = 0) out vec4 color_interp; + +void main() { + + const vec3 cube_triangles[36] = vec3[]( + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, -1.0f, 1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(-1.0f, -1.0f, 1.0f), + vec3(-1.0f, -1.0f, -1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(-1.0f, -1.0f, 1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(1.0f, -1.0f, -1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(1.0f, -1.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(1.0f, 1.0f, -1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(-1.0f, 1.0f, -1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(1.0f, 1.0f, 1.0f), + vec3(-1.0f, 1.0f, 1.0f), + vec3(1.0f, -1.0f, 1.0f)); + + vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5; +#ifdef MODE_DEBUG_LIGHT_FULL + uvec3 posu = uvec3(gl_InstanceIndex % params.bounds.x, (gl_InstanceIndex / params.bounds.x) % params.bounds.y, gl_InstanceIndex / (params.bounds.y * params.bounds.x)); +#else + uint cell_index = gl_InstanceIndex + params.cell_offset; + + uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); +#endif + +#ifdef MODE_DEBUG_EMISSION + color_interp.xyz = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); +#endif + +#ifdef MODE_DEBUG_COLOR + color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz; +#endif + +#ifdef MODE_DEBUG_LIGHT + +#ifdef USE_ANISOTROPY + +#define POS_X 0 +#define POS_Y 1 +#define POS_Z 2 +#define NEG_X 3 +#define NEG_Y 4 +#define NEG_Z 5 + + const uint triangle_aniso[12] = uint[]( + NEG_X, + NEG_Z, + NEG_Y, + NEG_Z, + NEG_X, + NEG_Y, + POS_Z, + POS_X, + POS_X, + POS_Y, + POS_Y, + POS_Z); + + color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range; + vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; + vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; + uint side = triangle_aniso[gl_VertexIndex / 3]; + + float strength = 0.0; + switch (side) { + case POS_X: strength = aniso_pos.x; break; + case POS_Y: strength = aniso_pos.y; break; + case POS_Z: strength = aniso_pos.z; break; + case NEG_X: strength = aniso_neg.x; break; + case NEG_Y: strength = aniso_neg.y; break; + case NEG_Z: strength = aniso_neg.z; break; + } + + color_interp.xyz *= strength; + +#else + color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)); + color_interp.xyz *params.dynamic_range; + +#endif + +#endif + float scale = (1 << params.level); + + gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0); + +#ifdef MODE_DEBUG_LIGHT_FULL + if (color_interp.a == 0.0) { + gl_Position = vec4(0.0); //force clip and not draw + } +#else + color_interp.a = params.alpha; +#endif +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) in vec4 color_interp; +/* clang-format on */ +layout(location = 0) out vec4 frag_color; + +void main() { + + frag_color = color_interp; + +#ifdef MODE_DEBUG_LIGHT_FULL + + //there really is no alpha, so use dither + + int x = int(gl_FragCoord.x) % 4; + int y = int(gl_FragCoord.y) % 4; + int index = x + y * 4; + float limit = 0.0; + if (x < 8) { + if (index == 0) limit = 0.0625; + if (index == 1) limit = 0.5625; + if (index == 2) limit = 0.1875; + if (index == 3) limit = 0.6875; + if (index == 4) limit = 0.8125; + if (index == 5) limit = 0.3125; + if (index == 6) limit = 0.9375; + if (index == 7) limit = 0.4375; + if (index == 8) limit = 0.25; + if (index == 9) limit = 0.75; + if (index == 10) limit = 0.125; + if (index == 11) limit = 0.625; + if (index == 12) limit = 1.0; + if (index == 13) limit = 0.5; + if (index == 14) limit = 0.875; + if (index == 15) limit = 0.375; + } + if (frag_color.a < limit) { + discard; + } +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl new file mode 100644 index 0000000000..d089236723 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/giprobe_sdf.glsl @@ -0,0 +1,187 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; +/* clang-format on */ + +#define MAX_DISTANCE 100000 + +#define NO_CHILDREN 0xFFFFFFFF +#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) + +struct CellChildren { + uint children[8]; +}; + +layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { + CellChildren data[]; +} +cell_children; + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; + +layout(set = 0, binding = 2, std430) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +layout(r8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D sdf_tex; + +layout(push_constant, binding = 0, std430) uniform Params { + uint offset; + uint end; + uint pad0; + uint pad1; +} +params; + +void main() { + + vec3 pos = vec3(gl_GlobalInvocationID); + float closest_dist = 100000.0; + + for (uint i = params.offset; i < params.end; i++) { + vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21)); + float dist = length(pos - posu); + if (dist < closest_dist) { + closest_dist = dist; + } + } + + uint dist_8; + + if (closest_dist < 0.0001) { // same cell + dist_8 = 0; //equals to -1 + } else { + dist_8 = clamp(uint(closest_dist), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid + } + + imageStore(sdf_tex, ivec3(gl_GlobalInvocationID), uvec4(dist_8)); + //imageStore(sdf_tex,pos,uvec4(pos*2,0)); +} + +#if 0 +layout(push_constant, binding = 0, std430) uniform Params { + + ivec3 limits; + uint stack_size; +} params; + +float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) { + + vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1))))); + return length(delta); +} + +void main() { + + ivec3 pos = ivec3(gl_GlobalInvocationID); + + uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + uint stack_indices[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + ivec3 stack_positions[10] = ivec3[](ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0)); + + const uint cell_orders[8] = uint[]( + 0x11f58d1, + 0xe2e70a, + 0xd47463, + 0xbb829c, + 0x8d11f5, + 0x70ae2e, + 0x463d47, + 0x29cbb8); + + bool cell_found = false; + bool cell_found_exact = false; + ivec3 closest_cell_pos; + float closest_distance = MAX_DISTANCE; + int stack_pos = 0; + + while (true) { + + uint index = stack_indices[stack_pos] >> 24; + + if (index == 8) { + //go up + if (stack_pos == 0) { + break; //done going through octree + } + stack_pos--; + continue; + } + + stack_indices[stack_pos] = (stack_indices[stack_pos] & ((1 << 24) - 1)) | ((index + 1) << 24); + + uint cell_index = (stack_indices[stack_pos] >> (index * 3)) & 0x7; + uint child_cell = cell_children.data[stack[stack_pos]].children[cell_index]; + + if (child_cell == NO_CHILDREN) { + continue; + } + + ivec3 child_cell_size = params.limits >> (stack_pos + 1); + ivec3 child_cell_pos = stack_positions[stack_pos]; + + child_cell_pos += mix(ivec3(0), child_cell_size, bvec3(uvec3(index & 1, index & 2, index & 4) != uvec3(0))); + + bool is_leaf = stack_pos == (params.stack_size - 2); + + if (child_cell_pos == pos && is_leaf) { + //we may actually end up in the exact cell. + //if this happens, just abort + cell_found_exact = true; + break; + } + + if (cell_found) { + //discard by distance + float distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); + if (distance >= closest_distance) { + continue; //pointless, just test next child + } else if (is_leaf) { + //closer than what we have AND end of stack, save and continue + closest_cell_pos = child_cell_pos; + closest_distance = distance; + continue; + } + } else if (is_leaf) { + //first solid cell we find, save and continue + closest_distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); + closest_cell_pos = child_cell_pos; + cell_found = true; + continue; + } + + bvec3 direction = greaterThan((pos - (child_cell_pos + (child_cell_size >> 1))), ivec3(0)); + uint cell_order = 0; + cell_order |= mix(0, 1, direction.x); + cell_order |= mix(0, 2, direction.y); + cell_order |= mix(0, 4, direction.z); + + stack[stack_pos + 1] = child_cell; + stack_indices[stack_pos + 1] = cell_orders[cell_order]; //start counting + stack_positions[stack_pos + 1] = child_cell_pos; + stack_pos++; //go up stack + } + + uint dist_8; + + if (cell_found_exact) { + dist_8 = 0; //equals to -1 + } else { + float closest_distance = length(vec3(pos - closest_cell_pos)); + dist_8 = clamp(uint(closest_distance), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid + } + + imageStore(sdf_tex, pos, uvec4(dist_8)); +} +#endif diff --git a/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl new file mode 100644 index 0000000000..c832223b1e --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/giprobe_write.glsl @@ -0,0 +1,335 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; +/* clang-format on */ + +#define NO_CHILDREN 0xFFFFFFFF +#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) + +struct CellChildren { + uint children[8]; +}; + +layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { + CellChildren data[]; +} +cell_children; + +struct CellData { + uint position; // xyz 10 bits + uint albedo; //rgb albedo + uint emission; //rgb normalized with e as multiplier + uint normal; //RGB normal encoded +}; + +layout(set = 0, binding = 2, std430) buffer CellDataBuffer { + CellData data[]; +} +cell_data; + +#define LIGHT_TYPE_DIRECTIONAL 0 +#define LIGHT_TYPE_OMNI 1 +#define LIGHT_TYPE_SPOT 2 + +#ifdef MODE_COMPUTE_LIGHT + +struct Light { + uint type; + float energy; + float radius; + float attenuation; + + vec3 color; + float spot_angle_radians; + + vec3 position; + float spot_attenuation; + + vec3 direction; + bool has_shadow; +}; + +layout(set = 0, binding = 3, std140) uniform Lights { + Light data[MAX_LIGHTS]; +} +lights; + +#endif + +layout(push_constant, binding = 0, std430) uniform Params { + ivec3 limits; + uint stack_size; + + float emission_scale; + float propagation; + float dynamic_range; + + uint light_count; + uint cell_offset; + uint cell_count; + uint pad[2]; +} +params; + +layout(set = 0, binding = 4, std140) uniform Outputs { + vec4 data[]; +} +output; + +#ifdef MODE_COMPUTE_LIGHT + +uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { + + uint result = NO_CHILDREN; + + ivec3 size = ivec3(max(max(params.limits.x, params.limits.y), params.limits.z)); + + while (distance > -distance_adv) { //use this to avoid precision errors + + uint cell = 0; + + ivec3 pos = ivec3(from); + + if (all(greaterThanEqual(pos, ivec3(0))) && all(lessThan(pos, size))) { + + ivec3 ofs = ivec3(0); + ivec3 half_size = size / 2; + + for (int i = 0; i < params.stack_size - 1; i++) { + + bvec3 greater = greaterThanEqual(pos, ofs + half_size); + + ofs += mix(ivec3(0), half_size, greater); + + uint child = 0; //wonder if this can be done faster + if (greater.x) { + child |= 1; + } + if (greater.y) { + child |= 2; + } + if (greater.z) { + child |= 4; + } + + cell = cell_children.data[cell].children[child]; + if (cell == NO_CHILDREN) + break; + + half_size >>= ivec3(1); + } + + if (cell != NO_CHILDREN) { + return cell; //found cell! + } + } + + from += direction * distance_adv; + distance -= distance_adv; + } + + return NO_CHILDREN; +} + +bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation, out vec3 light_pos) { + + if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { + + light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); + attenuation = 1.0; + + } else { + + light_pos = lights.data[light].position; + float distance = length(pos - light_pos); + if (distance >= lights.data[light].radius) { + return false; + } + + attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation); + + if (lights.data[light].type == LIGHT_TYPE_SPOT) { + + vec3 rel = normalize(pos - light_pos); + float angle = acos(dot(rel, lights.data[light].direction)); + if (angle > lights.data[light].spot_angle_radians) { + return false; + } + + float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1); + attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation); + } + } + + return true; +} + +float get_normal_advance(vec3 p_normal) { + + vec3 normal = p_normal; + vec3 unorm = abs(normal); + + if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { + // x code + unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); + } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { + // y code + unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); + } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { + // z code + unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); + } else { + // oh-no we messed up code + // has to be + unorm = vec3(1.0, 0.0, 0.0); + } + + return 1.0 / dot(normal, unorm); +} + +#endif + +void main() { + + uint cell_index = gl_GlobalInvocationID.x; + if (cell_index >= params.cell_count) { + return; + } + cell_index += params.cell_offset; + + uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); + vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo); + +#ifdef MODE_COMPUTE_LIGHT + + vec3 pos = vec3(posu) + vec3(0.5); + + vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission & 0x3FF, (cell_data.data[cell_index].emission >> 10) & 0x7FF, cell_data.data[cell_index].emission >> 21)) * params.emission_scale; + vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); + +#ifdef MODE_ANISOTROPIC + vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); + const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); +#else + vec3 accum = vec3(0.0); +#endif + + for (uint i = 0; i < params.light_count; i++) { + + float attenuation; + vec3 light_pos; + + if (!compute_light_vector(i, cell_index, pos, attenuation, light_pos)) { + continue; + } + + vec3 light_dir = pos - light_pos; + float distance = length(light_dir); + light_dir = normalize(light_dir); + + if (length(normal.xyz) > 0.2 && dot(normal.xyz, light_dir) >= 0) { + continue; //not facing the light + } + + if (lights.data[i].has_shadow) { + + float distance_adv = get_normal_advance(light_dir); + + distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always + + vec3 from = pos - light_dir * distance; //approximate + from -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion + + uint result = raymarch(distance, distance_adv, from, light_dir); + + if (result != cell_index) { + continue; //was occluded + } + } + + vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy; + +#ifdef MODE_ANISOTROPIC + for (uint j = 0; j < 6; j++) { + accum[j] += max(0.0, dot(accum_dir, -light_dir)) * light + emission; + } +#else + if (length(normal.xyz) > 0.2) { + accum += max(0.0, dot(normal.xyz, -light_dir)) * light + emission; + } else { + //all directions + accum += light + emission; + } +#endif + } + +#ifdef MODE_ANISOTROPIC + + output.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); + output.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); + output.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); + output.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); + output.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); + output.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); +#else + output.data[cell_index] = vec4(accum, 0.0); + +#endif + +#endif //MODE_COMPUTE_LIGHT + +#ifdef MODE_UPDATE_MIPMAPS + + { +#ifdef MODE_ANISOTROPIC + vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); +#else + vec3 light_accum = vec3(0.0); +#endif + float count = 0.0; + for (uint i = 0; i < 8; i++) { + uint child_index = cell_children.data[cell_index].children[i]; + if (child_index == NO_CHILDREN) { + continue; + } +#ifdef MODE_ANISOTROPIC + light_accum[1] += output.data[child_index * 6 + 0].rgb; + light_accum[2] += output.data[child_index * 6 + 1].rgb; + light_accum[3] += output.data[child_index * 6 + 2].rgb; + light_accum[4] += output.data[child_index * 6 + 3].rgb; + light_accum[5] += output.data[child_index * 6 + 4].rgb; + light_accum[6] += output.data[child_index * 6 + 5].rgb; + +#else + light_accum += output.data[child_index].rgb; + +#endif + + count += 1.0; + } + + float divisor = mix(8.0, count, params.propagation); +#ifdef MODE_ANISOTROPIC + output.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); + output.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); + output.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); + output.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); + output.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); + output.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); + +#else + output.data[cell_index] = vec4(light_accum / divisor, 0.0); +#endif + } +#endif + +#ifdef MODE_WRITE_TEXTURE + { + } +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl new file mode 100644 index 0000000000..4bf5b7e7f1 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/luminance_reduce.glsl @@ -0,0 +1,87 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +#define BLOCK_SIZE 8 + +layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; +/* clang-format on */ + +shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE]; + +#ifdef READ_TEXTURE + +//use for main texture +layout(set = 0, binding = 0) uniform sampler2D source_texture; + +#else + +//use for intermediate textures +layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_luminance; + +#endif + +layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_luminance; + +#ifdef WRITE_LUMINANCE +layout(set = 2, binding = 0) uniform sampler2D prev_luminance; +#endif + +layout(push_constant, binding = 1, std430) uniform Params { + ivec2 source_size; + float max_luminance; + float min_luminance; + float exposure_adjust; + float pad[3]; +} +params; + +void main() { + + uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x; + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + if (any(lessThan(pos, params.source_size))) { + +#ifdef READ_TEXTURE + vec3 v = texelFetch(source_texture, pos, 0).rgb; + tmp_data[t] = max(v.r, max(v.g, v.b)); +#else + tmp_data[t] = imageLoad(source_luminance, pos).r; +#endif + } else { + tmp_data[t] = 0.0; + } + + groupMemoryBarrier(); + barrier(); + + uint size = (BLOCK_SIZE * BLOCK_SIZE) >> 1; + + do { + if (t < size) { + tmp_data[t] += tmp_data[t + size]; + } + groupMemoryBarrier(); + barrier(); + + size >>= 1; + + } while (size >= 1); + + if (t == 0) { + //compute rect size + ivec2 rect_size = min(params.source_size - pos, ivec2(BLOCK_SIZE)); + float avg = tmp_data[0] / float(rect_size.x * rect_size.y); + //float avg = tmp_data[0] / float(BLOCK_SIZE*BLOCK_SIZE); + pos /= ivec2(BLOCK_SIZE); +#ifdef WRITE_LUMINANCE + float prev_lum = texelFetch(prev_luminance, ivec2(0, 0), 0).r; //1 pixel previous exposure + avg = clamp(prev_lum + (avg - prev_lum) * params.exposure_adjust, params.min_luminance, params.max_luminance); +#endif + imageStore(dest_luminance, pos, vec4(avg)); + } +} diff --git a/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl new file mode 100644 index 0000000000..3637b1abb2 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/roughness_limiter.glsl @@ -0,0 +1,73 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform sampler2D source_normal; +layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness; + +layout(push_constant, binding = 1, std430) uniform Params { + ivec2 screen_size; + float curve; + uint pad; +} +params; + +#define HALF_PI 1.5707963267948966 + +void main() { + + // Pixel being shaded + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing + return; + } + + vec3 normal_accum = vec3(0.0); + float accum = 0.0; + for (int i = 0; i <= 1; i++) { + for (int j = 0; j <= 1; j++) { + normal_accum += normalize(texelFetch(source_normal, pos + ivec2(i, j), 0).xyz * 2.0 - 1.0); + accum += 1.0; + } + } + + normal_accum /= accum; + + float r = length(normal_accum); + + float limit; + + if (r < 1.0) { + float threshold = 0.4; + + /* + //Formula from Filament, does not make sense to me. + + float r2 = r * r; + float kappa = (3.0f * r - r * r2) / (1.0f - r2); + float variance = 0.25f / kappa; + limit = sqrt(min(2.0f * variance, threshold * threshold)); +//*/ + /* + //Formula based on probability distribution graph + + float width = acos(max(0.0,r)); // convert to angle (width) + float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness + limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold +//*/ + + limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold + + //limit = 0.5; + } else { + limit = 0.0; + } + + imageStore(dest_roughness, pos, vec4(limit)); +} diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl new file mode 100644 index 0000000000..07f4770b14 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end.glsl @@ -0,0 +1,1718 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +#include "scene_high_end_inc.glsl" + +/* INPUT ATTRIBS */ + +layout(location = 0) in vec3 vertex_attrib; +/* clang-format on */ +layout(location = 1) in vec3 normal_attrib; +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +layout(location = 2) in vec4 tangent_attrib; +#endif + +#if defined(COLOR_USED) +layout(location = 3) in vec4 color_attrib; +#endif + +#if defined(UV_USED) +layout(location = 4) in vec2 uv_attrib; +#endif + +#if defined(UV2_USED) || defined(USE_LIGHTMAP) +layout(location = 5) in vec2 uv2_attrib; +#endif + +layout(location = 6) in uvec4 bone_attrib; // always bound, even if unused + +/* Varyings */ + +layout(location = 0) out vec3 vertex_interp; +layout(location = 1) out vec3 normal_interp; + +#if defined(COLOR_USED) +layout(location = 2) out vec4 color_interp; +#endif + +#if defined(UV_USED) +layout(location = 3) out vec2 uv_interp; +#endif + +#if defined(UV2_USED) || defined(USE_LIGHTMAP) +layout(location = 4) out vec2 uv2_interp; +#endif + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +layout(location = 5) out vec3 tangent_interp; +layout(location = 6) out vec3 binormal_interp; +#endif + +#ifdef USE_MATERIAL_UNIFORMS +layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ + /* clang-format off */ +MATERIAL_UNIFORMS + /* clang-format on */ +} material; +#endif + +/* clang-format off */ + +VERTEX_SHADER_GLOBALS + +/* clang-format on */ + +// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now. +// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316 +invariant gl_Position; + +layout(location = 7) flat out uint instance_index; + +#ifdef MODE_DUAL_PARABOLOID + +layout(location = 8) out float dp_clip; + +#endif + +void main() { + + instance_index = draw_call.instance_index; + vec4 instance_custom = vec4(0.0); +#if defined(COLOR_USED) + color_interp = color_attrib; +#endif + + mat4 world_matrix = instances.data[instance_index].transform; + mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform); + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) { + //multimesh, instances are for it + uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; + offset *= gl_InstanceIndex; + + mat4 matrix; + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { + matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); + offset += 2; + } else { + matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], transforms.data[offset + 2], vec4(0.0, 0.0, 0.0, 1.0)); + offset += 3; + } + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { +#ifdef COLOR_USED + color_interp *= transforms.data[offset]; +#endif + offset += 1; + } + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { + instance_custom = transforms.data[offset]; + } + + //transpose + matrix = transpose(matrix); + world_matrix = world_matrix * matrix; + world_normal_matrix = world_normal_matrix * mat3(matrix); + + } else { + //not a multimesh, instances are for multiple draw calls + instance_index += gl_InstanceIndex; + } + + vec3 vertex = vertex_attrib; + vec3 normal = normal_attrib; + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + vec3 tangent = tangent_attrib.xyz; + float binormalf = tangent_attrib.a; + vec3 binormal = normalize(cross(normal, tangent) * binormalf); +#endif + + if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) { + //multimesh, instances are for it + + uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3; + uvec2 bones_23 = uvec2(bone_attrib.y & 0xFFFF, bone_attrib.y >> 16) * 3; + vec2 weights_01 = unpackUnorm2x16(bone_attrib.z); + vec2 weights_23 = unpackUnorm2x16(bone_attrib.w); + + mat4 m = mat4(transforms.data[bones_01.x], transforms.data[bones_01.x + 1], transforms.data[bones_01.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.x; + m += mat4(transforms.data[bones_01.y], transforms.data[bones_01.y + 1], transforms.data[bones_01.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.y; + m += mat4(transforms.data[bones_23.x], transforms.data[bones_23.x + 1], transforms.data[bones_23.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x; + m += mat4(transforms.data[bones_23.y], transforms.data[bones_23.y + 1], transforms.data[bones_23.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y; + + //reverse order because its transposed + vertex = (vec4(vertex, 1.0) * m).xyz; + normal = (vec4(normal, 0.0) * m).xyz; + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + + tangent = (vec4(tangent, 0.0) * m).xyz; + binormal = (vec4(binormal, 0.0) * m).xyz; +#endif + } + +#if defined(UV_USED) + uv_interp = uv_attrib; +#endif + +#if defined(UV2_USED) || defined(USE_LIGHTMAP) + uv2_interp = uv2_attrib; +#endif + +#ifdef USE_OVERRIDE_POSITION + vec4 position; +#endif + + mat4 projection_matrix = scene_data.projection_matrix; + +//using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) + + vertex = (world_matrix * vec4(vertex, 1.0)).xyz; + + normal = world_normal_matrix * normal; + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + + tangent = world_normal_matrix * tangent; + binormal = world_normal_matrix * binormal; + +#endif +#endif + + float roughness = 1.0; + + mat4 modelview = scene_data.inv_camera_matrix * world_matrix; + mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix; + + { + /* clang-format off */ + +VERTEX_SHADER_CODE + + /* clang-format on */ + } + +// using local coordinates (default) +#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) + + vertex = (modelview * vec4(vertex, 1.0)).xyz; + normal = modelview_normal * normal; +#endif + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + + binormal = modelview_normal * binormal; + tangent = modelview_normal * tangent; +#endif + +//using world coordinates +#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) + + vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz; + normal = mat3(scene_data.inverse_normal_matrix) * normal; + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + + binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal; + tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent; +#endif +#endif + + vertex_interp = vertex; + normal_interp = normal; + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + tangent_interp = tangent; + binormal_interp = binormal; +#endif + +#ifdef MODE_RENDER_DEPTH + +#ifdef MODE_DUAL_PARABOLOID + + vertex_interp.z *= scene_data.dual_paraboloid_side; + normal_interp.z *= scene_data.dual_paraboloid_side; + + dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias + + //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges + + vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset; + float distance = length(vtx); + vtx = normalize(vtx); + vtx.xy /= 1.0 - vtx.z; + vtx.z = (distance / scene_data.z_far); + vtx.z = vtx.z * 2.0 - 1.0; + + vertex_interp = vtx; +#else + + float z_ofs = scene_data.z_offset; + z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale; + vertex_interp.z -= z_ofs; + +#endif + +#endif //MODE_RENDER_DEPTH + +#ifdef USE_OVERRIDE_POSITION + gl_Position = position; +#else + gl_Position = projection_matrix * vec4(vertex_interp, 1.0); +#endif +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +#include "scene_high_end_inc.glsl" + +/* Varyings */ + +layout(location = 0) in vec3 vertex_interp; +/* clang-format on */ +layout(location = 1) in vec3 normal_interp; + +#if defined(COLOR_USED) +layout(location = 2) in vec4 color_interp; +#endif + +#if defined(UV_USED) +layout(location = 3) in vec2 uv_interp; +#endif + +#if defined(UV2_USED) || defined(USE_LIGHTMAP) +layout(location = 4) in vec2 uv2_interp; +#endif + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) +layout(location = 5) in vec3 tangent_interp; +layout(location = 6) in vec3 binormal_interp; +#endif + +layout(location = 7) flat in uint instance_index; + +#ifdef MODE_DUAL_PARABOLOID + +layout(location = 8) in float dp_clip; + +#endif + +//defines to keep compatibility with vertex + +#define world_matrix instances.data[instance_index].transform +#define world_normal_matrix instances.data[instance_index].normal_transform +#define projection_matrix scene_data.projection_matrix + +#ifdef USE_MATERIAL_UNIFORMS +layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ + /* clang-format off */ +MATERIAL_UNIFORMS + /* clang-format on */ +} material; +#endif + +/* clang-format off */ + +FRAGMENT_SHADER_GLOBALS + +/* clang-format on */ + +#ifdef MODE_RENDER_DEPTH + +#ifdef MODE_RENDER_MATERIAL + +layout(location = 0) out vec4 albedo_output_buffer; +layout(location = 1) out vec4 normal_output_buffer; +layout(location = 2) out vec4 orm_output_buffer; +layout(location = 3) out vec4 emission_output_buffer; +layout(location = 4) out float depth_output_buffer; + +#endif + +#ifdef MODE_RENDER_NORMAL +layout(location = 0) out vec4 normal_output_buffer; +#ifdef MODE_RENDER_ROUGHNESS +layout(location = 1) out float roughness_output_buffer; +#endif //MODE_RENDER_ROUGHNESS +#endif //MODE_RENDER_NORMAL +#else // RENDER DEPTH + +#ifdef MODE_MULTIPLE_RENDER_TARGETS + +layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness +layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter) +#else + +layout(location = 0) out vec4 frag_color; +#endif + +#endif // RENDER DEPTH + +// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. +// We're dividing this factor off because the overall term we'll end up looks like +// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): +// +// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) +// +// We're basically regouping this as +// +// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] +// +// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. +// +// The contents of the D and G (G1) functions (GGX) are taken from +// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). +// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). + +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) + +float G_GGX_2cos(float cos_theta_m, float alpha) { + // Schlick's approximation + // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) + // Eq. (19), although see Heitz (2014) the about the problems with his derivation. + // It nevertheless approximates GGX well with k = alpha/2. + float k = 0.5 * alpha; + return 0.5 / (cos_theta_m * (1.0 - k) + k); + + // float cos2 = cos_theta_m * cos_theta_m; + // float sin2 = (1.0 - cos2); + // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); +} + +float D_GGX(float cos_theta_m, float alpha) { + float alpha2 = alpha * alpha; + float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; + return alpha2 / (M_PI * d * d); +} + +float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0 - cos2); + float s_x = alpha_x * cos_phi; + float s_y = alpha_y * sin_phi; + return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); +} + +float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { + float cos2 = cos_theta_m * cos_theta_m; + float sin2 = (1.0 - cos2); + float r_x = cos_phi / alpha_x; + float r_y = sin_phi / alpha_y; + float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); + return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); +} + +float SchlickFresnel(float u) { + float m = 1.0 - u; + float m2 = m * m; + return m2 * m2 * m; // pow(m,5) +} + +float GTR1(float NdotH, float a) { + if (a >= 1.0) return 1.0 / M_PI; + float a2 = a * a; + float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; + return (a2 - 1.0) / (M_PI * log(a2) * t); +} + +vec3 F0(float metallic, float specular, vec3 albedo) { + float dielectric = 0.16 * specular * specular; + // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; + // see https://google.github.io/filament/Filament.md.html + return mix(vec3(dielectric), albedo, vec3(metallic)); +} + +void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + vec3 transmission, +#endif +#ifdef LIGHT_RIM_USED + float rim, float rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + float clearcoat, float clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + vec3 B, vec3 T, float anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + inout float alpha, +#endif + inout vec3 diffuse_light, inout vec3 specular_light) { + +#if defined(USE_LIGHT_SHADER_CODE) + // light is written by the light shader + + vec3 normal = N; + vec3 albedo = diffuse_color; + vec3 light = L; + vec3 view = V; + + /* clang-format off */ + +LIGHT_SHADER_CODE + + /* clang-format on */ + +#else + float NdotL = dot(N, L); + float cNdotL = max(NdotL, 0.0); // clamped NdotL + float NdotV = dot(N, V); + float cNdotV = max(NdotV, 0.0); + +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) + vec3 H = normalize(V + L); +#endif + +#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) + float cNdotH = max(dot(N, H), 0.0); +#endif + +#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) + float cLdotH = max(dot(L, H), 0.0); +#endif + + if (metallic < 1.0) { +#if defined(DIFFUSE_OREN_NAYAR) + vec3 diffuse_brdf_NL; +#else + float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance +#endif + +#if defined(DIFFUSE_LAMBERT_WRAP) + // energy conserving lambert wrap shader + diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); + +#elif defined(DIFFUSE_OREN_NAYAR) + + { + // see http://mimosa-pudica.net/improved-oren-nayar.html + float LdotV = dot(L, V); + + float s = LdotV - NdotL * NdotV; + float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); + + float sigma2 = roughness * roughness; // TODO: this needs checking + vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); + float B = 0.45 * sigma2 / (sigma2 + 0.09); + + diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); + } + +#elif defined(DIFFUSE_TOON) + + diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); + +#elif defined(DIFFUSE_BURLEY) + + { + float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; + float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); + float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); + diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; + /* + float energyBias = mix(roughness, 0.0, 0.5); + float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); + float fd90 = energyBias + 2.0 * VoH * VoH * roughness; + float f0 = 1.0; + float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); + float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); + + diffuse_brdf_NL = lightScatter * viewScatter * energyFactor; + */ + } +#else + // lambert + diffuse_brdf_NL = cNdotL * (1.0 / M_PI); +#endif + + diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; + +#if defined(LIGHT_TRANSMISSION_USED) + diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; +#endif + +#if defined(LIGHT_RIM_USED) + float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); + diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; +#endif + } + + if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely + + // D + +#if defined(SPECULAR_BLINN) + + //normalized blinn + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float blinn = pow(cNdotH, shininess) * cNdotL; + blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + float intensity = blinn; + + specular_light += light_color * intensity * specular_blob_intensity * attenuation; + +#elif defined(SPECULAR_PHONG) + + vec3 R = normalize(-reflect(L, N)); + float cRdotV = max(0.0, dot(R, V)); + float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; + float phong = pow(cRdotV, shininess); + phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); + float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); + + specular_light += light_color * intensity * specular_blob_intensity * attenuation; + +#elif defined(SPECULAR_TOON) + + vec3 R = normalize(-reflect(L, N)); + float RdotV = dot(R, V); + float mid = 1.0 - roughness; + mid *= mid; + float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; + diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection + +#elif defined(SPECULAR_DISABLED) + // none.. + +#elif defined(SPECULAR_SCHLICK_GGX) + // shlick+ggx as default + +#if defined(LIGHT_ANISOTROPY_USED) + + float alpha_ggx = roughness * roughness; + float aspect = sqrt(1.0 - anisotropy * 0.9); + float ax = alpha_ggx / aspect; + float ay = alpha_ggx * aspect; + float XdotH = dot(T, H); + float YdotH = dot(B, H); + float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); + float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); + +#else + float alpha_ggx = roughness * roughness; + float D = D_GGX(cNdotH, alpha_ggx); + float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); +#endif + // F + vec3 f0 = F0(metallic, specular, diffuse_color); + float cLdotH5 = SchlickFresnel(cLdotH); + vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); + + vec3 specular_brdf_NL = cNdotL * D * F * G; + + specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; +#endif + +#if defined(LIGHT_CLEARCOAT_USED) + +#if !defined(SPECULAR_SCHLICK_GGX) + float cLdotH5 = SchlickFresnel(cLdotH); +#endif + float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); + float Fr = mix(.04, 1.0, cLdotH5); + float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); + + float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; + + specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; +#endif + } + +#ifdef USE_SHADOW_TO_OPACITY + alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); +#endif + +#endif //defined(USE_LIGHT_SHADER_CODE) +} + +#ifndef USE_NO_SHADOWS + +float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { + + //todo optimize + vec2 pos = coord.xy; + float depth = coord.z; + +#ifdef SHADOW_MODE_PCF_13 + + float avg = textureProj(shadow, vec4(pos, depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0)); + return avg * (1.0 / 13.0); +#endif + +#ifdef SHADOW_MODE_PCF_5 + + float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); + avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); + return avg * (1.0 / 5.0); + +#endif + +#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) + + return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); + +#endif +} + +#endif //USE_NO_SHADOWS + +void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + vec3 transmission, +#endif +#ifdef LIGHT_RIM_USED + float rim, float rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + float clearcoat, float clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + vec3 binormal, vec3 tangent, float anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + inout float alpha, +#endif + inout vec3 diffuse_light, inout vec3 specular_light) { + + vec3 light_rel_vec = lights.data[idx].position - vertex; + float light_length = length(light_rel_vec); + float normalized_distance = light_length * lights.data[idx].inv_radius; + vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); + float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x); + vec3 light_attenuation = vec3(omni_attenuation); + vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular); + color_specular.rgb *= attenuation_energy.y; + +#ifndef USE_NO_SHADOWS + vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled); + if (shadow_color_enabled.w > 0.5) { + // there is a shadowmap + + vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)); + float shadow_len = length(splane); + splane = normalize(splane); + vec4 clamp_rect = lights.data[idx].atlas_rect; + + if (splane.z >= 0.0) { + + splane.z += 1.0; + + clamp_rect.y += clamp_rect.w; + + } else { + + splane.z = 1.0 - splane.z; + } + + splane.xy /= splane.z; + splane.xy = splane.xy * 0.5 + 0.5; + splane.z = shadow_len * lights.data[idx].inv_radius; + splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; + splane.w = 1.0; //needed? i think it should be 1 already + float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane); + + light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow); + } +#endif //USE_NO_SHADOWS + + light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + transmission, +#endif +#ifdef LIGHT_RIM_USED + rim * omni_attenuation, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + alpha, +#endif + diffuse_light, + specular_light); +} + +void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + vec3 transmission, +#endif +#ifdef LIGHT_RIM_USED + float rim, float rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + float clearcoat, float clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + vec3 binormal, vec3 tangent, float anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + inout float alpha, +#endif + inout vec3 diffuse_light, + inout vec3 specular_light) { + + vec3 light_rel_vec = lights.data[idx].position - vertex; + float light_length = length(light_rel_vec); + float normalized_distance = light_length * lights.data[idx].inv_radius; + vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); + float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x); + vec3 spot_dir = lights.data[idx].direction; + vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle); + float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y); + float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y)); + spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x); + vec3 light_attenuation = vec3(spot_attenuation); + vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular); + color_specular.rgb *= attenuation_energy.y; + +/* + if (lights.data[idx].atlas_rect!=vec4(0.0)) { + //use projector texture + } + */ +#ifndef USE_NO_SHADOWS + vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled); + if (shadow_color_enabled.w > 0.5) { + //there is a shadowmap + vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)); + splane /= splane.w; + float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane); + + light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow); + } + +#endif //USE_NO_SHADOWS + + light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + transmission, +#endif +#ifdef LIGHT_RIM_USED + rim * spot_attenuation, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + alpha, +#endif + diffuse_light, specular_light); +} + +void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { + + vec3 box_extents = reflections.data[ref_index].box_extents; + vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz; + + if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box + return; + } + + vec3 ref_vec = normalize(reflect(vertex, normal)); + + vec3 inner_pos = abs(local_pos / box_extents); + float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); + //make blend more rounded + blend = mix(length(inner_pos), blend, blend); + blend *= blend; + blend = max(0.0, 1.0 - blend); + + if (reflections.data[ref_index].params.x > 0.0) { // compute reflection + + vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz; + + if (reflections.data[ref_index].params.w > 0.5) { //box project + + vec3 nrdir = normalize(local_ref_vec); + vec3 rbmax = (box_extents - local_pos) / nrdir; + vec3 rbmin = (-box_extents - local_pos) / nrdir; + + vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0))); + + float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); + vec3 posonbox = local_pos + nrdir * fa; + local_ref_vec = posonbox - reflections.data[ref_index].box_offset; + } + + vec4 reflection; + + reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb; + + if (reflections.data[ref_index].params.z < 0.5) { + reflection.rgb = mix(specular_light, reflection.rgb, blend); + } + + reflection.rgb *= reflections.data[ref_index].params.x; + reflection.a = blend; + reflection.rgb *= reflection.a; + + reflection_accum += reflection; + } + +#if !defined(USE_LIGHTMAP) && !defined(USE_VOXEL_CONE_TRACING) + if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox + + vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz; + + vec4 ambient_out; + + ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb; + + ambient_out.a = blend; + ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a); + if (reflections.data[ref_index].params.z < 0.5) { + ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); + } + + ambient_out.rgb *= ambient_out.a; + ambient_accum += ambient_out; + } else { + + vec4 ambient_out; + ambient_out.a = blend; + ambient_out.rgb = reflections.data[ref_index].ambient.rgb; + if (reflections.data[ref_index].params.z < 0.5) { + ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); + } + ambient_out.rgb *= ambient_out.a; + ambient_accum += ambient_out; + } +#endif //USE_LIGHTMAP or VCT +} + +#ifdef USE_VOXEL_CONE_TRACING + +//standard voxel cone trace +vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { + + float dist = p_bias; + vec4 color = vec4(0.0); + + while (dist < max_distance && color.a < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec3 uvw_pos = (pos + dist * direction) * cell_size; + float half_diameter = diameter * 0.5; + //check if outside, then break + if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { + break; + } + vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter)); + float a = (1.0 - color.a); + color += a * scolor; + dist += half_diameter; + } + + return color; +} + +#ifndef GI_PROBE_HIGH_QUALITY +//faster version for 45 degrees + +#ifdef GI_PROBE_USE_ANISOTROPY + +vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { + + float dist = p_bias; + vec4 color = vec4(0.0); + float radius = max(0.5, tan_half_angle * dist); + float lod_level = log2(radius * 2.0); + + while (dist < max_distance && color.a < 0.95) { + vec3 uvw_pos = (pos + dist * direction) * cell_size; + //check if outside, then break + if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { + break; + } + + vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level); + vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb; + vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb; + + scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0)); + lod_level += 1.0; + + float a = (1.0 - color.a); + scolor *= a; + color += scolor; + dist += radius; + radius = max(0.5, tan_half_angle * dist); + } + + return color; +} +#else + +vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { + + float dist = p_bias; + vec4 color = vec4(0.0); + float radius = max(0.5, tan_half_angle * dist); + float lod_level = log2(radius * 2.0); + + while (dist < max_distance && color.a < 0.95) { + vec3 uvw_pos = (pos + dist * direction) * cell_size; + + //check if outside, then break + if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { + break; + } + vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level); + lod_level += 1.0; + + float a = (1.0 - color.a); + scolor *= a; + color += scolor; + dist += radius; + radius = max(0.5, tan_half_angle * dist); + } + + return color; +} + +#endif + +#elif defined(GI_PROBE_USE_ANISOTROPY) + +//standard voxel cone trace +vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { + + float dist = p_bias; + vec4 color = vec4(0.0); + + while (dist < max_distance && color.a < 0.95) { + float diameter = max(1.0, 2.0 * tan_half_angle * dist); + vec3 uvw_pos = (pos + dist * direction) * cell_size; + float half_diameter = diameter * 0.5; + //check if outside, then break + if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { + break; + } + float log2_diameter = log2(diameter); + vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter); + vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb; + vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb; + + scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0)); + + float a = (1.0 - color.a); + scolor *= a; + color += scolor; + dist += half_diameter; + } + + return color; +} + +#endif + +void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) { + + position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz; + ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz); + normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz); + + position += normal * gi_probes.data[index].normal_bias; + + //this causes corrupted pixels, i have no idea why.. + if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) { + return; + } + + vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0); + float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); + //float blend=1.0; + + float max_distance = length(gi_probes.data[index].bounds); + vec3 cell_size = 1.0 / gi_probes.data[index].bounds; + + //radiance + +#ifdef GI_PROBE_HIGH_QUALITY + +#define MAX_CONE_DIRS 6 + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( + vec3(0.0, 0.0, 1.0), + vec3(0.866025, 0.0, 0.5), + vec3(0.267617, 0.823639, 0.5), + vec3(-0.700629, 0.509037, 0.5), + vec3(-0.700629, -0.509037, 0.5), + vec3(0.267617, -0.823639, 0.5)); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); + float cone_angle_tan = 0.577; + +#elif defined(GI_PROBE_LOW_QUALITY) + +#define MAX_CONE_DIRS 1 + + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( + vec3(0.0, 0.0, 1.0)); + + float cone_weights[MAX_CONE_DIRS] = float[](1.0); + float cone_angle_tan = 4; //~76 degrees +#else // MEDIUM QUALITY + +#define MAX_CONE_DIRS 4 + + vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( + vec3(0.707107, 0.0, 0.707107), + vec3(0.0, 0.707107, 0.707107), + vec3(-0.707107, 0.0, 0.707107), + vec3(0.0, -0.707107, 0.707107)); + + float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); + float cone_angle_tan = 0.98269; + +#endif + vec3 light = vec3(0.0); + + for (int i = 0; i < MAX_CONE_DIRS; i++) { + + vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz); + +#if defined(GI_PROBE_HIGH_QUALITY) || defined(GI_PROBE_LOW_QUALITY) + +#ifdef GI_PROBE_USE_ANISOTROPY + vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); +#else + + vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); + +#endif // GI_PROBE_USE_ANISOTROPY + +#else + +#ifdef GI_PROBE_USE_ANISOTROPY + vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); +#else + vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); +#endif // GI_PROBE_USE_ANISOTROPY + +#endif + if (gi_probes.data[index].blend_ambient) { + cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95)); + } + + light += cone_weights[i] * cone_light.rgb; + } + + light *= gi_probes.data[index].dynamic_range; + + if (gi_probes.data[index].ambient_occlusion > 0.001) { + + float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0; + + float taps, blend; + blend = modf(size, taps); + float ao = 0.0; + for (float i = 1.0; i <= taps; i++) { + vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size; + ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, i - 1.0).a * i; + } + + if (blend > 0.001) { + vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size; + ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, taps).a * (taps + 1.0) * blend; + } + + ao = 1.0 - min(1.0, ao); + + light = mix(scene_data.ao_color.rgb, light, mix(1.0, ao, gi_probes.data[index].ambient_occlusion)); + } + + out_diff += vec4(light * blend, blend); + + //irradiance +#ifndef GI_PROBE_LOW_QUALITY + vec4 irr_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); + if (gi_probes.data[index].blend_ambient) { + irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95)); + } + irr_light.rgb *= gi_probes.data[index].dynamic_range; + //irr_light=vec3(0.0); + + out_spec += vec4(irr_light.rgb * blend, blend); +#endif +} + +#endif //USE_VOXEL_CONE_TRACING + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) + +void main() { + +#ifdef MODE_DUAL_PARABOLOID + + if (dp_clip > 0.0) + discard; +#endif + + //lay out everything, whathever is unused is optimized away anyway + vec3 vertex = vertex_interp; + vec3 view = -normalize(vertex_interp); + vec3 albedo = vec3(1.0); + vec3 transmission = vec3(0.0); + float metallic = 0.0; + float specular = 0.5; + vec3 emission = vec3(0.0); + float roughness = 1.0; + float rim = 0.0; + float rim_tint = 0.0; + float clearcoat = 0.0; + float clearcoat_gloss = 0.0; + float anisotropy = 0.0; + vec2 anisotropy_flow = vec2(1.0, 0.0); + +#if defined(AO_USED) + float ao = 1.0; + float ao_light_affect = 0.0; +#endif + + float alpha = 1.0; + +#if defined(ALPHA_SCISSOR_USED) + float alpha_scissor = 0.5; +#endif + +#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) + vec3 binormal = normalize(binormal_interp); + vec3 tangent = normalize(tangent_interp); +#else + vec3 binormal = vec3(0.0); + vec3 tangent = vec3(0.0); +#endif + vec3 normal = normalize(normal_interp); + +#if defined(DO_SIDE_CHECK) + if (!gl_FrontFacing) { + normal = -normal; + } +#endif + +#if defined(UV_USED) + vec2 uv = uv_interp; +#endif + +#if defined(UV2_USED) || defined(USE_LIGHTMAP) + vec2 uv2 = uv2_interp; +#endif + +#if defined(COLOR_USED) + vec4 color = color_interp; +#endif + +#if defined(NORMALMAP_USED) + + vec3 normalmap = vec3(0.5); +#endif + + float normaldepth = 1.0; + + vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center + + float sss_strength = 0.0; + + { + /* clang-format off */ + +FRAGMENT_SHADER_CODE + + /* clang-format on */ + } + +#if !defined(USE_SHADOW_TO_OPACITY) + +#if defined(ALPHA_SCISSOR_USED) + if (alpha < alpha_scissor) { + discard; + } +#endif // ALPHA_SCISSOR_USED + +#ifdef USE_OPAQUE_PREPASS + + if (alpha < opaque_prepass_threshold) { + discard; + } + +#endif // USE_OPAQUE_PREPASS + +#endif // !USE_SHADOW_TO_OPACITY + +#if defined(NORMALMAP_USED) + + normalmap.xy = normalmap.xy * 2.0 - 1.0; + normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. + + normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)); + +#endif + +#if defined(LIGHT_ANISOTROPY_USED) + + if (anisotropy > 0.01) { + //rotation matrix + mat3 rot = mat3(tangent, binormal, normal); + //make local to space + tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0)); + binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0)); + } + +#endif + +#ifdef ENABLE_CLIP_ALPHA + if (albedo.a < 0.99) { + //used for doublepass and shadowmapping + discard; + } +#endif + + /////////////////////// LIGHTING ////////////////////////////// + + //apply energy conservation + + vec3 specular_light = vec3(0.0, 0.0, 0.0); + vec3 diffuse_light = vec3(0.0, 0.0, 0.0); + vec3 ambient_light = vec3(0.0, 0.0, 0.0); + +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) + + if (scene_data.roughness_limiter_enabled) { + float limit = texelFetch(sampler2D(roughness_buffer, material_samplers[SAMPLER_NEAREST_CLAMP]), ivec2(gl_FragCoord.xy), 0).r; + roughness = max(roughness, limit); + } + + if (scene_data.use_reflection_cubemap) { + + vec3 ref_vec = reflect(-view, normal); + ref_vec = scene_data.radiance_inverse_xform * ref_vec; +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + + float lod, blend; + blend = modf(roughness * MAX_ROUGHNESS_LOD, lod); + specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; + specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend); + +#else + specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb; + +#endif //USE_RADIANCE_CUBEMAP_ARRAY + specular_light *= scene_data.ambient_light_color_energy.a; + } + +#ifndef USE_LIGHTMAP + //lightmap overrides everything + if (scene_data.use_ambient_light) { + + ambient_light = scene_data.ambient_light_color_energy.rgb; + + if (scene_data.use_ambient_cubemap) { + vec3 ambient_dir = scene_data.radiance_inverse_xform * normal; +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb; +#else + vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb; +#endif //USE_RADIANCE_CUBEMAP_ARRAY + + ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix); + } + } +#endif // USE_LIGHTMAP + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) + + //radiance + + float specular_blob_intensity = 1.0; + +#if defined(SPECULAR_TOON) + specular_blob_intensity *= specular * 2.0; +#endif + +#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) + //gi probes + + //lightmap + + //lightmap capture + +#ifdef USE_VOXEL_CONE_TRACING + { // process giprobes + uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; + if (index1 != 0xFFFF) { + vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); + //find arbitrary tangent and bitangent, then build a matrix + vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); + vec3 tangent = normalize(cross(v0, normal)); + vec3 bitangent = normalize(cross(tangent, normal)); + mat3 normal_mat = mat3(tangent, bitangent, normal); + + vec4 amb_accum = vec4(0.0); + vec4 spec_accum = vec4(0.0); + gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + + uint index2 = instances.data[instance_index].gi_offset >> 16; + + if (index2 != 0xFFFF) { + gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); + } + + if (amb_accum.a > 0.0) { + amb_accum.rgb /= amb_accum.a; + } + + if (spec_accum.a > 0.0) { + spec_accum.rgb /= spec_accum.a; + } + + specular_light = spec_accum.rgb; + ambient_light = amb_accum.rgb; + } + } +#endif + + uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near))); + + { // process reflections + + vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); + vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); + + uint reflection_probe_count = cluster_cell.z >> CLUSTER_COUNTER_SHIFT; + uint reflection_probe_pointer = cluster_cell.z & CLUSTER_POINTER_MASK; + + for (uint i = 0; i < reflection_probe_count; i++) { + + uint ref_index = cluster_data.indices[reflection_probe_pointer + i]; + reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); + } + + if (reflection_accum.a > 0.0) { + specular_light = reflection_accum.rgb / reflection_accum.a; + } + +#if !defined(USE_LIGHTMAP) + if (ambient_accum.a > 0.0) { + ambient_light = ambient_accum.rgb / ambient_accum.a; + } +#endif + } + + { + +#if defined(DIFFUSE_TOON) + //simplify for toon, as + specular_light *= specular * metallic * albedo * 2.0; +#else + + // scales the specular reflections, needs to be be computed before lighting happens, + // but after environment, GI, and reflection probes are added + // Environment brdf approximation (Lazarov 2013) + // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile + const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); + const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); + vec4 r = roughness * c0 + c1; + float ndotv = clamp(dot(normal, view), 0.0, 1.0); + float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; + vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; + + vec3 f0 = F0(metallic, specular, albedo); + specular_light *= env.x * f0 + env.y; +#endif + } + + { //directional light + + for (uint i = 0; i < scene_data.directional_light_count; i++) { + + if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { + continue; //not masked + } + + vec3 light_attenuation = vec3(1.0); + + if (directional_lights.data[i].shadow_enabled) { + float depth_z = -vertex.z; + + vec4 pssm_coord; + + if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0)); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { + pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0)); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { + pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0)); + } else { + pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0)); + } + + pssm_coord /= pssm_coord.w; + + float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + + if (directional_lights.data[i].blend_splits) { + + float pssm_blend; + + if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { + pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0)); + pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { + pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0)); + pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); + } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { + pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0)); + pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); + } else { + pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached) + } + + pssm_coord /= pssm_coord.w; + + float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); + shadow = mix(shadow, shadow2, pssm_blend); + } + + shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance + + light_attenuation = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow); + } + + light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + transmission, +#endif +#ifdef LIGHT_RIM_USED + rim, rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + binormal, tangent, anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + alpha, +#endif + diffuse_light, + specular_light); + } + } + + { //omni lights + + uint omni_light_count = cluster_cell.x >> CLUSTER_COUNTER_SHIFT; + uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK; + + for (uint i = 0; i < omni_light_count; i++) { + + uint light_index = cluster_data.indices[omni_light_pointer + i]; + + if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { + continue; //not masked + } + + light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + transmission, +#endif +#ifdef LIGHT_RIM_USED + rim, + rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + tangent, binormal, anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + alpha, +#endif + diffuse_light, specular_light); + } + } + + { //spot lights + uint spot_light_count = cluster_cell.y >> CLUSTER_COUNTER_SHIFT; + uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK; + + for (uint i = 0; i < spot_light_count; i++) { + + uint light_index = cluster_data.indices[spot_light_pointer + i]; + + if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { + continue; //not masked + } + + light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity, +#ifdef LIGHT_TRANSMISSION_USED + transmission, +#endif +#ifdef LIGHT_RIM_USED + rim, + rim_tint, +#endif +#ifdef LIGHT_CLEARCOAT_USED + clearcoat, clearcoat_gloss, +#endif +#ifdef LIGHT_ANISOTROPY_USED + tangent, binormal, anisotropy, +#endif +#ifdef USE_SHADOW_TO_OPACITY + alpha, +#endif + diffuse_light, specular_light); + } + } + +#ifdef USE_SHADOW_TO_OPACITY + alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); + +#if defined(ALPHA_SCISSOR_USED) + if (alpha < alpha_scissor) { + discard; + } +#endif // ALPHA_SCISSOR_USED + +#ifdef USE_OPAQUE_PREPASS + + if (alpha < opaque_prepass_threshold) { + discard; + } + +#endif // USE_OPAQUE_PREPASS + +#endif // USE_SHADOW_TO_OPACITY + +#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) + +#ifdef MODE_RENDER_DEPTH + +#ifdef MODE_RENDER_MATERIAL + + albedo_output_buffer.rgb = albedo; + albedo_output_buffer.a = alpha; + + normal_output_buffer.rgb = normal * 0.5 + 0.5; + normal_output_buffer.a = 0.0; + depth_output_buffer.r = -vertex.z; + +#if defined(AO_USED) + orm_output_buffer.r = ao; +#else + orm_output_buffer.r = 0.0; +#endif + orm_output_buffer.g = roughness; + orm_output_buffer.b = metallic; + orm_output_buffer.a = sss_strength; + + emission_output_buffer.rgb = emission; + emission_output_buffer.a = 0.0; +#endif + +#ifdef MODE_RENDER_NORMAL + normal_output_buffer = vec4(normal * 0.5 + 0.5, 0.0); +#ifdef MODE_RENDER_ROUGHNESS + roughness_output_buffer = roughness; +#endif //MODE_RENDER_ROUGHNESS +#endif //MODE_RENDER_NORMAL + +//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) +#else + + specular_light *= scene_data.reflection_multiplier; + ambient_light *= albedo; //ambient must be multiplied by albedo at the end + +//ambient occlusion +#if defined(AO_USED) + + if (scene_data.ssao_enabled && scene_data.ssao_ao_affect > 0.0) { + float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; + ao = mix(ao, min(ao, ssao), scene_data.ssao_ao_affect); + ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect); + } + + ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); + ao_light_affect = mix(1.0, ao, ao_light_affect); + specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect); + diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); + +#else + + if (scene_data.ssao_enabled) { + float ao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; + ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); + float ao_light_affect = mix(1.0, ao, scene_data.ssao_light_affect); + specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect); + diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); + } + +#endif // AO_USED + + // base color remapping + diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point + ambient_light *= 1.0 - metallic; + + //fog + +#ifdef MODE_MULTIPLE_RENDER_TARGETS + +#ifdef MODE_UNSHADED + diffuse_buffer = vec4(albedo.rgb, 0.0); + specular_buffer = vec4(0.0); + +#else + + diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength); + specular_buffer = vec4(specular_light, metallic); + +#endif + +#else //MODE_MULTIPLE_RENDER_TARGETS + +#ifdef MODE_UNSHADED + frag_color = vec4(albedo, alpha); +#else + frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); + //frag_color = vec4(1.0); + +#endif //USE_NO_SHADING + +#endif //MODE_MULTIPLE_RENDER_TARGETS + +#endif //MODE_RENDER_DEPTH +} diff --git a/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl new file mode 100644 index 0000000000..baef1e060f --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/scene_high_end_inc.glsl @@ -0,0 +1,266 @@ +#define M_PI 3.14159265359 +#define ROUGHNESS_MAX_LOD 5 + +layout(push_constant, binding = 0, std430) uniform DrawCall { + uint instance_index; + uint pad[3]; //16 bits minimum size +} +draw_call; + +/* Set 0 Scene data that never changes, ever */ + +#define SAMPLER_NEAREST_CLAMP 0 +#define SAMPLER_LINEAR_CLAMP 1 +#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 +#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3 +#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5 +#define SAMPLER_NEAREST_REPEAT 6 +#define SAMPLER_LINEAR_REPEAT 7 +#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8 +#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9 +#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 + +layout(set = 0, binding = 1) uniform sampler material_samplers[12]; + +layout(set = 0, binding = 2) uniform sampler shadow_sampler; + +layout(set = 0, binding = 3, std140) uniform SceneData { + + mat4 projection_matrix; + mat4 inv_projection_matrix; + + mat4 camera_matrix; + mat4 inv_camera_matrix; + + vec2 viewport_size; + vec2 screen_pixel_size; + + //used for shadow mapping only + float z_offset; + float z_slope_scale; + + float time; + float reflection_multiplier; // one normally, zero when rendering reflections + + vec4 ambient_light_color_energy; + + float ambient_color_sky_mix; + bool use_ambient_light; + bool use_ambient_cubemap; + bool use_reflection_cubemap; + + mat3 radiance_inverse_xform; + + vec2 shadow_atlas_pixel_size; + vec2 directional_shadow_pixel_size; + + uint directional_light_count; + float dual_paraboloid_side; + float z_far; + float z_near; + + bool ssao_enabled; + float ssao_light_affect; + float ssao_ao_affect; + bool roughness_limiter_enabled; + + vec4 ao_color; + +#if 0 + vec4 ambient_light_color; + vec4 bg_color; + + vec4 fog_color_enabled; + vec4 fog_sun_color_amount; + + float ambient_energy; + float bg_energy; +#endif + +#if 0 + vec2 shadow_atlas_pixel_size; + vec2 directional_shadow_pixel_size; + + float z_far; + + float subsurface_scatter_width; + float ambient_occlusion_affect_light; + float ambient_occlusion_affect_ao_channel; + float opaque_prepass_threshold; + + bool fog_depth_enabled; + float fog_depth_begin; + float fog_depth_end; + float fog_density; + float fog_depth_curve; + bool fog_transmit_enabled; + float fog_transmit_curve; + bool fog_height_enabled; + float fog_height_min; + float fog_height_max; + float fog_height_curve; +#endif +} +scene_data; + +#define INSTANCE_FLAGS_FORWARD_MASK 0x7 +#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3 +#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6 +#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9 + +#define INSTANCE_FLAGS_MULTIMESH (1 << 12) +#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) +#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) +#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15) +#define INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT 16 +//3 bits of stride +#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7 + +#define INSTANCE_FLAGS_SKELETON (1 << 19) + +struct InstanceData { + mat4 transform; + mat4 normal_transform; + uint flags; + uint instance_ofs; //instance_offset in instancing/skeleton buffer + uint gi_offset; //GI information when using lightmapping (VCT or lightmap) + uint layer_mask; +}; + +layout(set = 0, binding = 4, std430) buffer Instances { + InstanceData data[]; +} +instances; + +struct LightData { //this structure needs to be 128 bits + vec3 position; + float inv_radius; + vec3 direction; + uint attenuation_energy; //attenuation + uint color_specular; //rgb color, a specular (8 bit unorm) + uint cone_attenuation_angle; // attenuation and angle, (16bit float) + uint mask; + uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm) + vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot + mat4 shadow_matrix; +}; + +layout(set = 0, binding = 5, std140) uniform Lights { + LightData data[MAX_LIGHT_DATA_STRUCTS]; +} +lights; + +struct ReflectionData { + + vec3 box_extents; + float index; + vec3 box_offset; + uint mask; + vec4 params; // intensity, 0, interior , boxproject + vec4 ambient; // ambient color, energy + mat4 local_matrix; // up to here for spot and omni, rest is for directional + // notes: for ambientblend, use distance to edge to blend between already existing global environment +}; + +layout(set = 0, binding = 6, std140) uniform ReflectionProbeData { + ReflectionData data[MAX_REFLECTION_DATA_STRUCTS]; +} +reflections; + +struct DirectionalLightData { + vec3 direction; + float energy; + vec3 color; + float specular; + vec3 shadow_color; + uint mask; + bool blend_splits; + bool shadow_enabled; + float fade_from; + float fade_to; + vec4 shadow_split_offsets; + mat4 shadow_matrix1; + mat4 shadow_matrix2; + mat4 shadow_matrix3; + mat4 shadow_matrix4; +}; + +layout(set = 0, binding = 7, std140) uniform DirectionalLights { + DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; +} +directional_lights; + +struct GIProbeData { + mat4 xform; + vec3 bounds; + float dynamic_range; + + float bias; + float normal_bias; + bool blend_ambient; + uint texture_slot; + + float anisotropy_strength; + float ambient_occlusion; + float ambient_occlusion_size; + uint pad2; +}; + +layout(set = 0, binding = 8, std140) uniform GIProbes { + GIProbeData data[MAX_GI_PROBES]; +} +gi_probes; + +layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES]; + +#define CLUSTER_COUNTER_SHIFT 20 +#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1) +#define CLUSTER_COUNTER_MASK 0xfff + +layout(set = 0, binding = 10) uniform utexture3D cluster_texture; + +layout(set = 0, binding = 11, std430) buffer ClusterData { + uint indices[]; +} +cluster_data; + +layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas; + +// decal atlas + +/* Set 1, Radiance */ + +#ifdef USE_RADIANCE_CUBEMAP_ARRAY + +layout(set = 1, binding = 0) uniform textureCubeArray radiance_cubemap; + +#else + +layout(set = 1, binding = 0) uniform textureCube radiance_cubemap; + +#endif + +/* Set 2, Reflection and Shadow Atlases (view dependant) */ + +layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; + +layout(set = 2, binding = 1) uniform texture2D shadow_atlas; + +/* Set 1, Render Buffers */ + +layout(set = 3, binding = 0) uniform texture2D depth_buffer; +layout(set = 3, binding = 1) uniform texture2D color_buffer; +layout(set = 3, binding = 2) uniform texture2D normal_buffer; +layout(set = 3, binding = 3) uniform texture2D roughness_buffer; +layout(set = 3, binding = 4) uniform texture2D ao_buffer; + +/* Set 4 Skeleton & Instancing (Multimesh) */ + +layout(set = 4, binding = 0, std430) buffer Transforms { + vec4 data[]; +} +transforms; + +/* Set 5 User Material */ diff --git a/servers/rendering/rasterizer_rd/shaders/sky.glsl b/servers/rendering/rasterizer_rd/shaders/sky.glsl new file mode 100644 index 0000000000..3f433eb2ee --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/sky.glsl @@ -0,0 +1,181 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +layout(push_constant, binding = 1, std430) uniform Params { + mat3 orientation; + vec4 proj; + vec4 position_multiplier; + float time; +} +params; + +void main() { + + vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0)); + uv_interp = base_arr[gl_VertexIndex]; + gl_Position = vec4(uv_interp, 1.0, 1.0); +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +#define M_PI 3.14159265359 + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ + +layout(push_constant, binding = 1, std430) uniform Params { + mat3 orientation; + vec4 proj; + vec4 position_multiplier; + float time; //TODO consider adding vec2 screen res, and float radiance size +} +params; + +#define SAMPLER_NEAREST_CLAMP 0 +#define SAMPLER_LINEAR_CLAMP 1 +#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 +#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3 +#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5 +#define SAMPLER_NEAREST_REPEAT 6 +#define SAMPLER_LINEAR_REPEAT 7 +#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8 +#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9 +#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10 +#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 + +layout(set = 0, binding = 0) uniform sampler material_samplers[12]; + +#ifdef USE_MATERIAL_UNIFORMS +layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ + /* clang-format off */ + +MATERIAL_UNIFORMS + + /* clang-format on */ +} material; +#endif + +layout(set = 2, binding = 0) uniform textureCube radiance; +#ifdef USE_CUBEMAP_PASS +layout(set = 2, binding = 1) uniform textureCube half_res; +layout(set = 2, binding = 2) uniform textureCube quarter_res; +#else +layout(set = 2, binding = 1) uniform texture2D half_res; +layout(set = 2, binding = 2) uniform texture2D quarter_res; +#endif + +#ifdef USE_CUBEMAP_PASS +#define AT_CUBEMAP_PASS true +#else +#define AT_CUBEMAP_PASS false +#endif + +#ifdef USE_HALF_RES_PASS +#define AT_HALF_RES_PASS true +#else +#define AT_HALF_RES_PASS false +#endif + +#ifdef USE_QUARTER_RES_PASS +#define AT_QUARTER_RES_PASS true +#else +#define AT_QUARTER_RES_PASS false +#endif + +struct DirectionalLightData { + vec3 direction; + float energy; + vec3 color; + bool enabled; +}; + +layout(set = 3, binding = 0, std140) uniform DirectionalLights { + DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; +} +directional_lights; + +/* clang-format off */ + +FRAGMENT_SHADER_GLOBALS + +/* clang-format on */ + +layout(location = 0) out vec4 frag_color; + +void main() { + + vec3 cube_normal; + cube_normal.z = -1.0; + cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y; + cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w; + cube_normal = mat3(params.orientation) * cube_normal; + cube_normal.z = -cube_normal.z; + cube_normal = normalize(cube_normal); + + vec2 uv = uv_interp * 0.5 + 0.5; + + vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y)); + + if (panorama_coords.x < 0.0) { + panorama_coords.x += M_PI * 2.0; + } + + panorama_coords /= vec2(M_PI * 2.0, M_PI); + + vec3 color = vec3(0.0, 0.0, 0.0); + float alpha = 1.0; // Only available to subpasses + vec4 half_res_color = vec4(1.0); + vec4 quarter_res_color = vec4(1.0); + +#ifdef USE_CUBEMAP_PASS + float using_cubemap = 1.0; +#ifdef USES_HALF_RES_COLOR + half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal); +#endif +#ifdef USES_QUARTER_RES_COLOR + quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal); +#endif +#else + float using_cubemap = 0.0; +#ifdef USES_HALF_RES_COLOR + half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); +#endif +#ifdef USES_QUARTER_RES_COLOR + quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); +#endif +#endif + +// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in.. +#ifndef REALLYINCLUDETHIS + { + /* clang-format off */ + +LIGHT_SHADER_CODE + + /* clang-format on */ + } +#endif + { + /* clang-format off */ + +FRAGMENT_SHADER_CODE + + /* clang-format on */ + } + + frag_color.rgb = color * params.position_multiplier.w; + frag_color.a = alpha; +} diff --git a/servers/rendering/rasterizer_rd/shaders/ssao.glsl b/servers/rendering/rasterizer_rd/shaders/ssao.glsl new file mode 100644 index 0000000000..c9d7134610 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/ssao.glsl @@ -0,0 +1,252 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +/* clang-format on */ + +#define TWO_PI 6.283185307179586476925286766559 + +#ifdef SSAO_QUALITY_HIGH +#define NUM_SAMPLES (20) +#endif + +#ifdef SSAO_QUALITY_ULTRA +#define NUM_SAMPLES (48) +#endif + +#ifdef SSAO_QUALITY_LOW +#define NUM_SAMPLES (8) +#endif + +#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) && !defined(SSAO_QUALITY_ULTRA) +#define NUM_SAMPLES (12) +#endif + +// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower +// miplevel to maintain reasonable spatial locality in the cache +// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. +// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively +#define LOG_MAX_OFFSET (3) + +// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp +#define MAX_MIP_LEVEL (4) + +// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent +// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 + +const int ROTATIONS[] = int[]( + 1, 1, 2, 3, 2, 5, 2, 3, 2, + 3, 3, 5, 5, 3, 4, 7, 5, 5, 7, + 9, 8, 5, 5, 7, 7, 7, 8, 5, 8, + 11, 12, 7, 10, 13, 8, 11, 8, 7, 14, + 11, 11, 13, 12, 13, 19, 17, 13, 11, 18, + 19, 11, 11, 14, 17, 21, 15, 16, 17, 18, + 13, 17, 11, 17, 19, 18, 25, 18, 19, 19, + 29, 21, 19, 27, 31, 29, 21, 18, 17, 29, + 31, 31, 23, 18, 25, 26, 25, 23, 19, 34, + 19, 27, 21, 25, 39, 29, 17, 21, 27); +/* clang-format on */ + +//#define NUM_SPIRAL_TURNS (7) +const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1]; + +layout(set = 0, binding = 0) uniform sampler2D source_depth_mipmaps; +layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; + +#ifndef USE_HALF_SIZE +layout(set = 2, binding = 0) uniform sampler2D source_depth; +#endif + +layout(set = 3, binding = 0) uniform sampler2D source_normal; + +layout(push_constant, binding = 1, std430) uniform Params { + ivec2 screen_size; + float z_far; + float z_near; + + bool orthogonal; + float intensity_div_r6; + float radius; + float bias; + + vec4 proj_info; + vec2 pixel_size; + float proj_scale; + uint pad; +} +params; + +vec3 reconstructCSPosition(vec2 S, float z) { + if (params.orthogonal) { + return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z); + } else { + return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z); + } +} + +vec3 getPosition(ivec2 ssP) { + vec3 P; +#ifdef USE_HALF_SIZE + P.z = texelFetch(source_depth_mipmaps, ssP, 0).r; + P.z = -P.z; +#else + P.z = texelFetch(source_depth, ssP, 0).r; + + P.z = P.z * 2.0 - 1.0; + if (params.orthogonal) { + P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); + } + P.z = -P.z; +#endif + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + return P; +} + +/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ +vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) { + // Radius relative to ssR + float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); + float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; + + ssR = alpha; + return vec2(cos(angle), sin(angle)); +} + +/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ +vec3 getOffsetPosition(ivec2 ssP, float ssR) { + // Derivation: + // mipLevel = floor(log(ssR / MAX_OFFSET)); + + int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); + + vec3 P; + + // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. + // Manually clamp to the texture size because texelFetch bypasses the texture unit + ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (params.screen_size >> mipLevel) - ivec2(1)); + +#ifdef USE_HALF_SIZE + P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel).r; + P.z = -P.z; +#else + if (mipLevel < 1) { + //read from depth buffer + P.z = texelFetch(source_depth, mipP, 0).r; + P.z = P.z * 2.0 - 1.0; + if (params.orthogonal) { + P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); + } + P.z = -P.z; + + } else { + //read from mipmaps + P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r; + P.z = -P.z; + } +#endif + + // Offset to pixel center + P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); + + return P; +} + +/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds + to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius + + Note that units of H() in the HPG12 paper are meters, not + unitless. The whole falloff/sampling function is therefore + unitless. In this implementation, we factor out (9 / radius). + + Four versions of the falloff function are implemented below +*/ +float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { + // Offset on the unit disk, spun for this pixel + float ssR; + vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); + ssR *= ssDiskRadius; + + ivec2 ssP = ivec2(ssR * unitOffset) + ssC; + + if (any(lessThan(ssP, ivec2(0))) || any(greaterThanEqual(ssP, params.screen_size))) { + return 0.0; + } + + // The occluding point in camera space + vec3 Q = getOffsetPosition(ssP, ssR); + + vec3 v = Q - C; + + float vv = dot(v, v); + float vn = dot(v, n_C); + + const float epsilon = 0.01; + float radius2 = p_radius * p_radius; + + // A: From the HPG12 paper + // Note large epsilon to avoid overdarkening within cracks + //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; + + // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] + float f = max(radius2 - vv, 0.0); + return f * f * f * max((vn - params.bias) / (epsilon + vv), 0.0); + + // C: Medium contrast (which looks better at high radii), no division. Note that the + // contribution still falls off with radius^2, but we've adjusted the rate in a way that is + // more computationally efficient and happens to be aesthetically pleasing. + // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); + + // D: Low contrast, no division operation + // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); +} + +void main() { + // Pixel being shaded + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + return; + } + + // World space point being shaded + vec3 C = getPosition(ssC); + +#ifdef USE_HALF_SIZE + vec3 n_C = texelFetch(source_normal, ssC << 1, 0).xyz * 2.0 - 1.0; +#else + vec3 n_C = texelFetch(source_normal, ssC, 0).xyz * 2.0 - 1.0; +#endif + n_C = normalize(n_C); + n_C.y = -n_C.y; //because this code reads flipped + + // Hash function used in the HPG12 AlchemyAO paper + float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI); + + // Reconstruct normals from positions. These will lead to 1-pixel black lines + // at depth discontinuities, however the blur will wipe those out so they are not visible + // in the final image. + + // Choose the screen-space sample radius + // proportional to the projected area of the sphere + + float ssDiskRadius = -params.proj_scale * params.radius; + if (!params.orthogonal) { + ssDiskRadius = -params.proj_scale * params.radius / C.z; + } + float sum = 0.0; + for (int i = 0; i < NUM_SAMPLES; ++i) { + sum += sampleAO(ssC, C, n_C, ssDiskRadius, params.radius, i, randomPatternRotationAngle); + } + + float A = max(0.0, 1.0 - sum * params.intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); + + imageStore(dest_image, ssC, vec4(A)); +} diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl new file mode 100644 index 0000000000..e90c788e08 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/ssao_blur.glsl @@ -0,0 +1,157 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform sampler2D source_ssao; +layout(set = 1, binding = 0) uniform sampler2D source_depth; +#ifdef MODE_UPSCALE +layout(set = 2, binding = 0) uniform sampler2D source_depth_mipmaps; +#endif + +layout(r8, set = 3, binding = 0) uniform restrict writeonly image2D dest_image; + +////////////////////////////////////////////////////////////////////////////////////////////// +// Tunable Parameters: + +layout(push_constant, binding = 1, std430) uniform Params { + float edge_sharpness; /** Increase to make depth edges crisper. Decrease to reduce flicker. */ + int filter_scale; + float z_far; + float z_near; + bool orthogonal; + uint pad0; + uint pad1; + uint pad2; + ivec2 axis; /** (1, 0) or (0, 1) */ + ivec2 screen_size; +} +params; + +/** Filter radius in pixels. This will be multiplied by SCALE. */ +#define R (4) + +////////////////////////////////////////////////////////////////////////////////////////////// + +// Gaussian coefficients +const float gaussian[R + 1] = + //float[](0.356642, 0.239400, 0.072410, 0.009869); + //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 + float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 +//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 + +void main() { + + // Pixel being shaded + ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); + if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing + return; + } + +#ifdef MODE_UPSCALE + + //closest one should be the same pixel, but check nearby just in case + float depth = texelFetch(source_depth, ssC, 0).r; + + depth = depth * 2.0 - 1.0; + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } + + vec2 pixel_size = 1.0 / vec2(params.screen_size); + vec2 closest_uv = vec2(ssC) * pixel_size + pixel_size * 0.5; + vec2 from_uv = closest_uv; + vec2 ps2 = pixel_size; // * 2.0; + + float closest_depth = abs(textureLod(source_depth_mipmaps, closest_uv, 0.0).r - depth); + + vec2 offsets[4] = vec2[](vec2(ps2.x, 0), vec2(-ps2.x, 0), vec2(0, ps2.y), vec2(0, -ps2.y)); + for (int i = 0; i < 4; i++) { + vec2 neighbour = from_uv + offsets[i]; + float neighbour_depth = abs(textureLod(source_depth_mipmaps, neighbour, 0.0).r - depth); + if (neighbour_depth < closest_depth) { + closest_uv = neighbour; + closest_depth = neighbour_depth; + } + } + + float visibility = textureLod(source_ssao, closest_uv, 0.0).r; + imageStore(dest_image, ssC, vec4(visibility)); +#else + + float depth = texelFetch(source_depth, ssC, 0).r; + +#ifdef MODE_FULL_SIZE + depth = depth * 2.0 - 1.0; + + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } + +#endif + float depth_divide = 1.0 / params.z_far; + + //depth *= depth_divide; + + /* + if (depth > params.z_far * 0.999) { + discard; //skybox + } + */ + + float sum = texelFetch(source_ssao, ssC, 0).r; + + // Base weight for depth falloff. Increase this for more blurriness, + // decrease it for better edge discrimination + float BASE = gaussian[0]; + float totalWeight = BASE; + sum *= totalWeight; + + ivec2 clamp_limit = params.screen_size - ivec2(1); + + for (int r = -R; r <= R; ++r) { + // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, + // so the IF statement has no runtime cost + if (r != 0) { + + ivec2 ppos = ssC + params.axis * (r * params.filter_scale); + float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r; + ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit); + + float temp_depth = texelFetch(source_depth, rpos, 0).r; +#ifdef MODE_FULL_SIZE + temp_depth = temp_depth * 2.0 - 1.0; + if (params.orthogonal) { + temp_depth = ((temp_depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + temp_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - temp_depth * (params.z_far - params.z_near)); + } + //temp_depth *= depth_divide; +#endif + // spatial domain: offset gaussian tap + float weight = 0.3 + gaussian[abs(r)]; + //weight *= max(0.0, dot(temp_normal, normal)); + + // range domain (the "bilateral" weight). As depth difference increases, decrease weight. + weight *= max(0.0, 1.0 - params.edge_sharpness * abs(temp_depth - depth)); + + sum += value * weight; + totalWeight += weight; + } + } + + const float epsilon = 0.0001; + float visibility = sum / (totalWeight + epsilon); + + imageStore(dest_image, ssC, vec4(visibility)); +#endif +} diff --git a/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl new file mode 100644 index 0000000000..8728154347 --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/ssao_minify.glsl @@ -0,0 +1,48 @@ +/* clang-format off */ +[compute] + +#version 450 + +VERSION_DEFINES + +layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; +/* clang-format on */ + +layout(push_constant, binding = 1, std430) uniform Params { + vec2 pixel_size; + float z_far; + float z_near; + ivec2 source_size; + bool orthogonal; + uint pad; +} +params; + +#ifdef MINIFY_START +layout(set = 0, binding = 0) uniform sampler2D source_texture; +#else +layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_image; +#endif +layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; + +void main() { + + ivec2 pos = ivec2(gl_GlobalInvocationID.xy); + + if (any(greaterThan(pos, params.source_size >> 1))) { //too large, do nothing + return; + } + +#ifdef MINIFY_START + float depth = texelFetch(source_texture, pos << 1, 0).r * 2.0 - 1.0; + if (params.orthogonal) { + depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; + } else { + depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); + } +#else + float depth = imageLoad(source_image, pos << 1).r; +#endif + + imageStore(dest_image, pos, vec4(depth)); +} diff --git a/servers/rendering/rasterizer_rd/shaders/tonemap.glsl b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl new file mode 100644 index 0000000000..524ca5e2ea --- /dev/null +++ b/servers/rendering/rasterizer_rd/shaders/tonemap.glsl @@ -0,0 +1,305 @@ +/* clang-format off */ +[vertex] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +void main() { + + vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); + uv_interp = base_arr[gl_VertexIndex]; + gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); +} + +/* clang-format off */ +[fragment] + +#version 450 + +VERSION_DEFINES + +layout(location = 0) in vec2 uv_interp; +/* clang-format on */ + +layout(set = 0, binding = 0) uniform sampler2D source_color; +layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; +layout(set = 2, binding = 0) uniform sampler2D source_glow; +layout(set = 3, binding = 0) uniform sampler3D color_correction; + +layout(push_constant, binding = 1, std430) uniform Params { + vec3 bcs; + bool use_bcs; + + bool use_glow; + bool use_auto_exposure; + bool use_color_correction; + uint tonemapper; + + uvec2 glow_texture_size; + + float glow_intensity; + uint glow_level_flags; + uint glow_mode; + + float exposure; + float white; + float auto_exposure_grey; +} +params; + +layout(location = 0) out vec4 frag_color; + +#ifdef USE_GLOW_FILTER_BICUBIC +// w0, w1, w2, and w3 are the four cubic B-spline basis functions +float w0(float a) { + return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); +} + +float w1(float a) { + return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f); +} + +float w2(float a) { + return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f); +} + +float w3(float a) { + return (1.0f / 6.0f) * (a * a * a); +} + +// g0 and g1 are the two amplitude functions +float g0(float a) { + return w0(a) + w1(a); +} + +float g1(float a) { + return w2(a) + w3(a); +} + +// h0 and h1 are the two offset functions +float h0(float a) { + return -1.0f + w1(a) / (w0(a) + w1(a)); +} + +float h1(float a) { + return 1.0f + w3(a) / (w2(a) + w3(a)); +} + +vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { + float lod = float(p_lod); + vec2 tex_size = vec2(params.glow_texture_size >> p_lod); + vec2 pixel_size = vec2(1.0f) / tex_size; + + uv = uv * tex_size + vec2(0.5f); + + vec2 iuv = floor(uv); + vec2 fuv = fract(uv); + + float g0x = g0(fuv.x); + float g1x = g1(fuv.x); + float h0x = h0(fuv.x); + float h1x = h1(fuv.x); + float h0y = h0(fuv.y); + float h1y = h1(fuv.y); + + vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size; + vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size; + vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size; + vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size; + + return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) + + (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod))); +} + +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) + +#else + +#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod)) + +#endif + +vec3 tonemap_filmic(vec3 color, float white) { + // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers + // also useful to scale the input to the range that the tonemapper is designed for (some require very high input values) + // has no effect on the curve's general shape or visual properties + const float exposure_bias = 2.0f; + const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance + const float B = 0.30f * exposure_bias; + const float C = 0.10f; + const float D = 0.20f; + const float E = 0.01f; + const float F = 0.30f; + + vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; + float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F; + + return color_tonemapped / white_tonemapped; +} + +vec3 tonemap_aces(vec3 color, float white) { + const float exposure_bias = 0.85f; + const float A = 2.51f * exposure_bias * exposure_bias; + const float B = 0.03f * exposure_bias; + const float C = 2.43f * exposure_bias * exposure_bias; + const float D = 0.59f * exposure_bias; + const float E = 0.14f; + + vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E); + float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E); + + return color_tonemapped / white_tonemapped; +} + +vec3 tonemap_reinhard(vec3 color, float white) { + return (white * color + color) / (color * white + white); +} + +vec3 linear_to_srgb(vec3 color) { + //if going to srgb, clamp from 0 to 1. + color = clamp(color, vec3(0.0), vec3(1.0)); + const vec3 a = vec3(0.055f); + return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); +} + +#define TONEMAPPER_LINEAR 0 +#define TONEMAPPER_REINHARD 1 +#define TONEMAPPER_FILMIC 2 +#define TONEMAPPER_ACES 3 + +vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color + + if (params.tonemapper == TONEMAPPER_LINEAR) { + return color; + } else if (params.tonemapper == TONEMAPPER_REINHARD) { + return tonemap_reinhard(color, white); + } else if (params.tonemapper == TONEMAPPER_FILMIC) { + return tonemap_filmic(color, white); + } else { //aces + return tonemap_aces(color, white); + } +} + +vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels + vec3 glow = vec3(0.0f); + + if (bool(params.glow_level_flags & (1 << 0))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb; + } + + if (bool(params.glow_level_flags & (1 << 1))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb; + } + + if (bool(params.glow_level_flags & (1 << 2))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb; + } + + if (bool(params.glow_level_flags & (1 << 3))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb; + } + + if (bool(params.glow_level_flags & (1 << 4))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb; + } + + if (bool(params.glow_level_flags & (1 << 5))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb; + } + + if (bool(params.glow_level_flags & (1 << 6))) { + glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb; + } + + return glow; +} + +#define GLOW_MODE_ADD 0 +#define GLOW_MODE_SCREEN 1 +#define GLOW_MODE_SOFTLIGHT 2 +#define GLOW_MODE_REPLACE 3 +#define GLOW_MODE_MIX 4 + +vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode + if (params.glow_mode == GLOW_MODE_ADD) { + return color + glow; + } else if (params.glow_mode == GLOW_MODE_SCREEN) { + //need color clamping + return max((color + glow) - (color * glow), vec3(0.0)); + } else if (params.glow_mode == GLOW_MODE_SOFTLIGHT) { + //need color clamping + glow = glow * vec3(0.5f) + vec3(0.5f); + + color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r))); + color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g))); + color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (sqrt(color.b) - color.b))); + return color; + } else { //replace + return glow; + } +} + +vec3 apply_bcs(vec3 color, vec3 bcs) { + color = mix(vec3(0.0f), color, bcs.x); + color = mix(vec3(0.5f), color, bcs.y); + color = mix(vec3(dot(vec3(1.0f), color) * 0.33333f), color, bcs.z); + + return color; +} + +vec3 apply_color_correction(vec3 color, sampler3D correction_tex) { + return texture(correction_tex, color).rgb; +} + +void main() { + vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb; + + // Exposure + + if (params.use_auto_exposure) { + color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey; + } + + color *= params.exposure; + + // Early Tonemap & SRGB Conversion + + if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) { + + vec3 glow = gather_glow(source_glow, uv_interp); + color.rgb = mix(color.rgb, glow, params.glow_intensity); + } + + color = apply_tonemapping(color, params.white); + + color = linear_to_srgb(color); // regular linear -> SRGB conversion + + // Glow + + if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) { + + vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity; + + // high dynamic range -> SRGB + glow = apply_tonemapping(glow, params.white); + glow = linear_to_srgb(glow); + + color = apply_glow(color, glow); + } + + // Additional effects + + if (params.use_bcs) { + color = apply_bcs(color, params.bcs); + } + + if (params.use_color_correction) { + color = apply_color_correction(color, color_correction); + } + + frag_color = vec4(color, 1.0f); +} diff --git a/servers/rendering/rendering_device.cpp b/servers/rendering/rendering_device.cpp new file mode 100644 index 0000000000..3c1795161d --- /dev/null +++ b/servers/rendering/rendering_device.cpp @@ -0,0 +1,64 @@ +/*************************************************************************/ +/* rendering_device.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_device.h" + +RenderingDevice *RenderingDevice::singleton = NULL; + +RenderingDevice *RenderingDevice::get_singleton() { + return singleton; +} + +RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = NULL; +RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = NULL; + +void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) { + compile_function = p_function; +} +void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function) { + cache_function = p_function; +} + +Vector RenderingDevice::shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) { + if (p_allow_cache && cache_function) { + Vector cache = cache_function(p_stage, p_source_code, p_language); + if (cache.size()) { + return cache; + } + } + + ERR_FAIL_COND_V(!compile_function, Vector()); + + return compile_function(p_stage, p_source_code, p_language, r_error); +} + +RenderingDevice::RenderingDevice() { + singleton = this; +} diff --git a/servers/rendering/rendering_device.h b/servers/rendering/rendering_device.h new file mode 100644 index 0000000000..4705bcaa75 --- /dev/null +++ b/servers/rendering/rendering_device.h @@ -0,0 +1,1032 @@ +/*************************************************************************/ +/* rendering_device.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDERING_DEVICE_H +#define RENDERING_DEVICE_H + +#include "core/object.h" +#include "servers/display_server.h" + +class RenderingDevice : public Object { + GDCLASS(RenderingDevice, Object) +public: + enum ShaderStage { + SHADER_STAGE_VERTEX, + SHADER_STAGE_FRAGMENT, + SHADER_STAGE_TESSELATION_CONTROL, + SHADER_STAGE_TESSELATION_EVALUATION, + SHADER_STAGE_COMPUTE, + SHADER_STAGE_MAX, + SHADER_STAGE_VERTEX_BIT = (1 << SHADER_STAGE_VERTEX), + SHADER_STAGE_FRAGMENT_BIT = (1 << SHADER_STAGE_FRAGMENT), + SHADER_STAGE_TESSELATION_CONTROL_BIT = (1 << SHADER_STAGE_TESSELATION_CONTROL), + SHADER_STAGE_TESSELATION_EVALUATION_BIT = (1 << SHADER_STAGE_TESSELATION_EVALUATION), + SHADER_STAGE_COMPUTE_BIT = (1 << SHADER_STAGE_COMPUTE), + }; + + enum ShaderLanguage { + SHADER_LANGUAGE_GLSL, + SHADER_LANGUAGE_HLSL + }; + + typedef Vector (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error); + typedef Vector (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language); + +private: + static ShaderCompileFunction compile_function; + static ShaderCacheFunction cache_function; + + static RenderingDevice *singleton; + +public: + //base numeric ID for all types + enum { + INVALID_ID = -1 + }; + + /*****************/ + /**** GENERIC ****/ + /*****************/ + + enum CompareOperator { + COMPARE_OP_NEVER, + COMPARE_OP_LESS, + COMPARE_OP_EQUAL, + COMPARE_OP_LESS_OR_EQUAL, + COMPARE_OP_GREATER, + COMPARE_OP_NOT_EQUAL, + COMPARE_OP_GREATER_OR_EQUAL, + COMPARE_OP_ALWAYS, + COMPARE_OP_MAX //not an actual operator, just the amount of operators :D + }; + + enum DataFormat { + DATA_FORMAT_R4G4_UNORM_PACK8, + DATA_FORMAT_R4G4B4A4_UNORM_PACK16, + DATA_FORMAT_B4G4R4A4_UNORM_PACK16, + DATA_FORMAT_R5G6B5_UNORM_PACK16, + DATA_FORMAT_B5G6R5_UNORM_PACK16, + DATA_FORMAT_R5G5B5A1_UNORM_PACK16, + DATA_FORMAT_B5G5R5A1_UNORM_PACK16, + DATA_FORMAT_A1R5G5B5_UNORM_PACK16, + DATA_FORMAT_R8_UNORM, + DATA_FORMAT_R8_SNORM, + DATA_FORMAT_R8_USCALED, + DATA_FORMAT_R8_SSCALED, + DATA_FORMAT_R8_UINT, + DATA_FORMAT_R8_SINT, + DATA_FORMAT_R8_SRGB, + DATA_FORMAT_R8G8_UNORM, + DATA_FORMAT_R8G8_SNORM, + DATA_FORMAT_R8G8_USCALED, + DATA_FORMAT_R8G8_SSCALED, + DATA_FORMAT_R8G8_UINT, + DATA_FORMAT_R8G8_SINT, + DATA_FORMAT_R8G8_SRGB, + DATA_FORMAT_R8G8B8_UNORM, + DATA_FORMAT_R8G8B8_SNORM, + DATA_FORMAT_R8G8B8_USCALED, + DATA_FORMAT_R8G8B8_SSCALED, + DATA_FORMAT_R8G8B8_UINT, + DATA_FORMAT_R8G8B8_SINT, + DATA_FORMAT_R8G8B8_SRGB, + DATA_FORMAT_B8G8R8_UNORM, + DATA_FORMAT_B8G8R8_SNORM, + DATA_FORMAT_B8G8R8_USCALED, + DATA_FORMAT_B8G8R8_SSCALED, + DATA_FORMAT_B8G8R8_UINT, + DATA_FORMAT_B8G8R8_SINT, + DATA_FORMAT_B8G8R8_SRGB, + DATA_FORMAT_R8G8B8A8_UNORM, + DATA_FORMAT_R8G8B8A8_SNORM, + DATA_FORMAT_R8G8B8A8_USCALED, + DATA_FORMAT_R8G8B8A8_SSCALED, + DATA_FORMAT_R8G8B8A8_UINT, + DATA_FORMAT_R8G8B8A8_SINT, + DATA_FORMAT_R8G8B8A8_SRGB, + DATA_FORMAT_B8G8R8A8_UNORM, + DATA_FORMAT_B8G8R8A8_SNORM, + DATA_FORMAT_B8G8R8A8_USCALED, + DATA_FORMAT_B8G8R8A8_SSCALED, + DATA_FORMAT_B8G8R8A8_UINT, + DATA_FORMAT_B8G8R8A8_SINT, + DATA_FORMAT_B8G8R8A8_SRGB, + DATA_FORMAT_A8B8G8R8_UNORM_PACK32, + DATA_FORMAT_A8B8G8R8_SNORM_PACK32, + DATA_FORMAT_A8B8G8R8_USCALED_PACK32, + DATA_FORMAT_A8B8G8R8_SSCALED_PACK32, + DATA_FORMAT_A8B8G8R8_UINT_PACK32, + DATA_FORMAT_A8B8G8R8_SINT_PACK32, + DATA_FORMAT_A8B8G8R8_SRGB_PACK32, + DATA_FORMAT_A2R10G10B10_UNORM_PACK32, + DATA_FORMAT_A2R10G10B10_SNORM_PACK32, + DATA_FORMAT_A2R10G10B10_USCALED_PACK32, + DATA_FORMAT_A2R10G10B10_SSCALED_PACK32, + DATA_FORMAT_A2R10G10B10_UINT_PACK32, + DATA_FORMAT_A2R10G10B10_SINT_PACK32, + DATA_FORMAT_A2B10G10R10_UNORM_PACK32, + DATA_FORMAT_A2B10G10R10_SNORM_PACK32, + DATA_FORMAT_A2B10G10R10_USCALED_PACK32, + DATA_FORMAT_A2B10G10R10_SSCALED_PACK32, + DATA_FORMAT_A2B10G10R10_UINT_PACK32, + DATA_FORMAT_A2B10G10R10_SINT_PACK32, + DATA_FORMAT_R16_UNORM, + DATA_FORMAT_R16_SNORM, + DATA_FORMAT_R16_USCALED, + DATA_FORMAT_R16_SSCALED, + DATA_FORMAT_R16_UINT, + DATA_FORMAT_R16_SINT, + DATA_FORMAT_R16_SFLOAT, + DATA_FORMAT_R16G16_UNORM, + DATA_FORMAT_R16G16_SNORM, + DATA_FORMAT_R16G16_USCALED, + DATA_FORMAT_R16G16_SSCALED, + DATA_FORMAT_R16G16_UINT, + DATA_FORMAT_R16G16_SINT, + DATA_FORMAT_R16G16_SFLOAT, + DATA_FORMAT_R16G16B16_UNORM, + DATA_FORMAT_R16G16B16_SNORM, + DATA_FORMAT_R16G16B16_USCALED, + DATA_FORMAT_R16G16B16_SSCALED, + DATA_FORMAT_R16G16B16_UINT, + DATA_FORMAT_R16G16B16_SINT, + DATA_FORMAT_R16G16B16_SFLOAT, + DATA_FORMAT_R16G16B16A16_UNORM, + DATA_FORMAT_R16G16B16A16_SNORM, + DATA_FORMAT_R16G16B16A16_USCALED, + DATA_FORMAT_R16G16B16A16_SSCALED, + DATA_FORMAT_R16G16B16A16_UINT, + DATA_FORMAT_R16G16B16A16_SINT, + DATA_FORMAT_R16G16B16A16_SFLOAT, + DATA_FORMAT_R32_UINT, + DATA_FORMAT_R32_SINT, + DATA_FORMAT_R32_SFLOAT, + DATA_FORMAT_R32G32_UINT, + DATA_FORMAT_R32G32_SINT, + DATA_FORMAT_R32G32_SFLOAT, + DATA_FORMAT_R32G32B32_UINT, + DATA_FORMAT_R32G32B32_SINT, + DATA_FORMAT_R32G32B32_SFLOAT, + DATA_FORMAT_R32G32B32A32_UINT, + DATA_FORMAT_R32G32B32A32_SINT, + DATA_FORMAT_R32G32B32A32_SFLOAT, + DATA_FORMAT_R64_UINT, + DATA_FORMAT_R64_SINT, + DATA_FORMAT_R64_SFLOAT, + DATA_FORMAT_R64G64_UINT, + DATA_FORMAT_R64G64_SINT, + DATA_FORMAT_R64G64_SFLOAT, + DATA_FORMAT_R64G64B64_UINT, + DATA_FORMAT_R64G64B64_SINT, + DATA_FORMAT_R64G64B64_SFLOAT, + DATA_FORMAT_R64G64B64A64_UINT, + DATA_FORMAT_R64G64B64A64_SINT, + DATA_FORMAT_R64G64B64A64_SFLOAT, + DATA_FORMAT_B10G11R11_UFLOAT_PACK32, + DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32, + DATA_FORMAT_D16_UNORM, + DATA_FORMAT_X8_D24_UNORM_PACK32, + DATA_FORMAT_D32_SFLOAT, + DATA_FORMAT_S8_UINT, + DATA_FORMAT_D16_UNORM_S8_UINT, + DATA_FORMAT_D24_UNORM_S8_UINT, + DATA_FORMAT_D32_SFLOAT_S8_UINT, + DATA_FORMAT_BC1_RGB_UNORM_BLOCK, + DATA_FORMAT_BC1_RGB_SRGB_BLOCK, + DATA_FORMAT_BC1_RGBA_UNORM_BLOCK, + DATA_FORMAT_BC1_RGBA_SRGB_BLOCK, + DATA_FORMAT_BC2_UNORM_BLOCK, + DATA_FORMAT_BC2_SRGB_BLOCK, + DATA_FORMAT_BC3_UNORM_BLOCK, + DATA_FORMAT_BC3_SRGB_BLOCK, + DATA_FORMAT_BC4_UNORM_BLOCK, + DATA_FORMAT_BC4_SNORM_BLOCK, + DATA_FORMAT_BC5_UNORM_BLOCK, + DATA_FORMAT_BC5_SNORM_BLOCK, + DATA_FORMAT_BC6H_UFLOAT_BLOCK, + DATA_FORMAT_BC6H_SFLOAT_BLOCK, + DATA_FORMAT_BC7_UNORM_BLOCK, + DATA_FORMAT_BC7_SRGB_BLOCK, + DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, + DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, + DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, + DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, + DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, + DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, + DATA_FORMAT_EAC_R11_UNORM_BLOCK, + DATA_FORMAT_EAC_R11_SNORM_BLOCK, + DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, + DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, + DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, + DATA_FORMAT_ASTC_4x4_SRGB_BLOCK, + DATA_FORMAT_ASTC_5x4_UNORM_BLOCK, + DATA_FORMAT_ASTC_5x4_SRGB_BLOCK, + DATA_FORMAT_ASTC_5x5_UNORM_BLOCK, + DATA_FORMAT_ASTC_5x5_SRGB_BLOCK, + DATA_FORMAT_ASTC_6x5_UNORM_BLOCK, + DATA_FORMAT_ASTC_6x5_SRGB_BLOCK, + DATA_FORMAT_ASTC_6x6_UNORM_BLOCK, + DATA_FORMAT_ASTC_6x6_SRGB_BLOCK, + DATA_FORMAT_ASTC_8x5_UNORM_BLOCK, + DATA_FORMAT_ASTC_8x5_SRGB_BLOCK, + DATA_FORMAT_ASTC_8x6_UNORM_BLOCK, + DATA_FORMAT_ASTC_8x6_SRGB_BLOCK, + DATA_FORMAT_ASTC_8x8_UNORM_BLOCK, + DATA_FORMAT_ASTC_8x8_SRGB_BLOCK, + DATA_FORMAT_ASTC_10x5_UNORM_BLOCK, + DATA_FORMAT_ASTC_10x5_SRGB_BLOCK, + DATA_FORMAT_ASTC_10x6_UNORM_BLOCK, + DATA_FORMAT_ASTC_10x6_SRGB_BLOCK, + DATA_FORMAT_ASTC_10x8_UNORM_BLOCK, + DATA_FORMAT_ASTC_10x8_SRGB_BLOCK, + DATA_FORMAT_ASTC_10x10_UNORM_BLOCK, + DATA_FORMAT_ASTC_10x10_SRGB_BLOCK, + DATA_FORMAT_ASTC_12x10_UNORM_BLOCK, + DATA_FORMAT_ASTC_12x10_SRGB_BLOCK, + DATA_FORMAT_ASTC_12x12_UNORM_BLOCK, + DATA_FORMAT_ASTC_12x12_SRGB_BLOCK, + DATA_FORMAT_G8B8G8R8_422_UNORM, + DATA_FORMAT_B8G8R8G8_422_UNORM, + DATA_FORMAT_G8_B8_R8_3PLANE_420_UNORM, + DATA_FORMAT_G8_B8R8_2PLANE_420_UNORM, + DATA_FORMAT_G8_B8_R8_3PLANE_422_UNORM, + DATA_FORMAT_G8_B8R8_2PLANE_422_UNORM, + DATA_FORMAT_G8_B8_R8_3PLANE_444_UNORM, + DATA_FORMAT_R10X6_UNORM_PACK16, + DATA_FORMAT_R10X6G10X6_UNORM_2PACK16, + DATA_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, + DATA_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, + DATA_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, + DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, + DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, + DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, + DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, + DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, + DATA_FORMAT_R12X4_UNORM_PACK16, + DATA_FORMAT_R12X4G12X4_UNORM_2PACK16, + DATA_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, + DATA_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, + DATA_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, + DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, + DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, + DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, + DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, + DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, + DATA_FORMAT_G16B16G16R16_422_UNORM, + DATA_FORMAT_B16G16R16G16_422_UNORM, + DATA_FORMAT_G16_B16_R16_3PLANE_420_UNORM, + DATA_FORMAT_G16_B16R16_2PLANE_420_UNORM, + DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM, + DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM, + DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM, + DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, + DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, + DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, + DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, + DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, + DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, + DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, + DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, + DATA_FORMAT_MAX + }; + + /*****************/ + /**** TEXTURE ****/ + /*****************/ + + enum TextureType { + TEXTURE_TYPE_1D, + TEXTURE_TYPE_2D, + TEXTURE_TYPE_3D, + TEXTURE_TYPE_CUBE, + TEXTURE_TYPE_1D_ARRAY, + TEXTURE_TYPE_2D_ARRAY, + TEXTURE_TYPE_CUBE_ARRAY, + TEXTURE_TYPE_MAX + }; + + enum TextureSamples { + TEXTURE_SAMPLES_1, + TEXTURE_SAMPLES_2, + TEXTURE_SAMPLES_4, + TEXTURE_SAMPLES_8, + TEXTURE_SAMPLES_16, + TEXTURE_SAMPLES_32, + TEXTURE_SAMPLES_64, + TEXTURE_SAMPLES_MAX + }; + + enum TextureUsageBits { + TEXTURE_USAGE_SAMPLING_BIT = (1 << 0), + TEXTURE_USAGE_COLOR_ATTACHMENT_BIT = (1 << 1), + TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = (1 << 2), + TEXTURE_USAGE_STORAGE_BIT = (1 << 3), + TEXTURE_USAGE_STORAGE_ATOMIC_BIT = (1 << 4), + TEXTURE_USAGE_CPU_READ_BIT = (1 << 5), + TEXTURE_USAGE_CAN_UPDATE_BIT = (1 << 6), + TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7), + TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8), + TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT = (1 << 9), + }; + + enum TextureSwizzle { + TEXTURE_SWIZZLE_IDENTITY, + TEXTURE_SWIZZLE_ZERO, + TEXTURE_SWIZZLE_ONE, + TEXTURE_SWIZZLE_R, + TEXTURE_SWIZZLE_G, + TEXTURE_SWIZZLE_B, + TEXTURE_SWIZZLE_A, + TEXTURE_SWIZZLE_MAX + }; + + struct TextureFormat { + DataFormat format; + uint32_t width; + uint32_t height; + uint32_t depth; + uint32_t array_layers; + uint32_t mipmaps; + TextureType type; + TextureSamples samples; + uint32_t usage_bits; + Vector shareable_formats; + + TextureFormat() { + format = DATA_FORMAT_R8_UNORM; + width = 1; + height = 1; + depth = 1; + array_layers = 1; + mipmaps = 1; + type = TEXTURE_TYPE_2D; + samples = TEXTURE_SAMPLES_1; + usage_bits = 0; + } + }; + + struct TextureView { + DataFormat format_override; + TextureSwizzle swizzle_r; + TextureSwizzle swizzle_g; + TextureSwizzle swizzle_b; + TextureSwizzle swizzle_a; + + TextureView() { + format_override = DATA_FORMAT_MAX; //means, use same as format + swizzle_r = TEXTURE_SWIZZLE_R; + swizzle_g = TEXTURE_SWIZZLE_G; + swizzle_b = TEXTURE_SWIZZLE_B; + swizzle_a = TEXTURE_SWIZZLE_A; + } + }; + + virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector> &p_data = Vector>()) = 0; + virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0; + + enum TextureSliceType { + TEXTURE_SLICE_2D, + TEXTURE_SLICE_CUBEMAP, + TEXTURE_SLICE_3D, + }; + + virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; + + virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector &p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the beginning of the frame, unless sync with draw is used, which is used to mix updates with draw calls + virtual Vector texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush + + virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0; + virtual bool texture_is_shared(RID p_texture) = 0; + virtual bool texture_is_valid(RID p_texture) = 0; + + virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false) = 0; + virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false) = 0; + + /*********************/ + /**** FRAMEBUFFER ****/ + /*********************/ + + struct AttachmentFormat { + DataFormat format; + TextureSamples samples; + uint32_t usage_flags; + AttachmentFormat() { + format = DATA_FORMAT_R8G8B8A8_UNORM; + samples = TEXTURE_SAMPLES_1; + usage_flags = 0; + } + }; + + typedef int64_t FramebufferFormatID; + + // This ID is warranted to be unique for the same formats, does not need to be freed + virtual FramebufferFormatID framebuffer_format_create(const Vector &p_format) = 0; + virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0; + + virtual RID framebuffer_create(const Vector &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0; + + virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0; + + /*****************/ + /**** SAMPLER ****/ + /*****************/ + + enum SamplerFilter { + SAMPLER_FILTER_NEAREST, + SAMPLER_FILTER_LINEAR, + }; + + enum SamplerRepeatMode { + SAMPLER_REPEAT_MODE_REPEAT, + SAMPLER_REPEAT_MODE_MIRRORED_REPEAT, + SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE, + SAMPLER_REPEAT_MODE_CLAMP_TO_BORDER, + SAMPLER_REPEAT_MODE_MIRROR_CLAMP_TO_EDGE, + SAMPLER_REPEAT_MODE_MAX + }; + + enum SamplerBorderColor { + SAMPLER_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, + SAMPLER_BORDER_COLOR_INT_TRANSPARENT_BLACK, + SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK, + SAMPLER_BORDER_COLOR_INT_OPAQUE_BLACK, + SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_WHITE, + SAMPLER_BORDER_COLOR_INT_OPAQUE_WHITE, + SAMPLER_BORDER_COLOR_MAX + }; + + struct SamplerState { + SamplerFilter mag_filter; + SamplerFilter min_filter; + SamplerFilter mip_filter; + SamplerRepeatMode repeat_u; + SamplerRepeatMode repeat_v; + SamplerRepeatMode repeat_w; + float lod_bias; + bool use_anisotropy; + float anisotropy_max; + bool enable_compare; + CompareOperator compare_op; + float min_lod; + float max_lod; + SamplerBorderColor border_color; + bool unnormalized_uvw; + + SamplerState() { + mag_filter = SAMPLER_FILTER_NEAREST; + min_filter = SAMPLER_FILTER_NEAREST; + mip_filter = SAMPLER_FILTER_NEAREST; + repeat_u = SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + repeat_v = SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + repeat_w = SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + lod_bias = 0; + use_anisotropy = false; + anisotropy_max = 1.0; + enable_compare = false; + compare_op = COMPARE_OP_ALWAYS; + min_lod = 0; + max_lod = 1e20; //something very large should do + border_color = SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK; + unnormalized_uvw = false; + } + }; + + virtual RID sampler_create(const SamplerState &p_state) = 0; + + /**********************/ + /**** VERTEX ARRAY ****/ + /**********************/ + + enum VertexFrequency { + VERTEX_FREQUENCY_VERTEX, + VERTEX_FREQUENCY_INSTANCE, + }; + + struct VertexDescription { + uint32_t location; //shader location + uint32_t offset; + DataFormat format; + uint32_t stride; + VertexFrequency frequency; + VertexDescription() { + location = 0; + offset = 0; + stride = 0; + format = DATA_FORMAT_MAX; + frequency = VERTEX_FREQUENCY_VERTEX; + } + }; + virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector()) = 0; + + typedef int64_t VertexFormatID; + + // This ID is warranted to be unique for the same formats, does not need to be freed + virtual VertexFormatID vertex_format_create(const Vector &p_vertex_formats) = 0; + virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector &p_src_buffers) = 0; + + enum IndexBufferFormat { + INDEX_BUFFER_FORMAT_UINT16, + INDEX_BUFFER_FORMAT_UINT32, + }; + + virtual RID index_buffer_create(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data = Vector(), bool p_use_restart_indices = false) = 0; + virtual RID index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) = 0; + + /****************/ + /**** SHADER ****/ + /****************/ + + virtual Vector shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = NULL, bool p_allow_cache = true); + + static void shader_set_compile_function(ShaderCompileFunction p_function); + static void shader_set_cache_function(ShaderCacheFunction p_function); + + struct ShaderStageData { + ShaderStage shader_stage; + Vector spir_v; + + ShaderStageData() { + shader_stage = SHADER_STAGE_VERTEX; + } + }; + + virtual RID shader_create(const Vector &p_stages) = 0; + virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader) = 0; + + /******************/ + /**** UNIFORMS ****/ + /******************/ + + enum UniformType { + UNIFORM_TYPE_SAMPLER, //for sampling only (sampler GLSL type) + UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, // for sampling only, but includes a texture, (samplerXX GLSL type), first a sampler then a texture + UNIFORM_TYPE_TEXTURE, //only texture, (textureXX GLSL type) + UNIFORM_TYPE_IMAGE, // storage image (imageXX GLSL type), for compute mostly + UNIFORM_TYPE_TEXTURE_BUFFER, // buffer texture (or TBO, textureBuffer type) + UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER, // buffer texture with a sampler(or TBO, samplerBuffer type) + UNIFORM_TYPE_IMAGE_BUFFER, //texel buffer, (imageBuffer type), for compute mostly + UNIFORM_TYPE_UNIFORM_BUFFER, //regular uniform buffer (or UBO). + UNIFORM_TYPE_STORAGE_BUFFER, //storage buffer ("buffer" qualifier) like UBO, but supports storage, for compute mostly + UNIFORM_TYPE_INPUT_ATTACHMENT, //used for sub-pass read/write, for compute mostly + UNIFORM_TYPE_MAX + }; + + virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector()) = 0; + virtual RID storage_buffer_create(uint32_t p_size, const Vector &p_data = Vector()) = 0; + virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector &p_data = Vector()) = 0; + + struct Uniform { + UniformType type; + int binding; //binding index as specified in shader + + //for single items, provide one ID, for + //multiple items (declared as arrays in shader), + //provide more + //for sampler with texture, supply two IDs for each. + //accepted IDs are: Sampler, Texture, Uniform Buffer and Texture Buffer + Vector ids; + + Uniform() { + type = UNIFORM_TYPE_IMAGE; + binding = 0; + } + }; + + virtual RID uniform_set_create(const Vector &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0; + virtual bool uniform_set_is_valid(RID p_uniform_set) = 0; + + virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the beginning of the frame, unless sync with draw is used, which is used to mix updates with draw calls + virtual Vector buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving + + /*************************/ + /**** RENDER PIPELINE ****/ + /*************************/ + + enum RenderPrimitive { + RENDER_PRIMITIVE_POINTS, + RENDER_PRIMITIVE_LINES, + RENDER_PRIMITIVE_LINES_WITH_ADJACENCY, + RENDER_PRIMITIVE_LINESTRIPS, + RENDER_PRIMITIVE_LINESTRIPS_WITH_ADJACENCY, + RENDER_PRIMITIVE_TRIANGLES, + RENDER_PRIMITIVE_TRIANGLES_WITH_ADJACENCY, + RENDER_PRIMITIVE_TRIANGLE_STRIPS, + RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_AJACENCY, + RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX, + RENDER_PRIMITIVE_TESSELATION_PATCH, + RENDER_PRIMITIVE_MAX + }; + + //disable optimization, tessellate control points + + enum PolygonCullMode { + POLYGON_CULL_DISABLED, + POLYGON_CULL_FRONT, + POLYGON_CULL_BACK, + }; + + enum PolygonFrontFace { + POLYGON_FRONT_FACE_CLOCKWISE, + POLYGON_FRONT_FACE_COUNTER_CLOCKWISE, + }; + + enum StencilOperation { + STENCIL_OP_KEEP, + STENCIL_OP_ZERO, + STENCIL_OP_REPLACE, + STENCIL_OP_INCREMENT_AND_CLAMP, + STENCIL_OP_DECREMENT_AND_CLAMP, + STENCIL_OP_INVERT, + STENCIL_OP_INCREMENT_AND_WRAP, + STENCIL_OP_DECREMENT_AND_WRAP, + STENCIL_OP_MAX //not an actual operator, just the amount of operators :D + }; + + enum LogicOperation { + LOGIC_OP_CLEAR, + LOGIC_OP_AND, + LOGIC_OP_AND_REVERSE, + LOGIC_OP_COPY, + LOGIC_OP_AND_INVERTED, + LOGIC_OP_NO_OP, + LOGIC_OP_XOR, + LOGIC_OP_OR, + LOGIC_OP_NOR, + LOGIC_OP_EQUIVALENT, + LOGIC_OP_INVERT, + LOGIC_OP_OR_REVERSE, + LOGIC_OP_COPY_INVERTED, + LOGIC_OP_OR_INVERTED, + LOGIC_OP_NAND, + LOGIC_OP_SET, + LOGIC_OP_MAX //not an actual operator, just the amount of operators :D + }; + + enum BlendFactor { + BLEND_FACTOR_ZERO, + BLEND_FACTOR_ONE, + BLEND_FACTOR_SRC_COLOR, + BLEND_FACTOR_ONE_MINUS_SRC_COLOR, + BLEND_FACTOR_DST_COLOR, + BLEND_FACTOR_ONE_MINUS_DST_COLOR, + BLEND_FACTOR_SRC_ALPHA, + BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, + BLEND_FACTOR_DST_ALPHA, + BLEND_FACTOR_ONE_MINUS_DST_ALPHA, + BLEND_FACTOR_CONSTANT_COLOR, + BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, + BLEND_FACTOR_CONSTANT_ALPHA, + BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, + BLEND_FACTOR_SRC_ALPHA_SATURATE, + BLEND_FACTOR_SRC1_COLOR, + BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, + BLEND_FACTOR_SRC1_ALPHA, + BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, + BLEND_FACTOR_MAX + }; + + enum BlendOperation { + BLEND_OP_ADD, + BLEND_OP_SUBTRACT, + BLEND_OP_REVERSE_SUBTRACT, + BLEND_OP_MINIMUM, + BLEND_OP_MAXIMUM, //yes this one is an actual operator + BLEND_OP_MAX //not an actual operator, just the amount of operators :D + }; + + struct PipelineRasterizationState { + bool enable_depth_clamp; + bool discard_primitives; + bool wireframe; + PolygonCullMode cull_mode; + PolygonFrontFace front_face; + bool depth_bias_enable; + float depth_bias_constant_factor; + float depth_bias_clamp; + float depth_bias_slope_factor; + float line_width; + uint32_t patch_control_points; + PipelineRasterizationState() { + enable_depth_clamp = false; + discard_primitives = false; + wireframe = false; + cull_mode = POLYGON_CULL_DISABLED; + front_face = POLYGON_FRONT_FACE_CLOCKWISE; + depth_bias_enable = false; + depth_bias_constant_factor = 0; + depth_bias_clamp = 0; + depth_bias_slope_factor = 0; + line_width = 1.0; + patch_control_points = 1; + } + }; + + struct PipelineMultisampleState { + TextureSamples sample_count; + bool enable_sample_shading; + float min_sample_shading; + Vector sample_mask; + bool enable_alpha_to_coverage; + bool enable_alpha_to_one; + + PipelineMultisampleState() { + sample_count = TEXTURE_SAMPLES_1; + enable_sample_shading = false; + min_sample_shading = 0; + enable_alpha_to_coverage = false; + enable_alpha_to_one = false; + } + }; + + struct PipelineDepthStencilState { + + bool enable_depth_test; + bool enable_depth_write; + CompareOperator depth_compare_operator; + bool enable_depth_range; + float depth_range_min; + float depth_range_max; + bool enable_stencil; + + struct StencilOperationState { + StencilOperation fail; + StencilOperation pass; + StencilOperation depth_fail; + CompareOperator compare; + uint32_t compare_mask; + uint32_t write_mask; + uint32_t reference; + + StencilOperationState() { + fail = STENCIL_OP_ZERO; + pass = STENCIL_OP_ZERO; + depth_fail = STENCIL_OP_ZERO; + compare = COMPARE_OP_ALWAYS; + compare_mask = 0; + write_mask = 0; + reference = 0; + } + }; + + StencilOperationState stencil_operation_front; + StencilOperationState stencil_operation_back; + + PipelineDepthStencilState() { + enable_depth_test = false; + enable_depth_write = false; + depth_compare_operator = COMPARE_OP_ALWAYS; + enable_depth_range = false; + depth_range_min = 0; + depth_range_max = 0; + enable_stencil = false; + } + }; + + struct PipelineColorBlendState { + + bool enable_logic_op; + LogicOperation logic_op; + struct Attachment { + bool enable_blend; + BlendFactor src_color_blend_factor; + BlendFactor dst_color_blend_factor; + BlendOperation color_blend_op; + BlendFactor src_alpha_blend_factor; + BlendFactor dst_alpha_blend_factor; + BlendOperation alpha_blend_op; + bool write_r; + bool write_g; + bool write_b; + bool write_a; + Attachment() { + enable_blend = false; + src_color_blend_factor = BLEND_FACTOR_ZERO; + dst_color_blend_factor = BLEND_FACTOR_ZERO; + color_blend_op = BLEND_OP_ADD; + src_alpha_blend_factor = BLEND_FACTOR_ZERO; + dst_alpha_blend_factor = BLEND_FACTOR_ZERO; + alpha_blend_op = BLEND_OP_ADD; + write_r = true; + write_g = true; + write_b = true; + write_a = true; + } + }; + + static PipelineColorBlendState create_disabled(int p_attachments = 1) { + PipelineColorBlendState bs; + for (int i = 0; i < p_attachments; i++) { + bs.attachments.push_back(Attachment()); + } + return bs; + } + + static PipelineColorBlendState create_blend(int p_attachments = 1) { + PipelineColorBlendState bs; + for (int i = 0; i < p_attachments; i++) { + + Attachment ba; + ba.enable_blend = true; + ba.src_color_blend_factor = BLEND_FACTOR_SRC_ALPHA; + ba.dst_color_blend_factor = BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + ba.src_alpha_blend_factor = BLEND_FACTOR_SRC_ALPHA; + ba.dst_alpha_blend_factor = BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + + bs.attachments.push_back(ba); + } + return bs; + } + + Vector attachments; //one per render target texture + Color blend_constant; + + PipelineColorBlendState() { + enable_logic_op = false; + logic_op = LOGIC_OP_CLEAR; + } + }; + + enum PipelineDynamicStateFlags { + DYNAMIC_STATE_LINE_WIDTH = (1 << 0), + DYNAMIC_STATE_DEPTH_BIAS = (1 << 1), + DYNAMIC_STATE_BLEND_CONSTANTS = (1 << 2), + DYNAMIC_STATE_DEPTH_BOUNDS = (1 << 3), + DYNAMIC_STATE_STENCIL_COMPARE_MASK = (1 << 4), + DYNAMIC_STATE_STENCIL_WRITE_MASK = (1 << 5), + DYNAMIC_STATE_STENCIL_REFERENCE = (1 << 6), + }; + + virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0) = 0; + virtual bool render_pipeline_is_valid(RID p_pipeline) = 0; + + /**************************/ + /**** COMPUTE PIPELINE ****/ + /**************************/ + + virtual RID compute_pipeline_create(RID p_shader) = 0; + virtual bool compute_pipeline_is_valid(RID p_pipeline) = 0; + + /****************/ + /**** SCREEN ****/ + /****************/ + + virtual int screen_get_width(DisplayServer::WindowID p_screen = 0) const = 0; + virtual int screen_get_height(DisplayServer::WindowID p_screen = 0) const = 0; + virtual FramebufferFormatID screen_get_framebuffer_format() const = 0; + + /********************/ + /**** DRAW LISTS ****/ + /********************/ + + enum InitialAction { + INITIAL_ACTION_CLEAR, //start rendering and clear the framebuffer (supply params) + INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared) + INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously) + INITIAL_ACTION_MAX + }; + + enum FinalAction { + FINAL_ACTION_READ, //will no longer render to it, allows attached textures to be read again, but depth buffer contents will be dropped (Can't be read from) + FINAL_ACTION_DISCARD, // discard contents after rendering + FINAL_ACTION_CONTINUE, //will continue rendering later, attached textures can't be read until re-bound with "finish" + FINAL_ACTION_MAX + }; + + typedef int64_t DrawListID; + + virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()) = 0; + virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; + virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; + + virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; + virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; + virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0; + virtual void draw_list_bind_index_array(DrawListID p_list, RID p_index_array) = 0; + virtual void draw_list_set_line_width(DrawListID p_list, float p_width) = 0; + virtual void draw_list_set_push_constant(DrawListID p_list, void *p_data, uint32_t p_data_size) = 0; + + virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0) = 0; + + virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0; + virtual void draw_list_disable_scissor(DrawListID p_list) = 0; + + virtual void draw_list_end() = 0; + + /***********************/ + /**** COMPUTE LISTS ****/ + /***********************/ + + typedef int64_t ComputeListID; + + virtual ComputeListID compute_list_begin() = 0; + virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline) = 0; + virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0; + virtual void compute_list_set_push_constant(ComputeListID p_list, void *p_data, uint32_t p_data_size) = 0; + virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0; + virtual void compute_list_add_barrier(ComputeListID p_list) = 0; + + virtual void compute_list_end() = 0; + + /***************/ + /**** FREE! ****/ + /***************/ + + virtual void free(RID p_id) = 0; + + /****************/ + /**** Timing ****/ + /****************/ + + virtual void capture_timestamp(const String &p_name, bool p_sync_to_draw) = 0; + virtual uint32_t get_captured_timestamps_count() const = 0; + virtual uint64_t get_captured_timestamps_frame() const = 0; + virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0; + virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0; + virtual String get_captured_timestamp_name(uint32_t p_index) const = 0; + + /****************/ + /**** LIMITS ****/ + /****************/ + + enum Limit { + LIMIT_MAX_BOUND_UNIFORM_SETS, + LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS, + LIMIT_MAX_TEXTURES_PER_UNIFORM_SET, + LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET, + LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET, + LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET, + LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET, + LIMIT_MAX_DRAW_INDEXED_INDEX, + LIMIT_MAX_FRAMEBUFFER_HEIGHT, + LIMIT_MAX_FRAMEBUFFER_WIDTH, + LIMIT_MAX_TEXTURE_ARRAY_LAYERS, + LIMIT_MAX_TEXTURE_SIZE_1D, + LIMIT_MAX_TEXTURE_SIZE_2D, + LIMIT_MAX_TEXTURE_SIZE_3D, + LIMIT_MAX_TEXTURE_SIZE_CUBE, + LIMIT_MAX_TEXTURES_PER_SHADER_STAGE, + LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE, + LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE, + LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE, + LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE, + LIMIT_MAX_PUSH_CONSTANT_SIZE, + LIMIT_MAX_UNIFORM_BUFFER_SIZE, + LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET, + LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES, + LIMIT_MAX_VERTEX_INPUT_BINDINGS, + LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE, + LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT, + LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE, + LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X, + LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y, + LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z, + LIMIT_MAX_COMPUTE_WORKGROUP_INVOCATIONS, + LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X, + LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y, + LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z, + }; + + virtual int limit_get(Limit p_limit) = 0; + + //methods below not exposed, used by RenderingDeviceRD + virtual void prepare_screen_for_drawing() = 0; + + virtual void swap_buffers() = 0; + + virtual uint32_t get_frame_delay() const = 0; + + static RenderingDevice *get_singleton(); + + RenderingDevice(); +}; + +typedef RenderingDevice RD; + +#endif // RENDERING_DEVICE_H diff --git a/servers/rendering/rendering_server_canvas.cpp b/servers/rendering/rendering_server_canvas.cpp new file mode 100644 index 0000000000..7b28c586b9 --- /dev/null +++ b/servers/rendering/rendering_server_canvas.cpp @@ -0,0 +1,1479 @@ +/*************************************************************************/ +/* rendering_server_canvas.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server_canvas.h" +#include "rendering_server_globals.h" +#include "rendering_server_raster.h" +#include "rendering_server_viewport.h" + +static const int z_range = RS::CANVAS_ITEM_Z_MAX - RS::CANVAS_ITEM_Z_MIN + 1; + +void RenderingServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) { + + RENDER_TIMESTAMP("Cull CanvasItem Tree"); + + memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); + memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); + + for (int i = 0; i < p_child_item_count; i++) { + _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL); + } + if (p_canvas_item) { + _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL); + } + + RasterizerCanvas::Item *list = NULL; + RasterizerCanvas::Item *list_end = NULL; + + for (int i = 0; i < z_range; i++) { + if (!z_list[i]) + continue; + if (!list) { + list = z_list[i]; + list_end = z_last_list[i]; + } else { + list_end->next = z_list[i]; + list_end = z_last_list[i]; + } + } + + RENDER_TIMESTAMP("Render Canvas Items"); + + RSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_transform); +} + +void _collect_ysort_children(RenderingServerCanvas::Item *p_canvas_item, Transform2D p_transform, RenderingServerCanvas::Item *p_material_owner, RenderingServerCanvas::Item **r_items, int &r_index) { + int child_item_count = p_canvas_item->child_items.size(); + RenderingServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); + for (int i = 0; i < child_item_count; i++) { + if (child_items[i]->visible) { + if (r_items) { + r_items[r_index] = child_items[i]; + child_items[i]->ysort_xform = p_transform; + child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); + child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL; + } + + r_index++; + + if (child_items[i]->sort_y) + _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index); + } + } +} + +void _mark_ysort_dirty(RenderingServerCanvas::Item *ysort_owner, RID_PtrOwner &canvas_item_owner) { + do { + ysort_owner->ysort_children_count = -1; + ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : NULL; + } while (ysort_owner && ysort_owner->sort_y); +} + +void RenderingServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) { + + Item *ci = p_canvas_item; + + if (!ci->visible) + return; + + if (ci->children_order_dirty) { + + ci->child_items.sort_custom(); + ci->children_order_dirty = false; + } + + Rect2 rect = ci->get_rect(); + Transform2D xform = p_transform * ci->xform; + Rect2 global_rect = xform.xform(rect); + global_rect.position += p_clip_rect.position; + + if (ci->use_parent_material && p_material_owner) + ci->material_owner = p_material_owner; + else { + p_material_owner = ci; + ci->material_owner = NULL; + } + + Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a); + + if (modulate.a < 0.007) + return; + + int child_item_count = ci->child_items.size(); + Item **child_items = ci->child_items.ptrw(); + + if (ci->clip) { + if (p_canvas_clip != NULL) { + ci->final_clip_rect = p_canvas_clip->final_clip_rect.clip(global_rect); + } else { + ci->final_clip_rect = global_rect; + } + ci->final_clip_owner = ci; + + } else { + ci->final_clip_owner = p_canvas_clip; + } + + if (ci->sort_y) { + + if (ci->ysort_children_count == -1) { + ci->ysort_children_count = 0; + _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count); + } + + child_item_count = ci->ysort_children_count; + child_items = (Item **)alloca(child_item_count * sizeof(Item *)); + + int i = 0; + _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i); + + SortArray sorter; + sorter.sort(child_items, child_item_count); + } + + if (ci->z_relative) + p_z = CLAMP(p_z + ci->z_index, RS::CANVAS_ITEM_Z_MIN, RS::CANVAS_ITEM_Z_MAX); + else + p_z = ci->z_index; + + for (int i = 0; i < child_item_count; i++) { + + if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) + continue; + if (ci->sort_y) { + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); + } else { + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + } + } + + if (ci->copy_back_buffer) { + + ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); + } + + if (ci->update_when_visible) { + RenderingServerRaster::redraw_request(); + } + + if ((ci->commands != NULL && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { + //something to draw? + ci->final_transform = xform; + ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a); + ci->global_rect_cache = global_rect; + ci->global_rect_cache.position -= p_clip_rect.position; + ci->light_masked = false; + + int zidx = p_z - RS::CANVAS_ITEM_Z_MIN; + + if (z_last_list[zidx]) { + z_last_list[zidx]->next = ci; + z_last_list[zidx] = ci; + + } else { + z_list[zidx] = ci; + z_last_list[zidx] = ci; + } + + ci->z_final = p_z; + + ci->next = NULL; + } + + for (int i = 0; i < child_item_count; i++) { + + if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) + continue; + if (ci->sort_y) { + _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); + } else { + _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); + } + } +} + +void RenderingServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights) { + + if (!p_masked_lights) + return; + + RasterizerCanvas::Item *ci = p_canvas_item; + + while (ci) { + + RasterizerCanvas::Light *light = p_masked_lights; + while (light) { + + if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { + ci->light_masked = true; + } + + light = light->mask_next_ptr; + } + + ci = ci->next; + } +} + +void RenderingServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) { + + RENDER_TIMESTAMP(">Render Canvas"); + + if (p_canvas->children_order_dirty) { + + p_canvas->child_items.sort(); + p_canvas->children_order_dirty = false; + } + + int l = p_canvas->child_items.size(); + Canvas::ChildItem *ci = p_canvas->child_items.ptrw(); + + bool has_mirror = false; + for (int i = 0; i < l; i++) { + if (ci[i].mirror.x || ci[i].mirror.y) { + has_mirror = true; + break; + } + } + + if (!has_mirror) { + + _render_canvas_item_tree(p_render_target, ci, l, NULL, p_transform, p_clip_rect, p_canvas->modulate, p_lights); + + } else { + //used for parallaxlayer mirroring + for (int i = 0; i < l; i++) { + + const Canvas::ChildItem &ci2 = p_canvas->child_items[i]; + _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights); + + //mirroring (useful for scrolling backgrounds) + if (ci2.mirror.x != 0) { + + Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0)); + _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + } + if (ci2.mirror.y != 0) { + + Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y)); + _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + } + if (ci2.mirror.y != 0 && ci2.mirror.x != 0) { + + Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror); + _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); + } + } + } + + RENDER_TIMESTAMP("find_item(canvas_item); + ERR_FAIL_COND(idx == -1); + canvas->child_items.write[idx].mirror = p_mirroring; +} +void RenderingServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) { + + Canvas *canvas = canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + canvas->modulate = p_color; +} + +void RenderingServerCanvas::canvas_set_disable_scale(bool p_disable) { + disable_scale = p_disable; +} + +void RenderingServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) { + + Canvas *canvas = canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + canvas->parent = p_parent; + canvas->parent_scale = p_scale; +} + +RID RenderingServerCanvas::canvas_item_create() { + + Item *canvas_item = memnew(Item); + ERR_FAIL_COND_V(!canvas_item, RID()); + + return canvas_item_owner.make_rid(canvas_item); +} + +void RenderingServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + if (canvas_item->parent.is_valid()) { + + if (canvas_owner.owns(canvas_item->parent)) { + + Canvas *canvas = canvas_owner.getornull(canvas_item->parent); + canvas->erase_item(canvas_item); + } else if (canvas_item_owner.owns(canvas_item->parent)) { + + Item *item_owner = canvas_item_owner.getornull(canvas_item->parent); + item_owner->child_items.erase(canvas_item); + + if (item_owner->sort_y) { + _mark_ysort_dirty(item_owner, canvas_item_owner); + } + } + + canvas_item->parent = RID(); + } + + if (p_parent.is_valid()) { + if (canvas_owner.owns(p_parent)) { + + Canvas *canvas = canvas_owner.getornull(p_parent); + Canvas::ChildItem ci; + ci.item = canvas_item; + canvas->child_items.push_back(ci); + canvas->children_order_dirty = true; + } else if (canvas_item_owner.owns(p_parent)) { + + Item *item_owner = canvas_item_owner.getornull(p_parent); + item_owner->child_items.push_back(canvas_item); + item_owner->children_order_dirty = true; + + if (item_owner->sort_y) { + _mark_ysort_dirty(item_owner, canvas_item_owner); + } + + } else { + + ERR_FAIL_MSG("Invalid parent."); + } + } + + canvas_item->parent = p_parent; +} +void RenderingServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->visible = p_visible; + + _mark_ysort_dirty(canvas_item, canvas_item_owner); +} +void RenderingServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->light_mask = p_mask; +} + +void RenderingServerCanvas::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->xform = p_transform; +} +void RenderingServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->clip = p_clip; +} +void RenderingServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->distance_field = p_enable; +} +void RenderingServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->custom_rect = p_custom_rect; + canvas_item->rect = p_rect; +} +void RenderingServerCanvas::canvas_item_set_modulate(RID p_item, const Color &p_color) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->modulate = p_color; +} +void RenderingServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color &p_color) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->self_modulate = p_color; +} + +void RenderingServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->behind = p_enable; +} + +void RenderingServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool p_update) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->update_when_visible = p_update; +} + +void RenderingServerCanvas::canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + canvas_item->texture_filter = p_filter; +} + +void RenderingServerCanvas::canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + canvas_item->texture_repeat = p_repeat; +} + +void RenderingServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPrimitive *line = canvas_item->alloc_command(); + ERR_FAIL_COND(!line); + if (p_width > 1.001) { + + Vector2 t = (p_from - p_to).tangent().normalized(); + line->points[0] = p_from + t * p_width; + line->points[1] = p_from - t * p_width; + line->points[2] = p_to - t * p_width; + line->points[3] = p_to + t * p_width; + line->point_count = 4; + } else { + line->point_count = 2; + line->points[0] = p_from; + line->points[1] = p_to; + } + for (uint32_t i = 0; i < line->point_count; i++) { + line->colors[i] = p_color; + } + line->specular_shininess = Color(1, 1, 1, 1); +} + +void RenderingServerCanvas::canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width) { + + ERR_FAIL_COND(p_points.size() < 2); + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPolygon *pline = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline); + + pline->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); + + if (true || p_width <= 1) { +#define TODO make thick lines possible + Vector indices; + int pc = p_points.size(); + indices.resize((pc - 1) * 2); + { + int *iptr = indices.ptrw(); + for (int i = 0; i < (pc - 1); i++) { + iptr[i * 2 + 0] = i; + iptr[i * 2 + 1] = i + 1; + } + } + + pline->primitive = RS::PRIMITIVE_LINES; + pline->specular_shininess = Color(1, 1, 1, 1); + pline->polygon.create(indices, p_points, p_colors); + } else { +#if 0 + //make a trianglestrip for drawing the line... + Vector2 prev_t; + pline->triangles.resize(p_points.size() * 2); + if (p_antialiased) { + pline->lines.resize(p_points.size() * 2); + } + + if (p_colors.size() == 0) { + pline->triangle_colors.push_back(Color(1, 1, 1, 1)); + if (p_antialiased) { + pline->line_colors.push_back(Color(1, 1, 1, 1)); + } + } else if (p_colors.size() == 1) { + pline->triangle_colors = p_colors; + pline->line_colors = p_colors; + } else { + if (p_colors.size() != p_points.size()) { + pline->triangle_colors.push_back(p_colors[0]); + pline->line_colors.push_back(p_colors[0]); + } else { + pline->triangle_colors.resize(pline->triangles.size()); + pline->line_colors.resize(pline->lines.size()); + } + } + + for (int i = 0; i < p_points.size(); i++) { + + Vector2 t; + if (i == p_points.size() - 1) { + t = prev_t; + } else { + t = (p_points[i + 1] - p_points[i]).normalized().tangent(); + if (i == 0) { + prev_t = t; + } + } + + Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; + + if (p_antialiased) { + pline->lines.write[i] = p_points[i] + tangent; + pline->lines.write[p_points.size() * 2 - i - 1] = p_points[i] - tangent; + if (pline->line_colors.size() > 1) { + pline->line_colors.write[i] = p_colors[i]; + pline->line_colors.write[p_points.size() * 2 - i - 1] = p_colors[i]; + } + } + + pline->triangles.write[i * 2 + 0] = p_points[i] + tangent; + pline->triangles.write[i * 2 + 1] = p_points[i] - tangent; + + if (pline->triangle_colors.size() > 1) { + + pline->triangle_colors.write[i * 2 + 0] = p_colors[i]; + pline->triangle_colors.write[i * 2 + 1] = p_colors[i]; + } + + prev_t = t; + } +#endif + } +} + +void RenderingServerCanvas::canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width) { + + ERR_FAIL_COND(p_points.size() < 2); + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPolygon *pline = canvas_item->alloc_command(); + ERR_FAIL_COND(!pline); + + pline->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); + + if (true || p_width <= 1) { +#define TODO make thick lines possible + + pline->primitive = RS::PRIMITIVE_LINES; + pline->specular_shininess = Color(1, 1, 1, 1); + pline->polygon.create(Vector(), p_points, p_colors); + } else { + } +} + +void RenderingServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command(); + ERR_FAIL_COND(!rect); + rect->modulate = p_color; + rect->rect = p_rect; +} + +void RenderingServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPolygon *circle = canvas_item->alloc_command(); + ERR_FAIL_COND(!circle); + + circle->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); + + circle->primitive = RS::PRIMITIVE_TRIANGLES; + circle->specular_shininess = Color(1, 1, 1, 1); + + Vector indices; + Vector points; + + static const int circle_points = 64; + + points.resize(circle_points); + for (int i = 0; i < circle_points; i++) { + float angle = (i / float(circle_points)) * 2 * Math_PI; + points.write[i].x = Math::cos(angle) * p_radius; + points.write[i].y = Math::sin(angle) * p_radius; + points.write[i] += p_pos; + } + indices.resize((circle_points - 2) * 3); + + for (int i = 0; i < circle_points - 2; i++) { + indices.write[i * 3 + 0] = 0; + indices.write[i * 3 + 1] = i + 1; + indices.write[i * 3 + 2] = i + 2; + } + + Vector color; + color.push_back(p_color); + circle->polygon.create(indices, points, color); +} + +void RenderingServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command(); + ERR_FAIL_COND(!rect); + rect->modulate = p_modulate; + rect->rect = p_rect; + rect->flags = 0; + if (p_tile) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE; + rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION; + rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height)); + } + + if (p_rect.size.x < 0) { + + rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_rect.size.y < 0) { + + rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_transpose) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + rect->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + rect->specular_shininess = p_specular_color_shininess; +} + +void RenderingServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, bool p_clip_uv, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandRect *rect = canvas_item->alloc_command(); + ERR_FAIL_COND(!rect); + rect->modulate = p_modulate; + rect->rect = p_rect; + rect->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + rect->specular_shininess = p_specular_color_shininess; + rect->source = p_src_rect; + rect->flags = RasterizerCanvas::CANVAS_RECT_REGION; + + if (p_rect.size.x < 0) { + + rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->rect.size.x = -rect->rect.size.x; + } + if (p_src_rect.size.x < 0) { + + rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_H; + rect->source.size.x = -rect->source.size.x; + } + if (p_rect.size.y < 0) { + + rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->rect.size.y = -rect->rect.size.y; + } + if (p_src_rect.size.y < 0) { + + rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_V; + rect->source.size.y = -rect->source.size.y; + } + + if (p_transpose) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; + SWAP(rect->rect.size.x, rect->rect.size.y); + } + + if (p_clip_uv) { + rect->flags |= RasterizerCanvas::CANVAS_RECT_CLIP_UV; + } +} + +void RenderingServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode, RS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandNinePatch *style = canvas_item->alloc_command(); + ERR_FAIL_COND(!style); + style->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + style->specular_shininess = p_specular_color_shininess; + style->rect = p_rect; + style->source = p_source; + style->draw_center = p_draw_center; + style->color = p_modulate; + style->margin[MARGIN_LEFT] = p_topleft.x; + style->margin[MARGIN_TOP] = p_topleft.y; + style->margin[MARGIN_RIGHT] = p_bottomright.x; + style->margin[MARGIN_BOTTOM] = p_bottomright.y; + style->axis_x = p_x_axis_mode; + style->axis_y = p_y_axis_mode; +} +void RenderingServerCanvas::canvas_item_add_primitive(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, float p_width, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + uint32_t pc = p_points.size(); + ERR_FAIL_COND(pc == 0 || pc > 4); + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandPrimitive *prim = canvas_item->alloc_command(); + ERR_FAIL_COND(!prim); + + for (int i = 0; i < p_points.size(); i++) { + prim->points[i] = p_points[i]; + if (i < p_uvs.size()) { + prim->uvs[i] = p_uvs[i]; + } + if (i < p_colors.size()) { + prim->colors[i] = p_colors[i]; + } else if (p_colors.size()) { + prim->colors[i] = p_colors[0]; + } else { + prim->colors[i] = Color(1, 1, 1, 1); + } + } + + prim->point_count = p_points.size(); + + prim->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + prim->specular_shininess = p_specular_color_shininess; +} + +void RenderingServerCanvas::canvas_item_add_polygon(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); +#ifdef DEBUG_ENABLED + int pointcount = p_points.size(); + ERR_FAIL_COND(pointcount < 3); + int color_size = p_colors.size(); + int uv_size = p_uvs.size(); + ERR_FAIL_COND(color_size != 0 && color_size != 1 && color_size != pointcount); + ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount)); +#endif + Vector indices = Geometry::triangulate_polygon(p_points); + ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed."); + + Item::CommandPolygon *polygon = canvas_item->alloc_command(); + ERR_FAIL_COND(!polygon); + polygon->primitive = RS::PRIMITIVE_TRIANGLES; + polygon->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + polygon->specular_shininess = p_specular_color_shininess; + polygon->polygon.create(indices, p_points, p_colors, p_uvs); +} + +void RenderingServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, const Vector &p_bones, const Vector &p_weights, RID p_texture, int p_count, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + int vertex_count = p_points.size(); + ERR_FAIL_COND(vertex_count == 0); + ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1); + ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count); + ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4); + ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4); + + Vector indices = p_indices; + + Item::CommandPolygon *polygon = canvas_item->alloc_command(); + ERR_FAIL_COND(!polygon); + polygon->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + polygon->specular_shininess = p_specular_color_shininess; + polygon->polygon.create(indices, p_points, p_colors, p_uvs, p_bones, p_weights); + + polygon->primitive = RS::PRIMITIVE_TRIANGLES; +} + +void RenderingServerCanvas::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandTransform *tr = canvas_item->alloc_command(); + ERR_FAIL_COND(!tr); + tr->xform = p_transform; +} + +void RenderingServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandMesh *m = canvas_item->alloc_command(); + ERR_FAIL_COND(!m); + m->mesh = p_mesh; + m->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + m->specular_shininess = p_specular_color_shininess; + m->transform = p_transform; + m->modulate = p_modulate; +} +void RenderingServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandParticles *part = canvas_item->alloc_command(); + ERR_FAIL_COND(!part); + part->particles = p_particles; + part->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); + part->specular_shininess = p_specular_color_shininess; + + //take the chance and request processing for them, at least once until they become visible again + RSG::storage->particles_request_process(p_particles); +} + +void RenderingServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, RenderingServer::CanvasItemTextureFilter p_filter, RenderingServer::CanvasItemTextureRepeat p_repeat) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandMultiMesh *mm = canvas_item->alloc_command(); + ERR_FAIL_COND(!mm); + mm->multimesh = p_mesh; + mm->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, mm->multimesh); + mm->specular_shininess = p_specular_color_shininess; +} + +void RenderingServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + Item::CommandClipIgnore *ci = canvas_item->alloc_command(); + ERR_FAIL_COND(!ci); + ci->ignore = p_ignore; +} +void RenderingServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->sort_y = p_enable; + + _mark_ysort_dirty(canvas_item, canvas_item_owner); +} +void RenderingServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) { + + ERR_FAIL_COND(p_z < RS::CANVAS_ITEM_Z_MIN || p_z > RS::CANVAS_ITEM_Z_MAX); + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->z_index = p_z; +} +void RenderingServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->z_relative = p_enable; +} + +void RenderingServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->skeleton = p_skeleton; +} + +void RenderingServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + if (bool(canvas_item->copy_back_buffer != NULL) != p_enable) { + if (p_enable) { + canvas_item->copy_back_buffer = memnew(RasterizerCanvas::Item::CopyBackBuffer); + } else { + memdelete(canvas_item->copy_back_buffer); + canvas_item->copy_back_buffer = NULL; + } + } + + if (p_enable) { + canvas_item->copy_back_buffer->rect = p_rect; + canvas_item->copy_back_buffer->full = p_rect == Rect2(); + } +} + +void RenderingServerCanvas::canvas_item_clear(RID p_item) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->clear(); +} +void RenderingServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->index = p_index; + + if (canvas_item_owner.owns(canvas_item->parent)) { + Item *canvas_item_parent = canvas_item_owner.getornull(canvas_item->parent); + canvas_item_parent->children_order_dirty = true; + return; + } + + Canvas *canvas = canvas_owner.getornull(canvas_item->parent); + if (canvas) { + canvas->children_order_dirty = true; + return; + } +} + +void RenderingServerCanvas::canvas_item_set_material(RID p_item, RID p_material) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->material = p_material; +} + +void RenderingServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable) { + + Item *canvas_item = canvas_item_owner.getornull(p_item); + ERR_FAIL_COND(!canvas_item); + + canvas_item->use_parent_material = p_enable; +} + +RID RenderingServerCanvas::canvas_light_create() { + + RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light); + clight->light_internal = RSG::canvas_render->light_create(); + return canvas_light_owner.make_rid(clight); +} +void RenderingServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.getornull(clight->canvas); + canvas->lights.erase(clight); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas = RID(); + + clight->canvas = p_canvas; + + if (clight->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.getornull(clight->canvas); + canvas->lights.insert(clight); + } +} + +void RenderingServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->enabled = p_enabled; +} +void RenderingServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->scale = p_scale; +} +void RenderingServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->xform = p_transform; +} +void RenderingServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->texture = p_texture; + clight->version++; + RSG::canvas_render->light_set_texture(clight->light_internal, p_texture); +} +void RenderingServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->texture_offset = p_offset; +} +void RenderingServerCanvas::canvas_light_set_color(RID p_light, const Color &p_color) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->color = p_color; +} +void RenderingServerCanvas::canvas_light_set_height(RID p_light, float p_height) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->height = p_height; +} +void RenderingServerCanvas::canvas_light_set_energy(RID p_light, float p_energy) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->energy = p_energy; +} +void RenderingServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->z_min = p_min_z; + clight->z_max = p_max_z; +} +void RenderingServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->layer_max = p_max_layer; + clight->layer_min = p_min_layer; +} +void RenderingServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->item_mask = p_mask; +} +void RenderingServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->item_shadow_mask = p_mask; +} +void RenderingServerCanvas::canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->mode = p_mode; +} + +void RenderingServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + if (clight->use_shadow == p_enabled) { + return; + } + clight->use_shadow = p_enabled; + clight->version++; + RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); +} + +void RenderingServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size) { + + ERR_FAIL_COND(p_size < 32 || p_size > 16384); + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + int new_size = next_power_of_2(p_size); + if (new_size == clight->shadow_buffer_size) + return; + + clight->shadow_buffer_size = next_power_of_2(p_size); + clight->version++; + + RSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); +} + +void RenderingServerCanvas::canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_filter = p_filter; +} +void RenderingServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color &p_color) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + + clight->shadow_color = p_color; +} + +void RenderingServerCanvas::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) { + + RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); + ERR_FAIL_COND(!clight); + clight->shadow_smooth = p_smooth; +} + +RID RenderingServerCanvas::canvas_light_occluder_create() { + + RasterizerCanvas::LightOccluderInstance *occluder = memnew(RasterizerCanvas::LightOccluderInstance); + + return canvas_light_occluder_owner.make_rid(occluder); +} +void RenderingServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.getornull(occluder->canvas); + canvas->occluders.erase(occluder); + } + + if (!canvas_owner.owns(p_canvas)) + p_canvas = RID(); + + occluder->canvas = p_canvas; + + if (occluder->canvas.is_valid()) { + + Canvas *canvas = canvas_owner.getornull(occluder->canvas); + canvas->occluders.insert(occluder); + } +} +void RenderingServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->enabled = p_enabled; +} +void RenderingServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); + ERR_FAIL_COND(!occluder); + + if (occluder->polygon.is_valid()) { + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + } + + occluder->polygon = p_polygon; + occluder->occluder = RID(); + + if (occluder->polygon.is_valid()) { + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon); + if (!occluder_poly) { + occluder->polygon = RID(); + ERR_FAIL_COND(!occluder_poly); + } else { + occluder_poly->owners.insert(occluder); + occluder->occluder = occluder_poly->occluder; + occluder->aabb_cache = occluder_poly->aabb; + occluder->cull_cache = occluder_poly->cull_mode; + } + } +} +void RenderingServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->xform = p_xform; +} +void RenderingServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); + ERR_FAIL_COND(!occluder); + + occluder->light_mask = p_mask; +} + +RID RenderingServerCanvas::canvas_occluder_polygon_create() { + + LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon); + occluder_poly->occluder = RSG::canvas_render->occluder_polygon_create(); + return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); +} +void RenderingServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector &p_shape, bool p_closed) { + + if (p_shape.size() < 3) { + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape); + return; + } + + Vector lines; + int lc = p_shape.size() * 2; + + lines.resize(lc - (p_closed ? 0 : 2)); + { + Vector2 *w = lines.ptrw(); + const Vector2 *r = p_shape.ptr(); + + int max = lc / 2; + if (!p_closed) { + max--; + } + for (int i = 0; i < max; i++) { + + Vector2 a = r[i]; + Vector2 b = r[(i + 1) % (lc / 2)]; + w[i * 2 + 0] = a; + w[i * 2 + 1] = b; + } + } + + canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines); +} +void RenderingServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector &p_shape) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + ERR_FAIL_COND(p_shape.size() & 1); + + int lc = p_shape.size(); + occluder_poly->aabb = Rect2(); + { + const Vector2 *r = p_shape.ptr(); + for (int i = 0; i < lc; i++) { + if (i == 0) + occluder_poly->aabb.position = r[i]; + else + occluder_poly->aabb.expand_to(r[i]); + } + } + + RSG::canvas_render->occluder_polygon_set_shape_as_lines(occluder_poly->occluder, p_shape); + for (Set::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + E->get()->aabb_cache = occluder_poly->aabb; + } +} + +void RenderingServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); + ERR_FAIL_COND(!occluder_poly); + occluder_poly->cull_mode = p_mode; + RSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode); + for (Set::Element *E = occluder_poly->owners.front(); E; E = E->next()) { + E->get()->cull_cache = p_mode; + } +} + +bool RenderingServerCanvas::free(RID p_rid) { + + if (canvas_owner.owns(p_rid)) { + + Canvas *canvas = canvas_owner.getornull(p_rid); + ERR_FAIL_COND_V(!canvas, false); + + while (canvas->viewports.size()) { + + RenderingServerViewport::Viewport *vp = RSG::viewport->viewport_owner.getornull(canvas->viewports.front()->get()); + ERR_FAIL_COND_V(!vp, true); + + Map::Element *E = vp->canvas_map.find(p_rid); + ERR_FAIL_COND_V(!E, true); + vp->canvas_map.erase(p_rid); + + canvas->viewports.erase(canvas->viewports.front()); + } + + for (int i = 0; i < canvas->child_items.size(); i++) { + + canvas->child_items[i].item->parent = RID(); + } + + for (Set::Element *E = canvas->lights.front(); E; E = E->next()) { + + E->get()->canvas = RID(); + } + + for (Set::Element *E = canvas->occluders.front(); E; E = E->next()) { + + E->get()->canvas = RID(); + } + + canvas_owner.free(p_rid); + + memdelete(canvas); + + } else if (canvas_item_owner.owns(p_rid)) { + + Item *canvas_item = canvas_item_owner.getornull(p_rid); + ERR_FAIL_COND_V(!canvas_item, true); + + if (canvas_item->parent.is_valid()) { + + if (canvas_owner.owns(canvas_item->parent)) { + + Canvas *canvas = canvas_owner.getornull(canvas_item->parent); + canvas->erase_item(canvas_item); + } else if (canvas_item_owner.owns(canvas_item->parent)) { + + Item *item_owner = canvas_item_owner.getornull(canvas_item->parent); + item_owner->child_items.erase(canvas_item); + + if (item_owner->sort_y) { + _mark_ysort_dirty(item_owner, canvas_item_owner); + } + } + } + + for (int i = 0; i < canvas_item->child_items.size(); i++) { + + canvas_item->child_items[i]->parent = RID(); + } + + /* + if (canvas_item->material) { + canvas_item->material->owners.erase(canvas_item); + } + */ + + canvas_item_owner.free(p_rid); + + memdelete(canvas_item); + + } else if (canvas_light_owner.owns(p_rid)) { + + RasterizerCanvas::Light *canvas_light = canvas_light_owner.getornull(p_rid); + ERR_FAIL_COND_V(!canvas_light, true); + + if (canvas_light->canvas.is_valid()) { + Canvas *canvas = canvas_owner.getornull(canvas_light->canvas); + if (canvas) + canvas->lights.erase(canvas_light); + } + + RSG::canvas_render->free(canvas_light->light_internal); + + canvas_light_owner.free(p_rid); + memdelete(canvas_light); + + } else if (canvas_light_occluder_owner.owns(p_rid)) { + + RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid); + ERR_FAIL_COND_V(!occluder, true); + + if (occluder->polygon.is_valid()) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(occluder->polygon); + if (occluder_poly) { + occluder_poly->owners.erase(occluder); + } + } + + if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { + + Canvas *canvas = canvas_owner.getornull(occluder->canvas); + canvas->occluders.erase(occluder); + } + + canvas_light_occluder_owner.free(p_rid); + memdelete(occluder); + + } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) { + + LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid); + ERR_FAIL_COND_V(!occluder_poly, true); + RSG::canvas_render->free(occluder_poly->occluder); + + while (occluder_poly->owners.size()) { + + occluder_poly->owners.front()->get()->polygon = RID(); + occluder_poly->owners.erase(occluder_poly->owners.front()); + } + + canvas_light_occluder_polygon_owner.free(p_rid); + memdelete(occluder_poly); + } else { + return false; + } + + return true; +} + +RenderingServerCanvas::RenderingServerCanvas() { + + z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); + z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); + + disable_scale = false; +} + +RenderingServerCanvas::~RenderingServerCanvas() { + + memfree(z_list); + memfree(z_last_list); +} diff --git a/servers/rendering/rendering_server_canvas.h b/servers/rendering/rendering_server_canvas.h new file mode 100644 index 0000000000..579bcd36e7 --- /dev/null +++ b/servers/rendering/rendering_server_canvas.h @@ -0,0 +1,270 @@ +/*************************************************************************/ +/* rendering_server_canvas.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VISUALSERVERCANVAS_H +#define VISUALSERVERCANVAS_H + +#include "rasterizer.h" +#include "rendering_server_viewport.h" + +class RenderingServerCanvas { +public: + struct Item : public RasterizerCanvas::Item { + + RID parent; // canvas it belongs to + List::Element *E; + int z_index; + bool z_relative; + bool sort_y; + Color modulate; + Color self_modulate; + bool use_parent_material; + int index; + bool children_order_dirty; + int ysort_children_count; + Color ysort_modulate; + Transform2D ysort_xform; + Vector2 ysort_pos; + RS::CanvasItemTextureFilter texture_filter; + RS::CanvasItemTextureRepeat texture_repeat; + + Vector child_items; + + Item() { + children_order_dirty = true; + E = NULL; + z_index = 0; + modulate = Color(1, 1, 1, 1); + self_modulate = Color(1, 1, 1, 1); + sort_y = false; + use_parent_material = false; + z_relative = true; + index = 0; + ysort_children_count = -1; + ysort_xform = Transform2D(); + ysort_pos = Vector2(); + texture_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; + texture_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; + } + }; + + struct ItemIndexSort { + + _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { + + return p_left->index < p_right->index; + } + }; + + struct ItemPtrSort { + + _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { + + if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) + return p_left->ysort_pos.x < p_right->ysort_pos.x; + + return p_left->ysort_pos.y < p_right->ysort_pos.y; + } + }; + + struct LightOccluderPolygon { + + bool active; + Rect2 aabb; + RS::CanvasOccluderPolygonCullMode cull_mode; + RID occluder; + Set owners; + + LightOccluderPolygon() { + active = false; + cull_mode = RS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; + } + }; + + RID_PtrOwner canvas_light_occluder_polygon_owner; + + RID_PtrOwner canvas_light_occluder_owner; + + struct Canvas : public RenderingServerViewport::CanvasBase { + + Set viewports; + struct ChildItem { + + Point2 mirror; + Item *item; + bool operator<(const ChildItem &p_item) const { + return item->index < p_item.item->index; + } + }; + + Set lights; + + Set occluders; + + bool children_order_dirty; + Vector child_items; + Color modulate; + RID parent; + float parent_scale; + + int find_item(Item *p_item) { + for (int i = 0; i < child_items.size(); i++) { + if (child_items[i].item == p_item) + return i; + } + return -1; + } + void erase_item(Item *p_item) { + int idx = find_item(p_item); + if (idx >= 0) + child_items.remove(idx); + } + + Canvas() { + modulate = Color(1, 1, 1, 1); + children_order_dirty = true; + parent_scale = 1.0; + } + }; + + mutable RID_PtrOwner canvas_owner; + RID_PtrOwner canvas_item_owner; + RID_PtrOwner canvas_light_owner; + + bool disable_scale; + +private: + void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights); + void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); + void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights); + + RasterizerCanvas::Item **z_list; + RasterizerCanvas::Item **z_last_list; + +public: + void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect); + + RID canvas_create(); + void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring); + void canvas_set_modulate(RID p_canvas, const Color &p_color); + void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale); + void canvas_set_disable_scale(bool p_disable); + + RID canvas_item_create(); + void canvas_item_set_parent(RID p_item, RID p_parent); + + void canvas_item_set_visible(RID p_item, bool p_visible); + void canvas_item_set_light_mask(RID p_item, int p_mask); + + void canvas_item_set_transform(RID p_item, const Transform2D &p_transform); + void canvas_item_set_clip(RID p_item, bool p_clip); + void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); + void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()); + void canvas_item_set_modulate(RID p_item, const Color &p_color); + void canvas_item_set_self_modulate(RID p_item, const Color &p_color); + + void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable); + + void canvas_item_set_update_when_visible(RID p_item, bool p_update); + + void canvas_item_set_default_texture_filter(RID p_item, RS::CanvasItemTextureFilter p_filter); + void canvas_item_set_default_texture_repeat(RID p_item, RS::CanvasItemTextureRepeat p_repeat); + + void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); + void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0); + void canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0); + void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); + void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); + void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, RS::NinePatchAxisMode p_x_axis_mode = RS::NINE_PATCH_STRETCH, RS::NinePatchAxisMode p_y_axis_mode = RS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_primitive(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_polygon(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), RS::CanvasItemTextureFilter p_filter = RS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, RS::CanvasItemTextureRepeat p_repeat = RS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); + void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); + void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); + void canvas_item_set_z_index(RID p_item, int p_z); + void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); + void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect); + void canvas_item_attach_skeleton(RID p_item, RID p_skeleton); + + void canvas_item_clear(RID p_item); + void canvas_item_set_draw_index(RID p_item, int p_index); + + void canvas_item_set_material(RID p_item, RID p_material); + + void canvas_item_set_use_parent_material(RID p_item, bool p_enable); + + RID canvas_light_create(); + void canvas_light_attach_to_canvas(RID p_light, RID p_canvas); + void canvas_light_set_enabled(RID p_light, bool p_enabled); + void canvas_light_set_scale(RID p_light, float p_scale); + void canvas_light_set_transform(RID p_light, const Transform2D &p_transform); + void canvas_light_set_texture(RID p_light, RID p_texture); + void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset); + void canvas_light_set_color(RID p_light, const Color &p_color); + void canvas_light_set_height(RID p_light, float p_height); + void canvas_light_set_energy(RID p_light, float p_energy); + void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z); + void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer); + void canvas_light_set_item_cull_mask(RID p_light, int p_mask); + void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask); + + void canvas_light_set_mode(RID p_light, RS::CanvasLightMode p_mode); + + void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); + void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); + void canvas_light_set_shadow_filter(RID p_light, RS::CanvasLightShadowFilter p_filter); + void canvas_light_set_shadow_color(RID p_light, const Color &p_color); + void canvas_light_set_shadow_smooth(RID p_light, float p_smooth); + + RID canvas_light_occluder_create(); + void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas); + void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled); + void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon); + void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform); + void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask); + + RID canvas_occluder_polygon_create(); + void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector &p_shape, bool p_closed); + void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector &p_shape); + + void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, RS::CanvasOccluderPolygonCullMode p_mode); + + bool free(RID p_rid); + RenderingServerCanvas(); + ~RenderingServerCanvas(); +}; + +#endif // VISUALSERVERCANVAS_H diff --git a/servers/rendering/rendering_server_globals.cpp b/servers/rendering/rendering_server_globals.cpp new file mode 100644 index 0000000000..60183956e0 --- /dev/null +++ b/servers/rendering/rendering_server_globals.cpp @@ -0,0 +1,40 @@ +/*************************************************************************/ +/* rendering_server_globals.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server_globals.h" + +RasterizerStorage *RenderingServerGlobals::storage = NULL; +RasterizerCanvas *RenderingServerGlobals::canvas_render = NULL; +RasterizerScene *RenderingServerGlobals::scene_render = NULL; +Rasterizer *RenderingServerGlobals::rasterizer = NULL; + +RenderingServerCanvas *RenderingServerGlobals::canvas = NULL; +RenderingServerViewport *RenderingServerGlobals::viewport = NULL; +RenderingServerScene *RenderingServerGlobals::scene = NULL; diff --git a/servers/rendering/rendering_server_globals.h b/servers/rendering/rendering_server_globals.h new file mode 100644 index 0000000000..79abc55fea --- /dev/null +++ b/servers/rendering/rendering_server_globals.h @@ -0,0 +1,54 @@ +/*************************************************************************/ +/* rendering_server_globals.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDERING_SERVER_GLOBALS_H +#define RENDERING_SERVER_GLOBALS_H + +#include "rasterizer.h" + +class RenderingServerCanvas; +class RenderingServerViewport; +class RenderingServerScene; + +class RenderingServerGlobals { +public: + static RasterizerStorage *storage; + static RasterizerCanvas *canvas_render; + static RasterizerScene *scene_render; + static Rasterizer *rasterizer; + + static RenderingServerCanvas *canvas; + static RenderingServerViewport *viewport; + static RenderingServerScene *scene; +}; + +#define RSG RenderingServerGlobals + +#endif // RENDERING_SERVER_GLOBALS_H diff --git a/servers/rendering/rendering_server_raster.cpp b/servers/rendering/rendering_server_raster.cpp new file mode 100644 index 0000000000..9b769b46fc --- /dev/null +++ b/servers/rendering/rendering_server_raster.cpp @@ -0,0 +1,271 @@ +/*************************************************************************/ +/* rendering_server_raster.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server_raster.h" + +#include "core/io/marshalls.h" +#include "core/os/os.h" +#include "core/project_settings.h" +#include "core/sort_array.h" +#include "rendering_server_canvas.h" +#include "rendering_server_globals.h" +#include "rendering_server_scene.h" + +// careful, these may run in different threads than the visual server + +int RenderingServerRaster::changes = 0; + +/* BLACK BARS */ + +void RenderingServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) { + + black_margin[MARGIN_LEFT] = p_left; + black_margin[MARGIN_TOP] = p_top; + black_margin[MARGIN_RIGHT] = p_right; + black_margin[MARGIN_BOTTOM] = p_bottom; +} + +void RenderingServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) { + + black_image[MARGIN_LEFT] = p_left; + black_image[MARGIN_TOP] = p_top; + black_image[MARGIN_RIGHT] = p_right; + black_image[MARGIN_BOTTOM] = p_bottom; +} + +void RenderingServerRaster::_draw_margins() { + + RSG::canvas_render->draw_window_margins(black_margin, black_image); +}; + +/* FREE */ + +void RenderingServerRaster::free(RID p_rid) { + + if (RSG::storage->free(p_rid)) + return; + if (RSG::canvas->free(p_rid)) + return; + if (RSG::viewport->free(p_rid)) + return; + if (RSG::scene->free(p_rid)) + return; + if (RSG::scene_render->free(p_rid)) + return; +} + +/* EVENT QUEUING */ + +void RenderingServerRaster::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) { + + ERR_FAIL_NULL(p_where); + FrameDrawnCallbacks fdc; + fdc.object = p_where->get_instance_id(); + fdc.method = p_method; + fdc.param = p_userdata; + + frame_drawn_callbacks.push_back(fdc); +} + +void RenderingServerRaster::draw(bool p_swap_buffers, double frame_step) { + + //needs to be done before changes is reset to 0, to not force the editor to redraw + RS::get_singleton()->emit_signal("frame_pre_draw"); + + changes = 0; + + RSG::rasterizer->begin_frame(frame_step); + + TIMESTAMP_BEGIN() + + RSG::scene_render->update(); //update scenes stuff before updating instances + + RSG::scene->update_dirty_instances(); //update scene stuff + + RSG::scene->render_probes(); + RSG::viewport->draw_viewports(); + RSG::canvas_render->update(); + + _draw_margins(); + RSG::rasterizer->end_frame(p_swap_buffers); + + while (frame_drawn_callbacks.front()) { + + Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object); + if (obj) { + Callable::CallError ce; + const Variant *v = &frame_drawn_callbacks.front()->get().param; + obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce); + if (ce.error != Callable::CallError::CALL_OK) { + String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce); + ERR_PRINT("Error calling frame drawn function: " + err); + } + } + + frame_drawn_callbacks.pop_front(); + } + RS::get_singleton()->emit_signal("frame_post_draw"); + + if (RSG::storage->get_captured_timestamps_count()) { + Vector new_profile; + new_profile.resize(RSG::storage->get_captured_timestamps_count()); + + uint64_t base_cpu = RSG::storage->get_captured_timestamp_cpu_time(0); + uint64_t base_gpu = RSG::storage->get_captured_timestamp_gpu_time(0); + for (uint32_t i = 0; i < RSG::storage->get_captured_timestamps_count(); i++) { + uint64_t time_cpu = RSG::storage->get_captured_timestamp_cpu_time(i) - base_cpu; + uint64_t time_gpu = RSG::storage->get_captured_timestamp_gpu_time(i) - base_gpu; + new_profile.write[i].gpu_msec = float(time_gpu / 1000) / 1000.0; + new_profile.write[i].cpu_msec = float(time_cpu) / 1000.0; + new_profile.write[i].name = RSG::storage->get_captured_timestamp_name(i); + } + + frame_profile = new_profile; + } + + frame_profile_frame = RSG::storage->get_captured_timestamps_frame(); +} +void RenderingServerRaster::sync() { +} +bool RenderingServerRaster::has_changed() const { + + return changes > 0; +} +void RenderingServerRaster::init() { + + RSG::rasterizer->initialize(); +} +void RenderingServerRaster::finish() { + + if (test_cube.is_valid()) { + free(test_cube); + } + + RSG::rasterizer->finalize(); +} + +/* STATUS INFORMATION */ + +int RenderingServerRaster::get_render_info(RenderInfo p_info) { + + return RSG::storage->get_render_info(p_info); +} + +String RenderingServerRaster::get_video_adapter_name() const { + + return RSG::storage->get_video_adapter_name(); +} + +String RenderingServerRaster::get_video_adapter_vendor() const { + + return RSG::storage->get_video_adapter_vendor(); +} + +void RenderingServerRaster::set_frame_profiling_enabled(bool p_enable) { + RSG::storage->capturing_timestamps = p_enable; +} + +uint64_t RenderingServerRaster::get_frame_profile_frame() { + return frame_profile_frame; +} + +Vector RenderingServerRaster::get_frame_profile() { + return frame_profile; +} + +/* TESTING */ + +void RenderingServerRaster::set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { + + redraw_request(); + RSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter); +} +void RenderingServerRaster::set_default_clear_color(const Color &p_color) { + RSG::viewport->set_default_clear_color(p_color); +} + +bool RenderingServerRaster::has_feature(Features p_feature) const { + + return false; +} + +RID RenderingServerRaster::get_test_cube() { + if (!test_cube.is_valid()) { + test_cube = _make_test_cube(); + } + return test_cube; +} + +bool RenderingServerRaster::has_os_feature(const String &p_feature) const { + + return RSG::storage->has_os_feature(p_feature); +} + +void RenderingServerRaster::set_debug_generate_wireframes(bool p_generate) { + + RSG::storage->set_debug_generate_wireframes(p_generate); +} + +void RenderingServerRaster::call_set_use_vsync(bool p_enable) { + DisplayServer::get_singleton()->_set_use_vsync(p_enable); +} + +bool RenderingServerRaster::is_low_end() const { + // FIXME: Commented out when rebasing vulkan branch on master, + // causes a crash, it seems rasterizer is not initialized yet the + // first time it's called. + //return RSG::rasterizer->is_low_end(); + return false; +} +RenderingServerRaster::RenderingServerRaster() { + + RSG::canvas = memnew(RenderingServerCanvas); + RSG::viewport = memnew(RenderingServerViewport); + RSG::scene = memnew(RenderingServerScene); + RSG::rasterizer = Rasterizer::create(); + RSG::storage = RSG::rasterizer->get_storage(); + RSG::canvas_render = RSG::rasterizer->get_canvas(); + RSG::scene_render = RSG::rasterizer->get_scene(); + + frame_profile_frame = 0; + + for (int i = 0; i < 4; i++) { + black_margin[i] = 0; + black_image[i] = RID(); + } +} + +RenderingServerRaster::~RenderingServerRaster() { + + memdelete(RSG::canvas); + memdelete(RSG::viewport); + memdelete(RSG::rasterizer); + memdelete(RSG::scene); +} diff --git a/servers/rendering/rendering_server_raster.h b/servers/rendering/rendering_server_raster.h new file mode 100644 index 0000000000..24fbe4577a --- /dev/null +++ b/servers/rendering/rendering_server_raster.h @@ -0,0 +1,761 @@ +/*************************************************************************/ +/* rendering_server_raster.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDERING_SERVER_RASTER_H +#define RENDERING_SERVER_RASTER_H + +#include "core/math/octree.h" +#include "rendering_server_canvas.h" +#include "rendering_server_globals.h" +#include "rendering_server_scene.h" +#include "rendering_server_viewport.h" +#include "servers/rendering/rasterizer.h" +#include "servers/rendering_server.h" + +class RenderingServerRaster : public RenderingServer { + + enum { + + MAX_INSTANCE_CULL = 8192, + MAX_INSTANCE_LIGHTS = 4, + LIGHT_CACHE_DIRTY = -1, + MAX_LIGHTS_CULLED = 256, + MAX_ROOM_CULL = 32, + MAX_EXTERIOR_PORTALS = 128, + MAX_LIGHT_SAMPLERS = 256, + INSTANCE_ROOMLESS_MASK = (1 << 20) + + }; + + static int changes; + RID test_cube; + + int black_margin[4]; + RID black_image[4]; + + struct FrameDrawnCallbacks { + + ObjectID object; + StringName method; + Variant param; + }; + + List frame_drawn_callbacks; + + void _draw_margins(); + static void _changes_changed() {} + + uint64_t frame_profile_frame; + Vector frame_profile; + +public: + //if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed() + //#define DEBUG_CHANGES + +#ifdef DEBUG_CHANGES + _FORCE_INLINE_ static void redraw_request() { + changes++; + _changes_changed(); + } + +#define DISPLAY_CHANGED \ + changes++; \ + _changes_changed(); + +#else + _FORCE_INLINE_ static void redraw_request() { changes++; } + +#define DISPLAY_CHANGED \ + changes++; +#endif + +#define BIND0R(m_r, m_name) \ + m_r m_name() { return BINDBASE->m_name(); } +#define BIND1R(m_r, m_name, m_type1) \ + m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); } +#define BIND1RC(m_r, m_name, m_type1) \ + m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); } +#define BIND2R(m_r, m_name, m_type1, m_type2) \ + m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); } +#define BIND2RC(m_r, m_name, m_type1, m_type2) \ + m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); } +#define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); } +#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ + m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } + +#define BIND1(m_name, m_type1) \ + void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); } +#define BIND2(m_name, m_type1, m_type2) \ + void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); } +#define BIND2C(m_name, m_type1, m_type2) \ + void m_name(m_type1 arg1, m_type2 arg2) const { BINDBASE->m_name(arg1, arg2); } +#define BIND3(m_name, m_type1, m_type2, m_type3) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3); } +#define BIND4(m_name, m_type1, m_type2, m_type3, m_type4) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4); } +#define BIND5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); } +#define BIND6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } +#define BIND7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } +#define BIND8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } +#define BIND9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } +#define BIND10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } +#define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } +#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } +#define BIND13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } +#define BIND14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); } +#define BIND15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \ + void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); } + +//from now on, calls forwarded to this singleton +#define BINDBASE RSG::storage + + /* TEXTURE API */ + + //these go pass-through, as they can be called from any thread + BIND1R(RID, texture_2d_create, const Ref &) + BIND2R(RID, texture_2d_layered_create, const Vector> &, TextureLayeredType) + BIND1R(RID, texture_3d_create, const Vector> &) + BIND1R(RID, texture_proxy_create, RID) + + //goes pass-through + BIND3(texture_2d_update_immediate, RID, const Ref &, int) + //these go through command queue if they are in another thread + BIND3(texture_2d_update, RID, const Ref &, int) + BIND4(texture_3d_update, RID, const Ref &, int, int) + BIND2(texture_proxy_update, RID, RID) + + //these also go pass-through + BIND0R(RID, texture_2d_placeholder_create) + BIND0R(RID, texture_2d_layered_placeholder_create) + BIND0R(RID, texture_3d_placeholder_create) + + BIND1RC(Ref, texture_2d_get, RID) + BIND2RC(Ref, texture_2d_layer_get, RID, int) + BIND3RC(Ref, texture_3d_slice_get, RID, int, int) + + BIND2(texture_replace, RID, RID) + + BIND3(texture_set_size_override, RID, int, int) +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + BIND2(texture_bind, RID, uint32_t) +#endif + + BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *) + BIND3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *) + BIND3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *) + + BIND2(texture_set_path, RID, const String &) + BIND1RC(String, texture_get_path, RID) + BIND1(texture_debug_usage, List *) + + BIND2(texture_set_force_redraw_if_visible, RID, bool) + + /* SHADER API */ + + BIND0R(RID, shader_create) + + BIND2(shader_set_code, RID, const String &) + BIND1RC(String, shader_get_code, RID) + + BIND2C(shader_get_param_list, RID, List *) + + BIND3(shader_set_default_texture_param, RID, const StringName &, RID) + BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &) + BIND2RC(Variant, shader_get_param_default, RID, const StringName &) + + /* COMMON MATERIAL API */ + + BIND0R(RID, material_create) + + BIND2(material_set_shader, RID, RID) + + BIND3(material_set_param, RID, const StringName &, const Variant &) + BIND2RC(Variant, material_get_param, RID, const StringName &) + + BIND2(material_set_render_priority, RID, int) + BIND2(material_set_next_pass, RID, RID) + + /* MESH API */ + + virtual RID mesh_create_from_surfaces(const Vector &p_surfaces) { + RID mesh = mesh_create(); + for (int i = 0; i < p_surfaces.size(); i++) { + mesh_add_surface(mesh, p_surfaces[i]); + } + return mesh; + } + + BIND0R(RID, mesh_create) + + BIND2(mesh_add_surface, RID, const SurfaceData &) + + BIND1RC(int, mesh_get_blend_shape_count, RID) + + BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode) + BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID) + + BIND4(mesh_surface_update_region, RID, int, int, const Vector &) + + BIND3(mesh_surface_set_material, RID, int, RID) + BIND2RC(RID, mesh_surface_get_material, RID, int) + + BIND2RC(SurfaceData, mesh_get_surface, RID, int) + + BIND1RC(int, mesh_get_surface_count, RID) + + BIND2(mesh_set_custom_aabb, RID, const AABB &) + BIND1RC(AABB, mesh_get_custom_aabb, RID) + + BIND1(mesh_clear, RID) + + /* MULTIMESH API */ + + BIND0R(RID, multimesh_create) + + BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool) + BIND1RC(int, multimesh_get_instance_count, RID) + + BIND2(multimesh_set_mesh, RID, RID) + BIND3(multimesh_instance_set_transform, RID, int, const Transform &) + BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &) + BIND3(multimesh_instance_set_color, RID, int, const Color &) + BIND3(multimesh_instance_set_custom_data, RID, int, const Color &) + + BIND1RC(RID, multimesh_get_mesh, RID) + BIND1RC(AABB, multimesh_get_aabb, RID) + + BIND2RC(Transform, multimesh_instance_get_transform, RID, int) + BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int) + BIND2RC(Color, multimesh_instance_get_color, RID, int) + BIND2RC(Color, multimesh_instance_get_custom_data, RID, int) + + BIND2(multimesh_set_buffer, RID, const Vector &) + BIND1RC(Vector, multimesh_get_buffer, RID) + + BIND2(multimesh_set_visible_instances, RID, int) + BIND1RC(int, multimesh_get_visible_instances, RID) + + /* IMMEDIATE API */ + + BIND0R(RID, immediate_create) + BIND3(immediate_begin, RID, PrimitiveType, RID) + BIND2(immediate_vertex, RID, const Vector3 &) + BIND2(immediate_normal, RID, const Vector3 &) + BIND2(immediate_tangent, RID, const Plane &) + BIND2(immediate_color, RID, const Color &) + BIND2(immediate_uv, RID, const Vector2 &) + BIND2(immediate_uv2, RID, const Vector2 &) + BIND1(immediate_end, RID) + BIND1(immediate_clear, RID) + BIND2(immediate_set_material, RID, RID) + BIND1RC(RID, immediate_get_material, RID) + + /* SKELETON API */ + + BIND0R(RID, skeleton_create) + BIND3(skeleton_allocate, RID, int, bool) + BIND1RC(int, skeleton_get_bone_count, RID) + BIND3(skeleton_bone_set_transform, RID, int, const Transform &) + BIND2RC(Transform, skeleton_bone_get_transform, RID, int) + BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) + BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) + BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &) + + /* Light API */ + + BIND0R(RID, directional_light_create) + BIND0R(RID, omni_light_create) + BIND0R(RID, spot_light_create) + + BIND2(light_set_color, RID, const Color &) + BIND3(light_set_param, RID, LightParam, float) + BIND2(light_set_shadow, RID, bool) + BIND2(light_set_shadow_color, RID, const Color &) + BIND2(light_set_projector, RID, RID) + BIND2(light_set_negative, RID, bool) + BIND2(light_set_cull_mask, RID, uint32_t) + BIND2(light_set_reverse_cull_face_mode, RID, bool) + BIND2(light_set_use_gi, RID, bool) + + BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) + + BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) + BIND2(light_directional_set_blend_splits, RID, bool) + BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) + + /* PROBE API */ + + BIND0R(RID, reflection_probe_create) + + BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode) + BIND2(reflection_probe_set_intensity, RID, float) + BIND2(reflection_probe_set_interior_ambient, RID, const Color &) + BIND2(reflection_probe_set_interior_ambient_energy, RID, float) + BIND2(reflection_probe_set_interior_ambient_probe_contribution, RID, float) + BIND2(reflection_probe_set_max_distance, RID, float) + BIND2(reflection_probe_set_extents, RID, const Vector3 &) + BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &) + BIND2(reflection_probe_set_as_interior, RID, bool) + BIND2(reflection_probe_set_enable_box_projection, RID, bool) + BIND2(reflection_probe_set_enable_shadows, RID, bool) + BIND2(reflection_probe_set_cull_mask, RID, uint32_t) + BIND2(reflection_probe_set_resolution, RID, int) + + /* BAKED LIGHT API */ + + BIND0R(RID, gi_probe_create) + + BIND8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector &, const Vector &, const Vector &, const Vector &) + + BIND1RC(AABB, gi_probe_get_bounds, RID) + BIND1RC(Vector3i, gi_probe_get_octree_size, RID) + BIND1RC(Vector, gi_probe_get_octree_cells, RID) + BIND1RC(Vector, gi_probe_get_data_cells, RID) + BIND1RC(Vector, gi_probe_get_distance_field, RID) + BIND1RC(Vector, gi_probe_get_level_counts, RID) + BIND1RC(Transform, gi_probe_get_to_cell_xform, RID) + + BIND2(gi_probe_set_dynamic_range, RID, float) + BIND1RC(float, gi_probe_get_dynamic_range, RID) + + BIND2(gi_probe_set_propagation, RID, float) + BIND1RC(float, gi_probe_get_propagation, RID) + + BIND2(gi_probe_set_energy, RID, float) + BIND1RC(float, gi_probe_get_energy, RID) + + BIND2(gi_probe_set_ao, RID, float) + BIND1RC(float, gi_probe_get_ao, RID) + + BIND2(gi_probe_set_ao_size, RID, float) + BIND1RC(float, gi_probe_get_ao_size, RID) + + BIND2(gi_probe_set_bias, RID, float) + BIND1RC(float, gi_probe_get_bias, RID) + + BIND2(gi_probe_set_normal_bias, RID, float) + BIND1RC(float, gi_probe_get_normal_bias, RID) + + BIND2(gi_probe_set_interior, RID, bool) + BIND1RC(bool, gi_probe_is_interior, RID) + + BIND2(gi_probe_set_use_two_bounces, RID, bool) + BIND1RC(bool, gi_probe_is_using_two_bounces, RID) + + BIND2(gi_probe_set_anisotropy_strength, RID, float) + BIND1RC(float, gi_probe_get_anisotropy_strength, RID) + + /* LIGHTMAP CAPTURE */ + + BIND0R(RID, lightmap_capture_create) + + BIND2(lightmap_capture_set_bounds, RID, const AABB &) + BIND1RC(AABB, lightmap_capture_get_bounds, RID) + + BIND2(lightmap_capture_set_octree, RID, const Vector &) + BIND1RC(Vector, lightmap_capture_get_octree, RID) + + BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) + BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) + BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int) + BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) + + BIND2(lightmap_capture_set_energy, RID, float) + BIND1RC(float, lightmap_capture_get_energy, RID) + + /* PARTICLES */ + + BIND0R(RID, particles_create) + + BIND2(particles_set_emitting, RID, bool) + BIND1R(bool, particles_get_emitting, RID) + BIND2(particles_set_amount, RID, int) + BIND2(particles_set_lifetime, RID, float) + BIND2(particles_set_one_shot, RID, bool) + BIND2(particles_set_pre_process_time, RID, float) + BIND2(particles_set_explosiveness_ratio, RID, float) + BIND2(particles_set_randomness_ratio, RID, float) + BIND2(particles_set_custom_aabb, RID, const AABB &) + BIND2(particles_set_speed_scale, RID, float) + BIND2(particles_set_use_local_coordinates, RID, bool) + BIND2(particles_set_process_material, RID, RID) + BIND2(particles_set_fixed_fps, RID, int) + BIND2(particles_set_fractional_delta, RID, bool) + BIND1R(bool, particles_is_inactive, RID) + BIND1(particles_request_process, RID) + BIND1(particles_restart, RID) + + BIND2(particles_set_draw_order, RID, RS::ParticlesDrawOrder) + + BIND2(particles_set_draw_passes, RID, int) + BIND3(particles_set_draw_pass_mesh, RID, int, RID) + + BIND1R(AABB, particles_get_current_aabb, RID) + BIND2(particles_set_emission_transform, RID, const Transform &) + +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE RSG::scene + + /* CAMERA API */ + + BIND0R(RID, camera_create) + BIND4(camera_set_perspective, RID, float, float, float) + BIND4(camera_set_orthogonal, RID, float, float, float) + BIND5(camera_set_frustum, RID, float, Vector2, float, float) + BIND2(camera_set_transform, RID, const Transform &) + BIND2(camera_set_cull_mask, RID, uint32_t) + BIND2(camera_set_environment, RID, RID) + BIND2(camera_set_camera_effects, RID, RID) + BIND2(camera_set_use_vertical_aspect, RID, bool) + +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE RSG::viewport + + /* VIEWPORT TARGET API */ + + BIND0R(RID, viewport_create) + + BIND2(viewport_set_use_arvr, RID, bool) + BIND3(viewport_set_size, RID, int, int) + + BIND2(viewport_set_active, RID, bool) + BIND2(viewport_set_parent_viewport, RID, RID) + + BIND2(viewport_set_clear_mode, RID, ViewportClearMode) + + BIND3(viewport_attach_to_screen, RID, const Rect2 &, int) + BIND2(viewport_set_render_direct_to_screen, RID, bool) + + BIND2(viewport_set_update_mode, RID, ViewportUpdateMode) + BIND2(viewport_set_vflip, RID, bool) + + BIND1RC(RID, viewport_get_texture, RID) + + BIND2(viewport_set_hide_scenario, RID, bool) + BIND2(viewport_set_hide_canvas, RID, bool) + BIND2(viewport_set_disable_environment, RID, bool) + + BIND2(viewport_attach_camera, RID, RID) + BIND2(viewport_set_scenario, RID, RID) + BIND2(viewport_attach_canvas, RID, RID) + + BIND2(viewport_remove_canvas, RID, RID) + BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &) + BIND2(viewport_set_transparent_background, RID, bool) + + BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &) + BIND4(viewport_set_canvas_stacking, RID, RID, int, int) + BIND2(viewport_set_shadow_atlas_size, RID, int) + BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) + BIND2(viewport_set_msaa, RID, ViewportMSAA) + + BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo) + BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw) + + /* ENVIRONMENT API */ + +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE RSG::scene_render + + BIND1(directional_shadow_atlas_set_size, int) + + /* SKY API */ + + BIND0R(RID, sky_create) + BIND2(sky_set_radiance_size, RID, int) + BIND2(sky_set_mode, RID, SkyMode) + BIND2(sky_set_material, RID, RID) + + BIND0R(RID, environment_create) + + BIND2(environment_set_background, RID, EnvironmentBG) + BIND2(environment_set_sky, RID, RID) + BIND2(environment_set_sky_custom_fov, RID, float) + BIND2(environment_set_sky_orientation, RID, const Basis &) + BIND2(environment_set_bg_color, RID, const Color &) + BIND2(environment_set_bg_energy, RID, float) + BIND2(environment_set_canvas_max_layer, RID, int) + BIND7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &) + +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + BIND2(environment_set_camera_feed_id, RID, int) +#endif + BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool) + BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) + BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) + + BIND12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) + + BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) + + BIND6(environment_set_adjustment, RID, bool, float, float, float, RID) + + BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float) + BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) + BIND5(environment_set_fog_height, RID, bool, float, float, float) + + BIND2(screen_space_roughness_limiter_set_active, bool, float) + + /* CAMERA EFFECTS */ + + BIND0R(RID, camera_effects_create) + + BIND2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool) + BIND1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape) + + BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) + BIND3(camera_effects_set_custom_exposure, RID, bool, float) + + /* SCENARIO API */ + +#undef BINDBASE +#define BINDBASE RSG::scene + + BIND0R(RID, scenario_create) + + BIND2(scenario_set_debug, RID, ScenarioDebugMode) + BIND2(scenario_set_environment, RID, RID) + BIND2(scenario_set_camera_effects, RID, RID) + BIND2(scenario_set_fallback_environment, RID, RID) + + /* INSTANCING API */ + BIND0R(RID, instance_create) + + BIND2(instance_set_base, RID, RID) + BIND2(instance_set_scenario, RID, RID) + BIND2(instance_set_layer_mask, RID, uint32_t) + BIND2(instance_set_transform, RID, const Transform &) + BIND2(instance_attach_object_instance_id, RID, ObjectID) + BIND3(instance_set_blend_shape_weight, RID, int, float) + BIND3(instance_set_surface_material, RID, int, RID) + BIND2(instance_set_visible, RID, bool) + BIND3(instance_set_use_lightmap, RID, RID, RID) + + BIND2(instance_set_custom_aabb, RID, AABB) + + BIND2(instance_attach_skeleton, RID, RID) + BIND2(instance_set_exterior, RID, bool) + + BIND2(instance_set_extra_visibility_margin, RID, real_t) + + // don't use these in a game! + BIND2RC(Vector, instances_cull_aabb, const AABB &, RID) + BIND3RC(Vector, instances_cull_ray, const Vector3 &, const Vector3 &, RID) + BIND2RC(Vector, instances_cull_convex, const Vector &, RID) + + BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool) + BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting) + BIND2(instance_geometry_set_material_override, RID, RID) + + BIND5(instance_geometry_set_draw_range, RID, float, float, float, float) + BIND2(instance_geometry_set_as_instance_lod, RID, RID) + +#undef BINDBASE +//from now on, calls forwarded to this singleton +#define BINDBASE RSG::canvas + + /* CANVAS (2D) */ + + BIND0R(RID, canvas_create) + BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &) + BIND2(canvas_set_modulate, RID, const Color &) + BIND3(canvas_set_parent, RID, RID, float) + BIND1(canvas_set_disable_scale, bool) + + BIND0R(RID, canvas_item_create) + BIND2(canvas_item_set_parent, RID, RID) + + BIND2(canvas_item_set_visible, RID, bool) + BIND2(canvas_item_set_light_mask, RID, int) + + BIND2(canvas_item_set_update_when_visible, RID, bool) + + BIND2(canvas_item_set_transform, RID, const Transform2D &) + BIND2(canvas_item_set_clip, RID, bool) + BIND2(canvas_item_set_distance_field_mode, RID, bool) + BIND3(canvas_item_set_custom_rect, RID, bool, const Rect2 &) + BIND2(canvas_item_set_modulate, RID, const Color &) + BIND2(canvas_item_set_self_modulate, RID, const Color &) + + BIND2(canvas_item_set_draw_behind_parent, RID, bool) + + BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) + BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) + + BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) + BIND4(canvas_item_add_polyline, RID, const Vector &, const Vector &, float) + BIND4(canvas_item_add_multiline, RID, const Vector &, const Vector &, float) + BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) + BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) + BIND11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND11(canvas_item_add_primitive, RID, const Vector &, const Vector &, const Vector &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND10(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND14(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + BIND2(canvas_item_add_set_transform, RID, const Transform2D &) + BIND2(canvas_item_add_clip_ignore, RID, bool) + BIND2(canvas_item_set_sort_children_by_y, RID, bool) + BIND2(canvas_item_set_z_index, RID, int) + BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool) + BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) + BIND2(canvas_item_attach_skeleton, RID, RID) + + BIND1(canvas_item_clear, RID) + BIND2(canvas_item_set_draw_index, RID, int) + + BIND2(canvas_item_set_material, RID, RID) + + BIND2(canvas_item_set_use_parent_material, RID, bool) + + BIND0R(RID, canvas_light_create) + BIND2(canvas_light_attach_to_canvas, RID, RID) + BIND2(canvas_light_set_enabled, RID, bool) + BIND2(canvas_light_set_scale, RID, float) + BIND2(canvas_light_set_transform, RID, const Transform2D &) + BIND2(canvas_light_set_texture, RID, RID) + BIND2(canvas_light_set_texture_offset, RID, const Vector2 &) + BIND2(canvas_light_set_color, RID, const Color &) + BIND2(canvas_light_set_height, RID, float) + BIND2(canvas_light_set_energy, RID, float) + BIND3(canvas_light_set_z_range, RID, int, int) + BIND3(canvas_light_set_layer_range, RID, int, int) + BIND2(canvas_light_set_item_cull_mask, RID, int) + BIND2(canvas_light_set_item_shadow_cull_mask, RID, int) + + BIND2(canvas_light_set_mode, RID, CanvasLightMode) + + BIND2(canvas_light_set_shadow_enabled, RID, bool) + BIND2(canvas_light_set_shadow_buffer_size, RID, int) + BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) + BIND2(canvas_light_set_shadow_color, RID, const Color &) + BIND2(canvas_light_set_shadow_smooth, RID, float) + + BIND0R(RID, canvas_light_occluder_create) + BIND2(canvas_light_occluder_attach_to_canvas, RID, RID) + BIND2(canvas_light_occluder_set_enabled, RID, bool) + BIND2(canvas_light_occluder_set_polygon, RID, RID) + BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &) + BIND2(canvas_light_occluder_set_light_mask, RID, int) + + BIND0R(RID, canvas_occluder_polygon_create) + BIND3(canvas_occluder_polygon_set_shape, RID, const Vector &, bool) + BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector &) + + BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) + + /* BLACK BARS */ + + virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom); + virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom); + + /* FREE */ + + virtual void free(RID p_rid); ///< free RIDs associated with the visual server + + /* EVENT QUEUING */ + + virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata); + + virtual void draw(bool p_swap_buffers, double frame_step); + virtual void sync(); + virtual bool has_changed() const; + virtual void init(); + virtual void finish(); + + /* STATUS INFORMATION */ + + virtual int get_render_info(RenderInfo p_info); + virtual String get_video_adapter_name() const; + virtual String get_video_adapter_vendor() const; + + virtual void set_frame_profiling_enabled(bool p_enable); + virtual Vector get_frame_profile(); + virtual uint64_t get_frame_profile_frame(); + + virtual RID get_test_cube(); + + /* TESTING */ + + virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true); + virtual void set_default_clear_color(const Color &p_color); + + virtual bool has_feature(Features p_feature) const; + + virtual bool has_os_feature(const String &p_feature) const; + virtual void set_debug_generate_wireframes(bool p_generate); + + virtual void call_set_use_vsync(bool p_enable); + + virtual bool is_low_end() const; + + RenderingServerRaster(); + ~RenderingServerRaster(); + +#undef DISPLAY_CHANGED + +#undef BIND0R +#undef BIND1RC +#undef BIND2RC +#undef BIND3RC +#undef BIND4RC + +#undef BIND1 +#undef BIND2 +#undef BIND3 +#undef BIND4 +#undef BIND5 +#undef BIND6 +#undef BIND7 +#undef BIND8 +#undef BIND9 +#undef BIND10 +}; + +#endif diff --git a/servers/rendering/rendering_server_scene.cpp b/servers/rendering/rendering_server_scene.cpp new file mode 100644 index 0000000000..0530846e95 --- /dev/null +++ b/servers/rendering/rendering_server_scene.cpp @@ -0,0 +1,2839 @@ +/*************************************************************************/ +/* rendering_server_scene.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server_scene.h" + +#include "core/os/os.h" +#include "rendering_server_globals.h" +#include "rendering_server_raster.h" + +#include + +/* CAMERA API */ + +RID RenderingServerScene::camera_create() { + + Camera *camera = memnew(Camera); + return camera_owner.make_rid(camera); +} + +void RenderingServerScene::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::PERSPECTIVE; + camera->fov = p_fovy_degrees; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + +void RenderingServerScene::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::ORTHOGONAL; + camera->size = p_size; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + +void RenderingServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->type = Camera::FRUSTUM; + camera->size = p_size; + camera->offset = p_offset; + camera->znear = p_z_near; + camera->zfar = p_z_far; +} + +void RenderingServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->transform = p_transform.orthonormalized(); +} + +void RenderingServerScene::camera_set_cull_mask(RID p_camera, uint32_t p_layers) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + camera->visible_layers = p_layers; +} + +void RenderingServerScene::camera_set_environment(RID p_camera, RID p_env) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->env = p_env; +} + +void RenderingServerScene::camera_set_camera_effects(RID p_camera, RID p_fx) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->effects = p_fx; +} + +void RenderingServerScene::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) { + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + camera->vaspect = p_enable; +} + +/* SCENARIO API */ + +void *RenderingServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) { + + //RenderingServerScene *self = (RenderingServerScene*)p_self; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A, B); //lesser always first + } + + if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceLightData *light = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + InstanceLightData::PairInfo pinfo; + pinfo.geometry = A; + pinfo.L = geom->lighting.push_back(B); + + List::Element *E = light->geometries.push_back(pinfo); + + if (geom->can_cast_shadows) { + + light->shadow_dirty = true; + } + geom->lighting_dirty = true; + + return E; //this element should make freeing faster + } else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceReflectionProbeData *reflection_probe = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + InstanceReflectionProbeData::PairInfo pinfo; + pinfo.geometry = A; + pinfo.L = geom->reflection_probes.push_back(B); + + List::Element *E = reflection_probe->geometries.push_back(pinfo); + + geom->reflection_dirty = true; + + return E; //this element should make freeing faster + } else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceLightmapCaptureData *lightmap_capture = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + InstanceLightmapCaptureData::PairInfo pinfo; + pinfo.geometry = A; + pinfo.L = geom->lightmap_captures.push_back(B); + + List::Element *E = lightmap_capture->geometries.push_back(pinfo); + ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture + + return E; //this element should make freeing faster + } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceGIProbeData *gi_probe = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + InstanceGIProbeData::PairInfo pinfo; + pinfo.geometry = A; + pinfo.L = geom->gi_probes.push_back(B); + + List::Element *E; + if (A->dynamic_gi) { + E = gi_probe->dynamic_geometries.push_back(pinfo); + } else { + E = gi_probe->geometries.push_back(pinfo); + } + + geom->gi_probes_dirty = true; + + return E; //this element should make freeing faster + + } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { + + InstanceGIProbeData *gi_probe = static_cast(B->base_data); + return gi_probe->lights.insert(A); + } + + return NULL; +} +void RenderingServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) { + + //RenderingServerScene *self = (RenderingServerScene*)p_self; + Instance *A = p_A; + Instance *B = p_B; + + //instance indices are designed so greater always contains lesser + if (A->base_type > B->base_type) { + SWAP(A, B); //lesser always first + } + + if (B->base_type == RS::INSTANCE_LIGHT && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceLightData *light = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + List::Element *E = reinterpret_cast::Element *>(udata); + + geom->lighting.erase(E->get().L); + light->geometries.erase(E); + + if (geom->can_cast_shadows) { + light->shadow_dirty = true; + } + geom->lighting_dirty = true; + + } else if (B->base_type == RS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceReflectionProbeData *reflection_probe = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + List::Element *E = reinterpret_cast::Element *>(udata); + + geom->reflection_probes.erase(E->get().L); + reflection_probe->geometries.erase(E); + + geom->reflection_dirty = true; + } else if (B->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceLightmapCaptureData *lightmap_capture = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + List::Element *E = reinterpret_cast::Element *>(udata); + + geom->lightmap_captures.erase(E->get().L); + lightmap_capture->geometries.erase(E); + ((RenderingServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture + + } else if (B->base_type == RS::INSTANCE_GI_PROBE && ((1 << A->base_type) & RS::INSTANCE_GEOMETRY_MASK)) { + + InstanceGIProbeData *gi_probe = static_cast(B->base_data); + InstanceGeometryData *geom = static_cast(A->base_data); + + List::Element *E = reinterpret_cast::Element *>(udata); + + geom->gi_probes.erase(E->get().L); + if (A->dynamic_gi) { + gi_probe->dynamic_geometries.erase(E); + } else { + gi_probe->geometries.erase(E); + } + + geom->gi_probes_dirty = true; + + } else if (B->base_type == RS::INSTANCE_GI_PROBE && A->base_type == RS::INSTANCE_LIGHT) { + + InstanceGIProbeData *gi_probe = static_cast(B->base_data); + Set::Element *E = reinterpret_cast::Element *>(udata); + + gi_probe->lights.erase(E); + } +} + +RID RenderingServerScene::scenario_create() { + + Scenario *scenario = memnew(Scenario); + ERR_FAIL_COND_V(!scenario, RID()); + RID scenario_rid = scenario_owner.make_rid(scenario); + scenario->self = scenario_rid; + + scenario->octree.set_pair_callback(_instance_pair, this); + scenario->octree.set_unpair_callback(_instance_unpair, this); + scenario->reflection_probe_shadow_atlas = RSG::scene_render->shadow_atlas_create(); + RSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest + RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4); + RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4); + RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4); + RSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8); + scenario->reflection_atlas = RSG::scene_render->reflection_atlas_create(); + return scenario_rid; +} + +void RenderingServerScene::scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->debug = p_debug_mode; +} + +void RenderingServerScene::scenario_set_environment(RID p_scenario, RID p_environment) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->environment = p_environment; +} + +void RenderingServerScene::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->camera_effects = p_camera_effects; +} + +void RenderingServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + scenario->fallback_environment = p_environment; +} + +void RenderingServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + RSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count); +} + +/* INSTANCING API */ + +void RenderingServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) { + + if (p_update_aabb) + p_instance->update_aabb = true; + if (p_update_dependencies) + p_instance->update_dependencies = true; + + if (p_instance->update_item.in_list()) + return; + + _instance_update_list.add(&p_instance->update_item); +} + +RID RenderingServerScene::instance_create() { + + Instance *instance = memnew(Instance); + ERR_FAIL_COND_V(!instance, RID()); + + RID instance_rid = instance_owner.make_rid(instance); + instance->self = instance_rid; + + return instance_rid; +} + +void RenderingServerScene::instance_set_base(RID p_instance, RID p_base) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + Scenario *scenario = instance->scenario; + + if (instance->base_type != RS::INSTANCE_NONE) { + //free anything related to that base + + if (scenario && instance->octree_id) { + scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away + instance->octree_id = 0; + } + + switch (instance->base_type) { + case RS::INSTANCE_LIGHT: { + + InstanceLightData *light = static_cast(instance->base_data); +#ifdef DEBUG_ENABLED + if (light->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from light."); + } +#endif + if (instance->scenario && light->D) { + instance->scenario->directional_lights.erase(light->D); + light->D = NULL; + } + RSG::scene_render->free(light->instance); + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = static_cast(instance->base_data); + RSG::scene_render->free(reflection_probe->instance); + if (reflection_probe->update_list.in_list()) { + reflection_probe_render_list.remove(&reflection_probe->update_list); + } + } break; + case RS::INSTANCE_LIGHTMAP_CAPTURE: { + + InstanceLightmapCaptureData *lightmap_capture = static_cast(instance->base_data); + //erase dependencies, since no longer a lightmap + while (lightmap_capture->users.front()) { + instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID()); + } + } break; + case RS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast(instance->base_data); +#ifdef DEBUG_ENABLED + if (gi_probe->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); + } +#endif +#ifdef DEBUG_ENABLED + if (gi_probe->lights.size()) { + ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); + } +#endif + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + + if (instance->lightmap_capture) { + Instance *capture = (Instance *)instance->lightmap_capture; + InstanceLightmapCaptureData *lightmap_capture = static_cast(capture->base_data); + lightmap_capture->users.erase(instance); + instance->lightmap_capture = NULL; + instance->lightmap = RID(); + } + + RSG::scene_render->free(gi_probe->probe_instance); + + } break; + default: { + } + } + + if (instance->base_data) { + memdelete(instance->base_data); + instance->base_data = NULL; + } + + instance->blend_values.clear(); + instance->materials.clear(); + } + + instance->base_type = RS::INSTANCE_NONE; + instance->base = RID(); + + if (p_base.is_valid()) { + + instance->base_type = RSG::storage->get_base_type(p_base); + ERR_FAIL_COND(instance->base_type == RS::INSTANCE_NONE); + + switch (instance->base_type) { + case RS::INSTANCE_LIGHT: { + + InstanceLightData *light = memnew(InstanceLightData); + + if (scenario && RSG::storage->light_get_type(p_base) == RS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + + light->instance = RSG::scene_render->light_instance_create(p_base); + + instance->base_data = light; + } break; + case RS::INSTANCE_MESH: + case RS::INSTANCE_MULTIMESH: + case RS::INSTANCE_IMMEDIATE: + case RS::INSTANCE_PARTICLES: { + + InstanceGeometryData *geom = memnew(InstanceGeometryData); + instance->base_data = geom; + if (instance->base_type == RS::INSTANCE_MESH) { + instance->blend_values.resize(RSG::storage->mesh_get_blend_shape_count(p_base)); + } + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + + InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData); + reflection_probe->owner = instance; + instance->base_data = reflection_probe; + + reflection_probe->instance = RSG::scene_render->reflection_probe_instance_create(p_base); + } break; + case RS::INSTANCE_LIGHTMAP_CAPTURE: { + + InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData); + instance->base_data = lightmap_capture; + //lightmap_capture->instance = RSG::scene_render->lightmap_capture_instance_create(p_base); + } break; + case RS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); + instance->base_data = gi_probe; + gi_probe->owner = instance; + + if (scenario && !gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + gi_probe->probe_instance = RSG::scene_render->gi_probe_instance_create(p_base); + + } break; + default: { + } + } + + instance->base = p_base; + + //forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it + RSG::storage->base_update_dependency(p_base, instance); + } + + _instance_queue_update(instance, true, true); +} +void RenderingServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->scenario) { + + instance->scenario->instances.remove(&instance->scenario_item); + + if (instance->octree_id) { + instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away + instance->octree_id = 0; + } + + switch (instance->base_type) { + + case RS::INSTANCE_LIGHT: { + + InstanceLightData *light = static_cast(instance->base_data); +#ifdef DEBUG_ENABLED + if (light->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from light."); + } +#endif + if (light->D) { + instance->scenario->directional_lights.erase(light->D); + light->D = NULL; + } + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + InstanceReflectionProbeData *reflection_probe = static_cast(instance->base_data); + RSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); + + } break; + case RS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast(instance->base_data); + +#ifdef DEBUG_ENABLED + if (gi_probe->geometries.size()) { + ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); + } +#endif +#ifdef DEBUG_ENABLED + if (gi_probe->lights.size()) { + ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); + } +#endif + + if (gi_probe->update_element.in_list()) { + gi_probe_update_list.remove(&gi_probe->update_element); + } + } break; + default: { + } + } + + instance->scenario = NULL; + } + + if (p_scenario.is_valid()) { + + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND(!scenario); + + instance->scenario = scenario; + + scenario->instances.add(&instance->scenario_item); + + switch (instance->base_type) { + + case RS::INSTANCE_LIGHT: { + + InstanceLightData *light = static_cast(instance->base_data); + + if (RSG::storage->light_get_type(instance->base) == RS::LIGHT_DIRECTIONAL) { + light->D = scenario->directional_lights.push_back(instance); + } + } break; + case RS::INSTANCE_GI_PROBE: { + + InstanceGIProbeData *gi_probe = static_cast(instance->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + } break; + default: { + } + } + + _instance_queue_update(instance, true, true); + } +} +void RenderingServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->layer_mask = p_mask; +} +void RenderingServerScene::instance_set_transform(RID p_instance, const Transform &p_transform) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->transform == p_transform) + return; //must be checked to avoid worst evil + +#ifdef DEBUG_ENABLED + + for (int i = 0; i < 4; i++) { + const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin; + ERR_FAIL_COND(Math::is_inf(v.x)); + ERR_FAIL_COND(Math::is_nan(v.x)); + ERR_FAIL_COND(Math::is_inf(v.y)); + ERR_FAIL_COND(Math::is_nan(v.y)); + ERR_FAIL_COND(Math::is_inf(v.z)); + ERR_FAIL_COND(Math::is_nan(v.z)); + } + +#endif + instance->transform = p_transform; + _instance_queue_update(instance, true); +} +void RenderingServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->object_id = p_id; +} +void RenderingServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->update_item.in_list()) { + _update_dirty_instance(instance); + } + + ERR_FAIL_INDEX(p_shape, instance->blend_values.size()); + instance->blend_values.write[p_shape] = p_weight; +} + +void RenderingServerScene::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->base_type == RS::INSTANCE_MESH) { + //may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case + instance->materials.resize(MAX(p_surface + 1, RSG::storage->mesh_get_surface_count(instance->base))); + } + + ERR_FAIL_INDEX(p_surface, instance->materials.size()); + + instance->materials.write[p_surface] = p_material; + + _instance_queue_update(instance, false, true); +} + +void RenderingServerScene::instance_set_visible(RID p_instance, bool p_visible) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->visible == p_visible) + return; + + instance->visible = p_visible; + + switch (instance->base_type) { + case RS::INSTANCE_LIGHT: { + if (RSG::storage->light_get_type(instance->base) != RS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHT, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); + } + + } break; + case RS::INSTANCE_REFLECTION_PROBE: { + if (instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_REFLECTION_PROBE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); + } + + } break; + case RS::INSTANCE_LIGHTMAP_CAPTURE: { + if (instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? RS::INSTANCE_GEOMETRY_MASK : 0); + } + + } break; + case RS::INSTANCE_GI_PROBE: { + if (instance->octree_id && instance->scenario) { + instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << RS::INSTANCE_GI_PROBE, p_visible ? (RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT)) : 0); + } + + } break; + default: { + } + } +} +inline bool is_geometry_instance(RenderingServer::InstanceType p_type) { + return p_type == RS::INSTANCE_MESH || p_type == RS::INSTANCE_MULTIMESH || p_type == RS::INSTANCE_PARTICLES || p_type == RS::INSTANCE_IMMEDIATE; +} + +void RenderingServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->lightmap_capture) { + InstanceLightmapCaptureData *lightmap_capture = static_cast(((Instance *)instance->lightmap_capture)->base_data); + lightmap_capture->users.erase(instance); + instance->lightmap = RID(); + instance->lightmap_capture = NULL; + } + + if (p_lightmap_instance.is_valid()) { + Instance *lightmap_instance = instance_owner.getornull(p_lightmap_instance); + ERR_FAIL_COND(!lightmap_instance); + ERR_FAIL_COND(lightmap_instance->base_type != RS::INSTANCE_LIGHTMAP_CAPTURE); + instance->lightmap_capture = lightmap_instance; + + InstanceLightmapCaptureData *lightmap_capture = static_cast(((Instance *)instance->lightmap_capture)->base_data); + lightmap_capture->users.insert(instance); + instance->lightmap = p_lightmap; + } +} + +void RenderingServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + ERR_FAIL_COND(!is_geometry_instance(instance->base_type)); + + if (p_aabb != AABB()) { + + // Set custom AABB + if (instance->custom_aabb == NULL) + instance->custom_aabb = memnew(AABB); + *instance->custom_aabb = p_aabb; + + } else { + + // Clear custom AABB + if (instance->custom_aabb != NULL) { + memdelete(instance->custom_aabb); + instance->custom_aabb = NULL; + } + } + + if (instance->scenario) + _instance_queue_update(instance, true, false); +} + +void RenderingServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + if (instance->skeleton == p_skeleton) + return; + + instance->skeleton = p_skeleton; + + if (p_skeleton.is_valid()) { + //update the dependency now, so if cleared, we remove it + RSG::storage->skeleton_update_dependency(p_skeleton, instance); + } + _instance_queue_update(instance, true, true); +} + +void RenderingServerScene::instance_set_exterior(RID p_instance, bool p_enabled) { +} + +void RenderingServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) { + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->extra_margin = p_margin; + _instance_queue_update(instance, true, false); +} + +Vector RenderingServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const { + + Vector instances; + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, instances); + + const_cast(this)->update_dirty_instances(); // check dirty instances before culling + + int culled = 0; + Instance *cull[1024]; + culled = scenario->octree.cull_aabb(p_aabb, cull, 1024); + + for (int i = 0; i < culled; i++) { + + Instance *instance = cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_id.is_null()) + continue; + + instances.push_back(instance->object_id); + } + + return instances; +} +Vector RenderingServerScene::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { + + Vector instances; + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, instances); + const_cast(this)->update_dirty_instances(); // check dirty instances before culling + + int culled = 0; + Instance *cull[1024]; + culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024); + + for (int i = 0; i < culled; i++) { + Instance *instance = cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_id.is_null()) + continue; + + instances.push_back(instance->object_id); + } + + return instances; +} +Vector RenderingServerScene::instances_cull_convex(const Vector &p_convex, RID p_scenario) const { + + Vector instances; + Scenario *scenario = scenario_owner.getornull(p_scenario); + ERR_FAIL_COND_V(!scenario, instances); + const_cast(this)->update_dirty_instances(); // check dirty instances before culling + + int culled = 0; + Instance *cull[1024]; + + culled = scenario->octree.cull_convex(p_convex, cull, 1024); + + for (int i = 0; i < culled; i++) { + + Instance *instance = cull[i]; + ERR_CONTINUE(!instance); + if (instance->object_id.is_null()) + continue; + + instances.push_back(instance->object_id); + } + + return instances; +} + +void RenderingServerScene::instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + //ERR_FAIL_COND(((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK)); + + switch (p_flags) { + + case RS::INSTANCE_FLAG_USE_BAKED_LIGHT: { + + instance->baked_light = p_enabled; + + } break; + case RS::INSTANCE_FLAG_USE_DYNAMIC_GI: { + + if (p_enabled == instance->dynamic_gi) { + //bye, redundant + return; + } + + if (instance->octree_id != 0) { + //remove from octree, it needs to be re-paired + instance->scenario->octree.erase(instance->octree_id); + instance->octree_id = 0; + _instance_queue_update(instance, true, true); + } + + //once out of octree, can be changed + instance->dynamic_gi = p_enabled; + + } break; + case RS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: { + + instance->redraw_if_visible = p_enabled; + + } break; + default: { + } + } +} +void RenderingServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->cast_shadows = p_shadow_casting_setting; + _instance_queue_update(instance, false, true); +} +void RenderingServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) { + + Instance *instance = instance_owner.getornull(p_instance); + ERR_FAIL_COND(!instance); + + instance->material_override = p_material; + _instance_queue_update(instance, false, true); +} + +void RenderingServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) { +} +void RenderingServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) { +} + +void RenderingServerScene::_update_instance(Instance *p_instance) { + + p_instance->version++; + + if (p_instance->base_type == RS::INSTANCE_LIGHT) { + + InstanceLightData *light = static_cast(p_instance->base_data); + + RSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform); + light->shadow_dirty = true; + } + + if (p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE) { + + InstanceReflectionProbeData *reflection_probe = static_cast(p_instance->base_data); + + RSG::scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform); + reflection_probe->reflection_dirty = true; + } + + if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { + + InstanceGIProbeData *gi_probe = static_cast(p_instance->base_data); + + RSG::scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform); + } + + if (p_instance->base_type == RS::INSTANCE_PARTICLES) { + + RSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); + } + + if (p_instance->aabb.has_no_surface()) { + return; + } + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + + InstanceGeometryData *geom = static_cast(p_instance->base_data); + //make sure lights are updated if it casts shadow + + if (geom->can_cast_shadows) { + for (List::Element *E = geom->lighting.front(); E; E = E->next()) { + InstanceLightData *light = static_cast(E->get()->base_data); + light->shadow_dirty = true; + } + } + + if (!p_instance->lightmap_capture && geom->lightmap_captures.size()) { + //affected by lightmap captures, must update capture info! + _update_instance_lightmap_captures(p_instance); + } else { + if (!p_instance->lightmap_capture_data.empty()) { + p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data + } + } + } + + p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; + + AABB new_aabb; + + new_aabb = p_instance->transform.xform(p_instance->aabb); + + p_instance->transformed_aabb = new_aabb; + + if (!p_instance->scenario) { + + return; + } + + if (p_instance->octree_id == 0) { + + uint32_t base_type = 1 << p_instance->base_type; + uint32_t pairable_mask = 0; + bool pairable = false; + + if (p_instance->base_type == RS::INSTANCE_LIGHT || p_instance->base_type == RS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == RS::INSTANCE_LIGHTMAP_CAPTURE) { + + pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK : 0; + pairable = true; + } + + if (p_instance->base_type == RS::INSTANCE_GI_PROBE) { + //lights and geometries + pairable_mask = p_instance->visible ? RS::INSTANCE_GEOMETRY_MASK | (1 << RS::INSTANCE_LIGHT) : 0; + pairable = true; + } + + // not inside octree + p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask); + + } else { + + /* + if (new_aabb==p_instance->data.transformed_aabb) + return; + */ + + p_instance->scenario->octree.move(p_instance->octree_id, new_aabb); + } +} + +void RenderingServerScene::_update_instance_aabb(Instance *p_instance) { + + AABB new_aabb; + + ERR_FAIL_COND(p_instance->base_type != RS::INSTANCE_NONE && !p_instance->base.is_valid()); + + switch (p_instance->base_type) { + case RenderingServer::INSTANCE_NONE: { + + // do nothing + } break; + case RenderingServer::INSTANCE_MESH: { + + if (p_instance->custom_aabb) + new_aabb = *p_instance->custom_aabb; + else + new_aabb = RSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); + + } break; + + case RenderingServer::INSTANCE_MULTIMESH: { + + if (p_instance->custom_aabb) + new_aabb = *p_instance->custom_aabb; + else + new_aabb = RSG::storage->multimesh_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_IMMEDIATE: { + + if (p_instance->custom_aabb) + new_aabb = *p_instance->custom_aabb; + else + new_aabb = RSG::storage->immediate_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_PARTICLES: { + + if (p_instance->custom_aabb) + new_aabb = *p_instance->custom_aabb; + else + new_aabb = RSG::storage->particles_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_LIGHT: { + + new_aabb = RSG::storage->light_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_REFLECTION_PROBE: { + + new_aabb = RSG::storage->reflection_probe_get_aabb(p_instance->base); + + } break; + case RenderingServer::INSTANCE_GI_PROBE: { + + new_aabb = RSG::storage->gi_probe_get_bounds(p_instance->base); + + } break; + case RenderingServer::INSTANCE_LIGHTMAP_CAPTURE: { + + new_aabb = RSG::storage->lightmap_capture_get_bounds(p_instance->base); + + } break; + default: { + } + } + + // This is why I didn't re-use Instance::aabb to implement custom AABBs + if (p_instance->extra_margin) + new_aabb.grow_by(p_instance->extra_margin); + + p_instance->aabb = new_aabb; +} + +_FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) { + + static const Vector3 aniso_normal[6] = { + Vector3(-1, 0, 0), + Vector3(1, 0, 0), + Vector3(0, -1, 0), + Vector3(0, 1, 0), + Vector3(0, 0, -1), + Vector3(0, 0, 1) + }; + + int size = 1 << (p_cell_subdiv - 1); + + int clamp_v = size - 1; + //first of all, clamp + Vector3 pos; + pos.x = CLAMP(p_pos.x, 0, clamp_v); + pos.y = CLAMP(p_pos.y, 0, clamp_v); + pos.z = CLAMP(p_pos.z, 0, clamp_v); + + float level = (p_cell_subdiv - 1) - p_level; + + int target_level; + float level_filter; + if (level <= 0.0) { + level_filter = 0; + target_level = 0; + } else { + target_level = Math::ceil(level); + level_filter = target_level - level; + } + + Vector3 color[2][8]; + float alpha[2][8]; + zeromem(alpha, sizeof(float) * 2 * 8); + + //find cell at given level first + + for (int c = 0; c < 2; c++) { + + int current_level = MAX(0, target_level - c); + int level_cell_size = (1 << (p_cell_subdiv - 1)) >> current_level; + + for (int n = 0; n < 8; n++) { + + int x = int(pos.x); + int y = int(pos.y); + int z = int(pos.z); + + if (n & 1) + x += level_cell_size; + if (n & 2) + y += level_cell_size; + if (n & 4) + z += level_cell_size; + + int ofs_x = 0; + int ofs_y = 0; + int ofs_z = 0; + + x = CLAMP(x, 0, clamp_v); + y = CLAMP(y, 0, clamp_v); + z = CLAMP(z, 0, clamp_v); + + int half = size / 2; + uint32_t cell = 0; + for (int i = 0; i < current_level; i++) { + + const RasterizerStorage::LightmapCaptureOctree *bc = &p_octree[cell]; + + int child = 0; + if (x >= ofs_x + half) { + child |= 1; + ofs_x += half; + } + if (y >= ofs_y + half) { + child |= 2; + ofs_y += half; + } + if (z >= ofs_z + half) { + child |= 4; + ofs_z += half; + } + + cell = bc->children[child]; + if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) + break; + + half >>= 1; + } + + if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) { + alpha[c][n] = 0; + } else { + alpha[c][n] = p_octree[cell].alpha; + + for (int i = 0; i < 6; i++) { + //anisotropic read light + float amount = p_dir.dot(aniso_normal[i]); + if (amount < 0) + amount = 0; + color[c][n].x += p_octree[cell].light[i][0] / 1024.0 * amount; + color[c][n].y += p_octree[cell].light[i][1] / 1024.0 * amount; + color[c][n].z += p_octree[cell].light[i][2] / 1024.0 * amount; + } + } + + //print_line("\tlev " + itos(c) + " - " + itos(n) + " alpha: " + rtos(cells[test_cell].alpha) + " col: " + color[c][n]); + } + } + + float target_level_size = size >> target_level; + Vector3 pos_fract[2]; + + pos_fract[0].x = Math::fmod(pos.x, target_level_size) / target_level_size; + pos_fract[0].y = Math::fmod(pos.y, target_level_size) / target_level_size; + pos_fract[0].z = Math::fmod(pos.z, target_level_size) / target_level_size; + + target_level_size = size >> MAX(0, target_level - 1); + + pos_fract[1].x = Math::fmod(pos.x, target_level_size) / target_level_size; + pos_fract[1].y = Math::fmod(pos.y, target_level_size) / target_level_size; + pos_fract[1].z = Math::fmod(pos.z, target_level_size) / target_level_size; + + float alpha_interp[2]; + Vector3 color_interp[2]; + + for (int i = 0; i < 2; i++) { + + Vector3 color_x00 = color[i][0].linear_interpolate(color[i][1], pos_fract[i].x); + Vector3 color_xy0 = color[i][2].linear_interpolate(color[i][3], pos_fract[i].x); + Vector3 blend_z0 = color_x00.linear_interpolate(color_xy0, pos_fract[i].y); + + Vector3 color_x0z = color[i][4].linear_interpolate(color[i][5], pos_fract[i].x); + Vector3 color_xyz = color[i][6].linear_interpolate(color[i][7], pos_fract[i].x); + Vector3 blend_z1 = color_x0z.linear_interpolate(color_xyz, pos_fract[i].y); + + color_interp[i] = blend_z0.linear_interpolate(blend_z1, pos_fract[i].z); + + float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x); + float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x); + float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y); + + float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x); + float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x); + float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y); + + alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z); + } + + r_color = color_interp[0].linear_interpolate(color_interp[1], level_filter); + r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter); + + //print_line("pos: " + p_posf + " level " + rtos(p_level) + " down to " + itos(target_level) + "." + rtos(level_filter) + " color " + r_color + " alpha " + rtos(r_alpha)); +} + +_FORCE_INLINE_ static Color _light_capture_voxel_cone_trace(const RasterizerStorage::LightmapCaptureOctree *p_octree, const Vector3 &p_pos, const Vector3 &p_dir, float p_aperture, int p_cell_subdiv) { + + float bias = 0.0; //no need for bias here + float max_distance = (Vector3(1, 1, 1) * (1 << (p_cell_subdiv - 1))).length(); + + float dist = bias; + float alpha = 0.0; + Vector3 color; + + Vector3 scolor; + float salpha; + + while (dist < max_distance && alpha < 0.95) { + float diameter = MAX(1.0, 2.0 * p_aperture * dist); + _light_capture_sample_octree(p_octree, p_cell_subdiv, p_pos + dist * p_dir, p_dir, log2(diameter), scolor, salpha); + float a = (1.0 - alpha); + color += scolor * a; + alpha += a * salpha; + dist += diameter * 0.5; + } + + return Color(color.x, color.y, color.z, alpha); +} + +void RenderingServerScene::_update_instance_lightmap_captures(Instance *p_instance) { + + InstanceGeometryData *geom = static_cast(p_instance->base_data); + + static const Vector3 cone_traces[12] = { + Vector3(0, 0, 1), + Vector3(0.866025, 0, 0.5), + Vector3(0.267617, 0.823639, 0.5), + Vector3(-0.700629, 0.509037, 0.5), + Vector3(-0.700629, -0.509037, 0.5), + Vector3(0.267617, -0.823639, 0.5), + Vector3(0, 0, -1), + Vector3(0.866025, 0, -0.5), + Vector3(0.267617, 0.823639, -0.5), + Vector3(-0.700629, 0.509037, -0.5), + Vector3(-0.700629, -0.509037, -0.5), + Vector3(0.267617, -0.823639, -0.5) + }; + + float cone_aperture = 0.577; // tan(angle) 60 degrees + + if (p_instance->lightmap_capture_data.empty()) { + p_instance->lightmap_capture_data.resize(12); + } + + //print_line("update captures for pos: " + p_instance->transform.origin); + + for (int i = 0; i < 12; i++) + new (&p_instance->lightmap_capture_data.ptrw()[i]) Color; + + //this could use some sort of blending.. + for (List::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { + const Vector *octree = RSG::storage->lightmap_capture_get_octree_ptr(E->get()->base); + //print_line("octree size: " + itos(octree->size())); + if (octree->size() == 0) + continue; + Transform to_cell_xform = RSG::storage->lightmap_capture_get_octree_cell_transform(E->get()->base); + int cell_subdiv = RSG::storage->lightmap_capture_get_octree_cell_subdiv(E->get()->base); + to_cell_xform = to_cell_xform * E->get()->transform.affine_inverse(); + + const RasterizerStorage::LightmapCaptureOctree *octree_r = octree->ptr(); + + Vector3 pos = to_cell_xform.xform(p_instance->transform.origin); + + for (int i = 0; i < 12; i++) { + + Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized(); + Color capture = _light_capture_voxel_cone_trace(octree_r, pos, dir, cone_aperture, cell_subdiv); + p_instance->lightmap_capture_data.write[i] += capture; + } + } +} + +bool RenderingServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) { + + InstanceLightData *light = static_cast(p_instance->base_data); + + Transform light_transform = p_instance->transform; + light_transform.orthonormalize(); //scale does not count on lights + + bool animated_material_found = false; + + switch (RSG::storage->light_get_type(p_instance->base)) { + + case RS::LIGHT_DIRECTIONAL: { + + float max_distance = p_cam_projection.get_z_far(); + float shadow_max = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); + if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera + max_distance = MIN(shadow_max, max_distance); + } + max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001); + float min_distance = MIN(p_cam_projection.get_z_near(), max_distance); + + RS::LightDirectionalShadowDepthRangeMode depth_range_mode = RSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base); + + if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) { + //optimize min/max + Vector planes = p_cam_projection.get_projection_planes(p_cam_transform); + int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); + Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2)); + //check distance max and min + + bool found_items = false; + float z_max = -1e20; + float z_min = 1e20; + + for (int i = 0; i < cull_count; i++) { + + Instance *instance = instance_shadow_cull_result[i]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + continue; + } + + if (static_cast(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + + float max, min; + instance->transformed_aabb.project_range_in_plane(base, min, max); + + if (max > z_max) { + z_max = max; + } + + if (min < z_min) { + z_min = min; + } + + found_items = true; + } + + if (found_items) { + min_distance = MAX(min_distance, z_min); + max_distance = MIN(max_distance, z_max); + } + } + + float range = max_distance - min_distance; + + int splits = 0; + switch (RSG::storage->light_directional_get_shadow_mode(p_instance->base)) { + case RS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits = 1; break; + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits = 2; break; + case RS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits = 4; break; + } + + float distances[5]; + + distances[0] = min_distance; + for (int i = 0; i < splits; i++) { + distances[i + 1] = min_distance + RSG::storage->light_get_param(p_instance->base, RS::LightParam(RS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; + }; + + distances[splits] = max_distance; + + float texture_size = RSG::scene_render->get_directional_light_shadow_size(light->instance); + + bool overlap = RSG::storage->light_directional_get_blend_splits(p_instance->base); + + float first_radius = 0.0; + + for (int i = 0; i < splits; i++) { + + RENDER_TIMESTAMP("Culling Directional Light split" + itos(i)); + + // setup a camera matrix for that range! + CameraMatrix camera_matrix; + + float aspect = p_cam_projection.get_aspect(); + + if (p_cam_orthogonal) { + + Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); + + camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); + } else { + + float fov = p_cam_projection.get_fov(); + camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); + } + + //obtain the frustum endpoints + + Vector3 endpoints[8]; // frustum plane endpoints + bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints); + ERR_CONTINUE(!res); + + // obtain the light frustm ranges (given endpoints) + + Transform transform = light_transform; //discard scale and stabilize light + + Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized(); + Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized(); + Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized(); + //z_vec points agsint the camera, like in default opengl + + float x_min = 0.f, x_max = 0.f; + float y_min = 0.f, y_max = 0.f; + float z_min = 0.f, z_max = 0.f; + + // FIXME: z_max_cam is defined, computed, but not used below when setting up + // ortho_camera. Commented out for now to fix warnings but should be investigated. + float x_min_cam = 0.f, x_max_cam = 0.f; + float y_min_cam = 0.f, y_max_cam = 0.f; + float z_min_cam = 0.f; + //float z_max_cam = 0.f; + + float bias_scale = 1.0; + + //used for culling + + for (int j = 0; j < 8; j++) { + + float d_x = x_vec.dot(endpoints[j]); + float d_y = y_vec.dot(endpoints[j]); + float d_z = z_vec.dot(endpoints[j]); + + if (j == 0 || d_x < x_min) + x_min = d_x; + if (j == 0 || d_x > x_max) + x_max = d_x; + + if (j == 0 || d_y < y_min) + y_min = d_y; + if (j == 0 || d_y > y_max) + y_max = d_y; + + if (j == 0 || d_z < z_min) + z_min = d_z; + if (j == 0 || d_z > z_max) + z_max = d_z; + } + + { + //camera viewport stuff + + Vector3 center; + + for (int j = 0; j < 8; j++) { + + center += endpoints[j]; + } + center /= 8.0; + + //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5; + + float radius = 0; + + for (int j = 0; j < 8; j++) { + + float d = center.distance_to(endpoints[j]); + if (d > radius) + radius = d; + } + + radius *= texture_size / (texture_size - 2.0); //add a texel by each side + + if (i == 0) { + first_radius = radius; + } else { + bias_scale = radius / first_radius; + } + + x_max_cam = x_vec.dot(center) + radius; + x_min_cam = x_vec.dot(center) - radius; + y_max_cam = y_vec.dot(center) + radius; + y_min_cam = y_vec.dot(center) - radius; + //z_max_cam = z_vec.dot(center) + radius; + z_min_cam = z_vec.dot(center) - radius; + + if (depth_range_mode == RS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) { + //this trick here is what stabilizes the shadow (make potential jaggies to not move) + //at the cost of some wasted resolution. Still the quality increase is very well worth it + + float unit = radius * 2.0 / texture_size; + + x_max_cam = Math::stepify(x_max_cam, unit); + x_min_cam = Math::stepify(x_min_cam, unit); + y_max_cam = Math::stepify(y_max_cam, unit); + y_min_cam = Math::stepify(y_min_cam, unit); + } + } + + //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree + + Vector light_frustum_planes; + light_frustum_planes.resize(6); + + //right/left + light_frustum_planes.write[0] = Plane(x_vec, x_max); + light_frustum_planes.write[1] = Plane(-x_vec, -x_min); + //top/bottom + light_frustum_planes.write[2] = Plane(y_vec, y_max); + light_frustum_planes.write[3] = Plane(-y_vec, -y_min); + //near/far + light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6); + light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed + + int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); + + // a pre pass will need to be needed to determine the actual z-near to be used + + Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); + + for (int j = 0; j < cull_count; j++) { + + float min, max; + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); + j--; + continue; + } + + instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max); + instance->depth = near_plane.distance_to(instance->transform.origin); + instance->depth_layer = 0; + if (max > z_max) + z_max = max; + } + + { + + CameraMatrix ortho_camera; + real_t half_x = (x_max_cam - x_min_cam) * 0.5; + real_t half_y = (y_max_cam - y_min_cam) * 0.5; + + ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam)); + + Transform ortho_transform; + ortho_transform.basis = transform.basis; + ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max; + + RSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, 0, distances[i + 1], i, bias_scale); + } + + RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); + } + + } break; + case RS::LIGHT_OMNI: { + + RS::LightOmniShadowMode shadow_mode = RSG::storage->light_omni_get_shadow_mode(p_instance->base); + + if (shadow_mode == RS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !RSG::scene_render->light_instances_can_render_shadow_cube()) { + + for (int i = 0; i < 2; i++) { + + //using this one ensures that raster deferred will have it + RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i)); + + float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); + + float z = i == 0 ? -1 : 1; + Vector planes; + planes.resize(5); + planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius)); + planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius)); + planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius)); + planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius)); + planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius)); + + int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); + Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z); + + for (int j = 0; j < cull_count; j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); + j--; + } else { + if (static_cast(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + + instance->depth = near_plane.distance_to(instance->transform.origin); + instance->depth_layer = 0; + } + } + + RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i); + RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); + } + } else { //shadow cube + + float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); + CameraMatrix cm; + cm.set_perspective(90, 1, 0.01, radius); + + for (int i = 0; i < 6; i++) { + + RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i)); + //using this one ensures that raster deferred will have it + + static const Vector3 view_normals[6] = { + Vector3(+1, 0, 0), + Vector3(-1, 0, 0), + Vector3(0, -1, 0), + Vector3(0, +1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1) + }; + static const Vector3 view_up[6] = { + Vector3(0, -1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, -1), + Vector3(0, 0, +1), + Vector3(0, -1, 0), + Vector3(0, -1, 0) + }; + + Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]); + + Vector planes = cm.get_projection_planes(xform); + + int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); + + Plane near_plane(xform.origin, -xform.basis.get_axis(2)); + for (int j = 0; j < cull_count; j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); + j--; + } else { + if (static_cast(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + instance->depth = near_plane.distance_to(instance->transform.origin); + instance->depth_layer = 0; + } + } + + RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i); + RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); + } + + //restore the regular DP matrix + RSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0); + } + + } break; + case RS::LIGHT_SPOT: { + + RENDER_TIMESTAMP("Culling Spot Light"); + + float radius = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_RANGE); + float angle = RSG::storage->light_get_param(p_instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); + + CameraMatrix cm; + cm.set_perspective(angle * 2.0, 1.0, 0.01, radius); + + Vector planes = cm.get_projection_planes(light_transform); + int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, RS::INSTANCE_GEOMETRY_MASK); + + Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); + for (int j = 0; j < cull_count; j++) { + + Instance *instance = instance_shadow_cull_result[j]; + if (!instance->visible || !((1 << instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { + cull_count--; + SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); + j--; + } else { + if (static_cast(instance->base_data)->material_is_animated) { + animated_material_found = true; + } + instance->depth = near_plane.distance_to(instance->transform.origin); + instance->depth_layer = 0; + } + } + + RSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0); + RSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); + + } break; + } + + return animated_material_found; +} + +void RenderingServerScene::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { +// render to mono camera +#ifndef _3D_DISABLED + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + /* STEP 1 - SETUP CAMERA */ + CameraMatrix camera_matrix; + bool ortho = false; + + switch (camera->type) { + case Camera::ORTHOGONAL: { + + camera_matrix.set_orthogonal( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = true; + } break; + case Camera::PERSPECTIVE: { + + camera_matrix.set_perspective( + camera->fov, + p_viewport_size.width / (float)p_viewport_size.height, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = false; + + } break; + case Camera::FRUSTUM: { + + camera_matrix.set_frustum( + camera->size, + p_viewport_size.width / (float)p_viewport_size.height, + camera->offset, + camera->znear, + camera->zfar, + camera->vaspect); + ortho = false; + } break; + } + + _prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); +#endif +} + +void RenderingServerScene::render_camera(RID p_render_buffers, Ref &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { + // render for AR/VR interface + + Camera *camera = camera_owner.getornull(p_camera); + ERR_FAIL_COND(!camera); + + /* SETUP CAMERA, we are ignoring type and FOV here */ + float aspect = p_viewport_size.width / (float)p_viewport_size.height; + CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar); + + // We also ignore our camera position, it will have been positioned with a slightly old tracking position. + // Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo! + Transform world_origin = ARVRServer::get_singleton()->get_world_origin(); + Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin); + + // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye + if (p_eye == ARVRInterface::EYE_LEFT) { + ///@TODO possibly move responsibility for this into our ARVRServer or ARVRInterface? + + // Center our transform, we assume basis is equal. + Transform mono_transform = cam_transform; + Transform right_transform = p_interface->get_transform_for_eye(ARVRInterface::EYE_RIGHT, world_origin); + mono_transform.origin += right_transform.origin; + mono_transform.origin *= 0.5; + + // We need to combine our projection frustums for culling. + // Ideally we should use our clipping planes for this and combine them, + // however our shadow map logic uses our projection matrix. + // Note: as our left and right frustums should be mirrored, we don't need our right projection matrix. + + // - get some base values we need + float eye_dist = (mono_transform.origin - cam_transform.origin).length(); + float z_near = camera_matrix.get_z_near(); // get our near plane + float z_far = camera_matrix.get_z_far(); // get our far plane + float width = (2.0 * z_near) / camera_matrix.matrix[0][0]; + float x_shift = width * camera_matrix.matrix[2][0]; + float height = (2.0 * z_near) / camera_matrix.matrix[1][1]; + float y_shift = height * camera_matrix.matrix[2][1]; + + // printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift); + + // - calculate our near plane size (horizontal only, right_near is mirrored) + float left_near = -eye_dist - ((width - x_shift) * 0.5); + + // - calculate our far plane size (horizontal only, right_far is mirrored) + float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near); + float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near); + if (left_far > left_far_right_eye) { + // on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes. + left_far = left_far_right_eye; + } + + // - figure out required z-shift + float slope = (left_far - left_near) / (z_far - z_near); + float z_shift = (left_near / slope) - z_near; + + // - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift) + float top_near = (height - y_shift) * 0.5; + top_near += (top_near / z_near) * z_shift; + float bottom_near = -(height + y_shift) * 0.5; + bottom_near += (bottom_near / z_near) * z_shift; + + // printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift); + + // - generate our frustum + CameraMatrix combined_matrix; + combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift); + + // and finally move our camera back + Transform apply_z_shift; + apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards + mono_transform *= apply_z_shift; + + // now prepare our scene with our adjusted transform projection matrix + _prepare_scene(mono_transform, combined_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + } else if (p_eye == ARVRInterface::EYE_MONO) { + // For mono render, prepare as per usual + _prepare_scene(cam_transform, camera_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); + } + + // And render our scene... + _render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); +}; + +void RenderingServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { + // Note, in stereo rendering: + // - p_cam_transform will be a transform in the middle of our two eyes + // - p_cam_projection is a wider frustrum that encompasses both eyes + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + render_pass++; + uint32_t camera_layer_mask = p_visible_layers; + + RSG::scene_render->set_scene_pass(render_pass); + + RENDER_TIMESTAMP("Frustum Culling"); + + //rasterizer->set_camera(camera->transform, camera_matrix,ortho); + + Vector planes = p_cam_projection.get_projection_planes(p_cam_transform); + + Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized()); + float z_far = p_cam_projection.get_z_far(); + + /* STEP 2 - CULL */ + instance_cull_count = scenario->octree.cull_convex(planes, instance_cull_result, MAX_INSTANCE_CULL); + light_cull_count = 0; + + reflection_probe_cull_count = 0; + gi_probe_cull_count = 0; + + //light_samplers_culled=0; + + /* + print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); + print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); + print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); + print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); + */ + + /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */ + //removed, will replace with culling + + /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ + + for (int i = 0; i < instance_cull_count; i++) { + + Instance *ins = instance_cull_result[i]; + + bool keep = false; + + if ((camera_layer_mask & ins->layer_mask) == 0) { + //failure + } else if (ins->base_type == RS::INSTANCE_LIGHT && ins->visible) { + + if (light_cull_count < MAX_LIGHTS_CULLED) { + + InstanceLightData *light = static_cast(ins->base_data); + + if (!light->geometries.empty()) { + //do not add this light if no geometry is affected by it.. + light_cull_result[light_cull_count] = ins; + light_instance_cull_result[light_cull_count] = light->instance; + if (p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(ins->base)) { + RSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later + } + + light_cull_count++; + } + } + } else if (ins->base_type == RS::INSTANCE_REFLECTION_PROBE && ins->visible) { + + if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { + + InstanceReflectionProbeData *reflection_probe = static_cast(ins->base_data); + + if (p_reflection_probe != reflection_probe->instance) { + //avoid entering The Matrix + + if (!reflection_probe->geometries.empty()) { + //do not add this light if no geometry is affected by it.. + + if (reflection_probe->reflection_dirty || RSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) { + if (!reflection_probe->update_list.in_list()) { + reflection_probe->render_step = 0; + reflection_probe_render_list.add_last(&reflection_probe->update_list); + } + + reflection_probe->reflection_dirty = false; + } + + if (RSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) { + reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance; + reflection_probe_cull_count++; + } + } + } + } + + } else if (ins->base_type == RS::INSTANCE_GI_PROBE && ins->visible) { + + InstanceGIProbeData *gi_probe = static_cast(ins->base_data); + if (!gi_probe->update_element.in_list()) { + gi_probe_update_list.add(&gi_probe->update_element); + } + + if (gi_probe_cull_count < MAX_GI_PROBES_CULLED) { + gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance; + gi_probe_cull_count++; + } + + } else if (((1 << ins->base_type) & RS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != RS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { + + keep = true; + + InstanceGeometryData *geom = static_cast(ins->base_data); + + if (ins->redraw_if_visible) { + RenderingServerRaster::redraw_request(); + } + + if (ins->base_type == RS::INSTANCE_PARTICLES) { + //particles visible? process them + if (RSG::storage->particles_is_inactive(ins->base)) { + //but if nothing is going on, don't do it. + keep = false; + } else { + RSG::storage->particles_request_process(ins->base); + //particles visible? request redraw + RenderingServerRaster::redraw_request(); + } + } + + if (geom->lighting_dirty) { + int l = 0; + //only called when lights AABB enter/exit this geometry + ins->light_instances.resize(geom->lighting.size()); + + for (List::Element *E = geom->lighting.front(); E; E = E->next()) { + + InstanceLightData *light = static_cast(E->get()->base_data); + + ins->light_instances.write[l++] = light->instance; + } + + geom->lighting_dirty = false; + } + + if (geom->reflection_dirty) { + int l = 0; + //only called when reflection probe AABB enter/exit this geometry + ins->reflection_probe_instances.resize(geom->reflection_probes.size()); + + for (List::Element *E = geom->reflection_probes.front(); E; E = E->next()) { + + InstanceReflectionProbeData *reflection_probe = static_cast(E->get()->base_data); + + ins->reflection_probe_instances.write[l++] = reflection_probe->instance; + } + + geom->reflection_dirty = false; + } + + if (geom->gi_probes_dirty) { + int l = 0; + //only called when reflection probe AABB enter/exit this geometry + ins->gi_probe_instances.resize(geom->gi_probes.size()); + + for (List::Element *E = geom->gi_probes.front(); E; E = E->next()) { + + InstanceGIProbeData *gi_probe = static_cast(E->get()->base_data); + + ins->gi_probe_instances.write[l++] = gi_probe->probe_instance; + } + + geom->gi_probes_dirty = false; + } + + ins->depth = near_plane.distance_to(ins->transform.origin); + ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15); + } + + if (!keep) { + // remove, no reason to keep + instance_cull_count--; + SWAP(instance_cull_result[i], instance_cull_result[instance_cull_count]); + i--; + ins->last_render_pass = 0; // make invalid + } else { + + ins->last_render_pass = render_pass; + } + } + + /* STEP 5 - PROCESS LIGHTS */ + + RID *directional_light_ptr = &light_instance_cull_result[light_cull_count]; + directional_light_count = 0; + + // directional lights + { + + Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size()); + int directional_shadow_count = 0; + + for (List::Element *E = scenario->directional_lights.front(); E; E = E->next()) { + + if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) { + break; + } + + if (!E->get()->visible) + continue; + + InstanceLightData *light = static_cast(E->get()->base_data); + + //check shadow.. + + if (light) { + if (p_using_shadows && p_shadow_atlas.is_valid() && RSG::storage->light_has_shadow(E->get()->base)) { + lights_with_shadow[directional_shadow_count++] = E->get(); + } + //add to list + directional_light_ptr[directional_light_count++] = light->instance; + } + } + + RSG::scene_render->set_directional_shadow_count(directional_shadow_count); + + for (int i = 0; i < directional_shadow_count; i++) { + + RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i)); + + _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario); + + RENDER_TIMESTAMP(" sorter; + //sorter.sort(light_cull_result,light_cull_count); + for (int i = 0; i < light_cull_count; i++) { + + Instance *ins = light_cull_result[i]; + + if (!p_shadow_atlas.is_valid() || !RSG::storage->light_has_shadow(ins->base)) + continue; + + InstanceLightData *light = static_cast(ins->base_data); + + float coverage = 0.f; + + { //compute coverage + + Transform cam_xf = p_cam_transform; + float zn = p_cam_projection.get_z_near(); + Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane + + // near plane half width and height + Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents(); + + switch (RSG::storage->light_get_type(ins->base)) { + + case RS::LIGHT_OMNI: { + + float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); + + //get two points parallel to near plane + Vector3 points[2] = { + ins->transform.origin, + ins->transform.origin + cam_xf.basis.get_axis(0) * radius + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for (int j = 0; j < 2; j++) { + if (p.distance_to(points[j]) < 0) { + points[j].z = -zn; //small hack to keep size constant when hitting the screen + } + + p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane + } + } + + float screen_diameter = points[0].distance_to(points[1]) * 2; + coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); + } break; + case RS::LIGHT_SPOT: { + + float radius = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_RANGE); + float angle = RSG::storage->light_get_param(ins->base, RS::LIGHT_PARAM_SPOT_ANGLE); + + float w = radius * Math::sin(Math::deg2rad(angle)); + float d = radius * Math::cos(Math::deg2rad(angle)); + + Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d; + + Vector3 points[2] = { + base, + base + cam_xf.basis.get_axis(0) * w + }; + + if (!p_cam_orthogonal) { + //if using perspetive, map them to near plane + for (int j = 0; j < 2; j++) { + if (p.distance_to(points[j]) < 0) { + points[j].z = -zn; //small hack to keep size constant when hitting the screen + } + + p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane + } + } + + float screen_diameter = points[0].distance_to(points[1]) * 2; + coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); + + } break; + default: { + ERR_PRINT("Invalid Light Type"); + } + } + } + + if (light->shadow_dirty) { + light->last_version++; + light->shadow_dirty = false; + } + + bool redraw = RSG::scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version); + + if (redraw) { + //must redraw! + RENDER_TIMESTAMP(">Rendering Light " + itos(i)); + light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario); + RENDER_TIMESTAMP("environment.is_valid()) + environment = scenario->environment; + else + environment = scenario->fallback_environment; + + RID camera_effects; + if (p_force_camera_effects.is_valid()) { + camera_effects = p_force_camera_effects; + } else { + camera_effects = scenario->camera_effects; + } + /* PROCESS GEOMETRY AND DRAW SCENE */ + + RENDER_TIMESTAMP("Render Scene "); + RSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); +} + +void RenderingServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { + +#ifndef _3D_DISABLED + + Scenario *scenario = scenario_owner.getornull(p_scenario); + + RID environment; + if (scenario->environment.is_valid()) + environment = scenario->environment; + else + environment = scenario->fallback_environment; + RENDER_TIMESTAMP("Render Empty Scene "); + RSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, NULL, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0); +#endif +} + +bool RenderingServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) { + + InstanceReflectionProbeData *reflection_probe = static_cast(p_instance->base_data); + Scenario *scenario = p_instance->scenario; + ERR_FAIL_COND_V(!scenario, true); + + RenderingServerRaster::redraw_request(); //update, so it updates in editor + + if (p_step == 0) { + + if (!RSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { + return true; //all full + } + } + + if (p_step >= 0 && p_step < 6) { + + static const Vector3 view_normals[6] = { + Vector3(+1, 0, 0), + Vector3(-1, 0, 0), + Vector3(0, +1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1) + }; + static const Vector3 view_up[6] = { + Vector3(0, -1, 0), + Vector3(0, -1, 0), + Vector3(0, 0, +1), + Vector3(0, 0, -1), + Vector3(0, -1, 0), + Vector3(0, -1, 0) + }; + + Vector3 extents = RSG::storage->reflection_probe_get_extents(p_instance->base); + Vector3 origin_offset = RSG::storage->reflection_probe_get_origin_offset(p_instance->base); + float max_distance = RSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); + + Vector3 edge = view_normals[p_step] * extents; + float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit + + max_distance = MAX(max_distance, distance); + + //render cubemap side + CameraMatrix cm; + cm.set_perspective(90, 1, 0.01, max_distance); + + Transform local_view; + local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]); + + Transform xform = p_instance->transform * local_view; + + RID shadow_atlas; + + bool use_shadows = RSG::storage->reflection_probe_renders_shadows(p_instance->base); + if (use_shadows) { + + shadow_atlas = scenario->reflection_probe_shadow_atlas; + } + + RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step)); + _prepare_scene(xform, cm, false, RID(), RID(), RSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows); + _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step); + + } else { + //do roughness postprocess step until it believes it's done + RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step)); + return RSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); + } + + return false; +} + +void RenderingServerScene::render_probes() { + + /* REFLECTION PROBES */ + + SelfList *ref_probe = reflection_probe_render_list.first(); + + bool busy = false; + + while (ref_probe) { + + SelfList *next = ref_probe->next(); + RID base = ref_probe->self()->owner->base; + + switch (RSG::storage->reflection_probe_get_update_mode(base)) { + + case RS::REFLECTION_PROBE_UPDATE_ONCE: { + if (busy) //already rendering something + break; + + bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step); + if (done) { + reflection_probe_render_list.remove(ref_probe); + } else { + ref_probe->self()->render_step++; + } + + busy = true; //do not render another one of this kind + } break; + case RS::REFLECTION_PROBE_UPDATE_ALWAYS: { + + int step = 0; + bool done = false; + while (!done) { + done = _render_reflection_probe_step(ref_probe->self()->owner, step); + step++; + } + + reflection_probe_render_list.remove(ref_probe); + } break; + } + + ref_probe = next; + } + + /* GI PROBES */ + + SelfList *gi_probe = gi_probe_update_list.first(); + + if (gi_probe) { + RENDER_TIMESTAMP("Render GI Probes"); + } + + while (gi_probe) { + + SelfList *next = gi_probe->next(); + + InstanceGIProbeData *probe = gi_probe->self(); + //Instance *instance_probe = probe->owner; + + //check if probe must be setup, but don't do if on the lighting thread + + bool cache_dirty = false; + int cache_count = 0; + { + + int light_cache_size = probe->light_cache.size(); + const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr(); + const RID *instance_caches = probe->light_instances.ptr(); + + int idx = 0; //must count visible lights + for (Set::Element *E = probe->lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + if (cache_dirty) { + //do nothing, since idx must count all visible lights anyway + } else if (idx >= light_cache_size) { + cache_dirty = true; + } else { + + const InstanceGIProbeData::LightCache *cache = &caches[idx]; + + if ( + instance_caches[idx] != instance_light->instance || + cache->has_shadow != RSG::storage->light_has_shadow(instance->base) || + cache->type != RSG::storage->light_get_type(instance->base) || + cache->transform != instance->transform || + cache->color != RSG::storage->light_get_color(instance->base) || + cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) || + cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) || + cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || + cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || + cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || + cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) { + cache_dirty = true; + } + } + + idx++; + } + + for (List::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { + + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + if (cache_dirty) { + //do nothing, since idx must count all visible lights anyway + } else if (idx >= light_cache_size) { + cache_dirty = true; + } else { + + const InstanceGIProbeData::LightCache *cache = &caches[idx]; + + if ( + instance_caches[idx] != instance_light->instance || + cache->has_shadow != RSG::storage->light_has_shadow(instance->base) || + cache->type != RSG::storage->light_get_type(instance->base) || + cache->transform != instance->transform || + cache->color != RSG::storage->light_get_color(instance->base) || + cache->energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY) || + cache->bake_energy != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY) || + cache->radius != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE) || + cache->attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION) || + cache->spot_angle != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE) || + cache->spot_attenuation != RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION)) { + cache_dirty = true; + } + } + + idx++; + } + + if (idx != light_cache_size) { + cache_dirty = true; + } + + cache_count = idx; + } + + bool update_lights = RSG::scene_render->gi_probe_needs_update(probe->probe_instance); + + if (cache_dirty) { + probe->light_cache.resize(cache_count); + probe->light_instances.resize(cache_count); + + if (cache_count) { + InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw(); + RID *instance_caches = probe->light_instances.ptrw(); + + int idx = 0; //must count visible lights + for (Set::Element *E = probe->lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + + InstanceGIProbeData::LightCache *cache = &caches[idx]; + + instance_caches[idx] = instance_light->instance; + cache->has_shadow = RSG::storage->light_has_shadow(instance->base); + cache->type = RSG::storage->light_get_type(instance->base); + cache->transform = instance->transform; + cache->color = RSG::storage->light_get_color(instance->base); + cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY); + cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY); + cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE); + cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); + cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); + cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + idx++; + } + for (List::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { + Instance *instance = E->get(); + InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; + if (!instance->visible) { + continue; + } + + InstanceGIProbeData::LightCache *cache = &caches[idx]; + + instance_caches[idx] = instance_light->instance; + cache->has_shadow = RSG::storage->light_has_shadow(instance->base); + cache->type = RSG::storage->light_get_type(instance->base); + cache->transform = instance->transform; + cache->color = RSG::storage->light_get_color(instance->base); + cache->energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ENERGY); + cache->bake_energy = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_INDIRECT_ENERGY); + cache->radius = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_RANGE); + cache->attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_ATTENUATION); + cache->spot_angle = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ANGLE); + cache->spot_attenuation = RSG::storage->light_get_param(instance->base, RS::LIGHT_PARAM_SPOT_ATTENUATION); + + idx++; + } + } + + update_lights = true; + } + + instance_cull_count = 0; + for (List::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { + if (instance_cull_count < MAX_INSTANCE_CULL) { + Instance *ins = E->get().geometry; + if (!ins->visible) { + continue; + } + InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data; + + if (geom->gi_probes_dirty) { + //giprobes may be dirty, so update + int l = 0; + //only called when reflection probe AABB enter/exit this geometry + ins->gi_probe_instances.resize(geom->gi_probes.size()); + + for (List::Element *F = geom->gi_probes.front(); F; F = F->next()) { + + InstanceGIProbeData *gi_probe2 = static_cast(F->get()->base_data); + + ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance; + } + + geom->gi_probes_dirty = false; + } + + instance_cull_result[instance_cull_count++] = E->get().geometry; + } + } + + RSG::scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, instance_cull_count, (RasterizerScene::InstanceBase **)instance_cull_result); + + gi_probe_update_list.remove(gi_probe); + + gi_probe = next; + } +} + +void RenderingServerScene::_update_dirty_instance(Instance *p_instance) { + + if (p_instance->update_aabb) { + _update_instance_aabb(p_instance); + } + + if (p_instance->update_dependencies) { + + p_instance->instance_increase_version(); + + if (p_instance->base.is_valid()) { + RSG::storage->base_update_dependency(p_instance->base, p_instance); + } + + if (p_instance->material_override.is_valid()) { + RSG::storage->material_update_dependency(p_instance->material_override, p_instance); + } + + if (p_instance->base_type == RS::INSTANCE_MESH) { + //remove materials no longer used and un-own them + + int new_mat_count = RSG::storage->mesh_get_surface_count(p_instance->base); + p_instance->materials.resize(new_mat_count); + + int new_blend_shape_count = RSG::storage->mesh_get_blend_shape_count(p_instance->base); + if (new_blend_shape_count != p_instance->blend_values.size()) { + p_instance->blend_values.resize(new_blend_shape_count); + for (int i = 0; i < new_blend_shape_count; i++) { + p_instance->blend_values.write[i] = 0; + } + } + } + + if ((1 << p_instance->base_type) & RS::INSTANCE_GEOMETRY_MASK) { + + InstanceGeometryData *geom = static_cast(p_instance->base_data); + + bool can_cast_shadows = true; + bool is_animated = false; + + if (p_instance->cast_shadows == RS::SHADOW_CASTING_SETTING_OFF) { + can_cast_shadows = false; + } else if (p_instance->material_override.is_valid()) { + can_cast_shadows = RSG::storage->material_casts_shadows(p_instance->material_override); + is_animated = RSG::storage->material_is_animated(p_instance->material_override); + } else { + + if (p_instance->base_type == RS::INSTANCE_MESH) { + RID mesh = p_instance->base; + + if (mesh.is_valid()) { + bool cast_shadows = false; + + for (int i = 0; i < p_instance->materials.size(); i++) { + + RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : RSG::storage->mesh_surface_get_material(mesh, i); + + if (!mat.is_valid()) { + cast_shadows = true; + } else { + + if (RSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + + if (RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + RSG::storage->material_update_dependency(mat, p_instance); + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + + } else if (p_instance->base_type == RS::INSTANCE_MULTIMESH) { + RID mesh = RSG::storage->multimesh_get_mesh(p_instance->base); + if (mesh.is_valid()) { + + bool cast_shadows = false; + + int sc = RSG::storage->mesh_get_surface_count(mesh); + for (int i = 0; i < sc; i++) { + + RID mat = RSG::storage->mesh_surface_get_material(mesh, i); + + if (!mat.is_valid()) { + cast_shadows = true; + + } else { + + if (RSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + if (RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + RSG::storage->material_update_dependency(mat, p_instance); + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + + RSG::storage->base_update_dependency(mesh, p_instance); + } + } else if (p_instance->base_type == RS::INSTANCE_IMMEDIATE) { + + RID mat = RSG::storage->immediate_get_material(p_instance->base); + + can_cast_shadows = !mat.is_valid() || RSG::storage->material_casts_shadows(mat); + + if (mat.is_valid() && RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + if (mat.is_valid()) { + RSG::storage->material_update_dependency(mat, p_instance); + } + + } else if (p_instance->base_type == RS::INSTANCE_PARTICLES) { + + bool cast_shadows = false; + + int dp = RSG::storage->particles_get_draw_passes(p_instance->base); + + for (int i = 0; i < dp; i++) { + + RID mesh = RSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); + if (!mesh.is_valid()) + continue; + + int sc = RSG::storage->mesh_get_surface_count(mesh); + for (int j = 0; j < sc; j++) { + + RID mat = RSG::storage->mesh_surface_get_material(mesh, j); + + if (!mat.is_valid()) { + cast_shadows = true; + } else { + + if (RSG::storage->material_casts_shadows(mat)) { + cast_shadows = true; + } + + if (RSG::storage->material_is_animated(mat)) { + is_animated = true; + } + + RSG::storage->material_update_dependency(mat, p_instance); + } + } + } + + if (!cast_shadows) { + can_cast_shadows = false; + } + } + } + + if (can_cast_shadows != geom->can_cast_shadows) { + //ability to cast shadows change, let lights now + for (List::Element *E = geom->lighting.front(); E; E = E->next()) { + InstanceLightData *light = static_cast(E->get()->base_data); + light->shadow_dirty = true; + } + + geom->can_cast_shadows = can_cast_shadows; + } + + geom->material_is_animated = is_animated; + } + + if (p_instance->skeleton.is_valid()) { + RSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance); + } + + p_instance->clean_up_dependencies(); + } + + _instance_update_list.remove(&p_instance->update_item); + + _update_instance(p_instance); + + p_instance->update_aabb = false; + p_instance->update_dependencies = false; +} + +void RenderingServerScene::update_dirty_instances() { + + RSG::storage->update_dirty_resources(); + + while (_instance_update_list.first()) { + + _update_dirty_instance(_instance_update_list.first()->self()); + } +} + +bool RenderingServerScene::free(RID p_rid) { + + if (camera_owner.owns(p_rid)) { + + Camera *camera = camera_owner.getornull(p_rid); + + camera_owner.free(p_rid); + memdelete(camera); + + } else if (scenario_owner.owns(p_rid)) { + + Scenario *scenario = scenario_owner.getornull(p_rid); + + while (scenario->instances.first()) { + instance_set_scenario(scenario->instances.first()->self()->self, RID()); + } + RSG::scene_render->free(scenario->reflection_probe_shadow_atlas); + RSG::scene_render->free(scenario->reflection_atlas); + scenario_owner.free(p_rid); + memdelete(scenario); + + } else if (instance_owner.owns(p_rid)) { + // delete the instance + + update_dirty_instances(); + + Instance *instance = instance_owner.getornull(p_rid); + + instance_set_use_lightmap(p_rid, RID(), RID()); + instance_set_scenario(p_rid, RID()); + instance_set_base(p_rid, RID()); + instance_geometry_set_material_override(p_rid, RID()); + instance_attach_skeleton(p_rid, RID()); + + update_dirty_instances(); //in case something changed this + + instance_owner.free(p_rid); + memdelete(instance); + } else { + return false; + } + + return true; +} + +RenderingServerScene *RenderingServerScene::singleton = NULL; + +RenderingServerScene::RenderingServerScene() { + + render_pass = 1; + singleton = this; +} + +RenderingServerScene::~RenderingServerScene() { +} diff --git a/servers/rendering/rendering_server_scene.h b/servers/rendering/rendering_server_scene.h new file mode 100644 index 0000000000..6012a75660 --- /dev/null +++ b/servers/rendering/rendering_server_scene.h @@ -0,0 +1,440 @@ +/*************************************************************************/ +/* rendering_server_scene.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VISUALSERVERSCENE_H +#define VISUALSERVERSCENE_H + +#include "servers/rendering/rasterizer.h" + +#include "core/math/geometry.h" +#include "core/math/octree.h" +#include "core/os/semaphore.h" +#include "core/os/thread.h" +#include "core/rid_owner.h" +#include "core/self_list.h" +#include "servers/arvr/arvr_interface.h" + +class RenderingServerScene { +public: + enum { + + MAX_INSTANCE_CULL = 65536, + MAX_LIGHTS_CULLED = 4096, + MAX_REFLECTION_PROBES_CULLED = 4096, + MAX_GI_PROBES_CULLED = 4096, + MAX_ROOM_CULL = 32, + MAX_EXTERIOR_PORTALS = 128, + }; + + uint64_t render_pass; + + static RenderingServerScene *singleton; + + /* CAMERA API */ + + struct Camera { + + enum Type { + PERSPECTIVE, + ORTHOGONAL, + FRUSTUM + }; + Type type; + float fov; + float znear, zfar; + float size; + Vector2 offset; + uint32_t visible_layers; + bool vaspect; + RID env; + RID effects; + + Transform transform; + + Camera() { + + visible_layers = 0xFFFFFFFF; + fov = 70; + type = PERSPECTIVE; + znear = 0.05; + zfar = 100; + size = 1.0; + offset = Vector2(); + vaspect = false; + } + }; + + mutable RID_PtrOwner camera_owner; + + virtual RID camera_create(); + virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); + virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); + virtual void camera_set_transform(RID p_camera, const Transform &p_transform); + virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); + virtual void camera_set_environment(RID p_camera, RID p_env); + virtual void camera_set_camera_effects(RID p_camera, RID p_fx); + virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable); + + /* SCENARIO API */ + + struct Instance; + + struct Scenario { + + RS::ScenarioDebugMode debug; + RID self; + + Octree octree; + + List directional_lights; + RID environment; + RID fallback_environment; + RID camera_effects; + RID reflection_probe_shadow_atlas; + RID reflection_atlas; + + SelfList::List instances; + + Scenario() { debug = RS::SCENARIO_DEBUG_DISABLED; } + }; + + mutable RID_PtrOwner scenario_owner; + + static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int); + static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *); + + virtual RID scenario_create(); + + virtual void scenario_set_debug(RID p_scenario, RS::ScenarioDebugMode p_debug_mode); + virtual void scenario_set_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx); + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); + virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count); + + /* INSTANCING API */ + + struct InstanceBaseData { + + virtual ~InstanceBaseData() {} + }; + + struct Instance : RasterizerScene::InstanceBase { + + RID self; + //scenario stuff + OctreeElementID octree_id; + Scenario *scenario; + SelfList scenario_item; + + //aabb stuff + bool update_aabb; + bool update_dependencies; + + SelfList update_item; + + AABB *custom_aabb; // would using aabb directly with a bool be better? + float extra_margin; + ObjectID object_id; + + float lod_begin; + float lod_end; + float lod_begin_hysteresis; + float lod_end_hysteresis; + RID lod_instance; + + uint64_t last_render_pass; + uint64_t last_frame_pass; + + uint64_t version; // changes to this, and changes to base increase version + + InstanceBaseData *base_data; + + virtual void dependency_deleted(RID p_dependency) { + if (p_dependency == base) { + singleton->instance_set_base(self, RID()); + } else if (p_dependency == skeleton) { + singleton->instance_attach_skeleton(self, RID()); + } else { + singleton->_instance_queue_update(this, false, true); + } + } + + virtual void dependency_changed(bool p_aabb, bool p_dependencies) { + singleton->_instance_queue_update(this, p_aabb, p_dependencies); + } + + Instance() : + scenario_item(this), + update_item(this) { + + octree_id = 0; + scenario = NULL; + + update_aabb = false; + update_dependencies = false; + + extra_margin = 0; + + visible = true; + + lod_begin = 0; + lod_end = 0; + lod_begin_hysteresis = 0; + lod_end_hysteresis = 0; + + last_render_pass = 0; + last_frame_pass = 0; + version = 1; + base_data = NULL; + + custom_aabb = NULL; + } + + ~Instance() { + + if (base_data) + memdelete(base_data); + if (custom_aabb) + memdelete(custom_aabb); + } + }; + + SelfList::List _instance_update_list; + void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false); + + struct InstanceGeometryData : public InstanceBaseData { + + List lighting; + bool lighting_dirty; + bool can_cast_shadows; + bool material_is_animated; + + List reflection_probes; + bool reflection_dirty; + + List gi_probes; + bool gi_probes_dirty; + + List lightmap_captures; + + InstanceGeometryData() { + + lighting_dirty = false; + reflection_dirty = true; + can_cast_shadows = true; + material_is_animated = true; + gi_probes_dirty = true; + } + }; + + struct InstanceReflectionProbeData : public InstanceBaseData { + + Instance *owner; + + struct PairInfo { + List::Element *L; //reflection iterator in geometry + Instance *geometry; + }; + List geometries; + + RID instance; + bool reflection_dirty; + SelfList update_list; + + int render_step; + + InstanceReflectionProbeData() : + update_list(this) { + + reflection_dirty = true; + render_step = -1; + } + }; + + SelfList::List reflection_probe_render_list; + + struct InstanceLightData : public InstanceBaseData { + + struct PairInfo { + List::Element *L; //light iterator in geometry + Instance *geometry; + }; + + RID instance; + uint64_t last_version; + List::Element *D; // directional light in scenario + + bool shadow_dirty; + + List geometries; + + Instance *baked_light; + + InstanceLightData() { + + shadow_dirty = true; + D = NULL; + last_version = 0; + baked_light = NULL; + } + }; + + struct InstanceGIProbeData : public InstanceBaseData { + + Instance *owner; + + struct PairInfo { + List::Element *L; //gi probe iterator in geometry + Instance *geometry; + }; + + List geometries; + List dynamic_geometries; + + Set lights; + + struct LightCache { + + RS::LightType type; + Transform transform; + Color color; + float energy; + float bake_energy; + float radius; + float attenuation; + float spot_angle; + float spot_attenuation; + bool has_shadow; + }; + + Vector light_cache; + Vector light_instances; + + RID probe_instance; + + bool invalid; + uint32_t base_version; + + SelfList update_element; + + InstanceGIProbeData() : + update_element(this) { + invalid = true; + base_version = 0; + } + }; + + SelfList::List gi_probe_update_list; + + struct InstanceLightmapCaptureData : public InstanceBaseData { + + struct PairInfo { + List::Element *L; //iterator in geometry + Instance *geometry; + }; + List geometries; + + Set users; + + InstanceLightmapCaptureData() { + } + }; + + int instance_cull_count; + Instance *instance_cull_result[MAX_INSTANCE_CULL]; + Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps + Instance *light_cull_result[MAX_LIGHTS_CULLED]; + RID light_instance_cull_result[MAX_LIGHTS_CULLED]; + int light_cull_count; + int directional_light_count; + RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED]; + int reflection_probe_cull_count; + RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED]; + int gi_probe_cull_count; + + RID_PtrOwner instance_owner; + + virtual RID instance_create(); + + virtual void instance_set_base(RID p_instance, RID p_base); + virtual void instance_set_scenario(RID p_instance, RID p_scenario); + virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); + virtual void instance_set_transform(RID p_instance, const Transform &p_transform); + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); + virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); + virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); + virtual void instance_set_visible(RID p_instance, bool p_visible); + virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap); + + virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb); + + virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton); + virtual void instance_set_exterior(RID p_instance, bool p_enabled); + + virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin); + + // don't use these in a game! + virtual Vector instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const; + virtual Vector instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; + virtual Vector instances_cull_convex(const Vector &p_convex, RID p_scenario = RID()) const; + + virtual void instance_geometry_set_flag(RID p_instance, RS::InstanceFlags p_flags, bool p_enabled); + virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, RS::ShadowCastingSetting p_shadow_casting_setting); + virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); + + virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin); + virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance); + + _FORCE_INLINE_ void _update_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); + _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); + _FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance); + + _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario); + + bool _render_reflection_probe_step(Instance *p_instance, int p_step); + void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true); + void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); + void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas); + + void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); + void render_camera(RID p_render_buffers, Ref &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); + void update_dirty_instances(); + + void render_probes(); + + bool free(RID p_rid); + + RenderingServerScene(); + virtual ~RenderingServerScene(); +}; + +#endif // VISUALSERVERSCENE_H diff --git a/servers/rendering/rendering_server_viewport.cpp b/servers/rendering/rendering_server_viewport.cpp new file mode 100644 index 0000000000..24b2379d97 --- /dev/null +++ b/servers/rendering/rendering_server_viewport.cpp @@ -0,0 +1,780 @@ +/*************************************************************************/ +/* rendering_server_viewport.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server_viewport.h" + +#include "core/project_settings.h" +#include "rendering_server_canvas.h" +#include "rendering_server_globals.h" +#include "rendering_server_scene.h" + +static Transform2D _canvas_get_transform(RenderingServerViewport::Viewport *p_viewport, RenderingServerCanvas::Canvas *p_canvas, RenderingServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) { + + Transform2D xf = p_viewport->global_transform; + + float scale = 1.0; + if (p_viewport->canvas_map.has(p_canvas->parent)) { + xf = xf * p_viewport->canvas_map[p_canvas->parent].transform; + scale = p_canvas->parent_scale; + } + + xf = xf * p_canvas_data->transform; + + if (scale != 1.0 && !RSG::canvas->disable_scale) { + Vector2 pivot = p_vp_size * 0.5; + Transform2D xfpivot; + xfpivot.set_origin(pivot); + Transform2D xfscale; + xfscale.scale(Vector2(scale, scale)); + + xf = xfpivot.affine_inverse() * xf; + xf = xfscale * xf; + xf = xfpivot * xf; + } + + return xf; +} + +void RenderingServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) { + + RENDER_TIMESTAMP(">Begin Rendering 3D Scene"); + + Ref arvr_interface; + if (ARVRServer::get_singleton() != NULL) { + arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); + } + + if (p_viewport->use_arvr && arvr_interface.is_valid()) { + RSG::scene->render_camera(p_viewport->render_buffers, arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } else { + RSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); + } + RENDER_TIMESTAMP("get_default_clear_color(); + + if (!p_viewport->hide_canvas && !p_viewport->disable_environment && RSG::scene->scenario_owner.owns(p_viewport->scenario)) { + + RenderingServerScene::Scenario *scenario = RSG::scene->scenario_owner.getornull(p_viewport->scenario); + ERR_FAIL_COND(!scenario); + if (RSG::scene_render->is_environment(scenario->environment)) { + scenario_draw_canvas_bg = RSG::scene_render->environment_get_background(scenario->environment) == RS::ENV_BG_CANVAS; + + scenario_canvas_max_layer = RSG::scene_render->environment_get_canvas_max_layer(scenario->environment); + } + } + + bool can_draw_3d = RSG::scene->camera_owner.owns(p_viewport->camera); + + if (p_viewport->clear_mode != RS::VIEWPORT_CLEAR_NEVER) { + if (p_viewport->transparent_bg) { + bgcolor = Color(0, 0, 0, 0); + } + if (p_viewport->clear_mode == RS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { + p_viewport->clear_mode = RS::VIEWPORT_CLEAR_NEVER; + } + } + + if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) { + //wants to draw 3D but there is no render buffer, create + p_viewport->render_buffers = RSG::scene_render->render_buffers_create(); + RSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa); + } + + RSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor); + + if (!scenario_draw_canvas_bg && can_draw_3d) { + _draw_3d(p_viewport, p_eye); + } + + if (!p_viewport->hide_canvas) { + int i = 0; + + Map canvas_map; + + Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); + RasterizerCanvas::Light *lights = NULL; + RasterizerCanvas::Light *lights_with_shadow = NULL; + RasterizerCanvas::Light *lights_with_mask = NULL; + Rect2 shadow_rect; + + int light_count = 0; + + RENDER_TIMESTAMP("Cull Canvas Lights"); + for (Map::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { + + RenderingServerCanvas::Canvas *canvas = static_cast(E->get().canvas); + + Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); + + //find lights in canvas + + for (Set::Element *F = canvas->lights.front(); F; F = F->next()) { + + RasterizerCanvas::Light *cl = F->get(); + if (cl->enabled && cl->texture.is_valid()) { + //not super efficient.. + Size2 tsize = RSG::storage->texture_size_with_proxy(cl->texture); + tsize *= cl->scale; + + Vector2 offset = tsize / 2.0; + cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize); + cl->xform_cache = xf * cl->xform; + + if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) { + + cl->filter_next_ptr = lights; + lights = cl; + // cl->texture_cache = NULL; + Transform2D scale; + scale.scale(cl->rect_cache.size); + scale.elements[2] = cl->rect_cache.position; + cl->light_shader_xform = cl->xform * scale; + //cl->light_shader_pos = cl->xform_cache[2]; + if (cl->use_shadow) { + + cl->shadows_next_ptr = lights_with_shadow; + if (lights_with_shadow == NULL) { + shadow_rect = cl->xform_cache.xform(cl->rect_cache); + } else { + shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache)); + } + lights_with_shadow = cl; + cl->radius_cache = cl->rect_cache.size.length(); + } + if (cl->mode == RS::CANVAS_LIGHT_MODE_MASK) { + cl->mask_next_ptr = lights_with_mask; + lights_with_mask = cl; + } + + light_count++; + } + + //guess this is not needed, but keeping because it may be + //RSG::canvas_render->light_internal_update(cl->light_internal, cl); + } + } + + canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get(); + } + + if (lights_with_shadow) { + //update shadows if any + + RasterizerCanvas::LightOccluderInstance *occluders = NULL; + + RENDER_TIMESTAMP(">Render 2D Shadows"); + RENDER_TIMESTAMP("Cull Occluders"); + + //make list of occluders + for (Map::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { + + RenderingServerCanvas::Canvas *canvas = static_cast(E->get().canvas); + Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); + + for (Set::Element *F = canvas->occluders.front(); F; F = F->next()) { + + if (!F->get()->enabled) + continue; + F->get()->xform_cache = xf * F->get()->xform; + if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) { + + F->get()->next = occluders; + occluders = F->get(); + } + } + } + //update the light shadowmaps with them + + RasterizerCanvas::Light *light = lights_with_shadow; + while (light) { + + RENDER_TIMESTAMP("Render Shadow"); + + RSG::canvas_render->light_update_shadow(light->light_internal, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders); + light = light->shadows_next_ptr; + } + + //RSG::canvas_render->reset_canvas(); + RENDER_TIMESTAMP("key().get_layer() > scenario_canvas_max_layer) { + if (!can_draw_3d) { + RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); + } else { + _draw_3d(p_viewport, p_eye); + } + scenario_draw_canvas_bg = false; + } + + for (Map::Element *E = canvas_map.front(); E; E = E->next()) { + + RenderingServerCanvas::Canvas *canvas = static_cast(E->get()->canvas); + + Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size); + + RasterizerCanvas::Light *canvas_lights = NULL; + + RasterizerCanvas::Light *ptr = lights; + while (ptr) { + if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) { + ptr->next_ptr = canvas_lights; + canvas_lights = ptr; + } + ptr = ptr->filter_next_ptr; + } + + RSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, lights_with_mask, clip_rect); + i++; + + if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) { + if (!can_draw_3d) { + RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); + } else { + _draw_3d(p_viewport, p_eye); + } + + scenario_draw_canvas_bg = false; + } + } + + if (scenario_draw_canvas_bg) { + if (!can_draw_3d) { + RSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); + } else { + _draw_3d(p_viewport, p_eye); + } + } + + //RSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); + } + + if (RSG::storage->render_target_is_clear_requested(p_viewport->render_target)) { + //was never cleared in the end, force clear it + RSG::storage->render_target_do_clear_request(p_viewport->render_target); + } +} + +void RenderingServerViewport::draw_viewports() { + +#if 0 + // get our arvr interface in case we need it + Ref arvr_interface; + + if (ARVRServer::get_singleton() != NULL) { + arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); + + // process all our active interfaces + ARVRServer::get_singleton()->_process(); + } +#endif + + if (Engine::get_singleton()->is_editor_hint()) { + set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color")); + } + + //sort viewports + active_viewports.sort_custom(); + + Map> blit_to_screen_list; + //draw viewports + RENDER_TIMESTAMP(">Render Viewports"); + + //determine what is visible + draw_viewports_pass++; + + for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order + + Viewport *vp = active_viewports[i]; + + if (vp->update_mode == RS::VIEWPORT_UPDATE_DISABLED) + continue; + + if (!vp->render_target.is_valid()) { + continue; + } + //ERR_CONTINUE(!vp->render_target.is_valid()); + + bool visible = vp->viewport_to_screen_rect != Rect2(); + + if (vp->update_mode == RS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) { + visible = true; + } + + if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_VISIBLE && RSG::storage->render_target_was_used(vp->render_target)) { + visible = true; + } + + if (vp->update_mode == RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE) { + Viewport *parent = viewport_owner.getornull(vp->parent); + if (parent && parent->last_pass == draw_viewports_pass) { + visible = true; + } + } + + visible = visible && vp->size.x > 1 && vp->size.y > 1; + + if (visible) { + vp->last_pass = draw_viewports_pass; + } + } + + for (int i = 0; i < active_viewports.size(); i++) { + + Viewport *vp = active_viewports[i]; + + if (vp->last_pass != draw_viewports_pass) { + continue; //should not draw + } + + RENDER_TIMESTAMP(">Rendering Viewport " + itos(i)); + + RSG::storage->render_target_set_as_unused(vp->render_target); +#if 0 + if (vp->use_arvr && arvr_interface.is_valid()) { + // override our size, make sure it matches our required size + vp->size = arvr_interface->get_render_targetsize(); + RSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y); + + // render mono or left eye first + ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO; + + // check for an external texture destination for our left eye/mono + RSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono)); + + // set our render target as current + RSG::rasterizer->set_current_render_target(vp->render_target); + + // and draw left eye/mono + _draw_viewport(vp, leftOrMono); + arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect); + + // render right eye + if (leftOrMono == ARVRInterface::EYE_LEFT) { + // check for an external texture destination for our right eye + RSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT)); + + // commit for eye may have changed the render target + RSG::rasterizer->set_current_render_target(vp->render_target); + + _draw_viewport(vp, ARVRInterface::EYE_RIGHT); + arvr_interface->commit_for_eye(ARVRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect); + } + + // and for our frame timing, mark when we've finished committing our eyes + ARVRServer::get_singleton()->_mark_commit(); + } else { +#endif + { + RSG::storage->render_target_set_external_texture(vp->render_target, 0); + + RSG::scene_render->set_debug_draw_mode(vp->debug_draw); + RSG::storage->render_info_begin_capture(); + + // render standard mono camera + _draw_viewport(vp); + + RSG::storage->render_info_end_capture(); + vp->render_info[RS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_OBJECTS_IN_FRAME); + vp->render_info[RS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_VERTICES_IN_FRAME); + vp->render_info[RS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_MATERIAL_CHANGES_IN_FRAME); + vp->render_info[RS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SHADER_CHANGES_IN_FRAME); + vp->render_info[RS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_SURFACE_CHANGES_IN_FRAME); + vp->render_info[RS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = RSG::storage->get_captured_render_info(RS::INFO_DRAW_CALLS_IN_FRAME); + + if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !RSG::rasterizer->is_low_end())) { + //copy to screen if set as such + Rasterizer::BlitToScreen blit; + blit.render_target = vp->render_target; + if (vp->viewport_to_screen_rect != Rect2()) { + blit.rect = vp->viewport_to_screen_rect; + } else { + blit.rect.position = Vector2(); + blit.rect.size = vp->size; + } + + if (!blit_to_screen_list.has(vp->viewport_to_screen)) { + blit_to_screen_list[vp->viewport_to_screen] = Vector(); + } + + blit_to_screen_list[vp->viewport_to_screen].push_back(blit); + } + } + + if (vp->update_mode == RS::VIEWPORT_UPDATE_ONCE) { + vp->update_mode = RS::VIEWPORT_UPDATE_DISABLED; + } + + RENDER_TIMESTAMP("set_debug_draw_mode(RS::VIEWPORT_DEBUG_DRAW_DISABLED); + + RENDER_TIMESTAMP("prepare_for_blitting_render_targets(); + + for (Map>::Element *E = blit_to_screen_list.front(); E; E = E->next()) { + RSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size()); + } +} + +RID RenderingServerViewport::viewport_create() { + + Viewport *viewport = memnew(Viewport); + + RID rid = viewport_owner.make_rid(viewport); + + viewport->self = rid; + viewport->hide_scenario = false; + viewport->hide_canvas = false; + viewport->render_target = RSG::storage->render_target_create(); + viewport->shadow_atlas = RSG::scene_render->shadow_atlas_create(); + viewport->viewport_render_direct_to_screen = false; + + return rid; +} + +void RenderingServerViewport::viewport_set_use_arvr(RID p_viewport, bool p_use_arvr) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->use_arvr = p_use_arvr; +} + +void RenderingServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) { + + ERR_FAIL_COND(p_width < 0 && p_height < 0); + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->size = Size2(p_width, p_height); + RSG::storage->render_target_set_size(viewport->render_target, p_width, p_height); + if (viewport->render_buffers.is_valid()) { + if (p_width == 0 || p_height == 0) { + RSG::scene_render->free(viewport->render_buffers); + viewport->render_buffers = RID(); + } else { + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa); + } + } +} + +void RenderingServerViewport::viewport_set_active(RID p_viewport, bool p_active) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_active) { + ERR_FAIL_COND(active_viewports.find(viewport) != -1); //already active + active_viewports.push_back(viewport); + } else { + active_viewports.erase(viewport); + } +} + +void RenderingServerViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->parent = p_parent_viewport; +} + +void RenderingServerViewport::viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->clear_mode = p_clear_mode; +} + +void RenderingServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_screen != DisplayServer::INVALID_WINDOW_ID) { + // If using GLES2 we can optimize this operation by rendering directly to system_fbo + // instead of rendering to fbo and copying to system_fbo after + if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + RSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y); + RSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y); + } + + viewport->viewport_to_screen_rect = p_rect; + viewport->viewport_to_screen = p_screen; + } else { + + // if render_direct_to_screen was used, reset size and position + if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { + + RSG::storage->render_target_set_position(viewport->render_target, 0, 0); + RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + + viewport->viewport_to_screen_rect = Rect2(); + viewport->viewport_to_screen = DisplayServer::INVALID_WINDOW_ID; + } +} + +void RenderingServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (p_enable == viewport->viewport_render_direct_to_screen) + return; + + // if disabled, reset render_target size and position + if (!p_enable) { + + RSG::storage->render_target_set_position(viewport->render_target, 0, 0); + RSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); + } + + RSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); + viewport->viewport_render_direct_to_screen = p_enable; + + // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation + if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) { + + RSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y); + RSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y); + } +} + +void RenderingServerViewport::viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->update_mode = p_mode; +} + +RID RenderingServerViewport::viewport_get_texture(RID p_viewport) const { + + const Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND_V(!viewport, RID()); + + return RSG::storage->render_target_get_texture(viewport->render_target); +} + +void RenderingServerViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->hide_scenario = p_hide; +} +void RenderingServerViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->hide_canvas = p_hide; +} +void RenderingServerViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->disable_environment = p_disable; +} + +void RenderingServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->camera = p_camera; +} +void RenderingServerViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->scenario = p_scenario; +} +void RenderingServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(viewport->canvas_map.has(p_canvas)); + RenderingServerCanvas::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + canvas->viewports.insert(p_viewport); + viewport->canvas_map[p_canvas] = Viewport::CanvasData(); + viewport->canvas_map[p_canvas].layer = 0; + viewport->canvas_map[p_canvas].sublayer = 0; + viewport->canvas_map[p_canvas].canvas = canvas; +} + +void RenderingServerViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + RenderingServerCanvas::Canvas *canvas = RSG::canvas->canvas_owner.getornull(p_canvas); + ERR_FAIL_COND(!canvas); + + viewport->canvas_map.erase(p_canvas); + canvas->viewports.erase(p_viewport); +} +void RenderingServerViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); + viewport->canvas_map[p_canvas].transform = p_offset; +} +void RenderingServerViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + RSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_TRANSPARENT, p_enabled); + viewport->transparent_bg = p_enabled; +} + +void RenderingServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->global_transform = p_transform; +} +void RenderingServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); + viewport->canvas_map[p_canvas].layer = p_layer; + viewport->canvas_map[p_canvas].sublayer = p_sublayer; +} + +void RenderingServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->shadow_atlas_size = p_size; + + RSG::scene_render->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size); +} + +void RenderingServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + RSG::scene_render->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv); +} + +void RenderingServerViewport::viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + if (viewport->msaa == p_msaa) { + return; + } + viewport->msaa = p_msaa; + if (viewport->render_buffers.is_valid()) { + RSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa); + } +} + +int RenderingServerViewport::viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info) { + + ERR_FAIL_INDEX_V(p_info, RS::VIEWPORT_RENDER_INFO_MAX, -1); + + Viewport *viewport = viewport_owner.getornull(p_viewport); + if (!viewport) + return 0; //there should be a lock here.. + + return viewport->render_info[p_info]; +} + +void RenderingServerViewport::viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw) { + + Viewport *viewport = viewport_owner.getornull(p_viewport); + ERR_FAIL_COND(!viewport); + + viewport->debug_draw = p_draw; +} + +bool RenderingServerViewport::free(RID p_rid) { + + if (viewport_owner.owns(p_rid)) { + + Viewport *viewport = viewport_owner.getornull(p_rid); + + RSG::storage->free(viewport->render_target); + RSG::scene_render->free(viewport->shadow_atlas); + if (viewport->render_buffers.is_valid()) { + RSG::scene_render->free(viewport->render_buffers); + } + + while (viewport->canvas_map.front()) { + viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key()); + } + + viewport_set_scenario(p_rid, RID()); + active_viewports.erase(viewport); + + viewport_owner.free(p_rid); + memdelete(viewport); + + return true; + } + + return false; +} + +void RenderingServerViewport::set_default_clear_color(const Color &p_color) { + RSG::storage->set_default_clear_color(p_color); +} + +RenderingServerViewport::RenderingServerViewport() { +} diff --git a/servers/rendering/rendering_server_viewport.h b/servers/rendering/rendering_server_viewport.h new file mode 100644 index 0000000000..4ae7a7f536 --- /dev/null +++ b/servers/rendering/rendering_server_viewport.h @@ -0,0 +1,208 @@ +/*************************************************************************/ +/* rendering_server_viewport.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef VISUALSERVERVIEWPORT_H +#define VISUALSERVERVIEWPORT_H + +#include "core/rid_owner.h" +#include "core/self_list.h" +#include "rasterizer.h" +#include "servers/arvr/arvr_interface.h" +#include "servers/rendering_server.h" + +class RenderingServerViewport { +public: + struct CanvasBase { + }; + + struct Viewport { + + RID self; + RID parent; + + bool use_arvr; /* use arvr interface to override camera positioning and projection matrices and control output */ + + Size2i size; + RID camera; + RID scenario; + + RS::ViewportUpdateMode update_mode; + RID render_target; + RID render_target_texture; + RID render_buffers; + + RS::ViewportMSAA msaa; + + DisplayServer::WindowID viewport_to_screen; + Rect2 viewport_to_screen_rect; + bool viewport_render_direct_to_screen; + + bool hide_scenario; + bool hide_canvas; + bool disable_environment; + bool disable_3d_by_usage; + bool keep_3d_linear; + + RID shadow_atlas; + int shadow_atlas_size; + + uint64_t last_pass = 0; + + int render_info[RS::VIEWPORT_RENDER_INFO_MAX]; + RS::ViewportDebugDraw debug_draw; + + RS::ViewportClearMode clear_mode; + + bool transparent_bg; + + struct CanvasKey { + + int64_t stacking; + RID canvas; + bool operator<(const CanvasKey &p_canvas) const { + if (stacking == p_canvas.stacking) + return canvas < p_canvas.canvas; + return stacking < p_canvas.stacking; + } + CanvasKey() { + stacking = 0; + } + CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) { + canvas = p_canvas; + int64_t sign = p_layer < 0 ? -1 : 1; + stacking = sign * (((int64_t)ABS(p_layer)) << 32) + p_sublayer; + } + int get_layer() const { return stacking >> 32; } + }; + + struct CanvasData { + + CanvasBase *canvas; + Transform2D transform; + int layer; + int sublayer; + }; + + Transform2D global_transform; + + Map canvas_map; + + Viewport() { + update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE; + clear_mode = RS::VIEWPORT_CLEAR_ALWAYS; + transparent_bg = false; + disable_environment = false; + viewport_to_screen = DisplayServer::INVALID_WINDOW_ID; + shadow_atlas_size = 0; + keep_3d_linear = false; + debug_draw = RS::VIEWPORT_DEBUG_DRAW_DISABLED; + msaa = RS::VIEWPORT_MSAA_DISABLED; + for (int i = 0; i < RS::VIEWPORT_RENDER_INFO_MAX; i++) { + render_info[i] = 0; + } + use_arvr = false; + } + }; + + uint64_t draw_viewports_pass = 0; + + mutable RID_PtrOwner viewport_owner; + + struct ViewportSort { + _FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const { + + bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2(); + bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2(); + + if (left_to_screen == right_to_screen) { + + return p_right->parent == p_left->self; + } + return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1); + } + }; + + Vector active_viewports; + +private: + void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye); + void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO); + +public: + RID viewport_create(); + + void viewport_set_use_arvr(RID p_viewport, bool p_use_arvr); + + void viewport_set_size(RID p_viewport, int p_width, int p_height); + + void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID); + void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable); + + void viewport_set_active(RID p_viewport, bool p_active); + void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport); + void viewport_set_update_mode(RID p_viewport, RS::ViewportUpdateMode p_mode); + void viewport_set_vflip(RID p_viewport, bool p_enable); + + void viewport_set_clear_mode(RID p_viewport, RS::ViewportClearMode p_clear_mode); + + RID viewport_get_texture(RID p_viewport) const; + + void viewport_set_hide_scenario(RID p_viewport, bool p_hide); + void viewport_set_hide_canvas(RID p_viewport, bool p_hide); + void viewport_set_disable_environment(RID p_viewport, bool p_disable); + + void viewport_attach_camera(RID p_viewport, RID p_camera); + void viewport_set_scenario(RID p_viewport, RID p_scenario); + void viewport_attach_canvas(RID p_viewport, RID p_canvas); + void viewport_remove_canvas(RID p_viewport, RID p_canvas); + void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset); + void viewport_set_transparent_background(RID p_viewport, bool p_enabled); + + void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform); + void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer); + + void viewport_set_shadow_atlas_size(RID p_viewport, int p_size); + void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); + + void viewport_set_msaa(RID p_viewport, RS::ViewportMSAA p_msaa); + + virtual int viewport_get_render_info(RID p_viewport, RS::ViewportRenderInfo p_info); + virtual void viewport_set_debug_draw(RID p_viewport, RS::ViewportDebugDraw p_draw); + + void set_default_clear_color(const Color &p_color); + void draw_viewports(); + + bool free(RID p_rid); + + RenderingServerViewport(); + virtual ~RenderingServerViewport() {} +}; + +#endif // VISUALSERVERVIEWPORT_H diff --git a/servers/rendering/rendering_server_wrap_mt.cpp b/servers/rendering/rendering_server_wrap_mt.cpp new file mode 100644 index 0000000000..d1bb7b67c6 --- /dev/null +++ b/servers/rendering/rendering_server_wrap_mt.cpp @@ -0,0 +1,197 @@ +/*************************************************************************/ +/* rendering_server_wrap_mt.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server_wrap_mt.h" +#include "core/os/os.h" +#include "core/project_settings.h" +#include "servers/display_server.h" + +void RenderingServerWrapMT::thread_exit() { + + exit = true; +} + +void RenderingServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) { + + if (!atomic_decrement(&draw_pending)) { + + rendering_server->draw(p_swap_buffers, frame_step); + } +} + +void RenderingServerWrapMT::thread_flush() { + + atomic_decrement(&draw_pending); +} + +void RenderingServerWrapMT::_thread_callback(void *_instance) { + + RenderingServerWrapMT *vsmt = reinterpret_cast(_instance); + + vsmt->thread_loop(); +} + +void RenderingServerWrapMT::thread_loop() { + + server_thread = Thread::get_caller_id(); + + DisplayServer::get_singleton()->make_rendering_thread(); + + rendering_server->init(); + + exit = false; + draw_thread_up = true; + while (!exit) { + // flush commands one by one, until exit is requested + command_queue.wait_and_flush_one(); + } + + command_queue.flush_all(); // flush all + + rendering_server->finish(); +} + +/* EVENT QUEUING */ + +void RenderingServerWrapMT::sync() { + + if (create_thread) { + + atomic_increment(&draw_pending); + command_queue.push_and_sync(this, &RenderingServerWrapMT::thread_flush); + } else { + + command_queue.flush_all(); //flush all pending from other threads + } +} + +void RenderingServerWrapMT::draw(bool p_swap_buffers, double frame_step) { + + if (create_thread) { + + atomic_increment(&draw_pending); + command_queue.push(this, &RenderingServerWrapMT::thread_draw, p_swap_buffers, frame_step); + } else { + + rendering_server->draw(p_swap_buffers, frame_step); + } +} + +void RenderingServerWrapMT::init() { + + if (create_thread) { + + print_verbose("RenderingServerWrapMT: Creating render thread"); + DisplayServer::get_singleton()->release_rendering_thread(); + if (create_thread) { + thread = Thread::create(_thread_callback, this); + print_verbose("RenderingServerWrapMT: Starting render thread"); + } + while (!draw_thread_up) { + OS::get_singleton()->delay_usec(1000); + } + print_verbose("RenderingServerWrapMT: Finished render thread"); + } else { + + rendering_server->init(); + } +} + +void RenderingServerWrapMT::finish() { + + if (thread) { + + command_queue.push(this, &RenderingServerWrapMT::thread_exit); + Thread::wait_to_finish(thread); + memdelete(thread); + + thread = NULL; + } else { + rendering_server->finish(); + } + + sky_free_cached_ids(); + shader_free_cached_ids(); + material_free_cached_ids(); + mesh_free_cached_ids(); + multimesh_free_cached_ids(); + immediate_free_cached_ids(); + skeleton_free_cached_ids(); + directional_light_free_cached_ids(); + omni_light_free_cached_ids(); + spot_light_free_cached_ids(); + reflection_probe_free_cached_ids(); + gi_probe_free_cached_ids(); + lightmap_capture_free_cached_ids(); + particles_free_cached_ids(); + camera_free_cached_ids(); + viewport_free_cached_ids(); + environment_free_cached_ids(); + camera_effects_free_cached_ids(); + scenario_free_cached_ids(); + instance_free_cached_ids(); + canvas_free_cached_ids(); + canvas_item_free_cached_ids(); + canvas_light_occluder_free_cached_ids(); + canvas_occluder_polygon_free_cached_ids(); +} + +void RenderingServerWrapMT::set_use_vsync_callback(bool p_enable) { + + singleton_mt->call_set_use_vsync(p_enable); +} + +RenderingServerWrapMT *RenderingServerWrapMT::singleton_mt = NULL; + +RenderingServerWrapMT::RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread) : + command_queue(p_create_thread) { + + singleton_mt = this; + DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly + + rendering_server = p_contained; + create_thread = p_create_thread; + thread = NULL; + draw_pending = 0; + draw_thread_up = false; + pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); + + if (!p_create_thread) { + server_thread = Thread::get_caller_id(); + } else { + server_thread = 0; + } +} + +RenderingServerWrapMT::~RenderingServerWrapMT() { + + memdelete(rendering_server); + //finish(); +} diff --git a/servers/rendering/rendering_server_wrap_mt.h b/servers/rendering/rendering_server_wrap_mt.h new file mode 100644 index 0000000000..4d449ea913 --- /dev/null +++ b/servers/rendering/rendering_server_wrap_mt.h @@ -0,0 +1,678 @@ +/*************************************************************************/ +/* rendering_server_wrap_mt.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDERING_SERVER_WRAP_MT_H +#define RENDERING_SERVER_WRAP_MT_H + +#include "core/command_queue_mt.h" +#include "core/os/thread.h" +#include "servers/rendering_server.h" + +class RenderingServerWrapMT : public RenderingServer { + + // the real visual server + mutable RenderingServer *rendering_server; + + mutable CommandQueueMT command_queue; + + static void _thread_callback(void *_instance); + void thread_loop(); + + Thread::ID server_thread; + volatile bool exit; + Thread *thread; + volatile bool draw_thread_up; + bool create_thread; + + uint64_t draw_pending; + void thread_draw(bool p_swap_buffers, double frame_step); + void thread_flush(); + + void thread_exit(); + + Mutex alloc_mutex; + + int pool_max_size; + + //#define DEBUG_SYNC + + static RenderingServerWrapMT *singleton_mt; + +#ifdef DEBUG_SYNC +#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__)); +#else +#define SYNC_DEBUG +#endif + +public: +#define ServerName RenderingServer +#define ServerNameWrapMT RenderingServerWrapMT +#define server_name rendering_server +#include "servers/server_wrap_mt_common.h" + + //these go pass-through, as they can be called from any thread + virtual RID texture_2d_create(const Ref &p_image) { return rendering_server->texture_2d_create(p_image); } + virtual RID texture_2d_layered_create(const Vector> &p_layers, TextureLayeredType p_layered_type) { return rendering_server->texture_2d_layered_create(p_layers, p_layered_type); } + virtual RID texture_3d_create(const Vector> &p_slices) { return rendering_server->texture_3d_create(p_slices); } + virtual RID texture_proxy_create(RID p_base) { return rendering_server->texture_proxy_create(p_base); } + + //goes pass-through + virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0) { rendering_server->texture_2d_update_immediate(p_texture, p_image, p_layer); } + //these go through command queue if they are in another thread + FUNC3(texture_2d_update, RID, const Ref &, int) + FUNC4(texture_3d_update, RID, const Ref &, int, int) + FUNC2(texture_proxy_update, RID, RID) + + //these also go pass-through + virtual RID texture_2d_placeholder_create() { return rendering_server->texture_2d_placeholder_create(); } + virtual RID texture_2d_layered_placeholder_create() { return rendering_server->texture_2d_layered_placeholder_create(); } + virtual RID texture_3d_placeholder_create() { return rendering_server->texture_3d_placeholder_create(); } + + FUNC1RC(Ref, texture_2d_get, RID) + FUNC2RC(Ref, texture_2d_layer_get, RID, int) + FUNC3RC(Ref, texture_3d_slice_get, RID, int, int) + + FUNC2(texture_replace, RID, RID) + + FUNC3(texture_set_size_override, RID, int, int) +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + FUNC2(texture_bind, RID, uint32_t) +#endif + + FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *) + FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *) + FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *) + + FUNC2(texture_set_path, RID, const String &) + FUNC1RC(String, texture_get_path, RID) + FUNC1S(texture_debug_usage, List *) + + FUNC2(texture_set_force_redraw_if_visible, RID, bool) + + /* SHADER API */ + + FUNCRID(shader) + + FUNC2(shader_set_code, RID, const String &) + FUNC1RC(String, shader_get_code, RID) + + FUNC2SC(shader_get_param_list, RID, List *) + + FUNC3(shader_set_default_texture_param, RID, const StringName &, RID) + FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &) + FUNC2RC(Variant, shader_get_param_default, RID, const StringName &) + + /* COMMON MATERIAL API */ + + FUNCRID(material) + + FUNC2(material_set_shader, RID, RID) + + FUNC3(material_set_param, RID, const StringName &, const Variant &) + FUNC2RC(Variant, material_get_param, RID, const StringName &) + + FUNC2(material_set_render_priority, RID, int) + FUNC2(material_set_next_pass, RID, RID) + + /* MESH API */ + + virtual RID mesh_create_from_surfaces(const Vector &p_surfaces) { + return rendering_server->mesh_create_from_surfaces(p_surfaces); + } + + FUNCRID(mesh) + + FUNC2(mesh_add_surface, RID, const SurfaceData &) + + FUNC1RC(int, mesh_get_blend_shape_count, RID) + + FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode) + FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID) + + FUNC4(mesh_surface_update_region, RID, int, int, const Vector &) + + FUNC3(mesh_surface_set_material, RID, int, RID) + FUNC2RC(RID, mesh_surface_get_material, RID, int) + + FUNC2RC(SurfaceData, mesh_get_surface, RID, int) + + FUNC1RC(int, mesh_get_surface_count, RID) + + FUNC2(mesh_set_custom_aabb, RID, const AABB &) + FUNC1RC(AABB, mesh_get_custom_aabb, RID) + + FUNC1(mesh_clear, RID) + + /* MULTIMESH API */ + + FUNCRID(multimesh) + + FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool) + FUNC1RC(int, multimesh_get_instance_count, RID) + + FUNC2(multimesh_set_mesh, RID, RID) + FUNC3(multimesh_instance_set_transform, RID, int, const Transform &) + FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &) + FUNC3(multimesh_instance_set_color, RID, int, const Color &) + FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &) + + FUNC1RC(RID, multimesh_get_mesh, RID) + FUNC1RC(AABB, multimesh_get_aabb, RID) + + FUNC2RC(Transform, multimesh_instance_get_transform, RID, int) + FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int) + FUNC2RC(Color, multimesh_instance_get_color, RID, int) + FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int) + + FUNC2(multimesh_set_buffer, RID, const Vector &) + FUNC1RC(Vector, multimesh_get_buffer, RID) + + FUNC2(multimesh_set_visible_instances, RID, int) + FUNC1RC(int, multimesh_get_visible_instances, RID) + + /* IMMEDIATE API */ + + FUNCRID(immediate) + FUNC3(immediate_begin, RID, PrimitiveType, RID) + FUNC2(immediate_vertex, RID, const Vector3 &) + FUNC2(immediate_normal, RID, const Vector3 &) + FUNC2(immediate_tangent, RID, const Plane &) + FUNC2(immediate_color, RID, const Color &) + FUNC2(immediate_uv, RID, const Vector2 &) + FUNC2(immediate_uv2, RID, const Vector2 &) + FUNC1(immediate_end, RID) + FUNC1(immediate_clear, RID) + FUNC2(immediate_set_material, RID, RID) + FUNC1RC(RID, immediate_get_material, RID) + + /* SKELETON API */ + + FUNCRID(skeleton) + FUNC3(skeleton_allocate, RID, int, bool) + FUNC1RC(int, skeleton_get_bone_count, RID) + FUNC3(skeleton_bone_set_transform, RID, int, const Transform &) + FUNC2RC(Transform, skeleton_bone_get_transform, RID, int) + FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) + FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) + FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &) + + /* Light API */ + + FUNCRID(directional_light) + FUNCRID(omni_light) + FUNCRID(spot_light) + + FUNC2(light_set_color, RID, const Color &) + FUNC3(light_set_param, RID, LightParam, float) + FUNC2(light_set_shadow, RID, bool) + FUNC2(light_set_shadow_color, RID, const Color &) + FUNC2(light_set_projector, RID, RID) + FUNC2(light_set_negative, RID, bool) + FUNC2(light_set_cull_mask, RID, uint32_t) + FUNC2(light_set_reverse_cull_face_mode, RID, bool) + FUNC2(light_set_use_gi, RID, bool) + + FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) + + FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) + FUNC2(light_directional_set_blend_splits, RID, bool) + FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) + + /* PROBE API */ + + FUNCRID(reflection_probe) + + FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode) + FUNC2(reflection_probe_set_intensity, RID, float) + FUNC2(reflection_probe_set_interior_ambient, RID, const Color &) + FUNC2(reflection_probe_set_interior_ambient_energy, RID, float) + FUNC2(reflection_probe_set_interior_ambient_probe_contribution, RID, float) + FUNC2(reflection_probe_set_max_distance, RID, float) + FUNC2(reflection_probe_set_extents, RID, const Vector3 &) + FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &) + FUNC2(reflection_probe_set_as_interior, RID, bool) + FUNC2(reflection_probe_set_enable_box_projection, RID, bool) + FUNC2(reflection_probe_set_enable_shadows, RID, bool) + FUNC2(reflection_probe_set_cull_mask, RID, uint32_t) + FUNC2(reflection_probe_set_resolution, RID, int) + + /* BAKED LIGHT API */ + + FUNCRID(gi_probe) + + FUNC8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector &, const Vector &, const Vector &, const Vector &) + + FUNC1RC(AABB, gi_probe_get_bounds, RID) + FUNC1RC(Vector3i, gi_probe_get_octree_size, RID) + FUNC1RC(Vector, gi_probe_get_octree_cells, RID) + FUNC1RC(Vector, gi_probe_get_data_cells, RID) + FUNC1RC(Vector, gi_probe_get_distance_field, RID) + FUNC1RC(Vector, gi_probe_get_level_counts, RID) + FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID) + + FUNC2(gi_probe_set_dynamic_range, RID, float) + FUNC1RC(float, gi_probe_get_dynamic_range, RID) + + FUNC2(gi_probe_set_propagation, RID, float) + FUNC1RC(float, gi_probe_get_propagation, RID) + + FUNC2(gi_probe_set_energy, RID, float) + FUNC1RC(float, gi_probe_get_energy, RID) + + FUNC2(gi_probe_set_ao, RID, float) + FUNC1RC(float, gi_probe_get_ao, RID) + + FUNC2(gi_probe_set_ao_size, RID, float) + FUNC1RC(float, gi_probe_get_ao_size, RID) + + FUNC2(gi_probe_set_bias, RID, float) + FUNC1RC(float, gi_probe_get_bias, RID) + + FUNC2(gi_probe_set_normal_bias, RID, float) + FUNC1RC(float, gi_probe_get_normal_bias, RID) + + FUNC2(gi_probe_set_interior, RID, bool) + FUNC1RC(bool, gi_probe_is_interior, RID) + + FUNC2(gi_probe_set_use_two_bounces, RID, bool) + FUNC1RC(bool, gi_probe_is_using_two_bounces, RID) + + FUNC2(gi_probe_set_anisotropy_strength, RID, float) + FUNC1RC(float, gi_probe_get_anisotropy_strength, RID) + + /* LIGHTMAP CAPTURE */ + + FUNCRID(lightmap_capture) + + FUNC2(lightmap_capture_set_bounds, RID, const AABB &) + FUNC1RC(AABB, lightmap_capture_get_bounds, RID) + + FUNC2(lightmap_capture_set_octree, RID, const Vector &) + FUNC1RC(Vector, lightmap_capture_get_octree, RID) + FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) + FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) + FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int) + FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) + FUNC2(lightmap_capture_set_energy, RID, float) + FUNC1RC(float, lightmap_capture_get_energy, RID) + + /* PARTICLES */ + + FUNCRID(particles) + + FUNC2(particles_set_emitting, RID, bool) + FUNC1R(bool, particles_get_emitting, RID) + FUNC2(particles_set_amount, RID, int) + FUNC2(particles_set_lifetime, RID, float) + FUNC2(particles_set_one_shot, RID, bool) + FUNC2(particles_set_pre_process_time, RID, float) + FUNC2(particles_set_explosiveness_ratio, RID, float) + FUNC2(particles_set_randomness_ratio, RID, float) + FUNC2(particles_set_custom_aabb, RID, const AABB &) + FUNC2(particles_set_speed_scale, RID, float) + FUNC2(particles_set_use_local_coordinates, RID, bool) + FUNC2(particles_set_process_material, RID, RID) + FUNC2(particles_set_fixed_fps, RID, int) + FUNC2(particles_set_fractional_delta, RID, bool) + FUNC1R(bool, particles_is_inactive, RID) + FUNC1(particles_request_process, RID) + FUNC1(particles_restart, RID) + + FUNC2(particles_set_draw_order, RID, RS::ParticlesDrawOrder) + + FUNC2(particles_set_draw_passes, RID, int) + FUNC3(particles_set_draw_pass_mesh, RID, int, RID) + FUNC2(particles_set_emission_transform, RID, const Transform &) + + FUNC1R(AABB, particles_get_current_aabb, RID) + + /* CAMERA API */ + + FUNCRID(camera) + FUNC4(camera_set_perspective, RID, float, float, float) + FUNC4(camera_set_orthogonal, RID, float, float, float) + FUNC5(camera_set_frustum, RID, float, Vector2, float, float) + FUNC2(camera_set_transform, RID, const Transform &) + FUNC2(camera_set_cull_mask, RID, uint32_t) + FUNC2(camera_set_environment, RID, RID) + FUNC2(camera_set_camera_effects, RID, RID) + FUNC2(camera_set_use_vertical_aspect, RID, bool) + + /* VIEWPORT TARGET API */ + + FUNCRID(viewport) + + FUNC2(viewport_set_use_arvr, RID, bool) + + FUNC3(viewport_set_size, RID, int, int) + + FUNC2(viewport_set_active, RID, bool) + FUNC2(viewport_set_parent_viewport, RID, RID) + + FUNC2(viewport_set_clear_mode, RID, ViewportClearMode) + + FUNC3(viewport_attach_to_screen, RID, const Rect2 &, DisplayServer::WindowID) + FUNC2(viewport_set_render_direct_to_screen, RID, bool) + + FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) + + FUNC1RC(RID, viewport_get_texture, RID) + + FUNC2(viewport_set_hide_scenario, RID, bool) + FUNC2(viewport_set_hide_canvas, RID, bool) + FUNC2(viewport_set_disable_environment, RID, bool) + + FUNC2(viewport_attach_camera, RID, RID) + FUNC2(viewport_set_scenario, RID, RID) + FUNC2(viewport_attach_canvas, RID, RID) + + FUNC2(viewport_remove_canvas, RID, RID) + FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &) + FUNC2(viewport_set_transparent_background, RID, bool) + + FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &) + FUNC4(viewport_set_canvas_stacking, RID, RID, int, int) + FUNC2(viewport_set_shadow_atlas_size, RID, int) + FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) + FUNC2(viewport_set_msaa, RID, ViewportMSAA) + + //this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport + virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) { + return rendering_server->viewport_get_render_info(p_viewport, p_info); + } + + FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw) + + FUNC1(directional_shadow_atlas_set_size, int) + + /* SKY API */ + + FUNCRID(sky) + FUNC2(sky_set_radiance_size, RID, int) + FUNC2(sky_set_mode, RID, SkyMode) + FUNC2(sky_set_material, RID, RID) + + /* ENVIRONMENT API */ + + FUNCRID(environment) + + FUNC2(environment_set_background, RID, EnvironmentBG) + FUNC2(environment_set_sky, RID, RID) + FUNC2(environment_set_sky_custom_fov, RID, float) + FUNC2(environment_set_sky_orientation, RID, const Basis &) + FUNC2(environment_set_bg_color, RID, const Color &) + FUNC2(environment_set_bg_energy, RID, float) + FUNC2(environment_set_canvas_max_layer, RID, int) + FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &) + +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + FUNC2(environment_set_camera_feed_id, RID, int) +#endif + FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool) + FUNC9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) + + FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) + + FUNC12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) + + FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) + + FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID) + + FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float) + FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) + FUNC5(environment_set_fog_height, RID, bool, float, float, float) + + FUNC2(screen_space_roughness_limiter_set_active, bool, float) + + FUNCRID(camera_effects) + + FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool) + FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape) + + FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) + FUNC3(camera_effects_set_custom_exposure, RID, bool, float) + + FUNCRID(scenario) + + FUNC2(scenario_set_debug, RID, ScenarioDebugMode) + FUNC2(scenario_set_environment, RID, RID) + FUNC2(scenario_set_camera_effects, RID, RID) + FUNC2(scenario_set_fallback_environment, RID, RID) + + /* INSTANCING API */ + FUNCRID(instance) + + FUNC2(instance_set_base, RID, RID) + FUNC2(instance_set_scenario, RID, RID) + FUNC2(instance_set_layer_mask, RID, uint32_t) + FUNC2(instance_set_transform, RID, const Transform &) + FUNC2(instance_attach_object_instance_id, RID, ObjectID) + FUNC3(instance_set_blend_shape_weight, RID, int, float) + FUNC3(instance_set_surface_material, RID, int, RID) + FUNC2(instance_set_visible, RID, bool) + FUNC3(instance_set_use_lightmap, RID, RID, RID) + + FUNC2(instance_set_custom_aabb, RID, AABB) + + FUNC2(instance_attach_skeleton, RID, RID) + FUNC2(instance_set_exterior, RID, bool) + + FUNC2(instance_set_extra_visibility_margin, RID, real_t) + + // don't use these in a game! + FUNC2RC(Vector, instances_cull_aabb, const AABB &, RID) + FUNC3RC(Vector, instances_cull_ray, const Vector3 &, const Vector3 &, RID) + FUNC2RC(Vector, instances_cull_convex, const Vector &, RID) + + FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool) + FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting) + FUNC2(instance_geometry_set_material_override, RID, RID) + + FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float) + FUNC2(instance_geometry_set_as_instance_lod, RID, RID) + + /* CANVAS (2D) */ + + FUNCRID(canvas) + FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &) + FUNC2(canvas_set_modulate, RID, const Color &) + FUNC3(canvas_set_parent, RID, RID, float) + FUNC1(canvas_set_disable_scale, bool) + + FUNCRID(canvas_item) + FUNC2(canvas_item_set_parent, RID, RID) + + FUNC2(canvas_item_set_visible, RID, bool) + FUNC2(canvas_item_set_light_mask, RID, int) + + FUNC2(canvas_item_set_update_when_visible, RID, bool) + + FUNC2(canvas_item_set_transform, RID, const Transform2D &) + FUNC2(canvas_item_set_clip, RID, bool) + FUNC2(canvas_item_set_distance_field_mode, RID, bool) + FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &) + FUNC2(canvas_item_set_modulate, RID, const Color &) + FUNC2(canvas_item_set_self_modulate, RID, const Color &) + + FUNC2(canvas_item_set_draw_behind_parent, RID, bool) + + FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) + FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) + + FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) + FUNC4(canvas_item_add_polyline, RID, const Vector &, const Vector &, float) + FUNC4(canvas_item_add_multiline, RID, const Vector &, const Vector &, float) + FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) + FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) + FUNC11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC11(canvas_item_add_primitive, RID, const Vector &, const Vector &, const Vector &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC10(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC14(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) + FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) + FUNC2(canvas_item_add_clip_ignore, RID, bool) + FUNC2(canvas_item_set_sort_children_by_y, RID, bool) + FUNC2(canvas_item_set_z_index, RID, int) + FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool) + FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) + FUNC2(canvas_item_attach_skeleton, RID, RID) + + FUNC1(canvas_item_clear, RID) + FUNC2(canvas_item_set_draw_index, RID, int) + + FUNC2(canvas_item_set_material, RID, RID) + + FUNC2(canvas_item_set_use_parent_material, RID, bool) + + FUNC0R(RID, canvas_light_create) + FUNC2(canvas_light_attach_to_canvas, RID, RID) + FUNC2(canvas_light_set_enabled, RID, bool) + FUNC2(canvas_light_set_scale, RID, float) + FUNC2(canvas_light_set_transform, RID, const Transform2D &) + FUNC2(canvas_light_set_texture, RID, RID) + FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &) + FUNC2(canvas_light_set_color, RID, const Color &) + FUNC2(canvas_light_set_height, RID, float) + FUNC2(canvas_light_set_energy, RID, float) + FUNC3(canvas_light_set_z_range, RID, int, int) + FUNC3(canvas_light_set_layer_range, RID, int, int) + FUNC2(canvas_light_set_item_cull_mask, RID, int) + FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int) + + FUNC2(canvas_light_set_mode, RID, CanvasLightMode) + + FUNC2(canvas_light_set_shadow_enabled, RID, bool) + FUNC2(canvas_light_set_shadow_buffer_size, RID, int) + FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) + FUNC2(canvas_light_set_shadow_color, RID, const Color &) + FUNC2(canvas_light_set_shadow_smooth, RID, float) + + FUNCRID(canvas_light_occluder) + FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID) + FUNC2(canvas_light_occluder_set_enabled, RID, bool) + FUNC2(canvas_light_occluder_set_polygon, RID, RID) + FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &) + FUNC2(canvas_light_occluder_set_light_mask, RID, int) + + FUNCRID(canvas_occluder_polygon) + FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector &, bool) + FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector &) + + FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) + + /* BLACK BARS */ + + FUNC4(black_bars_set_margins, int, int, int, int) + FUNC4(black_bars_set_images, RID, RID, RID, RID) + + /* FREE */ + + FUNC1(free, RID) + + /* EVENT QUEUING */ + + FUNC3(request_frame_drawn_callback, Object *, const StringName &, const Variant &) + + virtual void init(); + virtual void finish(); + virtual void draw(bool p_swap_buffers, double frame_step); + virtual void sync(); + FUNC0RC(bool, has_changed) + + /* RENDER INFO */ + + //this passes directly to avoid stalling + virtual int get_render_info(RenderInfo p_info) { + return rendering_server->get_render_info(p_info); + } + + virtual String get_video_adapter_name() const { + return rendering_server->get_video_adapter_name(); + } + + virtual String get_video_adapter_vendor() const { + return rendering_server->get_video_adapter_vendor(); + } + + FUNC4(set_boot_image, const Ref &, const Color &, bool, bool) + FUNC1(set_default_clear_color, const Color &) + + FUNC0R(RID, get_test_cube) + + FUNC1(set_debug_generate_wireframes, bool) + + virtual bool has_feature(Features p_feature) const { + return rendering_server->has_feature(p_feature); + } + virtual bool has_os_feature(const String &p_feature) const { + return rendering_server->has_os_feature(p_feature); + } + + FUNC1(call_set_use_vsync, bool) + + static void set_use_vsync_callback(bool p_enable); + + virtual bool is_low_end() const { + return rendering_server->is_low_end(); + } + + virtual uint64_t get_frame_profile_frame() { + return rendering_server->get_frame_profile_frame(); + } + + virtual void set_frame_profiling_enabled(bool p_enabled) { + rendering_server->set_frame_profiling_enabled(p_enabled); + } + + virtual Vector get_frame_profile() { + return rendering_server->get_frame_profile(); + } + + RenderingServerWrapMT(RenderingServer *p_contained, bool p_create_thread); + ~RenderingServerWrapMT(); + +#undef ServerName +#undef ServerNameWrapMT +#undef server_name +}; + +#ifdef DEBUG_SYNC +#undef DEBUG_SYNC +#endif +#undef SYNC_DEBUG + +#endif diff --git a/servers/rendering/shader_language.cpp b/servers/rendering/shader_language.cpp new file mode 100644 index 0000000000..cf2a01c07c --- /dev/null +++ b/servers/rendering/shader_language.cpp @@ -0,0 +1,7006 @@ +/*************************************************************************/ +/* shader_language.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shader_language.h" +#include "core/os/os.h" +#include "core/print_string.h" +#include "servers/rendering_server.h" + +static bool _is_text_char(CharType c) { + + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; +} + +static bool _is_number(CharType c) { + + return (c >= '0' && c <= '9'); +} + +static bool _is_hex(CharType c) { + + return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); +} + +String ShaderLanguage::get_operator_text(Operator p_op) { + + static const char *op_names[OP_MAX] = { "==", + "!=", + "<", + "<=", + ">", + ">=", + "&&", + "||", + "!", + "-", + "+", + "-", + "*", + "/", + "%", + "<<", + ">>", + "=", + "+=", + "-=", + "*=", + "/=", + "%=", + "<<=", + ">>=", + "&=", + "|=", + "^=", + "&", + "|", + "^", + "~", + "++", + "--", + "?", + ":", + "++", + "--", + "()", + "construct", + "index" }; + + return op_names[p_op]; +} + +const char *ShaderLanguage::token_names[TK_MAX] = { + "EMPTY", + "IDENTIFIER", + "TRUE", + "FALSE", + "REAL_CONSTANT", + "INT_CONSTANT", + "TYPE_VOID", + "TYPE_BOOL", + "TYPE_BVEC2", + "TYPE_BVEC3", + "TYPE_BVEC4", + "TYPE_INT", + "TYPE_IVEC2", + "TYPE_IVEC3", + "TYPE_IVEC4", + "TYPE_UINT", + "TYPE_UVEC2", + "TYPE_UVEC3", + "TYPE_UVEC4", + "TYPE_FLOAT", + "TYPE_VEC2", + "TYPE_VEC3", + "TYPE_VEC4", + "TYPE_MAT2", + "TYPE_MAT3", + "TYPE_MAT4", + "TYPE_SAMPLER2D", + "TYPE_ISAMPLER2D", + "TYPE_USAMPLER2D", + "TYPE_SAMPLER2DARRAY", + "TYPE_ISAMPLER2DARRAY", + "TYPE_USAMPLER2DARRAY", + "TYPE_SAMPLER3D", + "TYPE_ISAMPLER3D", + "TYPE_USAMPLER3D", + "TYPE_SAMPLERCUBE", + "INTERPOLATION_FLAT", + "INTERPOLATION_SMOOTH", + "CONST", + "PRECISION_LOW", + "PRECISION_MID", + "PRECISION_HIGH", + "OP_EQUAL", + "OP_NOT_EQUAL", + "OP_LESS", + "OP_LESS_EQUAL", + "OP_GREATER", + "OP_GREATER_EQUAL", + "OP_AND", + "OP_OR", + "OP_NOT", + "OP_ADD", + "OP_SUB", + "OP_MUL", + "OP_DIV", + "OP_MOD", + "OP_SHIFT_LEFT", + "OP_SHIFT_RIGHT", + "OP_ASSIGN", + "OP_ASSIGN_ADD", + "OP_ASSIGN_SUB", + "OP_ASSIGN_MUL", + "OP_ASSIGN_DIV", + "OP_ASSIGN_MOD", + "OP_ASSIGN_SHIFT_LEFT", + "OP_ASSIGN_SHIFT_RIGHT", + "OP_ASSIGN_BIT_AND", + "OP_ASSIGN_BIT_OR", + "OP_ASSIGN_BIT_XOR", + "OP_BIT_AND", + "OP_BIT_OR", + "OP_BIT_XOR", + "OP_BIT_INVERT", + "OP_INCREMENT", + "OP_DECREMENT", + "CF_IF", + "CF_ELSE", + "CF_FOR", + "CF_WHILE", + "CF_DO", + "CF_SWITCH", + "CF_CASE", + "CF_BREAK", + "CF_CONTINUE", + "CF_RETURN", + "CF_DISCARD", + "BRACKET_OPEN", + "BRACKET_CLOSE", + "CURLY_BRACKET_OPEN", + "CURLY_BRACKET_CLOSE", + "PARENTHESIS_OPEN", + "PARENTHESIS_CLOSE", + "QUESTION", + "COMMA", + "COLON", + "SEMICOLON", + "PERIOD", + "UNIFORM", + "VARYING", + "IN", + "OUT", + "INOUT", + "RENDER_MODE", + "HINT_WHITE_TEXTURE", + "HINT_BLACK_TEXTURE", + "HINT_NORMAL_TEXTURE", + "HINT_ANISO_TEXTURE", + "HINT_ALBEDO_TEXTURE", + "HINT_BLACK_ALBEDO_TEXTURE", + "HINT_COLOR", + "HINT_RANGE", + "FILTER_NEAREST", + "FILTER_LINEAR", + "FILTER_NEAREST_MIPMAP", + "FILTER_LINEAR_MIPMAP", + "FILTER_NEAREST_MIPMAP_ANISO", + "FILTER_LINEAR_MIPMAP_ANISO", + "REPEAT_ENABLE", + "REPEAT_DISABLE", + "SHADER_TYPE", + "CURSOR", + "ERROR", + "EOF", +}; + +String ShaderLanguage::get_token_text(Token p_token) { + + String name = token_names[p_token.type]; + if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_REAL_CONSTANT) { + name += "(" + rtos(p_token.constant) + ")"; + } else if (p_token.type == TK_IDENTIFIER) { + name += "(" + String(p_token.text) + ")"; + } else if (p_token.type == TK_ERROR) { + name += "(" + String(p_token.text) + ")"; + } + + return name; +} + +ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type, const StringName &p_text) { + + Token tk; + tk.type = p_type; + tk.text = p_text; + tk.line = tk_line; + if (tk.type == TK_ERROR) { + _set_error(p_text); + } + return tk; +} + +const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { + { TK_TRUE, "true" }, + { TK_FALSE, "false" }, + { TK_TYPE_VOID, "void" }, + { TK_TYPE_BOOL, "bool" }, + { TK_TYPE_BVEC2, "bvec2" }, + { TK_TYPE_BVEC3, "bvec3" }, + { TK_TYPE_BVEC4, "bvec4" }, + { TK_TYPE_INT, "int" }, + { TK_TYPE_IVEC2, "ivec2" }, + { TK_TYPE_IVEC3, "ivec3" }, + { TK_TYPE_IVEC4, "ivec4" }, + { TK_TYPE_UINT, "uint" }, + { TK_TYPE_UVEC2, "uvec2" }, + { TK_TYPE_UVEC3, "uvec3" }, + { TK_TYPE_UVEC4, "uvec4" }, + { TK_TYPE_FLOAT, "float" }, + { TK_TYPE_VEC2, "vec2" }, + { TK_TYPE_VEC3, "vec3" }, + { TK_TYPE_VEC4, "vec4" }, + { TK_TYPE_MAT2, "mat2" }, + { TK_TYPE_MAT3, "mat3" }, + { TK_TYPE_MAT4, "mat4" }, + { TK_TYPE_SAMPLER2D, "sampler2D" }, + { TK_TYPE_ISAMPLER2D, "isampler2D" }, + { TK_TYPE_USAMPLER2D, "usampler2D" }, + { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" }, + { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" }, + { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" }, + { TK_TYPE_SAMPLER3D, "sampler3D" }, + { TK_TYPE_ISAMPLER3D, "isampler3D" }, + { TK_TYPE_USAMPLER3D, "usampler3D" }, + { TK_TYPE_SAMPLERCUBE, "samplerCube" }, + { TK_INTERPOLATION_FLAT, "flat" }, + { TK_INTERPOLATION_SMOOTH, "smooth" }, + { TK_CONST, "const" }, + { TK_STRUCT, "struct" }, + { TK_PRECISION_LOW, "lowp" }, + { TK_PRECISION_MID, "mediump" }, + { TK_PRECISION_HIGH, "highp" }, + { TK_CF_IF, "if" }, + { TK_CF_ELSE, "else" }, + { TK_CF_FOR, "for" }, + { TK_CF_WHILE, "while" }, + { TK_CF_DO, "do" }, + { TK_CF_SWITCH, "switch" }, + { TK_CF_CASE, "case" }, + { TK_CF_DEFAULT, "default" }, + { TK_CF_BREAK, "break" }, + { TK_CF_CONTINUE, "continue" }, + { TK_CF_RETURN, "return" }, + { TK_CF_DISCARD, "discard" }, + { TK_UNIFORM, "uniform" }, + { TK_VARYING, "varying" }, + { TK_ARG_IN, "in" }, + { TK_ARG_OUT, "out" }, + { TK_ARG_INOUT, "inout" }, + { TK_RENDER_MODE, "render_mode" }, + { TK_HINT_WHITE_TEXTURE, "hint_white" }, + { TK_HINT_BLACK_TEXTURE, "hint_black" }, + { TK_HINT_NORMAL_TEXTURE, "hint_normal" }, + { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal" }, + { TK_HINT_ROUGHNESS_R, "hint_roughness_r" }, + { TK_HINT_ROUGHNESS_G, "hint_roughness_g" }, + { TK_HINT_ROUGHNESS_B, "hint_roughness_b" }, + { TK_HINT_ROUGHNESS_A, "hint_roughness_a" }, + { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" }, + { TK_HINT_ANISO_TEXTURE, "hint_aniso" }, + { TK_HINT_ALBEDO_TEXTURE, "hint_albedo" }, + { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" }, + { TK_HINT_COLOR, "hint_color" }, + { TK_HINT_RANGE, "hint_range" }, + { TK_FILTER_NEAREST, "filter_nearest" }, + { TK_FILTER_LINEAR, "filter_linear" }, + { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" }, + { TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" }, + { TK_FILTER_NEAREST_MIPMAP_ANISO, "filter_nearest_mipmap_aniso" }, + { TK_FILTER_LINEAR_MIPMAP_ANISO, "filter_linear_mipmap_aniso" }, + { TK_REPEAT_ENABLE, "repeat_enable" }, + { TK_REPEAT_DISABLE, "repeat_disable" }, + { TK_SHADER_TYPE, "shader_type" }, + { TK_ERROR, NULL } +}; + +ShaderLanguage::Token ShaderLanguage::_get_token() { + +#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : CharType(0)) + + while (true) { + char_idx++; + switch (GETCHAR(-1)) { + + case 0: + return _make_token(TK_EOF); + case 0xFFFF: + return _make_token(TK_CURSOR); //for completion + case '\t': + case '\r': + case ' ': + continue; + case '\n': + tk_line++; + continue; + case '/': { + + switch (GETCHAR(0)) { + case '*': { // block comment + + char_idx++; + while (true) { + if (GETCHAR(0) == 0) { + return _make_token(TK_EOF); + } + if (GETCHAR(0) == '*' && GETCHAR(1) == '/') { + char_idx += 2; + break; + } else if (GETCHAR(0) == '\n') { + tk_line++; + } + + char_idx++; + } + + } break; + case '/': { // line comment skip + + while (true) { + if (GETCHAR(0) == '\n') { + tk_line++; + char_idx++; + break; + } + if (GETCHAR(0) == 0) { + return _make_token(TK_EOF); + } + char_idx++; + } + + } break; + case '=': { // diveq + + char_idx++; + return _make_token(TK_OP_ASSIGN_DIV); + + } break; + default: + return _make_token(TK_OP_DIV); + } + + continue; //a comment, continue to next token + } break; + case '=': { + + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_EQUAL); + } + + return _make_token(TK_OP_ASSIGN); + + } break; + case '<': { + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_LESS_EQUAL); + } else if (GETCHAR(0) == '<') { + char_idx++; + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SHIFT_LEFT); + } + + return _make_token(TK_OP_SHIFT_LEFT); + } + + return _make_token(TK_OP_LESS); + + } break; + case '>': { + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_GREATER_EQUAL); + } else if (GETCHAR(0) == '>') { + char_idx++; + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SHIFT_RIGHT); + } + + return _make_token(TK_OP_SHIFT_RIGHT); + } + + return _make_token(TK_OP_GREATER); + + } break; + case '!': { + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_NOT_EQUAL); + } + + return _make_token(TK_OP_NOT); + + } break; + //case '"' //string - no strings in shader + //case '\'' //string - no strings in shader + case '{': + return _make_token(TK_CURLY_BRACKET_OPEN); + case '}': + return _make_token(TK_CURLY_BRACKET_CLOSE); + case '[': + return _make_token(TK_BRACKET_OPEN); + case ']': + return _make_token(TK_BRACKET_CLOSE); + case '(': + return _make_token(TK_PARENTHESIS_OPEN); + case ')': + return _make_token(TK_PARENTHESIS_CLOSE); + case ',': + return _make_token(TK_COMMA); + case ';': + return _make_token(TK_SEMICOLON); + case '?': + return _make_token(TK_QUESTION); + case ':': + return _make_token(TK_COLON); + case '^': + return _make_token(TK_OP_BIT_XOR); + case '~': + return _make_token(TK_OP_BIT_INVERT); + case '&': { + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_AND); + } else if (GETCHAR(0) == '&') { + char_idx++; + return _make_token(TK_OP_AND); + } + return _make_token(TK_OP_BIT_AND); + } break; + case '|': { + + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_BIT_OR); + } else if (GETCHAR(0) == '|') { + char_idx++; + return _make_token(TK_OP_OR); + } + return _make_token(TK_OP_BIT_OR); + + } break; + case '*': { + + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_MUL); + } + return _make_token(TK_OP_MUL); + } break; + case '+': { + + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_ADD); + } else if (GETCHAR(0) == '+') { + + char_idx++; + return _make_token(TK_OP_INCREMENT); + } + + return _make_token(TK_OP_ADD); + } break; + case '-': { + + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_SUB); + } else if (GETCHAR(0) == '-') { + + char_idx++; + return _make_token(TK_OP_DECREMENT); + } + + return _make_token(TK_OP_SUB); + } break; + case '%': { + + if (GETCHAR(0) == '=') { + char_idx++; + return _make_token(TK_OP_ASSIGN_MOD); + } + + return _make_token(TK_OP_MOD); + } break; + default: { + + char_idx--; //go back one, since we have no idea what this is + + if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) { + // parse number + bool period_found = false; + bool exponent_found = false; + bool hexa_found = false; + bool sign_found = false; + bool float_suffix_found = false; + + String str; + int i = 0; + + while (true) { + if (GETCHAR(i) == '.') { + if (period_found || exponent_found || hexa_found || float_suffix_found) + return _make_token(TK_ERROR, "Invalid numeric constant"); + period_found = true; + } else if (GETCHAR(i) == 'x') { + if (hexa_found || str.length() != 1 || str[0] != '0') + return _make_token(TK_ERROR, "Invalid numeric constant"); + hexa_found = true; + } else if (GETCHAR(i) == 'e') { + if (hexa_found || exponent_found || float_suffix_found) + return _make_token(TK_ERROR, "Invalid numeric constant"); + exponent_found = true; + } else if (GETCHAR(i) == 'f') { + if (hexa_found || exponent_found) + return _make_token(TK_ERROR, "Invalid numeric constant"); + float_suffix_found = true; + } else if (_is_number(GETCHAR(i))) { + if (float_suffix_found) + return _make_token(TK_ERROR, "Invalid numeric constant"); + } else if (hexa_found && _is_hex(GETCHAR(i))) { + + } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) { + if (sign_found) + return _make_token(TK_ERROR, "Invalid numeric constant"); + sign_found = true; + } else + break; + + str += CharType(GETCHAR(i)); + i++; + } + + CharType last_char = str[str.length() - 1]; + + if (hexa_found) { + //integer(hex) + if (str.size() > 11 || !str.is_valid_hex_number(true)) { // > 0xFFFFFFFF + return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant"); + } + } else if (period_found || exponent_found || float_suffix_found) { + //floats + if (period_found) { + if (float_suffix_found) { + //checks for eg "1.f" or "1.99f" notations + if (last_char != 'f') { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } else { + //checks for eg. "1." or "1.99" notations + if (last_char != '.' && !_is_number(last_char)) { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } + } else if (float_suffix_found) { + // if no period found the float suffix must be the last character, like in "2f" for "2.0" + if (last_char != 'f') { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } + + if (float_suffix_found) { + //strip the suffix + str = str.left(str.length() - 1); + //compensate reading cursor position + char_idx += 1; + } + + if (!str.is_valid_float()) { + return _make_token(TK_ERROR, "Invalid (float) numeric constant"); + } + } else { + //integers + if (!_is_number(last_char)) { + return _make_token(TK_ERROR, "Invalid (integer) numeric constant"); + } + if (!str.is_valid_integer()) { + return _make_token(TK_ERROR, "Invalid numeric constant"); + } + } + + char_idx += str.length(); + Token tk; + if (period_found || exponent_found || float_suffix_found) + tk.type = TK_REAL_CONSTANT; + else + tk.type = TK_INT_CONSTANT; + + if (hexa_found) { + tk.constant = (double)str.hex_to_int64(true); + } else { + tk.constant = str.to_double(); + } + tk.line = tk_line; + + return tk; + } + + if (GETCHAR(0) == '.') { + //parse period + char_idx++; + return _make_token(TK_PERIOD); + } + + if (_is_text_char(GETCHAR(0))) { + // parse identifier + String str; + + while (_is_text_char(GETCHAR(0))) { + + str += CharType(GETCHAR(0)); + char_idx++; + } + + //see if keyword + //should be converted to a static map + int idx = 0; + + while (keyword_list[idx].text) { + + if (str == keyword_list[idx].text) { + + return _make_token(keyword_list[idx].token); + } + idx++; + } + + str = str.replace("dus_", "_"); + + return _make_token(TK_IDENTIFIER, str); + } + + if (GETCHAR(0) > 32) + return _make_token(TK_ERROR, "Tokenizer: Unknown character #" + itos(GETCHAR(0)) + ": '" + String::chr(GETCHAR(0)) + "'"); + else + return _make_token(TK_ERROR, "Tokenizer: Unknown character #" + itos(GETCHAR(0))); + + } break; + } + } + ERR_PRINT("BUG"); + return Token(); + +#undef GETCHAR +} + +String ShaderLanguage::token_debug(const String &p_code) { + + clear(); + + code = p_code; + + String output; + + Token tk = _get_token(); + while (tk.type != TK_EOF && tk.type != TK_ERROR) { + + output += itos(tk_line) + ": " + get_token_text(tk) + "\n"; + tk = _get_token(); + } + + return output; +} + +bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) { + return ( + p_type == TK_TYPE_VOID || + p_type == TK_TYPE_BOOL || + p_type == TK_TYPE_BVEC2 || + p_type == TK_TYPE_BVEC3 || + p_type == TK_TYPE_BVEC4 || + p_type == TK_TYPE_INT || + p_type == TK_TYPE_IVEC2 || + p_type == TK_TYPE_IVEC3 || + p_type == TK_TYPE_IVEC4 || + p_type == TK_TYPE_UINT || + p_type == TK_TYPE_UVEC2 || + p_type == TK_TYPE_UVEC3 || + p_type == TK_TYPE_UVEC4 || + p_type == TK_TYPE_FLOAT || + p_type == TK_TYPE_VEC2 || + p_type == TK_TYPE_VEC3 || + p_type == TK_TYPE_VEC4 || + p_type == TK_TYPE_MAT2 || + p_type == TK_TYPE_MAT3 || + p_type == TK_TYPE_MAT4); +} + +bool ShaderLanguage::is_token_datatype(TokenType p_type) { + + return ( + p_type == TK_TYPE_VOID || + p_type == TK_TYPE_BOOL || + p_type == TK_TYPE_BVEC2 || + p_type == TK_TYPE_BVEC3 || + p_type == TK_TYPE_BVEC4 || + p_type == TK_TYPE_INT || + p_type == TK_TYPE_IVEC2 || + p_type == TK_TYPE_IVEC3 || + p_type == TK_TYPE_IVEC4 || + p_type == TK_TYPE_UINT || + p_type == TK_TYPE_UVEC2 || + p_type == TK_TYPE_UVEC3 || + p_type == TK_TYPE_UVEC4 || + p_type == TK_TYPE_FLOAT || + p_type == TK_TYPE_VEC2 || + p_type == TK_TYPE_VEC3 || + p_type == TK_TYPE_VEC4 || + p_type == TK_TYPE_MAT2 || + p_type == TK_TYPE_MAT3 || + p_type == TK_TYPE_MAT4 || + p_type == TK_TYPE_SAMPLER2D || + p_type == TK_TYPE_ISAMPLER2D || + p_type == TK_TYPE_USAMPLER2D || + p_type == TK_TYPE_SAMPLER2DARRAY || + p_type == TK_TYPE_ISAMPLER2DARRAY || + p_type == TK_TYPE_USAMPLER2DARRAY || + p_type == TK_TYPE_SAMPLER3D || + p_type == TK_TYPE_ISAMPLER3D || + p_type == TK_TYPE_USAMPLER3D || + p_type == TK_TYPE_SAMPLERCUBE); +} + +ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { + + return DataType(p_type - TK_TYPE_VOID); +} + +bool ShaderLanguage::is_token_interpolation(TokenType p_type) { + + return ( + p_type == TK_INTERPOLATION_FLAT || + p_type == TK_INTERPOLATION_SMOOTH); +} + +ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenType p_type) { + + if (p_type == TK_INTERPOLATION_FLAT) + return INTERPOLATION_FLAT; + else + return INTERPOLATION_SMOOTH; +} + +bool ShaderLanguage::is_token_precision(TokenType p_type) { + + return ( + p_type == TK_PRECISION_LOW || + p_type == TK_PRECISION_MID || + p_type == TK_PRECISION_HIGH); +} + +ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) { + + if (p_type == TK_PRECISION_LOW) + return PRECISION_LOWP; + else if (p_type == TK_PRECISION_HIGH) + return PRECISION_HIGHP; + else + return PRECISION_MEDIUMP; +} + +String ShaderLanguage::get_precision_name(DataPrecision p_type) { + switch (p_type) { + case PRECISION_LOWP: return "lowp"; + case PRECISION_MEDIUMP: return "mediump"; + case PRECISION_HIGHP: return "highp"; + default: + break; + } + return ""; +} + +String ShaderLanguage::get_datatype_name(DataType p_type) { + + switch (p_type) { + + case TYPE_VOID: return "void"; + case TYPE_BOOL: return "bool"; + case TYPE_BVEC2: return "bvec2"; + case TYPE_BVEC3: return "bvec3"; + case TYPE_BVEC4: return "bvec4"; + case TYPE_INT: return "int"; + case TYPE_IVEC2: return "ivec2"; + case TYPE_IVEC3: return "ivec3"; + case TYPE_IVEC4: return "ivec4"; + case TYPE_UINT: return "uint"; + case TYPE_UVEC2: return "uvec2"; + case TYPE_UVEC3: return "uvec3"; + case TYPE_UVEC4: return "uvec4"; + case TYPE_FLOAT: return "float"; + case TYPE_VEC2: return "vec2"; + case TYPE_VEC3: return "vec3"; + case TYPE_VEC4: return "vec4"; + case TYPE_MAT2: return "mat2"; + case TYPE_MAT3: return "mat3"; + case TYPE_MAT4: return "mat4"; + case TYPE_SAMPLER2D: return "sampler2D"; + case TYPE_ISAMPLER2D: return "isampler2D"; + case TYPE_USAMPLER2D: return "usampler2D"; + case TYPE_SAMPLER2DARRAY: return "sampler2DArray"; + case TYPE_ISAMPLER2DARRAY: return "isampler2DArray"; + case TYPE_USAMPLER2DARRAY: return "usampler2DArray"; + case TYPE_SAMPLER3D: return "sampler3D"; + case TYPE_ISAMPLER3D: return "isampler3D"; + case TYPE_USAMPLER3D: return "usampler3D"; + case TYPE_SAMPLERCUBE: return "samplerCube"; + case TYPE_STRUCT: return "struct"; + } + + return ""; +} + +bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) { + + return is_token_datatype(p_type) && p_type != TK_TYPE_VOID; +} + +void ShaderLanguage::clear() { + + current_function = StringName(); + + completion_type = COMPLETION_NONE; + completion_block = NULL; + completion_function = StringName(); + completion_class = SubClassTag::TAG_GLOBAL; + completion_struct = StringName(); + + error_line = 0; + tk_line = 1; + char_idx = 0; + error_set = false; + error_str = ""; + while (nodes) { + Node *n = nodes; + nodes = nodes->next; + memdelete(n); + } +} + +bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) { + + if (p_builtin_types.has(p_identifier)) { + + if (r_data_type) { + *r_data_type = p_builtin_types[p_identifier].type; + } + if (r_is_const) { + *r_is_const = p_builtin_types[p_identifier].constant; + } + if (r_type) { + *r_type = IDENTIFIER_BUILTIN_VAR; + } + + return true; + } + + FunctionNode *function = NULL; + + while (p_block) { + + if (p_block->variables.has(p_identifier)) { + if (r_data_type) { + *r_data_type = p_block->variables[p_identifier].type; + } + if (r_is_const) { + *r_is_const = p_block->variables[p_identifier].is_const; + } + if (r_array_size) { + *r_array_size = p_block->variables[p_identifier].array_size; + } + if (r_type) { + *r_type = IDENTIFIER_LOCAL_VAR; + } + if (r_struct_name) { + *r_struct_name = p_block->variables[p_identifier].struct_name; + } + + return true; + } + + if (p_block->parent_function) { + function = p_block->parent_function; + break; + } else { + if (p_allow_reassign) { + break; + } + ERR_FAIL_COND_V(!p_block->parent_block, false); + p_block = p_block->parent_block; + } + } + + if (function) { + for (int i = 0; i < function->arguments.size(); i++) { + if (function->arguments[i].name == p_identifier) { + if (r_data_type) { + *r_data_type = function->arguments[i].type; + } + if (r_type) { + *r_type = IDENTIFIER_FUNCTION_ARGUMENT; + } + if (r_struct_name) { + *r_struct_name = function->arguments[i].type_str; + } + return true; + } + } + } + + if (shader->varyings.has(p_identifier)) { + if (r_data_type) { + *r_data_type = shader->varyings[p_identifier].type; + } + if (r_array_size) { + *r_array_size = shader->varyings[p_identifier].array_size; + } + if (r_type) { + *r_type = IDENTIFIER_VARYING; + } + return true; + } + + if (shader->uniforms.has(p_identifier)) { + if (r_data_type) { + *r_data_type = shader->uniforms[p_identifier].type; + } + if (r_type) { + *r_type = IDENTIFIER_UNIFORM; + } + return true; + } + + if (shader->constants.has(p_identifier)) { + if (r_data_type) { + *r_data_type = shader->constants[p_identifier].type; + } + if (r_type) { + *r_type = IDENTIFIER_CONSTANT; + } + if (r_struct_name) { + *r_struct_name = shader->constants[p_identifier].type_str; + } + return true; + } + + for (int i = 0; i < shader->functions.size(); i++) { + + if (!shader->functions[i].callable) + continue; + + if (shader->functions[i].name == p_identifier) { + if (r_data_type) { + *r_data_type = shader->functions[i].function->return_type; + } + if (r_type) { + *r_type = IDENTIFIER_FUNCTION; + } + return true; + } + } + + return false; +} + +bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) { + + bool valid = false; + DataType ret_type = TYPE_VOID; + + switch (p_op->op) { + case OP_EQUAL: + case OP_NOT_EQUAL: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + valid = na == nb; + ret_type = TYPE_BOOL; + } break; + case OP_LESS: + case OP_LESS_EQUAL: + case OP_GREATER: + case OP_GREATER_EQUAL: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + valid = na == nb && (na == TYPE_UINT || na == TYPE_INT || na == TYPE_FLOAT); + ret_type = TYPE_BOOL; + + } break; + case OP_AND: + case OP_OR: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + valid = na == nb && na == TYPE_BOOL; + ret_type = TYPE_BOOL; + + } break; + case OP_NOT: { + + DataType na = p_op->arguments[0]->get_datatype(); + valid = na == TYPE_BOOL; + ret_type = TYPE_BOOL; + + } break; + case OP_INCREMENT: + case OP_DECREMENT: + case OP_POST_INCREMENT: + case OP_POST_DECREMENT: + case OP_NEGATE: { + DataType na = p_op->arguments[0]->get_datatype(); + valid = na > TYPE_BOOL && na < TYPE_MAT2; + ret_type = na; + } break; + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na > nb) { + //make things easier; + SWAP(na, nb); + } + + if (na == nb) { + valid = (na > TYPE_BOOL && na <= TYPE_MAT4); + ret_type = na; + } else if (na == TYPE_INT && nb == TYPE_IVEC2) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_INT && nb == TYPE_IVEC3) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_INT && nb == TYPE_IVEC4) { + valid = true; + ret_type = TYPE_IVEC4; + } else if (na == TYPE_UINT && nb == TYPE_UVEC2) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UINT && nb == TYPE_UVEC3) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UINT && nb == TYPE_UVEC4) { + valid = true; + ret_type = TYPE_UVEC4; + } else if (na == TYPE_FLOAT && nb == TYPE_VEC2) { + valid = true; + ret_type = TYPE_VEC2; + } else if (na == TYPE_FLOAT && nb == TYPE_VEC3) { + valid = true; + ret_type = TYPE_VEC3; + } else if (na == TYPE_FLOAT && nb == TYPE_VEC4) { + valid = true; + ret_type = TYPE_VEC4; + } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT2) { + valid = true; + ret_type = TYPE_MAT2; + } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT3) { + valid = true; + ret_type = TYPE_MAT3; + } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT4) { + valid = true; + ret_type = TYPE_MAT4; + } else if (p_op->op == OP_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) { + valid = true; + ret_type = TYPE_VEC2; + } else if (p_op->op == OP_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) { + valid = true; + ret_type = TYPE_VEC3; + } else if (p_op->op == OP_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) { + valid = true; + ret_type = TYPE_VEC4; + } + } break; + case OP_ASSIGN_MOD: + case OP_MOD: { + /* + * The operator modulus (%) operates on signed or unsigned integers or integer vectors. The operand + * types must both be signed or both be unsigned. The operands cannot be vectors of differing size. If + * one operand is a scalar and the other vector, then the scalar is applied component-wise to the vector, + * resulting in the same type as the vector. If both are vectors of the same size, the result is computed + * component-wise. + */ + + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na == TYPE_INT && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_INT; + } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC4; + } else if (na == TYPE_IVEC2 && nb == TYPE_IVEC2) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_IVEC3) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { + valid = true; + ret_type = TYPE_IVEC4; + ///// + } else if (na == TYPE_UINT && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UINT; + } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC4; + } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { + valid = true; + ret_type = TYPE_UVEC4; + } + } break; + case OP_ASSIGN_SHIFT_LEFT: + case OP_ASSIGN_SHIFT_RIGHT: + case OP_SHIFT_LEFT: + case OP_SHIFT_RIGHT: { + + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na == TYPE_INT && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_INT; + } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC4; + } else if (na == TYPE_IVEC2 && nb == TYPE_IVEC2) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_IVEC3) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { + valid = true; + ret_type = TYPE_IVEC4; + } else if (na == TYPE_UINT && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UINT; + } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC4; + } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { + valid = true; + ret_type = TYPE_UVEC4; + } + } break; + case OP_ASSIGN: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + if (na == TYPE_STRUCT || nb == TYPE_STRUCT) { + valid = p_op->arguments[0]->get_datatype_name() == p_op->arguments[1]->get_datatype_name(); + } else { + valid = na == nb; + } + ret_type = na; + } break; + case OP_ASSIGN_ADD: + case OP_ASSIGN_SUB: + case OP_ASSIGN_MUL: + case OP_ASSIGN_DIV: { + + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na == nb) { + valid = (na > TYPE_BOOL && na < TYPE_MAT2) || (p_op->op == OP_ASSIGN_MUL && na >= TYPE_MAT2 && na <= TYPE_MAT4); + ret_type = na; + } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC4; + } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC4; + } else if (na == TYPE_VEC2 && nb == TYPE_FLOAT) { + valid = true; + ret_type = TYPE_VEC2; + } else if (na == TYPE_VEC3 && nb == TYPE_FLOAT) { + valid = true; + ret_type = TYPE_VEC3; + } else if (na == TYPE_VEC4 && nb == TYPE_FLOAT) { + valid = true; + ret_type = TYPE_VEC4; + } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT2 && nb == TYPE_VEC2) { + valid = true; + ret_type = TYPE_MAT2; + } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT3 && nb == TYPE_VEC3) { + valid = true; + ret_type = TYPE_MAT3; + } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) { + valid = true; + ret_type = TYPE_MAT4; + } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) { + valid = true; + ret_type = TYPE_VEC2; + } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) { + valid = true; + ret_type = TYPE_VEC3; + } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) { + valid = true; + ret_type = TYPE_VEC4; + } + } break; + case OP_ASSIGN_BIT_AND: + case OP_ASSIGN_BIT_OR: + case OP_ASSIGN_BIT_XOR: + case OP_BIT_AND: + case OP_BIT_OR: + case OP_BIT_XOR: { + + /* + * The bitwise operators and (&), exclusive-or (^), and inclusive-or (|). The operands must be of type + * signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If + * one operand is a scalar and the other a vector, the scalar is applied component-wise to the vector, + * resulting in the same type as the vector. The fundamental types of the operands (signed or unsigned) + * must match. + */ + + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + + if (na > nb && p_op->op >= OP_BIT_AND) { + //can swap for non assign + SWAP(na, nb); + } + + if (na == TYPE_INT && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_INT; + } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { + valid = true; + ret_type = TYPE_IVEC4; + } else if (na == TYPE_IVEC2 && nb == TYPE_IVEC2) { + valid = true; + ret_type = TYPE_IVEC2; + } else if (na == TYPE_IVEC3 && nb == TYPE_IVEC3) { + valid = true; + ret_type = TYPE_IVEC3; + } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { + valid = true; + ret_type = TYPE_IVEC4; + ///// + } else if (na == TYPE_UINT && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UINT; + } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { + valid = true; + ret_type = TYPE_UVEC4; + } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { + valid = true; + ret_type = TYPE_UVEC2; + } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { + valid = true; + ret_type = TYPE_UVEC3; + } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { + valid = true; + ret_type = TYPE_UVEC4; + } + } break; + case OP_BIT_INVERT: { //unaries + DataType na = p_op->arguments[0]->get_datatype(); + valid = na >= TYPE_INT && na < TYPE_FLOAT; + ret_type = na; + } break; + case OP_SELECT_IF: { + DataType na = p_op->arguments[0]->get_datatype(); + DataType nb = p_op->arguments[1]->get_datatype(); + DataType nc = p_op->arguments[2]->get_datatype(); + + valid = na == TYPE_BOOL && (nb == nc); + ret_type = nb; + } break; + default: { + ERR_FAIL_V(false); + } + } + + if (r_ret_type) + *r_ret_type = ret_type; + return valid; +} + +const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { + //constructors + { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + + { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + + { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + + { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + + { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + //conversion scalars + + { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, true }, + { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, + { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + //conversion vectors + + { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + + { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + + { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + + { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + + { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + + { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + + { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + + { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + + { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + //conversion between matrixes + + { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, + { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, + + //builtins - trigonometry + + { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + //builtins - exponential + { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + //builtins - common + { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, + { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + //builtins - geometric + { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, + { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, + { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, + { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, + { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, + { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, + { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, + { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, + { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, + + //builtins - texture + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, + { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, + + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + + { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, + { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, + { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, + { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, + + //sub-functions + + //array + { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true }, + + { NULL, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false } + +}; + +const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = { + //constructors + { "modf", 1 }, + { NULL, 0 } +}; + +bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) { + + ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false); + + Vector args; + Vector args2; + + ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false); + + StringName name = static_cast(p_func->arguments[0])->name.operator String(); + + for (int i = 1; i < p_func->arguments.size(); i++) { + args.push_back(p_func->arguments[i]->get_datatype()); + args2.push_back(p_func->arguments[i]->get_datatype_name()); + } + + int argcount = args.size(); + + bool failed_builtin = false; + bool unsupported_builtin = false; + int builtin_idx = 0; + + if (argcount <= 4) { + // test builtins + int idx = 0; + + while (builtin_func_defs[idx].name) { + + if (completion_class != builtin_func_defs[idx].tag) { + idx++; + continue; + } + + if (name == builtin_func_defs[idx].name) { + + failed_builtin = true; + bool fail = false; + for (int i = 0; i < argcount; i++) { + + if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) { + //all good, but needs implicit conversion later + } else if (args[i] != builtin_func_defs[idx].args[i]) { + fail = true; + break; + } + } + + if (!fail) { + if (RenderingServer::get_singleton()->is_low_end()) { + if (builtin_func_defs[idx].high_end) { + fail = true; + unsupported_builtin = true; + builtin_idx = idx; + } + } + } + + if (!fail && argcount < 4 && builtin_func_defs[idx].args[argcount] != TYPE_VOID) + fail = true; //make sure the number of arguments matches + + if (!fail) { + + //make sure its not an out argument used in the wrong way + int outarg_idx = 0; + while (builtin_func_out_args[outarg_idx].name) { + + if (String(name) == builtin_func_out_args[outarg_idx].name) { + int arg_idx = builtin_func_out_args[outarg_idx].argument; + + if (arg_idx < argcount) { + + if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) { + _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); + return false; + } + + if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { + ArrayNode *mn = static_cast(p_func->arguments[arg_idx + 1]); + if (mn->is_const) { + fail = true; + } + } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { + MemberNode *mn = static_cast(p_func->arguments[arg_idx + 1]); + if (mn->basetype_const) { + fail = true; + } + } else { // TYPE_VARIABLE + VariableNode *vn = static_cast(p_func->arguments[arg_idx + 1]); + if (vn->is_const) { + fail = true; + } else { + StringName varname = vn->name; + if (shader->uniforms.has(varname)) { + fail = true; + } else { + if (p_builtin_types.has(varname)) { + BuiltInInfo info = p_builtin_types[varname]; + if (info.constant) { + fail = true; + } + } + } + } + } + if (fail) { + _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out")); + return false; + } + + StringName var_name; + if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { + var_name = static_cast(p_func->arguments[arg_idx + 1])->name; + } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { + Node *n = static_cast(p_func->arguments[arg_idx + 1])->owner; + while (n->type == Node::TYPE_MEMBER) { + n = static_cast(n)->owner; + } + if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) { + _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); + return false; + } + if (n->type == Node::TYPE_VARIABLE) { + var_name = static_cast(n)->name; + } else { // TYPE_ARRAY + var_name = static_cast(n)->name; + } + } else { // TYPE_VARIABLE + var_name = static_cast(p_func->arguments[arg_idx + 1])->name; + } + const BlockNode *b = p_block; + bool valid = false; + while (b) { + if (b->variables.has(var_name) || p_builtin_types.has(var_name)) { + valid = true; + break; + } + if (b->parent_function) { + for (int i = 0; i < b->parent_function->arguments.size(); i++) { + if (b->parent_function->arguments[i].name == var_name) { + valid = true; + break; + } + } + } + b = b->parent_block; + } + + if (!valid) { + _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member."); + return false; + } + } + } + + outarg_idx++; + } + //implicitly convert values if possible + for (int i = 0; i < argcount; i++) { + + if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) { + //can't do implicit conversion here + continue; + } + + //this is an implicit conversion + ConstantNode *constant = static_cast(p_func->arguments[i + 1]); + ConstantNode *conversion = alloc_node(); + + conversion->datatype = builtin_func_defs[idx].args[i]; + conversion->values.resize(1); + + convert_constant(constant, builtin_func_defs[idx].args[i], conversion->values.ptrw()); + p_func->arguments.write[i + 1] = conversion; + } + + if (r_ret_type) + *r_ret_type = builtin_func_defs[idx].rettype; + + return true; + } + } + + idx++; + } + } + + if (unsupported_builtin) { + + String arglist = ""; + for (int i = 0; i < argcount; i++) { + if (i > 0) { + arglist += ", "; + } + arglist += get_datatype_name(builtin_func_defs[builtin_idx].args[i]); + } + + String err = "Built-in function \"" + String(name) + "(" + arglist + ")\" is supported only on high-end platform!"; + _set_error(err); + return false; + } + + if (failed_builtin) { + String err = "Invalid arguments for built-in function: " + String(name) + "("; + for (int i = 0; i < argcount; i++) { + if (i > 0) + err += ","; + + if (p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && p_func->arguments[i + 1]->get_datatype() == TYPE_INT && static_cast(p_func->arguments[i + 1])->values[0].sint < 0) { + err += "-"; + } + err += get_datatype_name(args[i]); + } + err += ")"; + _set_error(err); + return false; + } + + // try existing functions.. + + StringName exclude_function; + BlockNode *block = p_block; + + while (block) { + + if (block->parent_function) { + exclude_function = block->parent_function->name; + } + block = block->parent_block; + } + + if (name == exclude_function) { + _set_error("Recursion is not allowed"); + return false; + } + + for (int i = 0; i < shader->functions.size(); i++) { + + if (name != shader->functions[i].name) + continue; + + if (!shader->functions[i].callable) { + _set_error("Function '" + String(name) + " can't be called from source code."); + return false; + } + + FunctionNode *pfunc = shader->functions[i].function; + + if (pfunc->arguments.size() != args.size()) + continue; + + bool fail = false; + + for (int j = 0; j < args.size(); j++) { + if (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) { + fail = true; + break; + } + if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast(p_func->arguments[j + 1]), pfunc->arguments[j].type)) { + //all good, but it needs implicit conversion later + } else if (args[j] != pfunc->arguments[j].type) { + fail = true; + break; + } + } + + if (!fail) { + + //implicitly convert values if possible + for (int k = 0; k < args.size(); k++) { + + if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) { + //can't do implicit conversion here + continue; + } + + //this is an implicit conversion + ConstantNode *constant = static_cast(p_func->arguments[k + 1]); + ConstantNode *conversion = alloc_node(); + + conversion->datatype = pfunc->arguments[k].type; + conversion->values.resize(1); + + convert_constant(constant, pfunc->arguments[k].type, conversion->values.ptrw()); + p_func->arguments.write[k + 1] = conversion; + } + + if (r_ret_type) { + *r_ret_type = pfunc->return_type; + if (pfunc->return_type == TYPE_STRUCT) { + *r_ret_type_str = pfunc->return_struct_name; + } + } + + return true; + } + } + + return false; +} + +bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const { + if (a->get_datatype() != b->get_datatype()) { + return false; + } + if (a->get_datatype() == TYPE_STRUCT || b->get_datatype() == TYPE_STRUCT) { + if (a->get_datatype_name() != b->get_datatype_name()) { + return false; + } + } + return true; +} + +bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) { + + TkPos pos = _get_tkpos(); + Token tk = _get_token(); + + if (tk.type == TK_PARENTHESIS_CLOSE) { + return true; + } + + _set_tkpos(pos); + + while (true) { + + if (r_complete_arg) { + pos = _get_tkpos(); + tk = _get_token(); + + if (tk.type == TK_CURSOR) { + + *r_complete_arg = p_func->arguments.size() - 1; + } else { + + _set_tkpos(pos); + } + } + + Node *arg = _parse_and_reduce_expression(p_block, p_builtin_types); + + if (!arg) { + + return false; + } + + p_func->arguments.push_back(arg); + + tk = _get_token(); + + if (tk.type == TK_PARENTHESIS_CLOSE) { + + return true; + } else if (tk.type != TK_COMMA) { + // something is broken + _set_error("Expected ',' or ')' after argument"); + return false; + } + } + + return true; +} + +bool ShaderLanguage::is_token_operator(TokenType p_type) { + + return (p_type == TK_OP_EQUAL || + p_type == TK_OP_NOT_EQUAL || + p_type == TK_OP_LESS || + p_type == TK_OP_LESS_EQUAL || + p_type == TK_OP_GREATER || + p_type == TK_OP_GREATER_EQUAL || + p_type == TK_OP_AND || + p_type == TK_OP_OR || + p_type == TK_OP_NOT || + p_type == TK_OP_ADD || + p_type == TK_OP_SUB || + p_type == TK_OP_MUL || + p_type == TK_OP_DIV || + p_type == TK_OP_MOD || + p_type == TK_OP_SHIFT_LEFT || + p_type == TK_OP_SHIFT_RIGHT || + p_type == TK_OP_ASSIGN || + p_type == TK_OP_ASSIGN_ADD || + p_type == TK_OP_ASSIGN_SUB || + p_type == TK_OP_ASSIGN_MUL || + p_type == TK_OP_ASSIGN_DIV || + p_type == TK_OP_ASSIGN_MOD || + p_type == TK_OP_ASSIGN_SHIFT_LEFT || + p_type == TK_OP_ASSIGN_SHIFT_RIGHT || + p_type == TK_OP_ASSIGN_BIT_AND || + p_type == TK_OP_ASSIGN_BIT_OR || + p_type == TK_OP_ASSIGN_BIT_XOR || + p_type == TK_OP_BIT_AND || + p_type == TK_OP_BIT_OR || + p_type == TK_OP_BIT_XOR || + p_type == TK_OP_BIT_INVERT || + p_type == TK_OP_INCREMENT || + p_type == TK_OP_DECREMENT || + p_type == TK_QUESTION || + p_type == TK_COLON); +} + +bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) { + + if (p_constant->datatype == p_to_type) { + if (p_value) { + for (int i = 0; i < p_constant->values.size(); i++) { + p_value[i] = p_constant->values[i]; + } + } + return true; + } else if (p_constant->datatype == TYPE_INT && p_to_type == TYPE_FLOAT) { + + if (p_value) { + p_value->real = p_constant->values[0].sint; + } + return true; + } else if (p_constant->datatype == TYPE_UINT && p_to_type == TYPE_FLOAT) { + + if (p_value) { + p_value->real = p_constant->values[0].uint; + } + return true; + } else if (p_constant->datatype == TYPE_INT && p_to_type == TYPE_UINT) { + if (p_constant->values[0].sint < 0) { + return false; + } + if (p_value) { + p_value->uint = p_constant->values[0].sint; + } + return true; + } else if (p_constant->datatype == TYPE_UINT && p_to_type == TYPE_INT) { + + if (p_constant->values[0].uint > 0x7FFFFFFF) { + return false; + } + if (p_value) { + p_value->sint = p_constant->values[0].uint; + } + return true; + } else + return false; +} + +bool ShaderLanguage::is_scalar_type(DataType p_type) { + + return p_type == TYPE_BOOL || p_type == TYPE_INT || p_type == TYPE_UINT || p_type == TYPE_FLOAT; +} + +bool ShaderLanguage::is_sampler_type(DataType p_type) { + + return p_type == TYPE_SAMPLER2D || + p_type == TYPE_ISAMPLER2D || + p_type == TYPE_USAMPLER2D || + p_type == TYPE_SAMPLER2DARRAY || + p_type == TYPE_ISAMPLER2DARRAY || + p_type == TYPE_USAMPLER2DARRAY || + p_type == TYPE_SAMPLER3D || + p_type == TYPE_ISAMPLER3D || + p_type == TYPE_USAMPLER3D || + p_type == TYPE_SAMPLERCUBE; +} + +Variant ShaderLanguage::constant_value_to_variant(const Vector &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) { + if (p_value.size() > 0) { + Variant value; + switch (p_type) { + case ShaderLanguage::TYPE_BOOL: + value = Variant(p_value[0].boolean); + break; + case ShaderLanguage::TYPE_BVEC2: + case ShaderLanguage::TYPE_BVEC3: + case ShaderLanguage::TYPE_BVEC4: + case ShaderLanguage::TYPE_INT: + value = Variant(p_value[0].sint); + break; + case ShaderLanguage::TYPE_IVEC2: + value = Variant(Vector2(p_value[0].sint, p_value[1].sint)); + break; + case ShaderLanguage::TYPE_IVEC3: + value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint)); + break; + case ShaderLanguage::TYPE_IVEC4: + value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint)); + break; + case ShaderLanguage::TYPE_UINT: + value = Variant(p_value[0].uint); + break; + case ShaderLanguage::TYPE_UVEC2: + value = Variant(Vector2(p_value[0].uint, p_value[1].uint)); + break; + case ShaderLanguage::TYPE_UVEC3: + value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint)); + break; + case ShaderLanguage::TYPE_UVEC4: + value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint)); + break; + case ShaderLanguage::TYPE_FLOAT: + value = Variant(p_value[0].real); + break; + case ShaderLanguage::TYPE_VEC2: + value = Variant(Vector2(p_value[0].real, p_value[1].real)); + break; + case ShaderLanguage::TYPE_VEC3: + value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real)); + break; + case ShaderLanguage::TYPE_VEC4: + if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); + } else { + value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); + } + break; + case ShaderLanguage::TYPE_MAT2: + value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0)); + break; + case ShaderLanguage::TYPE_MAT3: { + Basis p; + p[0][0] = p_value[0].real; + p[0][1] = p_value[1].real; + p[0][2] = p_value[2].real; + p[1][0] = p_value[3].real; + p[1][1] = p_value[4].real; + p[1][2] = p_value[5].real; + p[2][0] = p_value[6].real; + p[2][1] = p_value[7].real; + p[2][2] = p_value[8].real; + value = Variant(p); + break; + } + case ShaderLanguage::TYPE_MAT4: { + Basis p; + p[0][0] = p_value[0].real; + p[0][1] = p_value[1].real; + p[0][2] = p_value[2].real; + p[1][0] = p_value[4].real; + p[1][1] = p_value[5].real; + p[1][2] = p_value[6].real; + p[2][0] = p_value[8].real; + p[2][1] = p_value[9].real; + p[2][2] = p_value[10].real; + Transform t = Transform(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real)); + value = Variant(t); + break; + } + case ShaderLanguage::TYPE_ISAMPLER2DARRAY: + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_ISAMPLER3D: + case ShaderLanguage::TYPE_SAMPLER2DARRAY: + case ShaderLanguage::TYPE_SAMPLER2D: + case ShaderLanguage::TYPE_SAMPLER3D: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER3D: + case ShaderLanguage::TYPE_SAMPLERCUBE: { + // Texture types, likely not relevant here. + break; + } + case ShaderLanguage::TYPE_STRUCT: + break; + case ShaderLanguage::TYPE_VOID: + break; + } + return value; + } + return Variant(); +} + +PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform &p_uniform) { + PropertyInfo pi; + switch (p_uniform.type) { + case ShaderLanguage::TYPE_VOID: pi.type = Variant::NIL; break; + case ShaderLanguage::TYPE_BOOL: pi.type = Variant::BOOL; break; + case ShaderLanguage::TYPE_BVEC2: + pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_FLAGS; + pi.hint_string = "x,y"; + break; + case ShaderLanguage::TYPE_BVEC3: + pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_FLAGS; + pi.hint_string = "x,y,z"; + break; + case ShaderLanguage::TYPE_BVEC4: + pi.type = Variant::INT; + pi.hint = PROPERTY_HINT_FLAGS; + pi.hint_string = "x,y,z,w"; + break; + case ShaderLanguage::TYPE_UINT: + case ShaderLanguage::TYPE_INT: { + pi.type = Variant::INT; + if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { + pi.hint = PROPERTY_HINT_RANGE; + pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]); + } + + } break; + case ShaderLanguage::TYPE_IVEC2: + case ShaderLanguage::TYPE_IVEC3: + case ShaderLanguage::TYPE_IVEC4: + case ShaderLanguage::TYPE_UVEC2: + case ShaderLanguage::TYPE_UVEC3: + case ShaderLanguage::TYPE_UVEC4: { + + pi.type = Variant::PACKED_INT32_ARRAY; + } break; + case ShaderLanguage::TYPE_FLOAT: { + pi.type = Variant::FLOAT; + if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { + pi.hint = PROPERTY_HINT_RANGE; + pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]); + } + + } break; + case ShaderLanguage::TYPE_VEC2: pi.type = Variant::VECTOR2; break; + case ShaderLanguage::TYPE_VEC3: pi.type = Variant::VECTOR3; break; + case ShaderLanguage::TYPE_VEC4: { + if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { + pi.type = Variant::COLOR; + } else { + pi.type = Variant::PLANE; + } + } break; + case ShaderLanguage::TYPE_MAT2: pi.type = Variant::TRANSFORM2D; break; + case ShaderLanguage::TYPE_MAT3: pi.type = Variant::BASIS; break; + case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break; + case ShaderLanguage::TYPE_SAMPLER2D: + case ShaderLanguage::TYPE_ISAMPLER2D: + case ShaderLanguage::TYPE_USAMPLER2D: { + + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture2D"; + } break; + case ShaderLanguage::TYPE_SAMPLER2DARRAY: + case ShaderLanguage::TYPE_ISAMPLER2DARRAY: + case ShaderLanguage::TYPE_USAMPLER2DARRAY: { + + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "TextureArray"; + } break; + case ShaderLanguage::TYPE_SAMPLER3D: + case ShaderLanguage::TYPE_ISAMPLER3D: + case ShaderLanguage::TYPE_USAMPLER3D: { + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "Texture3D"; + } break; + case ShaderLanguage::TYPE_SAMPLERCUBE: { + + pi.type = Variant::OBJECT; + pi.hint = PROPERTY_HINT_RESOURCE_TYPE; + pi.hint_string = "CubeMap"; + } break; + case ShaderLanguage::TYPE_STRUCT: { + // FIXME: Implement this. + } break; + } + return pi; +} + +uint32_t ShaderLanguage::get_type_size(DataType p_type) { + switch (p_type) { + case TYPE_VOID: + return 0; + case TYPE_BOOL: + case TYPE_INT: + case TYPE_UINT: + case TYPE_FLOAT: + return 4; + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: + return 8; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: + return 12; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: + return 16; + case TYPE_MAT2: + return 8; + case TYPE_MAT3: + return 12; + case TYPE_MAT4: + return 16; + case TYPE_SAMPLER2D: + case TYPE_ISAMPLER2D: + case TYPE_USAMPLER2D: + case TYPE_SAMPLER2DARRAY: + case TYPE_ISAMPLER2DARRAY: + case TYPE_USAMPLER2DARRAY: + case TYPE_SAMPLER3D: + case TYPE_ISAMPLER3D: + case TYPE_USAMPLER3D: + case TYPE_SAMPLERCUBE: + return 4; //not really, but useful for indices + case TYPE_STRUCT: + // FIXME: Implement. + return 0; + } + return 0; +} + +void ShaderLanguage::get_keyword_list(List *r_keywords) { + + Set kws; + + int idx = 0; + + while (keyword_list[idx].text) { + + kws.insert(keyword_list[idx].text); + idx++; + } + + idx = 0; + + while (builtin_func_defs[idx].name) { + + kws.insert(builtin_func_defs[idx].name); + + idx++; + } + + for (Set::Element *E = kws.front(); E; E = E->next()) { + r_keywords->push_back(E->get()); + } +} + +void ShaderLanguage::get_builtin_funcs(List *r_keywords) { + + Set kws; + + int idx = 0; + + while (builtin_func_defs[idx].name) { + + kws.insert(builtin_func_defs[idx].name); + + idx++; + } + + for (Set::Element *E = kws.front(); E; E = E->next()) { + r_keywords->push_back(E->get()); + } +} + +ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { + + static const DataType scalar_types[] = { + TYPE_VOID, + TYPE_BOOL, + TYPE_BOOL, + TYPE_BOOL, + TYPE_BOOL, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_INT, + TYPE_UINT, + TYPE_UINT, + TYPE_UINT, + TYPE_UINT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_FLOAT, + TYPE_INT, + TYPE_UINT, + TYPE_FLOAT, + }; + + return scalar_types[p_type]; +} + +int ShaderLanguage::get_cardinality(DataType p_type) { + static const int cardinality_table[] = { + 0, + 1, + 2, + 3, + 4, + 1, + 2, + 3, + 4, + 1, + 2, + 3, + 4, + 1, + 2, + 3, + 4, + 4, + 9, + 16, + 1, + 1, + 1, + 1, + }; + + return cardinality_table[p_type]; +} + +bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier) { + + identifier = StringName(); + + TkPos pos = { 0, 0 }; + + Token tk = _get_token(); + + if (tk.type == TK_IDENTIFIER) { + identifier = tk.text; + pos = _get_tkpos(); + tk = _get_token(); + } + + if (tk.type == TK_CURSOR) { + + completion_type = p_type; + completion_line = tk_line; + completion_block = p_block; + + pos = _get_tkpos(); + tk = _get_token(); + + if (tk.type == TK_IDENTIFIER) { + identifier = identifier.operator String() + tk.text.operator String(); + } else { + _set_tkpos(pos); + } + return true; + } else if (identifier != StringName()) { + _set_tkpos(pos); + } + + return false; +} + +bool ShaderLanguage::_is_operator_assign(Operator p_op) const { + switch (p_op) { + case OP_ASSIGN: + case OP_ASSIGN_ADD: + case OP_ASSIGN_SUB: + case OP_ASSIGN_MUL: + case OP_ASSIGN_DIV: + case OP_ASSIGN_MOD: + case OP_ASSIGN_SHIFT_LEFT: + case OP_ASSIGN_SHIFT_RIGHT: + case OP_ASSIGN_BIT_AND: + case OP_ASSIGN_BIT_OR: + case OP_ASSIGN_BIT_XOR: + return true; + default: + return false; + } + + return false; +} + +bool ShaderLanguage::_validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message) { + + if (p_node->type == Node::TYPE_OPERATOR) { + + OperatorNode *op = static_cast(p_node); + + if (op->op == OP_INDEX) { + return _validate_assign(op->arguments[0], p_builtin_types, r_message); + + } else if (_is_operator_assign(op->op)) { + //chained assignment + return _validate_assign(op->arguments[1], p_builtin_types, r_message); + + } else if (op->op == OP_CALL) { + if (r_message) + *r_message = RTR("Assignment to function."); + return false; + } + + } else if (p_node->type == Node::TYPE_MEMBER) { + + MemberNode *member = static_cast(p_node); + + if (member->has_swizzling_duplicates) { + if (r_message) + *r_message = RTR("Swizzling assignment contains duplicates."); + return false; + } + + return _validate_assign(member->owner, p_builtin_types, r_message); + + } else if (p_node->type == Node::TYPE_VARIABLE) { + + VariableNode *var = static_cast(p_node); + + if (shader->uniforms.has(var->name)) { + if (r_message) + *r_message = RTR("Assignment to uniform."); + return false; + } + + if (shader->varyings.has(var->name) && current_function != String("vertex")) { + if (r_message) + *r_message = RTR("Varyings can only be assigned in vertex function."); + return false; + } + + if (shader->constants.has(var->name) || var->is_const) { + if (r_message) + *r_message = RTR("Constants cannot be modified."); + return false; + } + + if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) { + return true; + } + } else if (p_node->type == Node::TYPE_ARRAY) { + + ArrayNode *arr = static_cast(p_node); + + if (arr->is_const) { + if (r_message) + *r_message = RTR("Constants cannot be modified."); + return false; + } + + if (shader->varyings.has(arr->name) && current_function != String("vertex")) { + if (r_message) + *r_message = RTR("Varyings can only be assigned in vertex function."); + return false; + } + + return true; + } + + if (r_message) + *r_message = "Assignment to constant expression."; + return false; +} + +bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) { + for (int i = 0; shader->functions.size(); i++) { + if (shader->functions[i].name == p_name) { + + ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); + FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; + if (arg->tex_builtin_check) { + _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."); + return false; + } else if (arg->tex_argument_check) { + //was checked, verify that filter and repeat are the same + if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) { + return true; + } else { + + _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using textures that differ in either filter or repeat setting."); + return false; + } + } else { + + arg->tex_argument_check = true; + arg->tex_argument_filter = p_filter; + arg->tex_argument_repeat = p_repeat; + for (Map>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) { + for (Set::Element *F = E->get().front(); F; F = F->next()) { + if (!_propagate_function_call_sampler_uniform_settings(E->key(), F->get(), p_filter, p_repeat)) { + return false; + } + } + } + return true; + } + } + } + ERR_FAIL_V(false); //bug? function not found +} +bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) { + for (int i = 0; shader->functions.size(); i++) { + if (shader->functions[i].name == p_name) { + + ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); + FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; + if (arg->tex_argument_check) { + _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."); + return false; + } else if (arg->tex_builtin_check) { + //was checked, verify that the built-in is the same + if (arg->tex_builtin == p_builtin) { + return true; + } else { + _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using different built-ins. Only calling with the same built-in is supported."); + return false; + } + } else { + + arg->tex_builtin_check = true; + arg->tex_builtin = p_builtin; + + for (Map>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) { + for (Set::Element *F = E->get().front(); F; F = F->next()) { + if (!_propagate_function_call_sampler_builtin_reference(E->key(), F->get(), p_builtin)) { + return false; + } + } + } + return true; + } + } + } + ERR_FAIL_V(false); //bug? function not found +} + +ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map &p_builtin_types) { + + Vector expression; + + //Vector operators; + + while (true) { + + Node *expr = NULL; + TkPos prepos = _get_tkpos(); + Token tk = _get_token(); + TkPos pos = _get_tkpos(); + + bool is_const = false; + + if (tk.type == TK_PARENTHESIS_OPEN) { + //handle subexpression + + expr = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!expr) + return NULL; + + tk = _get_token(); + + if (tk.type != TK_PARENTHESIS_CLOSE) { + + _set_error("Expected ')' in expression"); + return NULL; + } + + } else if (tk.type == TK_REAL_CONSTANT) { + + ConstantNode *constant = alloc_node(); + ConstantNode::Value v; + v.real = tk.constant; + constant->values.push_back(v); + constant->datatype = TYPE_FLOAT; + expr = constant; + + } else if (tk.type == TK_INT_CONSTANT) { + + ConstantNode *constant = alloc_node(); + ConstantNode::Value v; + v.sint = tk.constant; + constant->values.push_back(v); + constant->datatype = TYPE_INT; + expr = constant; + + } else if (tk.type == TK_TRUE) { + + //handle true constant + ConstantNode *constant = alloc_node(); + ConstantNode::Value v; + v.boolean = true; + constant->values.push_back(v); + constant->datatype = TYPE_BOOL; + expr = constant; + + } else if (tk.type == TK_FALSE) { + + //handle false constant + ConstantNode *constant = alloc_node(); + ConstantNode::Value v; + v.boolean = false; + constant->values.push_back(v); + constant->datatype = TYPE_BOOL; + expr = constant; + + } else if (tk.type == TK_TYPE_VOID) { + + //make sure void is not used in expression + _set_error("Void value not allowed in Expression"); + return NULL; + } else if (is_token_nonvoid_datatype(tk.type)) { + //basic type constructor + + OperatorNode *func = alloc_node(); + func->op = OP_CONSTRUCT; + + if (is_token_precision(tk.type)) { + + func->return_precision_cache = get_token_precision(tk.type); + tk = _get_token(); + } + + VariableNode *funcname = alloc_node(); + funcname->name = get_datatype_name(get_token_datatype(tk.type)); + func->arguments.push_back(funcname); + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after type name"); + return NULL; + } + + int carg = -1; + + bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); + + if (carg >= 0) { + completion_type = COMPLETION_CALL_ARGUMENTS; + completion_line = tk_line; + completion_block = p_block; + completion_function = funcname->name; + completion_argument = carg; + } + + if (!ok) + return NULL; + + if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) { + _set_error("No matching constructor found for: '" + String(funcname->name) + "'"); + return NULL; + } + + expr = _reduce_expression(p_block, func); + + } else if (tk.type == TK_IDENTIFIER) { + + _set_tkpos(prepos); + + StringName identifier; + + StructNode *pstruct = NULL; + bool struct_init = false; + + _get_completable_identifier(p_block, COMPLETION_IDENTIFIER, identifier); + + if (shader->structs.has(identifier)) { + pstruct = shader->structs[identifier].shader_struct; + struct_init = true; + } + + tk = _get_token(); + if (tk.type == TK_PARENTHESIS_OPEN) { + + if (struct_init) { //a struct constructor + + const StringName &name = identifier; + + OperatorNode *func = alloc_node(); + func->op = OP_STRUCT; + func->struct_name = name; + func->return_cache = TYPE_STRUCT; + VariableNode *funcname = alloc_node(); + funcname->name = name; + func->arguments.push_back(funcname); + + for (int i = 0; i < pstruct->members.size(); i++) { + Node *nexpr; + + if (pstruct->members[i]->array_size != 0) { + + DataType type = pstruct->members[i]->get_datatype(); + String struct_name = pstruct->members[i]->struct_name; + int array_size = pstruct->members[i]->array_size; + + DataType type2; + String struct_name2 = ""; + int array_size2 = 0; + + bool auto_size = false; + + tk = _get_token(); + + if (tk.type == TK_CURLY_BRACKET_OPEN) { + auto_size = true; + } else { + + if (shader->structs.has(tk.text)) { + type2 = TYPE_STRUCT; + struct_name2 = tk.text; + } else { + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for array"); + return NULL; + } + type2 = get_token_datatype(tk.type); + } + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + TkPos pos2 = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + array_size2 = array_size; + tk = _get_token(); + } else { + _set_tkpos(pos2); + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { + _set_error("Expected single integer constant > 0"); + return NULL; + } + + ConstantNode *cnode = (ConstantNode *)n; + if (cnode->values.size() == 1) { + array_size2 = cnode->values[0].sint; + if (array_size2 <= 0) { + _set_error("Expected single integer constant > 0"); + return NULL; + } + } else { + _set_error("Expected single integer constant > 0"); + return NULL; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return NULL; + } else { + tk = _get_token(); + } + } + } else { + _set_error("Expected '['"); + return NULL; + } + + if (type != type2 || struct_name != struct_name2 || array_size != array_size2) { + String error_str = "Cannot convert from '"; + if (type2 == TYPE_STRUCT) { + error_str += struct_name2; + } else { + error_str += get_datatype_name(type2); + } + error_str += "["; + error_str += itos(array_size2); + error_str += "]'"; + error_str += " to '"; + if (type == TYPE_STRUCT) { + error_str += struct_name; + } else { + error_str += get_datatype_name(type); + } + error_str += "["; + error_str += itos(array_size); + error_str += "]'"; + _set_error(error_str); + return NULL; + } + } + + ArrayConstructNode *an = alloc_node(); + an->datatype = type; + an->struct_name = struct_name; + + if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization + while (true) { + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) { + return NULL; + } + + if (type != n->get_datatype() || struct_name != n->get_datatype_name()) { + _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'"); + return NULL; + } + + tk = _get_token(); + if (tk.type == TK_COMMA) { + an->initializer.push_back(n); + continue; + } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) { + an->initializer.push_back(n); + break; + } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) { + an->initializer.push_back(n); + break; + } else { + if (auto_size) + _set_error("Expected '}' or ','"); + else + _set_error("Expected ')' or ','"); + return NULL; + } + } + if (an->initializer.size() != array_size) { + _set_error("Array size mismatch"); + return NULL; + } + } else { + _set_error("Expected array initialization!"); + return NULL; + } + + nexpr = an; + } else { + nexpr = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!nexpr) { + return NULL; + } + Node *node = pstruct->members[i]; + if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) { + String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype()); + String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype()); + _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'"); + return NULL; + } + } + + if (i + 1 < pstruct->members.size()) { + tk = _get_token(); + if (tk.type != TK_COMMA) { + _set_error("Expected ','"); + return NULL; + } + } + func->arguments.push_back(nexpr); + } + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')'"); + return NULL; + } + + expr = func; + + } else { //a function + + const StringName &name = identifier; + + OperatorNode *func = alloc_node(); + func->op = OP_CALL; + VariableNode *funcname = alloc_node(); + funcname->name = name; + func->arguments.push_back(funcname); + + int carg = -1; + + bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); + + // Check if block has a variable with the same name as function to prevent shader crash. + ShaderLanguage::BlockNode *bnode = p_block; + while (bnode) { + if (bnode->variables.has(name)) { + _set_error("Expected function name"); + return NULL; + } + bnode = bnode->parent_block; + } + + //test if function was parsed first + int function_index = -1; + for (int i = 0; i < shader->functions.size(); i++) { + if (shader->functions[i].name == name) { + //add to current function as dependency + for (int j = 0; j < shader->functions.size(); j++) { + if (shader->functions[j].name == current_function) { + shader->functions.write[j].uses_function.insert(name); + break; + } + } + + //see if texture arguments must connect + function_index = i; + break; + } + } + + if (carg >= 0) { + completion_type = COMPLETION_CALL_ARGUMENTS; + completion_line = tk_line; + completion_block = p_block; + completion_function = funcname->name; + completion_argument = carg; + } + + if (!ok) + return NULL; + + if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) { + _set_error("No matching function found for: '" + String(funcname->name) + "'"); + return NULL; + } + completion_class = TAG_GLOBAL; // reset sub-class + if (function_index >= 0) { + //connect texture arguments, so we can cache in the + //argument what type of filter and repeat to use + + FunctionNode *call_function = shader->functions[function_index].function; + if (call_function) { + + //get current base function + FunctionNode *base_function = NULL; + { + BlockNode *b = p_block; + + while (b) { + + if (b->parent_function) { + base_function = b->parent_function; + break; + } else { + b = b->parent_block; + } + } + } + + ERR_FAIL_COND_V(!base_function, NULL); //bug, wtf + + for (int i = 0; i < call_function->arguments.size(); i++) { + int argidx = i + 1; + if (argidx < func->arguments.size()) { + if (call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) { + bool error = false; + Node *n = func->arguments[argidx]; + if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { + error = true; + } else if (n->type == Node::TYPE_ARRAY) { + ArrayNode *an = static_cast(n); + if (an->call_expression != NULL) { + error = true; + } + } else if (n->type == Node::TYPE_VARIABLE) { + VariableNode *vn = static_cast(n); + if (vn->is_const) { + error = true; + } else { + StringName varname = vn->name; + if (shader->uniforms.has(varname)) { + error = true; + } else { + if (p_builtin_types.has(varname)) { + BuiltInInfo info = p_builtin_types[varname]; + if (info.constant) { + error = true; + } + } + } + } + } else if (n->type == Node::TYPE_MEMBER) { + MemberNode *mn = static_cast(n); + if (mn->basetype_const) { + error = true; + } + } + if (error) { + _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier))); + return NULL; + } + } + if (is_sampler_type(call_function->arguments[i].type)) { + //let's see where our argument comes from + Node *n = func->arguments[argidx]; + ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable + VariableNode *vn = static_cast(n); + StringName varname = vn->name; + if (shader->uniforms.has(varname)) { + //being sampler, this either comes from a uniform + ShaderNode::Uniform *u = &shader->uniforms[varname]; + ERR_CONTINUE(u->type != call_function->arguments[i].type); //this should have been validated previously + //propagate + if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat)) { + return NULL; + } + } else if (p_builtin_types.has(varname)) { + //a built-in + if (!_propagate_function_call_sampler_builtin_reference(name, i, varname)) { + return NULL; + } + } else { + //or this comes from an argument, but nothing else can be a sampler + bool found = false; + for (int j = 0; j < base_function->arguments.size(); j++) { + if (base_function->arguments[j].name == varname) { + if (!base_function->arguments[j].tex_argument_connect.has(call_function->name)) { + base_function->arguments.write[j].tex_argument_connect[call_function->name] = Set(); + } + base_function->arguments.write[j].tex_argument_connect[call_function->name].insert(i); + found = true; + break; + } + } + ERR_CONTINUE(!found); + } + } + } else { + break; + } + } + } + } + expr = func; + } + } else { + //an identifier + + _set_tkpos(pos); + + DataType data_type; + IdentifierType ident_type; + int array_size = 0; + StringName struct_name; + + if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) { + int idx = 0; + bool found = false; + + while (builtin_func_defs[idx].name) { + if (builtin_func_defs[idx].tag == p_block->block_tag && builtin_func_defs[idx].name == identifier) { + found = true; + break; + } + idx++; + } + if (!found) { + _set_error("Unknown identifier in expression: " + String(identifier)); + return NULL; + } + } else { + + if (!_find_identifier(p_block, false, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { + _set_error("Unknown identifier in expression: " + String(identifier)); + return NULL; + } + + if (ident_type == IDENTIFIER_FUNCTION) { + _set_error("Can't use function as identifier: " + String(identifier)); + return NULL; + } + } + + Node *index_expression = NULL; + Node *call_expression = NULL; + + if (array_size > 0) { + tk = _get_token(); + + if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) { + _set_error("Expected '[' or '.'"); + return NULL; + } + + if (tk.type == TK_PERIOD) { + completion_class = TAG_ARRAY; + p_block->block_tag = SubClassTag::TAG_ARRAY; + call_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + p_block->block_tag = SubClassTag::TAG_GLOBAL; + if (!call_expression) + return NULL; + data_type = call_expression->get_datatype(); + } else { // indexing + + index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!index_expression) + return NULL; + + if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) { + _set_error("Only integer expressions are allowed for indexing"); + return NULL; + } + + if (index_expression->type == Node::TYPE_CONSTANT) { + ConstantNode *cnode = (ConstantNode *)index_expression; + if (cnode) { + if (!cnode->values.empty()) { + int value = cnode->values[0].sint; + if (value < 0 || value >= array_size) { + _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); + return NULL; + } + } + } + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return NULL; + } + } + + ArrayNode *arrname = alloc_node(); + arrname->name = identifier; + arrname->datatype_cache = data_type; + arrname->struct_name = struct_name; + arrname->index_expression = index_expression; + arrname->call_expression = call_expression; + arrname->is_const = is_const; + expr = arrname; + + } else { + + VariableNode *varname = alloc_node(); + varname->name = identifier; + varname->datatype_cache = data_type; + varname->is_const = is_const; + varname->struct_name = struct_name; + expr = varname; + } + } + } else if (tk.type == TK_OP_ADD) { + continue; //this one does nothing + } else if (tk.type == TK_OP_SUB || tk.type == TK_OP_NOT || tk.type == TK_OP_BIT_INVERT || tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) { + + Expression e; + e.is_op = true; + + switch (tk.type) { + case TK_OP_SUB: e.op = OP_NEGATE; break; + case TK_OP_NOT: e.op = OP_NOT; break; + case TK_OP_BIT_INVERT: e.op = OP_BIT_INVERT; break; + case TK_OP_INCREMENT: e.op = OP_INCREMENT; break; + case TK_OP_DECREMENT: e.op = OP_DECREMENT; break; + default: ERR_FAIL_V(NULL); + } + + expression.push_back(e); + continue; + } else { + _set_error("Expected expression, found: " + get_token_text(tk)); + return NULL; + //nothing + } + + ERR_FAIL_COND_V(!expr, NULL); + + /* OK now see what's NEXT to the operator.. */ + /* OK now see what's NEXT to the operator.. */ + /* OK now see what's NEXT to the operator.. */ + + while (true) { + TkPos pos2 = _get_tkpos(); + tk = _get_token(); + + if (tk.type == TK_CURSOR) { + //do nothing + } else if (tk.type == TK_IDENTIFIER) { + + } else if (tk.type == TK_PERIOD) { + + DataType dt = expr->get_datatype(); + String st = expr->get_datatype_name(); + + StringName identifier; + if (_get_completable_identifier(p_block, dt == TYPE_STRUCT ? COMPLETION_STRUCT : COMPLETION_INDEX, identifier)) { + if (dt == TYPE_STRUCT) { + completion_struct = st; + } else { + completion_base = dt; + } + } + + if (identifier == StringName()) { + _set_error("Expected identifier as member"); + return NULL; + } + String ident = identifier; + + bool ok = true; + bool repeated = false; + DataType member_type = TYPE_VOID; + StringName member_struct_name = ""; + int array_size = 0; + + Set position_symbols; + Set color_symbols; + Set texture_symbols; + + bool mix_error = false; + + switch (dt) { + case TYPE_STRUCT: { + ok = false; + String member_name = String(ident.ptr()); + if (shader->structs.has(st)) { + StructNode *n = shader->structs[st].shader_struct; + for (List::Element *E = n->members.front(); E; E = E->next()) { + if (String(E->get()->name) == member_name) { + member_type = E->get()->datatype; + array_size = E->get()->array_size; + if (member_type == TYPE_STRUCT) { + member_struct_name = E->get()->struct_name; + } + ok = true; + break; + } + } + } + + } break; + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: { + + int l = ident.length(); + if (l == 1) { + member_type = DataType(dt - 1); + } else if (l == 2) { + member_type = dt; + } else if (l == 3) { + member_type = DataType(dt + 1); + } else if (l == 4) { + member_type = DataType(dt + 2); + } else { + ok = false; + break; + } + + const CharType *c = ident.ptr(); + for (int i = 0; i < l; i++) { + + switch (c[i]) { + case 'r': + case 'g': + if (position_symbols.size() > 0 || texture_symbols.size() > 0) { + mix_error = true; + break; + } + if (!color_symbols.has(c[i])) { + color_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + case 'x': + case 'y': + if (color_symbols.size() > 0 || texture_symbols.size() > 0) { + mix_error = true; + break; + } + if (!position_symbols.has(c[i])) { + position_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + case 's': + case 't': + if (color_symbols.size() > 0 || position_symbols.size() > 0) { + mix_error = true; + break; + } + if (!texture_symbols.has(c[i])) { + texture_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + default: + ok = false; + break; + } + } + + } break; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: { + + int l = ident.length(); + if (l == 1) { + member_type = DataType(dt - 2); + } else if (l == 2) { + member_type = DataType(dt - 1); + } else if (l == 3) { + member_type = dt; + } else if (l == 4) { + member_type = DataType(dt + 1); + } else { + ok = false; + break; + } + + const CharType *c = ident.ptr(); + for (int i = 0; i < l; i++) { + + switch (c[i]) { + case 'r': + case 'g': + case 'b': + if (position_symbols.size() > 0 || texture_symbols.size() > 0) { + mix_error = true; + break; + } + if (!color_symbols.has(c[i])) { + color_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + case 'x': + case 'y': + case 'z': + if (color_symbols.size() > 0 || texture_symbols.size() > 0) { + mix_error = true; + break; + } + if (!position_symbols.has(c[i])) { + position_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + case 's': + case 't': + case 'p': + if (color_symbols.size() > 0 || position_symbols.size() > 0) { + mix_error = true; + break; + } + if (!texture_symbols.has(c[i])) { + texture_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + default: + ok = false; + break; + } + } + + } break; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: { + + int l = ident.length(); + if (l == 1) { + member_type = DataType(dt - 3); + } else if (l == 2) { + member_type = DataType(dt - 2); + } else if (l == 3) { + member_type = DataType(dt - 1); + } else if (l == 4) { + member_type = dt; + } else { + ok = false; + break; + } + + const CharType *c = ident.ptr(); + for (int i = 0; i < l; i++) { + + switch (c[i]) { + case 'r': + case 'g': + case 'b': + case 'a': + if (position_symbols.size() > 0 || texture_symbols.size() > 0) { + mix_error = true; + break; + } + if (!color_symbols.has(c[i])) { + color_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + case 'x': + case 'y': + case 'z': + case 'w': + if (color_symbols.size() > 0 || texture_symbols.size() > 0) { + mix_error = true; + break; + } + if (!position_symbols.has(c[i])) { + position_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + case 's': + case 't': + case 'p': + case 'q': + if (color_symbols.size() > 0 || position_symbols.size() > 0) { + mix_error = true; + break; + } + if (!texture_symbols.has(c[i])) { + texture_symbols.insert(c[i]); + } else { + repeated = true; + } + break; + default: + ok = false; + break; + } + } + + } break; + + default: { + ok = false; + } + } + + if (mix_error) { + _set_error("Cannot combine symbols from different sets in expression ." + ident); + return NULL; + } + + if (!ok) { + _set_error("Invalid member for " + (dt == TYPE_STRUCT ? st : get_datatype_name(dt)) + " expression: ." + ident); + return NULL; + } + + MemberNode *mn = alloc_node(); + mn->basetype = dt; + mn->basetype_const = is_const; + mn->datatype = member_type; + mn->base_struct_name = st; + mn->struct_name = member_struct_name; + mn->array_size = array_size; + mn->name = ident; + mn->owner = expr; + mn->has_swizzling_duplicates = repeated; + + if (array_size > 0) { + + tk = _get_token(); + if (tk.type == TK_PERIOD) { + _set_error("Nested array length() is not yet implemented"); + return NULL; + } else if (tk.type == TK_BRACKET_OPEN) { + + Node *index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!index_expression) + return NULL; + + if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) { + _set_error("Only integer expressions are allowed for indexing"); + return NULL; + } + + if (index_expression->type == Node::TYPE_CONSTANT) { + ConstantNode *cnode = (ConstantNode *)index_expression; + if (cnode) { + if (!cnode->values.empty()) { + int value = cnode->values[0].sint; + if (value < 0 || value >= array_size) { + _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); + return NULL; + } + } + } + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return NULL; + } + mn->index_expression = index_expression; + + } else { + _set_error("Expected '[' or '.'"); + return NULL; + } + } + + expr = mn; + + //todo + //member (period) has priority over any operator + //creates a subindexing expression in place + + /*} else if (tk.type==TK_BRACKET_OPEN) { + //todo + //subindexing has priority over any operator + //creates a subindexing expression in place + + */ + } else if (tk.type == TK_BRACKET_OPEN) { + + Node *index = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!index) + return NULL; + + if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) { + _set_error("Only integer datatypes are allowed for indexing"); + return NULL; + } + + DataType member_type = TYPE_VOID; + + switch (expr->get_datatype()) { + case TYPE_BVEC2: + case TYPE_VEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_MAT2: + if (index->type == Node::TYPE_CONSTANT) { + uint32_t index_constant = static_cast(index)->values[0].uint; + if (index_constant >= 2) { + _set_error("Index out of range (0-1)"); + return NULL; + } + } + + switch (expr->get_datatype()) { + case TYPE_BVEC2: member_type = TYPE_BOOL; break; + case TYPE_VEC2: member_type = TYPE_FLOAT; break; + case TYPE_IVEC2: member_type = TYPE_INT; break; + case TYPE_UVEC2: member_type = TYPE_UINT; break; + case TYPE_MAT2: member_type = TYPE_VEC2; break; + default: break; + } + + break; + case TYPE_BVEC3: + case TYPE_VEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_MAT3: + if (index->type == Node::TYPE_CONSTANT) { + uint32_t index_constant = static_cast(index)->values[0].uint; + if (index_constant >= 3) { + _set_error("Index out of range (0-2)"); + return NULL; + } + } + + switch (expr->get_datatype()) { + case TYPE_BVEC3: member_type = TYPE_BOOL; break; + case TYPE_VEC3: member_type = TYPE_FLOAT; break; + case TYPE_IVEC3: member_type = TYPE_INT; break; + case TYPE_UVEC3: member_type = TYPE_UINT; break; + case TYPE_MAT3: member_type = TYPE_VEC3; break; + default: break; + } + break; + case TYPE_BVEC4: + case TYPE_VEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_MAT4: + if (index->type == Node::TYPE_CONSTANT) { + uint32_t index_constant = static_cast(index)->values[0].uint; + if (index_constant >= 4) { + _set_error("Index out of range (0-3)"); + return NULL; + } + } + + switch (expr->get_datatype()) { + case TYPE_BVEC4: member_type = TYPE_BOOL; break; + case TYPE_VEC4: member_type = TYPE_FLOAT; break; + case TYPE_IVEC4: member_type = TYPE_INT; break; + case TYPE_UVEC4: member_type = TYPE_UINT; break; + case TYPE_MAT4: member_type = TYPE_VEC4; break; + default: break; + } + break; + default: { + _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed"); + return NULL; + } + } + + OperatorNode *op = alloc_node(); + op->op = OP_INDEX; + op->return_cache = member_type; + op->arguments.push_back(expr); + op->arguments.push_back(index); + expr = op; + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']' after indexing expression"); + return NULL; + } + + } else if (tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) { + + OperatorNode *op = alloc_node(); + op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT; + op->arguments.push_back(expr); + + if (!_validate_operator(op, &op->return_cache)) { + _set_error("Invalid base type for increment/decrement operator"); + return NULL; + } + + if (!_validate_assign(expr, p_builtin_types)) { + _set_error("Invalid use of increment/decrement operator in constant expression."); + return NULL; + } + expr = op; + } else { + + _set_tkpos(pos2); + break; + } + } + + Expression e; + e.is_op = false; + e.node = expr; + expression.push_back(e); + + pos = _get_tkpos(); + tk = _get_token(); + + if (is_token_operator(tk.type)) { + + Expression o; + o.is_op = true; + + switch (tk.type) { + + case TK_OP_EQUAL: o.op = OP_EQUAL; break; + case TK_OP_NOT_EQUAL: o.op = OP_NOT_EQUAL; break; + case TK_OP_LESS: o.op = OP_LESS; break; + case TK_OP_LESS_EQUAL: o.op = OP_LESS_EQUAL; break; + case TK_OP_GREATER: o.op = OP_GREATER; break; + case TK_OP_GREATER_EQUAL: o.op = OP_GREATER_EQUAL; break; + case TK_OP_AND: o.op = OP_AND; break; + case TK_OP_OR: o.op = OP_OR; break; + case TK_OP_ADD: o.op = OP_ADD; break; + case TK_OP_SUB: o.op = OP_SUB; break; + case TK_OP_MUL: o.op = OP_MUL; break; + case TK_OP_DIV: o.op = OP_DIV; break; + case TK_OP_MOD: o.op = OP_MOD; break; + case TK_OP_SHIFT_LEFT: o.op = OP_SHIFT_LEFT; break; + case TK_OP_SHIFT_RIGHT: o.op = OP_SHIFT_RIGHT; break; + case TK_OP_ASSIGN: o.op = OP_ASSIGN; break; + case TK_OP_ASSIGN_ADD: o.op = OP_ASSIGN_ADD; break; + case TK_OP_ASSIGN_SUB: o.op = OP_ASSIGN_SUB; break; + case TK_OP_ASSIGN_MUL: o.op = OP_ASSIGN_MUL; break; + case TK_OP_ASSIGN_DIV: o.op = OP_ASSIGN_DIV; break; + case TK_OP_ASSIGN_MOD: o.op = OP_ASSIGN_MOD; break; + case TK_OP_ASSIGN_SHIFT_LEFT: o.op = OP_ASSIGN_SHIFT_LEFT; break; + case TK_OP_ASSIGN_SHIFT_RIGHT: o.op = OP_ASSIGN_SHIFT_RIGHT; break; + case TK_OP_ASSIGN_BIT_AND: o.op = OP_ASSIGN_BIT_AND; break; + case TK_OP_ASSIGN_BIT_OR: o.op = OP_ASSIGN_BIT_OR; break; + case TK_OP_ASSIGN_BIT_XOR: o.op = OP_ASSIGN_BIT_XOR; break; + case TK_OP_BIT_AND: o.op = OP_BIT_AND; break; + case TK_OP_BIT_OR: o.op = OP_BIT_OR; break; + case TK_OP_BIT_XOR: o.op = OP_BIT_XOR; break; + case TK_QUESTION: o.op = OP_SELECT_IF; break; + case TK_COLON: o.op = OP_SELECT_ELSE; break; + default: { + _set_error("Invalid token for operator: " + get_token_text(tk)); + return NULL; + } + } + + expression.push_back(o); + + } else { + _set_tkpos(pos); //something else, so rollback and end + break; + } + } + + /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ + + while (expression.size() > 1) { + + int next_op = -1; + int min_priority = 0xFFFFF; + bool is_unary = false; + bool is_ternary = false; + + for (int i = 0; i < expression.size(); i++) { + + if (!expression[i].is_op) { + + continue; + } + + bool unary = false; + bool ternary = false; + + int priority; + switch (expression[i].op) { + case OP_EQUAL: priority = 8; break; + case OP_NOT_EQUAL: priority = 8; break; + case OP_LESS: priority = 7; break; + case OP_LESS_EQUAL: priority = 7; break; + case OP_GREATER: priority = 7; break; + case OP_GREATER_EQUAL: priority = 7; break; + case OP_AND: priority = 12; break; + case OP_OR: priority = 14; break; + case OP_NOT: + priority = 3; + unary = true; + break; + case OP_NEGATE: + priority = 3; + unary = true; + break; + case OP_ADD: priority = 5; break; + case OP_SUB: priority = 5; break; + case OP_MUL: priority = 4; break; + case OP_DIV: priority = 4; break; + case OP_MOD: priority = 4; break; + case OP_SHIFT_LEFT: priority = 6; break; + case OP_SHIFT_RIGHT: priority = 6; break; + case OP_ASSIGN: priority = 16; break; + case OP_ASSIGN_ADD: priority = 16; break; + case OP_ASSIGN_SUB: priority = 16; break; + case OP_ASSIGN_MUL: priority = 16; break; + case OP_ASSIGN_DIV: priority = 16; break; + case OP_ASSIGN_MOD: priority = 16; break; + case OP_ASSIGN_SHIFT_LEFT: priority = 16; break; + case OP_ASSIGN_SHIFT_RIGHT: priority = 16; break; + case OP_ASSIGN_BIT_AND: priority = 16; break; + case OP_ASSIGN_BIT_OR: priority = 16; break; + case OP_ASSIGN_BIT_XOR: priority = 16; break; + case OP_BIT_AND: priority = 9; break; + case OP_BIT_OR: priority = 11; break; + case OP_BIT_XOR: priority = 10; break; + case OP_BIT_INVERT: + priority = 3; + unary = true; + break; + case OP_INCREMENT: + priority = 3; + unary = true; + break; + case OP_DECREMENT: + priority = 3; + unary = true; + break; + case OP_SELECT_IF: + priority = 15; + ternary = true; + break; + case OP_SELECT_ELSE: + priority = 15; + ternary = true; + break; + + default: + ERR_FAIL_V(NULL); //unexpected operator + } + + if (priority < min_priority) { + // < is used for left to right (default) + // <= is used for right to left + next_op = i; + min_priority = priority; + is_unary = unary; + is_ternary = ternary; + } + } + + ERR_FAIL_COND_V(next_op == -1, NULL); + + // OK! create operator.. + // OK! create operator.. + if (is_unary) { + + int expr_pos = next_op; + while (expression[expr_pos].is_op) { + + expr_pos++; + if (expr_pos == expression.size()) { + //can happen.. + _set_error("Unexpected end of expression..."); + return NULL; + } + } + + //consecutively do unary operators + for (int i = expr_pos - 1; i >= next_op; i--) { + + OperatorNode *op = alloc_node(); + op->op = expression[i].op; + if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) { + + _set_error("Can't use increment/decrement operator in constant expression."); + return NULL; + } + op->arguments.push_back(expression[i + 1].node); + + expression.write[i].is_op = false; + expression.write[i].node = op; + + if (!_validate_operator(op, &op->return_cache)) { + + String at; + for (int j = 0; j < op->arguments.size(); j++) { + if (j > 0) + at += " and "; + at += get_datatype_name(op->arguments[j]->get_datatype()); + } + _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); + return NULL; + } + expression.remove(i + 1); + } + + } else if (is_ternary) { + + if (next_op < 1 || next_op >= (expression.size() - 1)) { + _set_error("Parser bug..."); + ERR_FAIL_V(NULL); + } + + if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) { + _set_error("Missing matching ':' for select operator"); + return NULL; + } + + OperatorNode *op = alloc_node(); + op->op = expression[next_op].op; + op->arguments.push_back(expression[next_op - 1].node); + op->arguments.push_back(expression[next_op + 1].node); + op->arguments.push_back(expression[next_op + 3].node); + + expression.write[next_op - 1].is_op = false; + expression.write[next_op - 1].node = op; + if (!_validate_operator(op, &op->return_cache)) { + + String at; + for (int i = 0; i < op->arguments.size(); i++) { + if (i > 0) + at += " and "; + at += get_datatype_name(op->arguments[i]->get_datatype()); + } + _set_error("Invalid argument to ternary ?: operator: " + at); + return NULL; + } + + for (int i = 0; i < 4; i++) { + expression.remove(next_op); + } + + } else { + + if (next_op < 1 || next_op >= (expression.size() - 1)) { + _set_error("Parser bug..."); + ERR_FAIL_V(NULL); + } + + OperatorNode *op = alloc_node(); + op->op = expression[next_op].op; + + if (expression[next_op - 1].is_op) { + + _set_error("Parser bug..."); + ERR_FAIL_V(NULL); + } + + if (_is_operator_assign(op->op)) { + + String assign_message; + if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) { + + _set_error(assign_message); + return NULL; + } + } + + if (expression[next_op + 1].is_op) { + // this is not invalid and can really appear + // but it becomes invalid anyway because no binary op + // can be followed by a unary op in a valid combination, + // due to how precedence works, unaries will always disappear first + + _set_error("Parser bug..."); + } + + op->arguments.push_back(expression[next_op - 1].node); //expression goes as left + op->arguments.push_back(expression[next_op + 1].node); //next expression goes as right + expression.write[next_op - 1].node = op; + + //replace all 3 nodes by this operator and make it an expression + + if (!_validate_operator(op, &op->return_cache)) { + + String at; + for (int i = 0; i < op->arguments.size(); i++) { + if (i > 0) + at += " and "; + if (op->arguments[i]->get_datatype() == TYPE_STRUCT) { + at += op->arguments[i]->get_datatype_name(); + } else { + at += get_datatype_name(op->arguments[i]->get_datatype()); + } + } + _set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at); + return NULL; + } + + expression.remove(next_op); + expression.remove(next_op); + } + } + + return expression[0].node; +} + +ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) { + + if (p_node->type != Node::TYPE_OPERATOR) + return p_node; + + //for now only reduce simple constructors + OperatorNode *op = static_cast(p_node); + + if (op->op == OP_CONSTRUCT) { + + ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node); + + DataType type = op->get_datatype(); + DataType base = get_scalar_type(type); + int cardinality = get_cardinality(type); + + Vector values; + + for (int i = 1; i < op->arguments.size(); i++) { + + op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]); + if (op->arguments[i]->type == Node::TYPE_CONSTANT) { + ConstantNode *cn = static_cast(op->arguments[i]); + + if (get_scalar_type(cn->datatype) == base) { + for (int j = 0; j < cn->values.size(); j++) { + values.push_back(cn->values[j]); + } + } else if (get_scalar_type(cn->datatype) == cn->datatype) { + + ConstantNode::Value v; + if (!convert_constant(cn, base, &v)) { + return p_node; + } + values.push_back(v); + } else { + return p_node; + } + + } else { + return p_node; + } + } + + if (values.size() == 1) { + if (type >= TYPE_MAT2 && type <= TYPE_MAT4) { + ConstantNode::Value value = values[0]; + ConstantNode::Value zero; + zero.real = 0.0f; + int size = 2 + (type - TYPE_MAT2); + + values.clear(); + for (int i = 0; i < size; i++) { + for (int j = 0; j < size; j++) { + values.push_back(i == j ? value : zero); + } + } + } else { + ConstantNode::Value value = values[0]; + for (int i = 1; i < cardinality; i++) { + values.push_back(value); + } + } + } else if (values.size() != cardinality) { + ERR_PRINT("Failed to reduce expression, values and cardinality mismatch."); + return p_node; + } + + ConstantNode *cn = alloc_node(); + cn->datatype = op->get_datatype(); + cn->values = values; + return cn; + } else if (op->op == OP_NEGATE) { + + op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]); + if (op->arguments[0]->type == Node::TYPE_CONSTANT) { + + ConstantNode *cn = static_cast(op->arguments[0]); + + DataType base = get_scalar_type(cn->datatype); + + Vector values; + + for (int i = 0; i < cn->values.size(); i++) { + + ConstantNode::Value nv; + switch (base) { + case TYPE_BOOL: { + nv.boolean = !cn->values[i].boolean; + } break; + case TYPE_INT: { + nv.sint = -cn->values[i].sint; + } break; + case TYPE_UINT: { + // Intentionally wrap the unsigned int value, because GLSL does. + nv.uint = 0 - cn->values[i].uint; + } break; + case TYPE_FLOAT: { + nv.real = -cn->values[i].real; + } break; + default: { + } + } + + values.push_back(nv); + } + + cn->values = values; + return cn; + } + } + + return p_node; +} + +ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map &p_builtin_types) { + + ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types); + if (!expr) //errored + return NULL; + + expr = _reduce_expression(p_block, expr); + + return expr; +} + +Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) { + + while (true) { + + TkPos pos = _get_tkpos(); + + Token tk = _get_token(); + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) { + if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) { + _set_error("Switch may contains only case and default blocks"); + return ERR_PARSE_ERROR; + } + } + + bool is_struct = shader->structs.has(tk.text); + + if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block + if (p_just_one) { + _set_error("Unexpected '}'"); + return ERR_PARSE_ERROR; + } + + return OK; + + } else if (tk.type == TK_CONST || is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type) || is_struct) { + String struct_name = ""; + if (is_struct) { + struct_name = tk.text; + } + + bool is_const = false; + + if (tk.type == TK_CONST) { + is_const = true; + tk = _get_token(); + + if (!is_struct) { + is_struct = shader->structs.has(tk.text); // check again. + struct_name = tk.text; + } + } + + DataPrecision precision = PRECISION_DEFAULT; + if (is_token_precision(tk.type)) { + precision = get_token_precision(tk.type); + tk = _get_token(); + + if (!is_struct) { + is_struct = shader->structs.has(tk.text); // check again. + } + if (is_struct && precision != PRECISION_DEFAULT) { + _set_error("Precision modifier cannot be used on structs."); + return ERR_PARSE_ERROR; + } + if (!is_token_nonvoid_datatype(tk.type)) { + _set_error("Expected datatype after precision"); + return ERR_PARSE_ERROR; + } + } + + if (!is_struct) { + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for variable (samplers not allowed)"); + return ERR_PARSE_ERROR; + } + } + + DataType type = is_struct ? TYPE_STRUCT : get_token_datatype(tk.type); + + if (_validate_datatype(type) != OK) { + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + Node *vardecl = NULL; + + while (true) { + + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier after type"); + return ERR_PARSE_ERROR; + } + + StringName name = tk.text; + ShaderLanguage::IdentifierType itype; + if (_find_identifier(p_block, true, p_builtin_types, name, (ShaderLanguage::DataType *)0, &itype)) { + if (itype != IDENTIFIER_FUNCTION) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + } + + BlockNode::Variable var; + var.type = type; + var.precision = precision; + var.line = tk_line; + var.array_size = 0; + var.is_const = is_const; + var.struct_name = struct_name; + + tk = _get_token(); + + if (tk.type == TK_BRACKET_OPEN) { + bool unknown_size = false; + + if (RenderingServer::get_singleton()->is_low_end() && is_const) { + _set_error("Local const arrays are supported only on high-end platform!"); + return ERR_PARSE_ERROR; + } + + ArrayDeclarationNode *node = alloc_node(); + if (is_struct) { + node->struct_name = struct_name; + node->datatype = TYPE_STRUCT; + } else { + node->datatype = type; + } + node->precision = precision; + node->is_const = is_const; + vardecl = (Node *)node; + + ArrayDeclarationNode::Declaration decl; + decl.name = name; + decl.size = 0U; + + tk = _get_token(); + + if (tk.type == TK_BRACKET_CLOSE) { + unknown_size = true; + } else { + + if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { + _set_error("Expected integer constant > 0 or ']'"); + return ERR_PARSE_ERROR; + } + + decl.size = ((uint32_t)tk.constant); + tk = _get_token(); + + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + var.array_size = decl.size; + } + + bool full_def = false; + + tk = _get_token(); + if (tk.type == TK_OP_ASSIGN) { + + if (RenderingServer::get_singleton()->is_low_end()) { + _set_error("Array initialization is supported only on high-end platform!"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_CURLY_BRACKET_OPEN) { + + if (unknown_size) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + + full_def = true; + + DataPrecision precision2 = PRECISION_DEFAULT; + if (is_token_precision(tk.type)) { + precision2 = get_token_precision(tk.type); + tk = _get_token(); + if (shader->structs.has(tk.text)) { + _set_error("Precision modifier cannot be used on structs."); + return ERR_PARSE_ERROR; + } + if (!is_token_nonvoid_datatype(tk.type)) { + _set_error("Expected datatype after precision"); + return ERR_PARSE_ERROR; + } + } + + DataType type2; + String struct_name2 = ""; + + if (shader->structs.has(tk.text)) { + type2 = TYPE_STRUCT; + struct_name2 = tk.text; + } else { + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for array"); + return ERR_PARSE_ERROR; + } + type2 = get_token_datatype(tk.type); + } + + int array_size2 = 0; + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + TkPos pos2 = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + array_size2 = var.array_size; + tk = _get_token(); + } else { + _set_tkpos(pos2); + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + ConstantNode *cnode = (ConstantNode *)n; + if (cnode->values.size() == 1) { + array_size2 = cnode->values[0].sint; + if (array_size2 <= 0) { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_BRACKET_CLOSE) { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } else { + tk = _get_token(); + } + } + } else { + _set_error("Expected '['"); + return ERR_PARSE_ERROR; + } + + if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) { + String error_str = "Cannot convert from '"; + if (precision2 != PRECISION_DEFAULT) { + error_str += get_precision_name(precision2); + error_str += " "; + } + if (type2 == TYPE_STRUCT) { + error_str += struct_name2; + } else { + error_str += get_datatype_name(type2); + } + error_str += "["; + error_str += itos(array_size2); + error_str += "]'"; + error_str += " to '"; + if (precision != PRECISION_DEFAULT) { + error_str += get_precision_name(precision); + error_str += " "; + } + if (type == TYPE_STRUCT) { + error_str += struct_name; + } else { + error_str += get_datatype_name(type); + } + error_str += "["; + error_str += itos(var.array_size); + error_str += "]'"; + _set_error(error_str); + return ERR_PARSE_ERROR; + } + } + + bool curly = tk.type == TK_CURLY_BRACKET_OPEN; + + if (unknown_size) { + if (!curly) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + } else { + if (full_def) { + if (curly) { + _set_error("Expected '('"); + return ERR_PARSE_ERROR; + } + } + } + + if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization + while (true) { + + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) { + return ERR_PARSE_ERROR; + } + + if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + _set_error("Expected constant expression"); + return ERR_PARSE_ERROR; + } + + if (var.type != n->get_datatype() || struct_name != n->get_datatype_name()) { + _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? struct_name : get_datatype_name(var.type)) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type == TK_COMMA) { + decl.initializer.push_back(n); + continue; + } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) { + decl.initializer.push_back(n); + break; + } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) { + decl.initializer.push_back(n); + break; + } else { + if (curly) + _set_error("Expected '}' or ','"); + else + _set_error("Expected ')' or ','"); + return ERR_PARSE_ERROR; + } + } + if (unknown_size) { + decl.size = decl.initializer.size(); + var.array_size = decl.initializer.size(); + } else if (decl.initializer.size() != var.array_size) { + _set_error("Array size mismatch"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } + } else { + if (unknown_size) { + _set_error("Expected array initialization"); + return ERR_PARSE_ERROR; + } + if (is_const) { + _set_error("Expected initialization of constant"); + return ERR_PARSE_ERROR; + } + } + + node->declarations.push_back(decl); + } else if (tk.type == TK_OP_ASSIGN) { + + VariableDeclarationNode *node = alloc_node(); + if (is_struct) { + node->struct_name = struct_name; + node->datatype = TYPE_STRUCT; + } else { + node->datatype = type; + } + node->precision = precision; + node->is_const = is_const; + vardecl = (Node *)node; + + VariableDeclarationNode::Declaration decl; + decl.name = name; + decl.initializer = NULL; + + //variable created with assignment! must parse an expression + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } + decl.initializer = n; + + if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) { + _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + node->declarations.push_back(decl); + } else { + if (is_const) { + _set_error("Expected initialization of constant"); + return ERR_PARSE_ERROR; + } + + VariableDeclarationNode *node = alloc_node(); + if (is_struct) { + node->struct_name = struct_name; + node->datatype = TYPE_STRUCT; + } else { + node->datatype = type; + } + node->precision = precision; + vardecl = (Node *)node; + + VariableDeclarationNode::Declaration decl; + decl.name = name; + decl.initializer = NULL; + node->declarations.push_back(decl); + } + + p_block->statements.push_back(vardecl); + + p_block->variables[name] = var; + + if (tk.type == TK_COMMA) { + tk = _get_token(); + //another variable + } else if (tk.type == TK_SEMICOLON) { + break; + } else { + _set_error("Expected ',' or ';' after variable"); + return ERR_PARSE_ERROR; + } + } + } else if (tk.type == TK_CURLY_BRACKET_OPEN) { + //a sub block, just because.. + BlockNode *block = alloc_node(); + block->parent_block = p_block; + if (_parse_block(block, p_builtin_types, false, p_can_break, p_can_continue) != OK) { + return ERR_PARSE_ERROR; + } + p_block->statements.push_back(block); + } else if (tk.type == TK_CF_IF) { + //if () {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after if"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node(); + cf->flow_op = FLOW_OP_IF; + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + if (n->get_datatype() != TYPE_BOOL) { + _set_error("Expected boolean expression"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after expression"); + return ERR_PARSE_ERROR; + } + + BlockNode *block = alloc_node(); + block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); + if (err) + return err; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_CF_ELSE) { + + block = alloc_node(); + block->parent_block = p_block; + cf->blocks.push_back(block); + err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); + + } else { + _set_tkpos(pos); //rollback + } + } else if (tk.type == TK_CF_SWITCH) { + + if (RenderingServer::get_singleton()->is_low_end()) { + _set_error("\"switch\" operator is supported only on high-end platform!"); + return ERR_PARSE_ERROR; + } + + // switch() {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after switch"); + return ERR_PARSE_ERROR; + } + ControlFlowNode *cf = alloc_node(); + cf->flow_op = FLOW_OP_SWITCH; + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + if (n->get_datatype() != TYPE_INT) { + _set_error("Expected integer expression"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after expression"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + if (tk.type != TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' after switch statement"); + return ERR_PARSE_ERROR; + } + BlockNode *switch_block = alloc_node(); + switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH; + switch_block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(switch_block); + p_block->statements.push_back(cf); + + int prev_type = TK_CF_CASE; + while (true) { // Go-through multiple cases. + + if (_parse_block(switch_block, p_builtin_types, true, true, false) != OK) { + return ERR_PARSE_ERROR; + } + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) { + if (prev_type == TK_CF_DEFAULT) { + if (tk.type == TK_CF_CASE) { + _set_error("Cases must be defined before default case."); + return ERR_PARSE_ERROR; + } else if (prev_type == TK_CF_DEFAULT) { + _set_error("Default case must be defined only once."); + return ERR_PARSE_ERROR; + } + } + prev_type = tk.type; + _set_tkpos(pos); + continue; + } else { + Set constants; + for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. + ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; + if (flow) { + if (flow->flow_op == FLOW_OP_CASE) { + ConstantNode *n2 = static_cast(flow->expressions[0]); + if (!n2) { + return ERR_PARSE_ERROR; + } + if (n2->values.empty()) { + return ERR_PARSE_ERROR; + } + if (constants.has(n2->values[0].sint)) { + _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'"); + return ERR_PARSE_ERROR; + } + constants.insert(n2->values[0].sint); + } else if (flow->flow_op == FLOW_OP_DEFAULT) { + continue; + } else { + return ERR_PARSE_ERROR; + } + } else { + return ERR_PARSE_ERROR; + } + } + break; + } + } + + } else if (tk.type == TK_CF_CASE) { + // case x : break; | return; + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { + _set_tkpos(pos); + return OK; + } + + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { + _set_error("case must be placed within switch block"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + int sign = 1; + + if (tk.type == TK_OP_SUB) { + sign = -1; + tk = _get_token(); + } + + if (tk.type != TK_INT_CONSTANT) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + int constant = (int)tk.constant * sign; + + tk = _get_token(); + + if (tk.type != TK_COLON) { + _set_error("Expected ':'"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node(); + cf->flow_op = FLOW_OP_CASE; + + ConstantNode *n = alloc_node(); + ConstantNode::Value v; + v.sint = constant; + n->values.push_back(v); + n->datatype = TYPE_INT; + + BlockNode *case_block = alloc_node(); + case_block->block_type = BlockNode::BLOCK_TYPE_CASE; + case_block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(case_block); + p_block->statements.push_back(cf); + + Error err = _parse_block(case_block, p_builtin_types, false, true, false); + if (err) + return err; + + return OK; + + } else if (tk.type == TK_CF_DEFAULT) { + + if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { + _set_tkpos(pos); + return OK; + } + + if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { + _set_error("default must be placed within switch block"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_COLON) { + _set_error("Expected ':'"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node(); + cf->flow_op = FLOW_OP_DEFAULT; + + BlockNode *default_block = alloc_node(); + default_block->block_type = BlockNode::BLOCK_TYPE_DEFAULT; + default_block->parent_block = p_block; + cf->blocks.push_back(default_block); + p_block->statements.push_back(cf); + + Error err = _parse_block(default_block, p_builtin_types, false, true, false); + if (err) + return err; + + return OK; + + } else if (tk.type == TK_CF_DO || tk.type == TK_CF_WHILE) { + // do {} while() + // while() {} + bool is_do = tk.type == TK_CF_DO; + + BlockNode *do_block = NULL; + if (is_do) { + + do_block = alloc_node(); + do_block->parent_block = p_block; + + Error err = _parse_block(do_block, p_builtin_types, true, true, true); + if (err) + return err; + + tk = _get_token(); + if (tk.type != TK_CF_WHILE) { + _set_error("Expected while after do"); + return ERR_PARSE_ERROR; + } + } + tk = _get_token(); + + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after while"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node(); + if (is_do) { + cf->flow_op = FLOW_OP_DO; + } else { + cf->flow_op = FLOW_OP_WHILE; + } + Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after expression"); + return ERR_PARSE_ERROR; + } + if (!is_do) { + BlockNode *block = alloc_node(); + block->parent_block = p_block; + cf->expressions.push_back(n); + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + Error err = _parse_block(block, p_builtin_types, true, true, true); + if (err) + return err; + } else { + + cf->expressions.push_back(n); + cf->blocks.push_back(do_block); + p_block->statements.push_back(cf); + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } + } else if (tk.type == TK_CF_FOR) { + // for() {} + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after for"); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *cf = alloc_node(); + cf->flow_op = FLOW_OP_FOR; + + BlockNode *init_block = alloc_node(); + init_block->parent_block = p_block; + init_block->single_statement = true; + cf->blocks.push_back(init_block); + if (_parse_block(init_block, p_builtin_types, true, false, false) != OK) { + return ERR_PARSE_ERROR; + } + + Node *n = _parse_and_reduce_expression(init_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + if (n->get_datatype() != TYPE_BOOL) { + _set_error("Middle expression is expected to be boolean."); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after middle expression"); + return ERR_PARSE_ERROR; + } + + cf->expressions.push_back(n); + + n = _parse_and_reduce_expression(init_block, p_builtin_types); + if (!n) + return ERR_PARSE_ERROR; + + cf->expressions.push_back(n); + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ')' after third expression"); + return ERR_PARSE_ERROR; + } + + BlockNode *block = alloc_node(); + block->parent_block = init_block; + cf->blocks.push_back(block); + p_block->statements.push_back(cf); + + Error err = _parse_block(block, p_builtin_types, true, true, true); + if (err) + return err; + + } else if (tk.type == TK_CF_RETURN) { + + //check return type + BlockNode *b = p_block; + while (b && !b->parent_function) { + b = b->parent_block; + } + + if (!b) { + _set_error("Bug"); + return ERR_BUG; + } + + ControlFlowNode *flow = alloc_node(); + flow->flow_op = FLOW_OP_RETURN; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_SEMICOLON) { + //all is good + if (b->parent_function->return_type != TYPE_VOID) { + _set_error("Expected return with expression of type '" + get_datatype_name(b->parent_function->return_type) + "'"); + return ERR_PARSE_ERROR; + } + } else { + _set_tkpos(pos); //rollback, wants expression + Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!expr) + return ERR_PARSE_ERROR; + + if (b->parent_function->return_type != expr->get_datatype()) { + _set_error("Expected return expression of type '" + get_datatype_name(b->parent_function->return_type) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after return expression"); + return ERR_PARSE_ERROR; + } + + flow->expressions.push_back(expr); + } + + p_block->statements.push_back(flow); + + BlockNode *block = p_block; + while (block) { + if (block->block_type == BlockNode::BLOCK_TYPE_CASE || block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { + return OK; + } + block = block->parent_block; + } + } else if (tk.type == TK_CF_DISCARD) { + + //check return type + BlockNode *b = p_block; + while (b && !b->parent_function) { + b = b->parent_block; + } + if (!b) { + _set_error("Bug"); + return ERR_BUG; + } + + if (!b->parent_function->can_discard) { + _set_error("Use of 'discard' is not allowed here."); + return ERR_PARSE_ERROR; + } + + ControlFlowNode *flow = alloc_node(); + flow->flow_op = FLOW_OP_DISCARD; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after discard"); + } + + p_block->statements.push_back(flow); + } else if (tk.type == TK_CF_BREAK) { + + if (!p_can_break) { + //all is good + _set_error("Breaking is not allowed here"); + } + + ControlFlowNode *flow = alloc_node(); + flow->flow_op = FLOW_OP_BREAK; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after break"); + } + + p_block->statements.push_back(flow); + + BlockNode *block = p_block; + while (block) { + if (block->block_type == BlockNode::BLOCK_TYPE_CASE || block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { + return OK; + } + block = block->parent_block; + } + + } else if (tk.type == TK_CF_CONTINUE) { + + if (!p_can_continue) { + //all is good + _set_error("Continuing is not allowed here"); + } + + ControlFlowNode *flow = alloc_node(); + flow->flow_op = FLOW_OP_CONTINUE; + + pos = _get_tkpos(); + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + //all is good + _set_error("Expected ';' after continue"); + } + + p_block->statements.push_back(flow); + + } else { + + //nothing else, so expression + _set_tkpos(pos); //rollback + Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); + if (!expr) + return ERR_PARSE_ERROR; + p_block->statements.push_back(expr); + tk = _get_token(); + + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after statement"); + return ERR_PARSE_ERROR; + } + } + + if (p_just_one) + break; + } + + return OK; +} + +String ShaderLanguage::_get_shader_type_list(const Set &p_shader_types) const { + + // Return a list of shader types as an human-readable string + String valid_types; + for (const Set::Element *E = p_shader_types.front(); E; E = E->next()) { + if (valid_types != String()) { + valid_types += ", "; + } + + valid_types += "'" + E->get() + "'"; + } + + return valid_types; +} + +String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const { + switch (p_qualifier) { + case ArgumentQualifier::ARGUMENT_QUALIFIER_IN: + return "in"; + case ArgumentQualifier::ARGUMENT_QUALIFIER_OUT: + return "out"; + case ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT: + return "inout"; + } + return ""; +} + +Error ShaderLanguage::_validate_datatype(DataType p_type) { + if (RenderingServer::get_singleton()->is_low_end()) { + bool invalid_type = false; + + switch (p_type) { + case TYPE_UINT: + case TYPE_UVEC2: + case TYPE_UVEC3: + case TYPE_UVEC4: + case TYPE_ISAMPLER2D: + case TYPE_USAMPLER2D: + case TYPE_ISAMPLER3D: + case TYPE_USAMPLER3D: + case TYPE_USAMPLER2DARRAY: + case TYPE_ISAMPLER2DARRAY: + invalid_type = true; + break; + default: + break; + } + + if (invalid_type) { + _set_error(vformat("\"%s\" type is supported only on high-end platform!", get_datatype_name(p_type))); + return ERR_UNAVAILABLE; + } + } + return OK; +} + +Error ShaderLanguage::_parse_shader(const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types) { + + Token tk = _get_token(); + + if (tk.type != TK_SHADER_TYPE) { + _set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types)); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier after 'shader_type', indicating type of shader. Valid types are: " + _get_shader_type_list(p_shader_types)); + return ERR_PARSE_ERROR; + } + + String shader_type_identifier; + + shader_type_identifier = tk.text; + + if (!p_shader_types.has(shader_type_identifier)) { + _set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types)); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';' after 'shader_type '."); + } + + tk = _get_token(); + + int texture_uniforms = 0; + int uniforms = 0; + + while (tk.type != TK_EOF) { + + switch (tk.type) { + case TK_RENDER_MODE: { + + while (true) { + + StringName mode; + _get_completable_identifier(NULL, COMPLETION_RENDER_MODE, mode); + + if (mode == StringName()) { + _set_error("Expected identifier for render mode"); + return ERR_PARSE_ERROR; + } + + if (p_render_modes.find(mode) == -1) { + _set_error("Invalid render mode: '" + String(mode) + "'"); + return ERR_PARSE_ERROR; + } + + if (shader->render_modes.find(mode) != -1) { + _set_error("Duplicate render mode: '" + String(mode) + "'"); + return ERR_PARSE_ERROR; + } + + shader->render_modes.push_back(mode); + + tk = _get_token(); + if (tk.type == TK_COMMA) { + //all good, do nothing + } else if (tk.type == TK_SEMICOLON) { + break; //done + } else { + _set_error("Unexpected token: " + get_token_text(tk)); + return ERR_PARSE_ERROR; + } + } + } break; + case TK_STRUCT: { + ShaderNode::Struct st; + DataType type; + + tk = _get_token(); + if (tk.type == TK_IDENTIFIER) { + st.name = tk.text; + tk = _get_token(); + if (tk.type != TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected struct identifier!"); + return ERR_PARSE_ERROR; + } + + StructNode *st_node = alloc_node(); + st.shader_struct = st_node; + + int member_count = 0; + Set member_names; + while (true) { // variables list + tk = _get_token(); + if (tk.type == TK_CURLY_BRACKET_CLOSE) { + break; + } + StringName struct_name = ""; + bool struct_dt = false; + bool use_precision = false; + DataPrecision precision = DataPrecision::PRECISION_DEFAULT; + + if (tk.type == TK_STRUCT) { + _set_error("nested structs are not allowed!"); + return ERR_PARSE_ERROR; + } + + if (is_token_precision(tk.type)) { + precision = get_token_precision(tk.type); + use_precision = true; + tk = _get_token(); + } + + if (shader->structs.has(tk.text)) { + struct_name = tk.text; + struct_dt = true; + if (use_precision) { + _set_error("Precision modifier cannot be used on structs."); + return ERR_PARSE_ERROR; + } + } + + if (!is_token_datatype(tk.type) && !struct_dt) { + _set_error("Expected datatype."); + return ERR_PARSE_ERROR; + } else { + type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type); + + if (is_sampler_type(type)) { + _set_error("sampler datatype not allowed here"); + return ERR_PARSE_ERROR; + } else if (type == TYPE_VOID) { + _set_error("void datatype not allowed here"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier!"); + return ERR_PARSE_ERROR; + } + + MemberNode *member = alloc_node(); + member->precision = precision; + member->datatype = type; + member->struct_name = struct_name; + member->name = tk.text; + + if (member_names.has(member->name)) { + _set_error("Redefinition of '" + String(member->name) + "'"); + return ERR_PARSE_ERROR; + } + member_names.insert(member->name); + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + tk = _get_token(); + if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { + member->array_size = (int)tk.constant; + + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + } + st_node->members.push_back(member); + + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ']' or ';'"); + return ERR_PARSE_ERROR; + } + member_count++; + } + } + if (member_count == 0) { + _set_error("Empty structs are not allowed!"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + shader->structs[st.name] = st; + shader->vstructs.push_back(st); // struct's order is important! + + } break; + case TK_UNIFORM: + case TK_VARYING: { + + bool uniform = tk.type == TK_UNIFORM; + DataPrecision precision = PRECISION_DEFAULT; + DataInterpolation interpolation = INTERPOLATION_SMOOTH; + DataType type; + StringName name; + + tk = _get_token(); + if (is_token_interpolation(tk.type)) { + interpolation = get_token_interpolation(tk.type); + tk = _get_token(); + } + + if (is_token_precision(tk.type)) { + precision = get_token_precision(tk.type); + tk = _get_token(); + } + + if (!is_token_datatype(tk.type)) { + _set_error("Expected datatype. "); + return ERR_PARSE_ERROR; + } + + type = get_token_datatype(tk.type); + + if (type == TYPE_VOID) { + _set_error("void datatype not allowed here"); + return ERR_PARSE_ERROR; + } + + if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { + _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed."); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier!"); + return ERR_PARSE_ERROR; + } + + name = tk.text; + + if (_find_identifier(NULL, false, Map(), name)) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + + if (has_builtin(p_functions, name)) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + + if (uniform) { + + ShaderNode::Uniform uniform2; + + if (is_sampler_type(type)) { + uniform2.texture_order = texture_uniforms++; + uniform2.order = -1; + if (_validate_datatype(type) != OK) { + return ERR_PARSE_ERROR; + } + } else { + uniform2.texture_order = -1; + uniform2.order = uniforms++; + } + uniform2.type = type; + uniform2.precision = precision; + + //todo parse default value + + tk = _get_token(); + + if (tk.type == TK_COLON) { + //hint + do { + tk = _get_token(); + if (tk.type == TK_HINT_WHITE_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_WHITE; + } else if (tk.type == TK_HINT_BLACK_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_BLACK; + } else if (tk.type == TK_HINT_NORMAL_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_NORMAL; + } else if (tk.type == TK_HINT_ROUGHNESS_NORMAL_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL; + } else if (tk.type == TK_HINT_ROUGHNESS_R) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_R; + } else if (tk.type == TK_HINT_ROUGHNESS_G) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_G; + } else if (tk.type == TK_HINT_ROUGHNESS_B) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_B; + } else if (tk.type == TK_HINT_ROUGHNESS_A) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A; + } else if (tk.type == TK_HINT_ROUGHNESS_GRAY) { + uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY; + } else if (tk.type == TK_HINT_ANISO_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_ANISO; + } else if (tk.type == TK_HINT_ALBEDO_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO; + } else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) { + uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; + } else if (tk.type == TK_HINT_COLOR) { + if (type != TYPE_VEC4) { + _set_error("Color hint is for vec4 only"); + return ERR_PARSE_ERROR; + } + uniform2.hint = ShaderNode::Uniform::HINT_COLOR; + } else if (tk.type == TK_HINT_RANGE) { + + uniform2.hint = ShaderNode::Uniform::HINT_RANGE; + if (type != TYPE_FLOAT && type != TYPE_INT) { + _set_error("Range hint is for float and int only"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + _set_error("Expected '(' after hint_range"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + float sign = 1.0; + + if (tk.type == TK_OP_SUB) { + sign = -1.0; + tk = _get_token(); + } + + if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { + _set_error("Expected integer constant"); + return ERR_PARSE_ERROR; + } + + uniform2.hint_range[0] = tk.constant; + uniform2.hint_range[0] *= sign; + + tk = _get_token(); + + if (tk.type != TK_COMMA) { + _set_error("Expected ',' after integer constant"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + sign = 1.0; + + if (tk.type == TK_OP_SUB) { + sign = -1.0; + tk = _get_token(); + } + + if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { + _set_error("Expected integer constant after ','"); + return ERR_PARSE_ERROR; + } + + uniform2.hint_range[1] = tk.constant; + uniform2.hint_range[1] *= sign; + + tk = _get_token(); + + if (tk.type == TK_COMMA) { + tk = _get_token(); + + if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { + _set_error("Expected integer constant after ','"); + return ERR_PARSE_ERROR; + } + + uniform2.hint_range[2] = tk.constant; + tk = _get_token(); + } else { + if (type == TYPE_INT) { + uniform2.hint_range[2] = 1; + } else { + uniform2.hint_range[2] = 0.001; + } + } + + if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ','"); + return ERR_PARSE_ERROR; + } + } else if (tk.type == TK_FILTER_LINEAR) { + uniform2.filter = FILTER_LINEAR; + } else if (tk.type == TK_FILTER_NEAREST) { + uniform2.filter = FILTER_NEAREST; + } else if (tk.type == TK_FILTER_NEAREST_MIPMAP) { + uniform2.filter = FILTER_NEAREST_MIPMAP; + } else if (tk.type == TK_FILTER_LINEAR_MIPMAP) { + uniform2.filter = FILTER_LINEAR_MIPMAP; + } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISO) { + uniform2.filter = FILTER_NEAREST_MIPMAP_ANISO; + } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISO) { + uniform2.filter = FILTER_LINEAR_MIPMAP_ANISO; + } else if (tk.type == TK_REPEAT_DISABLE) { + uniform2.repeat = REPEAT_DISABLE; + } else if (tk.type == TK_REPEAT_ENABLE) { + uniform2.repeat = REPEAT_ENABLE; + } else { + _set_error("Expected valid type hint after ':'."); + } + + if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { + _set_error("This hint is only for sampler types"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + } while (tk.type == TK_COMMA); + } + + if (tk.type == TK_OP_ASSIGN) { + + Node *expr = _parse_and_reduce_expression(NULL, Map()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type != Node::TYPE_CONSTANT) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } + + ConstantNode *cn = static_cast(expr); + + uniform2.default_value.resize(cn->values.size()); + + if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) { + _set_error("Can't convert constant to " + get_datatype_name(uniform2.type)); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } + + shader->uniforms[name] = uniform2; + + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } else { + + ShaderNode::Varying varying; + varying.type = type; + varying.precision = precision; + varying.interpolation = interpolation; + + tk = _get_token(); + if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) { + _set_error("Expected ';' or '['"); + return ERR_PARSE_ERROR; + } + + if (tk.type == TK_BRACKET_OPEN) { + tk = _get_token(); + if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { + varying.array_size = (int)tk.constant; + + tk = _get_token(); + if (tk.type == TK_BRACKET_CLOSE) { + tk = _get_token(); + if (tk.type != TK_SEMICOLON) { + _set_error("Expected ';'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected ']'"); + return ERR_PARSE_ERROR; + } + } else { + _set_error("Expected single integer constant > 0"); + return ERR_PARSE_ERROR; + } + } + + shader->varyings[name] = varying; + } + + } break; + default: { + //function or constant variable + + bool is_constant = false; + bool is_struct = false; + StringName struct_name; + DataPrecision precision = PRECISION_DEFAULT; + DataType type; + StringName name; + + if (tk.type == TK_CONST) { + is_constant = true; + tk = _get_token(); + } + + if (is_token_precision(tk.type)) { + precision = get_token_precision(tk.type); + tk = _get_token(); + } + + if (shader->structs.has(tk.text)) { + if (precision != PRECISION_DEFAULT) { + _set_error("Precision modifier cannot be used on structs."); + return ERR_PARSE_ERROR; + } + is_struct = true; + struct_name = tk.text; + } else { + + if (!is_token_datatype(tk.type)) { + _set_error("Expected constant, function, uniform or varying"); + return ERR_PARSE_ERROR; + } + + if (!is_token_variable_datatype(tk.type)) { + _set_error("Invalid data type for constants or function return (samplers not allowed)"); + return ERR_PARSE_ERROR; + } + } + + if (is_struct) { + type = TYPE_STRUCT; + } else { + type = get_token_datatype(tk.type); + } + TkPos prev_pos = _get_tkpos(); + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + _set_error("Cannot use arrays as return types"); + return ERR_PARSE_ERROR; + } + _set_tkpos(prev_pos); + + _get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name); + + if (name == StringName()) { + _set_error("Expected function name after datatype"); + return ERR_PARSE_ERROR; + } + + if (_find_identifier(NULL, false, Map(), name)) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + + if (has_builtin(p_functions, name)) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + if (tk.type != TK_PARENTHESIS_OPEN) { + if (type == TYPE_VOID) { + _set_error("Expected '(' after function identifier"); + return ERR_PARSE_ERROR; + } + + //variable + + while (true) { + ShaderNode::Constant constant; + constant.type = is_struct ? TYPE_STRUCT : type; + constant.type_str = struct_name; + constant.precision = precision; + constant.initializer = NULL; + + if (tk.type == TK_OP_ASSIGN) { + + if (!is_constant) { + _set_error("Expected 'const' keyword before constant definition"); + return ERR_PARSE_ERROR; + } + + //variable created with assignment! must parse an expression + Node *expr = _parse_and_reduce_expression(NULL, Map()); + if (!expr) + return ERR_PARSE_ERROR; + if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { + _set_error("Expected constant expression after '='"); + return ERR_PARSE_ERROR; + } + + constant.initializer = static_cast(expr); + + if (is_struct) { + if (expr->get_datatype_name() != struct_name) { + _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + struct_name + "'"); + return ERR_PARSE_ERROR; + } + } else if (type != expr->get_datatype()) { + _set_error("Invalid assignment of '" + get_datatype_name(expr->get_datatype()) + "' to '" + get_datatype_name(type) + "'"); + return ERR_PARSE_ERROR; + } + tk = _get_token(); + } else { + _set_error("Expected initialization of constant"); + return ERR_PARSE_ERROR; + } + + shader->constants[name] = constant; + if (tk.type == TK_COMMA) { + tk = _get_token(); + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier after type"); + return ERR_PARSE_ERROR; + } + + name = tk.text; + if (_find_identifier(NULL, false, Map(), name)) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + + if (has_builtin(p_functions, name)) { + _set_error("Redefinition of '" + String(name) + "'"); + return ERR_PARSE_ERROR; + } + + tk = _get_token(); + + } else if (tk.type == TK_SEMICOLON) { + break; + } else { + _set_error("Expected ',' or ';' after constant"); + return ERR_PARSE_ERROR; + } + } + + break; + } + + Map builtin_types; + if (p_functions.has(name)) { + builtin_types = p_functions[name].built_ins; + } + + if (p_functions.has("global")) { // Adds global variables: 'TIME' + for (Map::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) { + builtin_types.insert(E->key(), E->value()); + } + } + + ShaderNode::Function function; + + function.callable = !p_functions.has(name); + function.name = name; + + FunctionNode *func_node = alloc_node(); + + function.function = func_node; + + shader->functions.push_back(function); + + func_node->name = name; + func_node->return_type = type; + func_node->return_struct_name = struct_name; + func_node->return_precision = precision; + + if (p_functions.has(name)) { + func_node->can_discard = p_functions[name].can_discard; + } + + func_node->body = alloc_node(); + func_node->body->parent_function = func_node; + + tk = _get_token(); + + while (true) { + if (tk.type == TK_PARENTHESIS_CLOSE) { + break; + } + + ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; + + if (tk.type == TK_ARG_IN) { + qualifier = ARGUMENT_QUALIFIER_IN; + tk = _get_token(); + } else if (tk.type == TK_ARG_OUT) { + qualifier = ARGUMENT_QUALIFIER_OUT; + tk = _get_token(); + } else if (tk.type == TK_ARG_INOUT) { + qualifier = ARGUMENT_QUALIFIER_INOUT; + tk = _get_token(); + } + + DataType ptype; + StringName pname; + StringName param_struct_name; + DataPrecision pprecision = PRECISION_DEFAULT; + bool use_precision = false; + + if (is_token_precision(tk.type)) { + pprecision = get_token_precision(tk.type); + tk = _get_token(); + use_precision = true; + } + + is_struct = false; + + if (shader->structs.has(tk.text)) { + is_struct = true; + param_struct_name = tk.text; + if (use_precision) { + _set_error("Precision modifier cannot be used on structs."); + return ERR_PARSE_ERROR; + } + } + + if (!is_struct && !is_token_datatype(tk.type)) { + _set_error("Expected a valid datatype for argument"); + return ERR_PARSE_ERROR; + } + + if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) { + if (is_sampler_type(get_token_datatype(tk.type))) { + _set_error("Opaque types cannot be output parameters."); + return ERR_PARSE_ERROR; + } + } + + if (is_struct) { + ptype = TYPE_STRUCT; + } else { + ptype = get_token_datatype(tk.type); + if (_validate_datatype(ptype) != OK) { + return ERR_PARSE_ERROR; + } + if (ptype == TYPE_VOID) { + _set_error("void not allowed in argument"); + return ERR_PARSE_ERROR; + } + } + + tk = _get_token(); + + if (tk.type == TK_BRACKET_OPEN) { + _set_error("Arrays as parameters are not implemented yet"); + return ERR_PARSE_ERROR; + } + if (tk.type != TK_IDENTIFIER) { + _set_error("Expected identifier for argument name"); + return ERR_PARSE_ERROR; + } + + pname = tk.text; + + ShaderLanguage::IdentifierType itype; + if (_find_identifier(func_node->body, false, builtin_types, pname, (ShaderLanguage::DataType *)0, &itype)) { + if (itype != IDENTIFIER_FUNCTION) { + _set_error("Redefinition of '" + String(pname) + "'"); + return ERR_PARSE_ERROR; + } + } + + if (has_builtin(p_functions, pname)) { + _set_error("Redefinition of '" + String(pname) + "'"); + return ERR_PARSE_ERROR; + } + + FunctionNode::Argument arg; + arg.type = ptype; + arg.name = pname; + arg.type_str = param_struct_name; + arg.precision = pprecision; + arg.qualifier = qualifier; + arg.tex_argument_check = false; + arg.tex_builtin_check = false; + arg.tex_argument_filter = FILTER_DEFAULT; + arg.tex_argument_repeat = REPEAT_DEFAULT; + + func_node->arguments.push_back(arg); + + tk = _get_token(); + if (tk.type == TK_BRACKET_OPEN) { + _set_error("Arrays as parameters are not implemented yet"); + return ERR_PARSE_ERROR; + } + + if (tk.type == TK_COMMA) { + tk = _get_token(); + //do none and go on + } else if (tk.type != TK_PARENTHESIS_CLOSE) { + _set_error("Expected ',' or ')' after identifier"); + return ERR_PARSE_ERROR; + } + } + + if (p_functions.has(name)) { + //if one of the core functions, make sure they are of the correct form + if (func_node->arguments.size() > 0) { + _set_error("Function '" + String(name) + "' expects no arguments."); + return ERR_PARSE_ERROR; + } + if (func_node->return_type != TYPE_VOID) { + _set_error("Function '" + String(name) + "' must be of void return type."); + return ERR_PARSE_ERROR; + } + } + + //all good let's parse inside the function! + tk = _get_token(); + if (tk.type != TK_CURLY_BRACKET_OPEN) { + _set_error("Expected '{' to begin function"); + return ERR_PARSE_ERROR; + } + + current_function = name; + + Error err = _parse_block(func_node->body, builtin_types); + if (err) + return err; + + if (func_node->return_type != DataType::TYPE_VOID) { + + BlockNode *block = func_node->body; + if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) { + _set_error("Expected at least one return statement in a non-void function."); + return ERR_PARSE_ERROR; + } + } + current_function = StringName(); + } + } + + tk = _get_token(); + } + + return OK; +} + +bool ShaderLanguage::has_builtin(const Map &p_functions, const StringName &p_name) { + + if (p_functions.has("vertex")) { + if (p_functions["vertex"].built_ins.has(p_name)) { + return true; + } + } + if (p_functions.has("fragment")) { + if (p_functions["fragment"].built_ins.has(p_name)) { + return true; + } + } + if (p_functions.has("light")) { + if (p_functions["light"].built_ins.has(p_name)) { + return true; + } + } + return false; +} + +Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op) { + + bool found = false; + + for (int i = p_flow->blocks.size() - 1; i >= 0; i--) { + if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) { + BlockNode *last_block = (BlockNode *)p_flow->blocks[i]; + if (_find_last_flow_op_in_block(last_block, p_op) == OK) { + found = true; + break; + } + } + } + if (found) { + return OK; + } + return FAILED; +} + +Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) { + + bool found = false; + + for (int i = p_block->statements.size() - 1; i >= 0; i--) { + + if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) { + ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i]; + if (flow->flow_op == p_op) { + found = true; + break; + } else { + if (_find_last_flow_op_in_op(flow, p_op) == OK) { + found = true; + break; + } + } + } else if (p_block->statements[i]->type == Node::TYPE_BLOCK) { + BlockNode *block = (BlockNode *)p_block->statements[i]; + if (_find_last_flow_op_in_block(block, p_op) == OK) { + found = true; + break; + } + } + } + + if (found) { + return OK; + } + return FAILED; +} + +// skips over whitespace and /* */ and // comments +static int _get_first_ident_pos(const String &p_code) { + + int idx = 0; + +#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0)) + + while (true) { + if (GETCHAR(0) == '/' && GETCHAR(1) == '/') { + idx += 2; + while (true) { + if (GETCHAR(0) == 0) return 0; + if (GETCHAR(0) == '\n') { + idx++; + break; // loop + } + idx++; + } + } else if (GETCHAR(0) == '/' && GETCHAR(1) == '*') { + idx += 2; + while (true) { + if (GETCHAR(0) == 0) return 0; + if (GETCHAR(0) == '*' && GETCHAR(1) == '/') { + idx += 2; + break; // loop + } + idx++; + } + } else { + switch (GETCHAR(0)) { + case ' ': + case '\t': + case '\r': + case '\n': { + idx++; + } break; // switch + default: + return idx; + } + } + } + +#undef GETCHAR +} + +String ShaderLanguage::get_shader_type(const String &p_code) { + + bool reading_type = false; + + String cur_identifier; + + for (int i = _get_first_ident_pos(p_code); i < p_code.length(); i++) { + + if (p_code[i] == ';') { + break; + + } else if (p_code[i] <= 32) { + if (cur_identifier != String()) { + if (!reading_type) { + if (cur_identifier != "shader_type") { + return String(); + } + + reading_type = true; + cur_identifier = String(); + } else { + return cur_identifier; + } + } + } else { + cur_identifier += String::chr(p_code[i]); + } + } + + if (reading_type) + return cur_identifier; + + return String(); +} + +Error ShaderLanguage::compile(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types) { + + clear(); + + code = p_code; + + nodes = NULL; + + shader = alloc_node(); + Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); + + if (err != OK) { + return err; + } + return OK; +} + +Error ShaderLanguage::complete(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types, List *r_options, String &r_call_hint) { + + clear(); + + code = p_code; + + nodes = NULL; + + shader = alloc_node(); + _parse_shader(p_functions, p_render_modes, p_shader_types); + + switch (completion_type) { + + case COMPLETION_NONE: { + //do nothing + return OK; + } break; + case COMPLETION_RENDER_MODE: { + for (int i = 0; i < p_render_modes.size(); i++) { + ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM); + r_options->push_back(option); + } + + return OK; + } break; + case COMPLETION_STRUCT: { + + if (shader->structs.has(completion_struct)) { + StructNode *node = shader->structs[completion_struct].shader_struct; + for (int i = 0; i < node->members.size(); i++) { + ScriptCodeCompletionOption option(node->members[i]->name, ScriptCodeCompletionOption::KIND_MEMBER); + r_options->push_back(option); + } + } + + return OK; + } break; + case COMPLETION_MAIN_FUNCTION: { + + for (const Map::Element *E = p_functions.front(); E; E = E->next()) { + ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_FUNCTION); + r_options->push_back(option); + } + + return OK; + } break; + case COMPLETION_IDENTIFIER: + case COMPLETION_FUNCTION_CALL: { + + bool comp_ident = completion_type == COMPLETION_IDENTIFIER; + Map matches; + StringName skip_function; + BlockNode *block = completion_block; + + if (completion_class == TAG_GLOBAL) { + while (block) { + if (comp_ident) { + for (const Map::Element *E = block->variables.front(); E; E = E->next()) { + + if (E->get().line < completion_line) { + matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE); + } + } + } + + if (block->parent_function) { + if (comp_ident) { + for (int i = 0; i < block->parent_function->arguments.size(); i++) { + matches.insert(block->parent_function->arguments[i].name, ScriptCodeCompletionOption::KIND_VARIABLE); + } + } + skip_function = block->parent_function->name; + } + block = block->parent_block; + } + + if (comp_ident) { + if (p_functions.has("global")) { + for (Map::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) { + ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + if (E->get().constant) { + kind = ScriptCodeCompletionOption::KIND_CONSTANT; + } + matches.insert(E->key(), kind); + } + } + + if (skip_function != StringName() && p_functions.has(skip_function)) { + for (Map::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) { + ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; + if (E->get().constant) { + kind = ScriptCodeCompletionOption::KIND_CONSTANT; + } + matches.insert(E->key(), kind); + } + } + + for (const Map::Element *E = shader->varyings.front(); E; E = E->next()) { + matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE); + } + for (const Map::Element *E = shader->uniforms.front(); E; E = E->next()) { + matches.insert(E->key(), ScriptCodeCompletionOption::KIND_MEMBER); + } + } + + for (int i = 0; i < shader->functions.size(); i++) { + if (!shader->functions[i].callable || shader->functions[i].name == skip_function) + continue; + matches.insert(String(shader->functions[i].name), ScriptCodeCompletionOption::KIND_FUNCTION); + } + + int idx = 0; + bool low_end = RenderingServer::get_singleton()->is_low_end(); + + while (builtin_func_defs[idx].name) { + if (low_end && builtin_func_defs[idx].high_end) { + idx++; + continue; + } + matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION); + idx++; + } + + } else { // sub-class + int idx = 0; + bool low_end = RenderingServer::get_singleton()->is_low_end(); + + while (builtin_func_defs[idx].name) { + if (low_end && builtin_func_defs[idx].high_end) { + idx++; + continue; + } + if (builtin_func_defs[idx].tag == completion_class) { + matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION); + } + idx++; + } + } + + for (Map::Element *E = matches.front(); E; E = E->next()) { + ScriptCodeCompletionOption option(E->key(), E->value()); + if (E->value() == ScriptCodeCompletionOption::KIND_FUNCTION) { + option.insert_text += "("; + } + r_options->push_back(option); + } + + return OK; + } break; + case COMPLETION_CALL_ARGUMENTS: { + + for (int i = 0; i < shader->functions.size(); i++) { + if (!shader->functions[i].callable) + continue; + if (shader->functions[i].name == completion_function) { + + String calltip; + + calltip += get_datatype_name(shader->functions[i].function->return_type); + calltip += " "; + calltip += shader->functions[i].name; + calltip += "("; + + for (int j = 0; j < shader->functions[i].function->arguments.size(); j++) { + + if (j > 0) + calltip += ", "; + else + calltip += " "; + + if (j == completion_argument) { + calltip += CharType(0xFFFF); + } + + if (shader->functions[i].function->arguments[j].qualifier != ArgumentQualifier::ARGUMENT_QUALIFIER_IN) { + if (shader->functions[i].function->arguments[j].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT) { + calltip += "out "; + } else { // ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT + calltip += "inout "; + } + } + + calltip += get_datatype_name(shader->functions[i].function->arguments[j].type); + calltip += " "; + calltip += shader->functions[i].function->arguments[j].name; + + if (j == completion_argument) { + calltip += CharType(0xFFFF); + } + } + + if (shader->functions[i].function->arguments.size()) + calltip += " "; + calltip += ")"; + + r_call_hint = calltip; + return OK; + } + } + + int idx = 0; + + String calltip; + bool low_end = RenderingServer::get_singleton()->is_low_end(); + + while (builtin_func_defs[idx].name) { + + if (low_end && builtin_func_defs[idx].high_end) { + idx++; + continue; + } + + int idx2 = 0; + int out_arg = -1; + while (builtin_func_out_args[idx2].name != nullptr) { + if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) { + out_arg = builtin_func_out_args[idx2].argument; + break; + } + idx2++; + } + + if (completion_function == builtin_func_defs[idx].name) { + + if (builtin_func_defs[idx].tag != completion_class) { + idx++; + continue; + } + + if (calltip.length()) + calltip += "\n"; + + calltip += get_datatype_name(builtin_func_defs[idx].rettype); + calltip += " "; + calltip += builtin_func_defs[idx].name; + calltip += "("; + + bool found_arg = false; + for (int i = 0; i < 4; i++) { + + if (builtin_func_defs[idx].args[i] == TYPE_VOID) + break; + + if (i > 0) + calltip += ", "; + else + calltip += " "; + + if (i == completion_argument) { + calltip += CharType(0xFFFF); + } + + if (out_arg >= 0 && i == out_arg) { + calltip += "out "; + } + + calltip += get_datatype_name(builtin_func_defs[idx].args[i]); + + if (i == completion_argument) { + calltip += CharType(0xFFFF); + } + + found_arg = true; + } + + if (found_arg) + calltip += " "; + calltip += ")"; + } + idx++; + } + + r_call_hint = calltip; + + return OK; + + } break; + case COMPLETION_INDEX: { + + const char colv[4] = { 'r', 'g', 'b', 'a' }; + const char coordv[4] = { 'x', 'y', 'z', 'w' }; + const char coordt[4] = { 's', 't', 'p', 'q' }; + + int limit = 0; + + switch (completion_base) { + case TYPE_BVEC2: + case TYPE_IVEC2: + case TYPE_UVEC2: + case TYPE_VEC2: { + limit = 2; + + } break; + case TYPE_BVEC3: + case TYPE_IVEC3: + case TYPE_UVEC3: + case TYPE_VEC3: { + + limit = 3; + + } break; + case TYPE_BVEC4: + case TYPE_IVEC4: + case TYPE_UVEC4: + case TYPE_VEC4: { + + limit = 4; + + } break; + case TYPE_MAT2: limit = 2; break; + case TYPE_MAT3: limit = 3; break; + case TYPE_MAT4: limit = 4; break; + default: { + } + } + + for (int i = 0; i < limit; i++) { + r_options->push_back(ScriptCodeCompletionOption(String::chr(colv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); + r_options->push_back(ScriptCodeCompletionOption(String::chr(coordv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); + r_options->push_back(ScriptCodeCompletionOption(String::chr(coordt[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); + } + + } break; + } + + return ERR_PARSE_ERROR; +} + +String ShaderLanguage::get_error_text() { + + return error_str; +} + +int ShaderLanguage::get_error_line() { + + return error_line; +} + +ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() { + + return shader; +} + +ShaderLanguage::ShaderLanguage() { + + nodes = NULL; + completion_class = TAG_GLOBAL; +} + +ShaderLanguage::~ShaderLanguage() { + + clear(); +} diff --git a/servers/rendering/shader_language.h b/servers/rendering/shader_language.h new file mode 100644 index 0000000000..bdc15cc4aa --- /dev/null +++ b/servers/rendering/shader_language.h @@ -0,0 +1,900 @@ +/*************************************************************************/ +/* shader_language.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHADER_LANGUAGE_H +#define SHADER_LANGUAGE_H + +#include "core/list.h" +#include "core/map.h" +#include "core/script_language.h" +#include "core/string_name.h" +#include "core/typedefs.h" +#include "core/ustring.h" +#include "core/variant.h" + +class ShaderLanguage { + +public: + enum TokenType { + TK_EMPTY, + TK_IDENTIFIER, + TK_TRUE, + TK_FALSE, + TK_REAL_CONSTANT, + TK_INT_CONSTANT, + TK_TYPE_VOID, + TK_TYPE_BOOL, + TK_TYPE_BVEC2, + TK_TYPE_BVEC3, + TK_TYPE_BVEC4, + TK_TYPE_INT, + TK_TYPE_IVEC2, + TK_TYPE_IVEC3, + TK_TYPE_IVEC4, + TK_TYPE_UINT, + TK_TYPE_UVEC2, + TK_TYPE_UVEC3, + TK_TYPE_UVEC4, + TK_TYPE_FLOAT, + TK_TYPE_VEC2, + TK_TYPE_VEC3, + TK_TYPE_VEC4, + TK_TYPE_MAT2, + TK_TYPE_MAT3, + TK_TYPE_MAT4, + TK_TYPE_SAMPLER2D, + TK_TYPE_ISAMPLER2D, + TK_TYPE_USAMPLER2D, + TK_TYPE_SAMPLER2DARRAY, + TK_TYPE_ISAMPLER2DARRAY, + TK_TYPE_USAMPLER2DARRAY, + TK_TYPE_SAMPLER3D, + TK_TYPE_ISAMPLER3D, + TK_TYPE_USAMPLER3D, + TK_TYPE_SAMPLERCUBE, + TK_INTERPOLATION_FLAT, + TK_INTERPOLATION_SMOOTH, + TK_CONST, + TK_STRUCT, + TK_PRECISION_LOW, + TK_PRECISION_MID, + TK_PRECISION_HIGH, + TK_OP_EQUAL, + TK_OP_NOT_EQUAL, + TK_OP_LESS, + TK_OP_LESS_EQUAL, + TK_OP_GREATER, + TK_OP_GREATER_EQUAL, + TK_OP_AND, + TK_OP_OR, + TK_OP_NOT, + TK_OP_ADD, + TK_OP_SUB, + TK_OP_MUL, + TK_OP_DIV, + TK_OP_MOD, + TK_OP_SHIFT_LEFT, + TK_OP_SHIFT_RIGHT, + TK_OP_ASSIGN, + TK_OP_ASSIGN_ADD, + TK_OP_ASSIGN_SUB, + TK_OP_ASSIGN_MUL, + TK_OP_ASSIGN_DIV, + TK_OP_ASSIGN_MOD, + TK_OP_ASSIGN_SHIFT_LEFT, + TK_OP_ASSIGN_SHIFT_RIGHT, + TK_OP_ASSIGN_BIT_AND, + TK_OP_ASSIGN_BIT_OR, + TK_OP_ASSIGN_BIT_XOR, + TK_OP_BIT_AND, + TK_OP_BIT_OR, + TK_OP_BIT_XOR, + TK_OP_BIT_INVERT, + TK_OP_INCREMENT, + TK_OP_DECREMENT, + TK_CF_IF, + TK_CF_ELSE, + TK_CF_FOR, + TK_CF_WHILE, + TK_CF_DO, + TK_CF_SWITCH, + TK_CF_CASE, + TK_CF_DEFAULT, + TK_CF_BREAK, + TK_CF_CONTINUE, + TK_CF_RETURN, + TK_CF_DISCARD, + TK_BRACKET_OPEN, + TK_BRACKET_CLOSE, + TK_CURLY_BRACKET_OPEN, + TK_CURLY_BRACKET_CLOSE, + TK_PARENTHESIS_OPEN, + TK_PARENTHESIS_CLOSE, + TK_QUESTION, + TK_COMMA, + TK_COLON, + TK_SEMICOLON, + TK_PERIOD, + TK_UNIFORM, + TK_VARYING, + TK_ARG_IN, + TK_ARG_OUT, + TK_ARG_INOUT, + TK_RENDER_MODE, + TK_HINT_WHITE_TEXTURE, + TK_HINT_BLACK_TEXTURE, + TK_HINT_NORMAL_TEXTURE, + TK_HINT_ROUGHNESS_NORMAL_TEXTURE, + TK_HINT_ROUGHNESS_R, + TK_HINT_ROUGHNESS_G, + TK_HINT_ROUGHNESS_B, + TK_HINT_ROUGHNESS_A, + TK_HINT_ROUGHNESS_GRAY, + TK_HINT_ANISO_TEXTURE, + TK_HINT_ALBEDO_TEXTURE, + TK_HINT_BLACK_ALBEDO_TEXTURE, + TK_HINT_COLOR, + TK_HINT_RANGE, + TK_FILTER_NEAREST, + TK_FILTER_LINEAR, + TK_FILTER_NEAREST_MIPMAP, + TK_FILTER_LINEAR_MIPMAP, + TK_FILTER_NEAREST_MIPMAP_ANISO, + TK_FILTER_LINEAR_MIPMAP_ANISO, + TK_REPEAT_ENABLE, + TK_REPEAT_DISABLE, + TK_SHADER_TYPE, + TK_CURSOR, + TK_ERROR, + TK_EOF, + TK_MAX + }; + +/* COMPILER */ + +// lame work around to Apple defining this as a macro in 10.12 SDK +#ifdef TYPE_BOOL +#undef TYPE_BOOL +#endif + + enum DataType { + TYPE_VOID, + TYPE_BOOL, + TYPE_BVEC2, + TYPE_BVEC3, + TYPE_BVEC4, + TYPE_INT, + TYPE_IVEC2, + TYPE_IVEC3, + TYPE_IVEC4, + TYPE_UINT, + TYPE_UVEC2, + TYPE_UVEC3, + TYPE_UVEC4, + TYPE_FLOAT, + TYPE_VEC2, + TYPE_VEC3, + TYPE_VEC4, + TYPE_MAT2, + TYPE_MAT3, + TYPE_MAT4, + TYPE_SAMPLER2D, + TYPE_ISAMPLER2D, + TYPE_USAMPLER2D, + TYPE_SAMPLER2DARRAY, + TYPE_ISAMPLER2DARRAY, + TYPE_USAMPLER2DARRAY, + TYPE_SAMPLER3D, + TYPE_ISAMPLER3D, + TYPE_USAMPLER3D, + TYPE_SAMPLERCUBE, + TYPE_STRUCT, + }; + + enum DataPrecision { + PRECISION_LOWP, + PRECISION_MEDIUMP, + PRECISION_HIGHP, + PRECISION_DEFAULT, + }; + + enum DataInterpolation { + INTERPOLATION_FLAT, + INTERPOLATION_SMOOTH, + }; + + enum Operator { + OP_EQUAL, + OP_NOT_EQUAL, + OP_LESS, + OP_LESS_EQUAL, + OP_GREATER, + OP_GREATER_EQUAL, + OP_AND, + OP_OR, + OP_NOT, + OP_NEGATE, + OP_ADD, + OP_SUB, + OP_MUL, + OP_DIV, + OP_MOD, + OP_SHIFT_LEFT, + OP_SHIFT_RIGHT, + OP_ASSIGN, + OP_ASSIGN_ADD, + OP_ASSIGN_SUB, + OP_ASSIGN_MUL, + OP_ASSIGN_DIV, + OP_ASSIGN_MOD, + OP_ASSIGN_SHIFT_LEFT, + OP_ASSIGN_SHIFT_RIGHT, + OP_ASSIGN_BIT_AND, + OP_ASSIGN_BIT_OR, + OP_ASSIGN_BIT_XOR, + OP_BIT_AND, + OP_BIT_OR, + OP_BIT_XOR, + OP_BIT_INVERT, + OP_INCREMENT, + OP_DECREMENT, + OP_SELECT_IF, + OP_SELECT_ELSE, //used only internally, then only IF appears with 3 arguments + OP_POST_INCREMENT, + OP_POST_DECREMENT, + OP_CALL, + OP_CONSTRUCT, + OP_STRUCT, + OP_INDEX, + OP_MAX + }; + + enum FlowOperation { + FLOW_OP_IF, + FLOW_OP_RETURN, + FLOW_OP_FOR, + FLOW_OP_WHILE, + FLOW_OP_DO, + FLOW_OP_BREAK, + FLOW_OP_SWITCH, + FLOW_OP_CASE, + FLOW_OP_DEFAULT, + FLOW_OP_CONTINUE, + FLOW_OP_DISCARD + }; + + enum ArgumentQualifier { + ARGUMENT_QUALIFIER_IN, + ARGUMENT_QUALIFIER_OUT, + ARGUMENT_QUALIFIER_INOUT, + }; + + enum SubClassTag { + TAG_GLOBAL, + TAG_ARRAY, + }; + + enum TextureFilter { + FILTER_NEAREST, + FILTER_LINEAR, + FILTER_NEAREST_MIPMAP, + FILTER_LINEAR_MIPMAP, + FILTER_NEAREST_MIPMAP_ANISO, + FILTER_LINEAR_MIPMAP_ANISO, + FILTER_DEFAULT, + }; + + enum TextureRepeat { + REPEAT_DISABLE, + REPEAT_ENABLE, + REPEAT_DEFAULT, + }; + + struct Node { + Node *next; + + enum Type { + TYPE_SHADER, + TYPE_FUNCTION, + TYPE_BLOCK, + TYPE_VARIABLE, + TYPE_VARIABLE_DECLARATION, + TYPE_CONSTANT, + TYPE_OPERATOR, + TYPE_CONTROL_FLOW, + TYPE_MEMBER, + TYPE_ARRAY, + TYPE_ARRAY_DECLARATION, + TYPE_ARRAY_CONSTRUCT, + TYPE_STRUCT, + }; + + Type type; + + virtual DataType get_datatype() const { return TYPE_VOID; } + virtual String get_datatype_name() const { return ""; } + + Node(Type t) : + next(NULL), + type(t) {} + virtual ~Node() {} + }; + + template + T *alloc_node() { + T *node = memnew(T); + node->next = nodes; + nodes = node; + return node; + } + + Node *nodes; + + struct OperatorNode : public Node { + DataType return_cache; + DataPrecision return_precision_cache; + Operator op; + StringName struct_name; + Vector arguments; + virtual DataType get_datatype() const { return return_cache; } + virtual String get_datatype_name() const { return String(struct_name); } + + OperatorNode() : + Node(TYPE_OPERATOR), + return_cache(TYPE_VOID), + return_precision_cache(PRECISION_DEFAULT), + op(OP_EQUAL), + struct_name("") {} + }; + + struct VariableNode : public Node { + DataType datatype_cache; + StringName name; + StringName struct_name; + virtual DataType get_datatype() const { return datatype_cache; } + virtual String get_datatype_name() const { return String(struct_name); } + bool is_const; + + VariableNode() : + Node(TYPE_VARIABLE), + datatype_cache(TYPE_VOID), + is_const(false) {} + }; + + struct VariableDeclarationNode : public Node { + DataPrecision precision; + DataType datatype; + String struct_name; + bool is_const; + + struct Declaration { + StringName name; + Node *initializer; + }; + + Vector declarations; + virtual DataType get_datatype() const { return datatype; } + + VariableDeclarationNode() : + Node(TYPE_VARIABLE_DECLARATION), + precision(PRECISION_DEFAULT), + datatype(TYPE_VOID), + is_const(false) {} + }; + + struct ArrayNode : public Node { + DataType datatype_cache; + StringName struct_name; + StringName name; + Node *index_expression; + Node *call_expression; + bool is_const; + + virtual DataType get_datatype() const { return datatype_cache; } + virtual String get_datatype_name() const { return String(struct_name); } + + ArrayNode() : + Node(TYPE_ARRAY), + datatype_cache(TYPE_VOID), + index_expression(NULL), + call_expression(NULL), + is_const(false) {} + }; + + struct ArrayConstructNode : public Node { + DataType datatype; + String struct_name; + Vector initializer; + + ArrayConstructNode() : + Node(TYPE_ARRAY_CONSTRUCT), + datatype(TYPE_VOID) { + } + }; + + struct ArrayDeclarationNode : public Node { + DataPrecision precision; + DataType datatype; + String struct_name; + bool is_const; + + struct Declaration { + StringName name; + uint32_t size; + Vector initializer; + }; + + Vector declarations; + virtual DataType get_datatype() const { return datatype; } + + ArrayDeclarationNode() : + Node(TYPE_ARRAY_DECLARATION), + precision(PRECISION_DEFAULT), + datatype(TYPE_VOID), + is_const(false) {} + }; + + struct ConstantNode : public Node { + DataType datatype; + + union Value { + bool boolean; + float real; + int32_t sint; + uint32_t uint; + }; + + Vector values; + virtual DataType get_datatype() const { return datatype; } + + ConstantNode() : + Node(TYPE_CONSTANT), + datatype(TYPE_VOID) {} + }; + + struct FunctionNode; + + struct BlockNode : public Node { + FunctionNode *parent_function; + BlockNode *parent_block; + + enum BlockType { + BLOCK_TYPE_STANDART, + BLOCK_TYPE_SWITCH, + BLOCK_TYPE_CASE, + BLOCK_TYPE_DEFAULT, + }; + + int block_type; + SubClassTag block_tag; + + struct Variable { + DataType type; + StringName struct_name; + DataPrecision precision; + int line; //for completion + int array_size; + bool is_const; + }; + + Map variables; + List statements; + bool single_statement; + + BlockNode() : + Node(TYPE_BLOCK), + parent_function(NULL), + parent_block(NULL), + block_type(BLOCK_TYPE_STANDART), + block_tag(SubClassTag::TAG_GLOBAL), + single_statement(false) {} + }; + + struct ControlFlowNode : public Node { + FlowOperation flow_op; + Vector expressions; + Vector blocks; + + ControlFlowNode() : + Node(TYPE_CONTROL_FLOW), + flow_op(FLOW_OP_IF) {} + }; + + struct MemberNode : public Node { + DataType basetype; + bool basetype_const; + StringName base_struct_name; + DataPrecision precision; + DataType datatype; + int array_size; + StringName struct_name; + StringName name; + Node *owner; + Node *index_expression; + bool has_swizzling_duplicates; + + virtual DataType get_datatype() const { return datatype; } + virtual String get_datatype_name() const { return String(struct_name); } + + MemberNode() : + Node(TYPE_MEMBER), + basetype(TYPE_VOID), + basetype_const(false), + datatype(TYPE_VOID), + array_size(0), + owner(NULL), + index_expression(NULL), + has_swizzling_duplicates(false) {} + }; + + struct StructNode : public Node { + + List members; + StructNode() : + Node(TYPE_STRUCT) {} + }; + + struct FunctionNode : public Node { + + struct Argument { + ArgumentQualifier qualifier; + StringName name; + DataType type; + StringName type_str; + DataPrecision precision; + //for passing textures as arguments + bool tex_argument_check; + TextureFilter tex_argument_filter; + TextureRepeat tex_argument_repeat; + bool tex_builtin_check; + StringName tex_builtin; + + Map> tex_argument_connect; + }; + + StringName name; + DataType return_type; + StringName return_struct_name; + DataPrecision return_precision; + Vector arguments; + BlockNode *body; + bool can_discard; + + FunctionNode() : + Node(TYPE_FUNCTION), + return_type(TYPE_VOID), + return_precision(PRECISION_DEFAULT), + body(NULL), + can_discard(false) {} + }; + + struct ShaderNode : public Node { + + struct Constant { + DataType type; + StringName type_str; + DataPrecision precision; + ConstantNode *initializer; + }; + + struct Function { + StringName name; + FunctionNode *function; + Set uses_function; + bool callable; + }; + + struct Struct { + StringName name; + StructNode *shader_struct; + }; + + struct Varying { + DataType type; + DataInterpolation interpolation; + DataPrecision precision; + int array_size; + + Varying() : + type(TYPE_VOID), + interpolation(INTERPOLATION_FLAT), + precision(PRECISION_DEFAULT), + array_size(0) {} + }; + + struct Uniform { + enum Hint { + HINT_NONE, + HINT_COLOR, + HINT_RANGE, + HINT_ALBEDO, + HINT_BLACK_ALBEDO, + HINT_NORMAL, + HINT_ROUGHNESS_NORMAL, + HINT_ROUGHNESS_R, + HINT_ROUGHNESS_G, + HINT_ROUGHNESS_B, + HINT_ROUGHNESS_A, + HINT_ROUGHNESS_GRAY, + HINT_BLACK, + HINT_WHITE, + HINT_ANISO, + HINT_MAX + }; + + int order; + int texture_order; + DataType type; + DataPrecision precision; + Vector default_value; + Hint hint; + TextureFilter filter; + TextureRepeat repeat; + float hint_range[3]; + + Uniform() : + order(0), + texture_order(0), + type(TYPE_VOID), + precision(PRECISION_DEFAULT), + hint(HINT_NONE), + filter(FILTER_DEFAULT), + repeat(REPEAT_DEFAULT) { + hint_range[0] = 0.0f; + hint_range[1] = 1.0f; + hint_range[2] = 0.001f; + } + }; + + Map constants; + Map varyings; + Map uniforms; + Map structs; + Vector render_modes; + + Vector functions; + Vector vstructs; + + ShaderNode() : + Node(TYPE_SHADER) {} + }; + + struct Expression { + bool is_op; + union { + Operator op; + Node *node; + }; + }; + + struct VarInfo { + StringName name; + DataType type; + }; + + enum CompletionType { + COMPLETION_NONE, + COMPLETION_RENDER_MODE, + COMPLETION_MAIN_FUNCTION, + COMPLETION_IDENTIFIER, + COMPLETION_FUNCTION_CALL, + COMPLETION_CALL_ARGUMENTS, + COMPLETION_INDEX, + COMPLETION_STRUCT, + }; + + struct Token { + TokenType type; + StringName text; + double constant; + uint16_t line; + }; + + static String get_operator_text(Operator p_op); + static String get_token_text(Token p_token); + + static bool is_token_datatype(TokenType p_type); + static bool is_token_variable_datatype(TokenType p_type); + static DataType get_token_datatype(TokenType p_type); + static bool is_token_interpolation(TokenType p_type); + static DataInterpolation get_token_interpolation(TokenType p_type); + static bool is_token_precision(TokenType p_type); + static DataPrecision get_token_precision(TokenType p_type); + static String get_precision_name(DataPrecision p_type); + static String get_datatype_name(DataType p_type); + static bool is_token_nonvoid_datatype(TokenType p_type); + static bool is_token_operator(TokenType p_type); + + static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = NULL); + static DataType get_scalar_type(DataType p_type); + static int get_cardinality(DataType p_type); + static bool is_scalar_type(DataType p_type); + static bool is_sampler_type(DataType p_type); + static Variant constant_value_to_variant(const Vector &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE); + static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform); + static uint32_t get_type_size(DataType p_type); + + static void get_keyword_list(List *r_keywords); + static void get_builtin_funcs(List *r_keywords); + + struct BuiltInInfo { + DataType type; + bool constant; + + BuiltInInfo() : + type(TYPE_VOID), + constant(false) {} + + BuiltInInfo(DataType p_type, bool p_constant = false) : + type(p_type), + constant(p_constant) {} + }; + + struct FunctionInfo { + Map built_ins; + bool can_discard; + }; + static bool has_builtin(const Map &p_functions, const StringName &p_name); + +private: + struct KeyWord { + TokenType token; + const char *text; + }; + + static const KeyWord keyword_list[]; + + bool error_set; + String error_str; + int error_line; + + String code; + int char_idx; + int tk_line; + + StringName current_function; + + struct TkPos { + int char_idx; + int tk_line; + }; + + TkPos _get_tkpos() { + TkPos tkp; + tkp.char_idx = char_idx; + tkp.tk_line = tk_line; + return tkp; + } + + void _set_tkpos(TkPos p_pos) { + char_idx = p_pos.char_idx; + tk_line = p_pos.tk_line; + } + + void _set_error(const String &p_str) { + if (error_set) + return; + + error_line = tk_line; + error_set = true; + error_str = p_str; + } + + static const char *token_names[TK_MAX]; + + Token _make_token(TokenType p_type, const StringName &p_text = StringName()); + Token _get_token(); + + ShaderNode *shader; + + enum IdentifierType { + IDENTIFIER_FUNCTION, + IDENTIFIER_UNIFORM, + IDENTIFIER_VARYING, + IDENTIFIER_FUNCTION_ARGUMENT, + IDENTIFIER_LOCAL_VAR, + IDENTIFIER_BUILTIN_VAR, + IDENTIFIER_CONSTANT, + }; + + bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL, StringName *r_struct_name = NULL); + bool _is_operator_assign(Operator p_op) const; + bool _validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message = NULL); + bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); + + struct BuiltinFuncDef { + enum { MAX_ARGS = 5 }; + const char *name; + DataType rettype; + const DataType args[MAX_ARGS]; + SubClassTag tag; + bool high_end; + }; + + struct BuiltinFuncOutArgs { //arguments used as out in built in functions + const char *name; + int argument; + }; + + CompletionType completion_type; + int completion_line; + BlockNode *completion_block; + DataType completion_base; + SubClassTag completion_class; + StringName completion_function; + StringName completion_struct; + int completion_argument; + + bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); + static const BuiltinFuncDef builtin_func_defs[]; + static const BuiltinFuncOutArgs builtin_func_out_args[]; + + Error _validate_datatype(DataType p_type); + bool _compare_datatypes_in_nodes(Node *a, Node *b) const; + + bool _validate_function_call(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str); + bool _parse_function_arguments(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL); + bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat); + bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); + + Node *_parse_expression(BlockNode *p_block, const Map &p_builtin_types); + ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); + + Node *_parse_and_reduce_expression(BlockNode *p_block, const Map &p_builtin_types); + Error _parse_block(BlockNode *p_block, const Map &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); + String _get_shader_type_list(const Set &p_shader_types) const; + String _get_qualifier_str(ArgumentQualifier p_qualifier) const; + + Error _parse_shader(const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types); + + Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op); + Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op); + +public: + //static void get_keyword_list(ShaderType p_type,List *p_keywords); + + void clear(); + + static String get_shader_type(const String &p_code); + Error compile(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types); + Error complete(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types, List *r_options, String &r_call_hint); + + String get_error_text(); + int get_error_line(); + + ShaderNode *get_shader(); + + String token_debug(const String &p_code); + + ShaderLanguage(); + ~ShaderLanguage(); +}; + +#endif // SHADER_LANGUAGE_H diff --git a/servers/rendering/shader_types.cpp b/servers/rendering/shader_types.cpp new file mode 100644 index 0000000000..b144d6d612 --- /dev/null +++ b/servers/rendering/shader_types.cpp @@ -0,0 +1,328 @@ +/*************************************************************************/ +/* shader_types.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "shader_types.h" + +const Map &ShaderTypes::get_functions(RS::ShaderMode p_mode) { + + return shader_modes[p_mode].functions; +} + +const Vector &ShaderTypes::get_modes(RS::ShaderMode p_mode) { + + return shader_modes[p_mode].modes; +} + +const Set &ShaderTypes::get_types() { + return shader_types; +} + +ShaderTypes *ShaderTypes::singleton = NULL; + +static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) { + + return ShaderLanguage::BuiltInInfo(p_type, true); +} + +ShaderTypes::ShaderTypes() { + singleton = this; + + /*************** SPATIAL ***********************/ + + shader_modes[RS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].can_discard = false; + + //builtins + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SPECULAR"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM_TINT"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT_GLOSS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["fragment"].can_discard = true; + + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; + + shader_modes[RS::SHADER_SPATIAL].functions["light"].can_discard = true; + + //order used puts first enum mode (default) first + shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mix"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_add"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_sub"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("blend_mul"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_always"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_draw_never"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("depth_test_disabled"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_back"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_front"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("cull_disabled"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("unshaded"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("wireframe"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_burley"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("diffuse_toon"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_blinn"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_phong"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_toon"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("specular_disabled"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("world_vertex_coords"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadows_disabled"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled"); + shader_modes[RS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity"); + + shader_modes[RS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); + + /************ CANVAS ITEM **************************/ + + shader_modes[RS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; + + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false; + + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SHADOW_VERTEX"] = ShaderLanguage::TYPE_VEC2; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["LIGHT_VERTEX"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; + + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_MODULATE"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true; + + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform"); + + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix"); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_add"); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub"); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul"); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha"); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled"); + + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("unshaded"); + shader_modes[RS::SHADER_CANVAS_ITEM].modes.push_back("light_only"); + + /************ PARTICLES **************************/ + + shader_modes[RS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); + shader_modes[RS::SHADER_PARTICLES].functions["vertex"].can_discard = false; + + shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_force"); + shader_modes[RS::SHADER_PARTICLES].modes.push_back("disable_velocity"); + shader_modes[RS::SHADER_PARTICLES].modes.push_back("keep_data"); + + /************ SKY **************************/ + + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_QUARTER_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["AT_CUBEMAP_PASS"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT0_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT1_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT2_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); + shader_modes[RS::SHADER_SKY].functions["global"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); + + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3; + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3); + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2); + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + shader_modes[RS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); + + shader_modes[RS::SHADER_SKY].modes.push_back("use_half_res_pass"); + shader_modes[RS::SHADER_SKY].modes.push_back("use_quarter_res_pass"); + + shader_types.insert("spatial"); + shader_types.insert("canvas_item"); + shader_types.insert("particles"); + shader_types.insert("sky"); +} diff --git a/servers/rendering/shader_types.h b/servers/rendering/shader_types.h new file mode 100644 index 0000000000..499a761265 --- /dev/null +++ b/servers/rendering/shader_types.h @@ -0,0 +1,62 @@ +/*************************************************************************/ +/* shader_types.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef SHADERTYPES_H +#define SHADERTYPES_H + +#include "core/ordered_hash_map.h" +#include "servers/rendering_server.h" +#include "shader_language.h" + +class ShaderTypes { + + struct Type { + + Map functions; + Vector modes; + }; + + Map shader_modes; + + static ShaderTypes *singleton; + + Set shader_types; + +public: + static ShaderTypes *get_singleton() { return singleton; } + + const Map &get_functions(RS::ShaderMode p_mode); + const Vector &get_modes(RS::ShaderMode p_mode); + const Set &get_types(); + + ShaderTypes(); +}; + +#endif // SHADERTYPES_H diff --git a/servers/rendering_server.cpp b/servers/rendering_server.cpp new file mode 100644 index 0000000000..0c5b9a258f --- /dev/null +++ b/servers/rendering_server.cpp @@ -0,0 +1,2363 @@ +/*************************************************************************/ +/* rendering_server.cpp */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#include "rendering_server.h" + +#include "core/method_bind_ext.gen.inc" +#include "core/project_settings.h" + +RenderingServer *RenderingServer::singleton = NULL; +RenderingServer *(*RenderingServer::create_func)() = NULL; + +RenderingServer *RenderingServer::get_singleton() { + + return singleton; +} + +RenderingServer *RenderingServer::create() { + + ERR_FAIL_COND_V(singleton, NULL); + + if (create_func) + return create_func(); + + return NULL; +} + +Array RenderingServer::_texture_debug_usage_bind() { + + List list; + texture_debug_usage(&list); + Array arr; + for (const List::Element *E = list.front(); E; E = E->next()) { + + Dictionary dict; + dict["texture"] = E->get().texture; + dict["width"] = E->get().width; + dict["height"] = E->get().height; + dict["depth"] = E->get().depth; + dict["format"] = E->get().format; + dict["bytes"] = E->get().bytes; + dict["path"] = E->get().path; + arr.push_back(dict); + } + return arr; +} + +Array RenderingServer::_shader_get_param_list_bind(RID p_shader) const { + + List l; + shader_get_param_list(p_shader, &l); + return convert_property_list(&l); +} + +static Array to_array(const Vector &ids) { + Array a; + a.resize(ids.size()); + for (int i = 0; i < ids.size(); ++i) { + a[i] = ids[i]; + } + return a; +} + +Array RenderingServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const { + + Vector ids = instances_cull_aabb(p_aabb, p_scenario); + return to_array(ids); +} + +Array RenderingServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { + + Vector ids = instances_cull_ray(p_from, p_to, p_scenario); + return to_array(ids); +} + +Array RenderingServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const { + + Vector planes; + for (int i = 0; i < p_convex.size(); ++i) { + Variant v = p_convex[i]; + ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, Array()); + planes.push_back(v); + } + + Vector ids = instances_cull_convex(planes, p_scenario); + return to_array(ids); +} + +RID RenderingServer::get_test_texture() { + + if (test_texture.is_valid()) { + return test_texture; + }; + +#define TEST_TEXTURE_SIZE 256 + + Vector test_data; + test_data.resize(TEST_TEXTURE_SIZE * TEST_TEXTURE_SIZE * 3); + + { + uint8_t *w = test_data.ptrw(); + + for (int x = 0; x < TEST_TEXTURE_SIZE; x++) { + + for (int y = 0; y < TEST_TEXTURE_SIZE; y++) { + + Color c; + int r = 255 - (x + y) / 2; + + if ((x % (TEST_TEXTURE_SIZE / 8)) < 2 || (y % (TEST_TEXTURE_SIZE / 8)) < 2) { + + c.r = y; + c.g = r; + c.b = x; + + } else { + + c.r = r; + c.g = x; + c.b = y; + } + + w[(y * TEST_TEXTURE_SIZE + x) * 3 + 0] = uint8_t(CLAMP(c.r * 255, 0, 255)); + w[(y * TEST_TEXTURE_SIZE + x) * 3 + 1] = uint8_t(CLAMP(c.g * 255, 0, 255)); + w[(y * TEST_TEXTURE_SIZE + x) * 3 + 2] = uint8_t(CLAMP(c.b * 255, 0, 255)); + } + } + } + + Ref data = memnew(Image(TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, false, Image::FORMAT_RGB8, test_data)); + + test_texture = texture_2d_create(data); + + return test_texture; +} + +void RenderingServer::_free_internal_rids() { + + if (test_texture.is_valid()) + free(test_texture); + if (white_texture.is_valid()) + free(white_texture); + if (test_material.is_valid()) + free(test_material); +} + +RID RenderingServer::_make_test_cube() { + + Vector vertices; + Vector normals; + Vector tangents; + Vector uvs; + +#define ADD_VTX(m_idx) \ + vertices.push_back(face_points[m_idx]); \ + normals.push_back(normal_points[m_idx]); \ + tangents.push_back(normal_points[m_idx][1]); \ + tangents.push_back(normal_points[m_idx][2]); \ + tangents.push_back(normal_points[m_idx][0]); \ + tangents.push_back(1.0); \ + uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); + + for (int i = 0; i < 6; i++) { + + Vector3 face_points[4]; + Vector3 normal_points[4]; + float uv_points[8] = { 0, 0, 0, 1, 1, 1, 1, 0 }; + + for (int j = 0; j < 4; j++) { + + float v[3]; + v[0] = 1.0; + v[1] = 1 - 2 * ((j >> 1) & 1); + v[2] = v[1] * (1 - 2 * (j & 1)); + + for (int k = 0; k < 3; k++) { + + if (i < 3) + face_points[j][(i + k) % 3] = v[k]; + else + face_points[3 - j][(i + k) % 3] = -v[k]; + } + normal_points[j] = Vector3(); + normal_points[j][i % 3] = (i >= 3 ? -1 : 1); + } + + //tri 1 + ADD_VTX(0); + ADD_VTX(1); + ADD_VTX(2); + //tri 2 + ADD_VTX(2); + ADD_VTX(3); + ADD_VTX(0); + } + + RID test_cube = mesh_create(); + + Array d; + d.resize(RS::ARRAY_MAX); + d[RenderingServer::ARRAY_NORMAL] = normals; + d[RenderingServer::ARRAY_TANGENT] = tangents; + d[RenderingServer::ARRAY_TEX_UV] = uvs; + d[RenderingServer::ARRAY_VERTEX] = vertices; + + Vector indices; + indices.resize(vertices.size()); + for (int i = 0; i < vertices.size(); i++) + indices.set(i, i); + d[RenderingServer::ARRAY_INDEX] = indices; + + mesh_add_surface_from_arrays(test_cube, PRIMITIVE_TRIANGLES, d); + + /* + test_material = fixed_material_create(); + //material_set_flag(material, MATERIAL_FLAG_BILLBOARD_TOGGLE,true); + fixed_material_set_texture( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, get_test_texture() ); + fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR_EXP, 70 ); + fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_EMISSION, Color(0.2,0.2,0.2) ); + + fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, Color(1, 1, 1) ); + fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR, Color(1,1,1) ); +*/ + mesh_surface_set_material(test_cube, 0, test_material); + + return test_cube; +} + +RID RenderingServer::make_sphere_mesh(int p_lats, int p_lons, float p_radius) { + + Vector vertices; + Vector normals; + + for (int i = 1; i <= p_lats; i++) { + double lat0 = Math_PI * (-0.5 + (double)(i - 1) / p_lats); + double z0 = Math::sin(lat0); + double zr0 = Math::cos(lat0); + + double lat1 = Math_PI * (-0.5 + (double)i / p_lats); + double z1 = Math::sin(lat1); + double zr1 = Math::cos(lat1); + + for (int j = p_lons; j >= 1; j--) { + + double lng0 = 2 * Math_PI * (double)(j - 1) / p_lons; + double x0 = Math::cos(lng0); + double y0 = Math::sin(lng0); + + double lng1 = 2 * Math_PI * (double)(j) / p_lons; + double x1 = Math::cos(lng1); + double y1 = Math::sin(lng1); + + Vector3 v[4] = { + Vector3(x1 * zr0, z0, y1 * zr0), + Vector3(x1 * zr1, z1, y1 * zr1), + Vector3(x0 * zr1, z1, y0 * zr1), + Vector3(x0 * zr0, z0, y0 * zr0) + }; + +#define ADD_POINT(m_idx) \ + normals.push_back(v[m_idx]); \ + vertices.push_back(v[m_idx] * p_radius); + + ADD_POINT(0); + ADD_POINT(1); + ADD_POINT(2); + + ADD_POINT(2); + ADD_POINT(3); + ADD_POINT(0); + } + } + + RID mesh = mesh_create(); + Array d; + d.resize(RS::ARRAY_MAX); + + d[ARRAY_VERTEX] = vertices; + d[ARRAY_NORMAL] = normals; + + mesh_add_surface_from_arrays(mesh, PRIMITIVE_TRIANGLES, d); + + return mesh; +} + +RID RenderingServer::get_white_texture() { + + if (white_texture.is_valid()) + return white_texture; + + Vector wt; + wt.resize(16 * 3); + { + uint8_t *w = wt.ptrw(); + for (int i = 0; i < 16 * 3; i++) + w[i] = 255; + } + Ref white = memnew(Image(4, 4, 0, Image::FORMAT_RGB8, wt)); + white_texture = texture_2d_create(white); + return white_texture; +} + +#define SMALL_VEC2 Vector2(0.00001, 0.00001) +#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001) + +Error RenderingServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, Vector &r_vertex_array, int p_vertex_array_len, Vector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb) { + + uint8_t *vw = r_vertex_array.ptrw(); + + uint8_t *iw = NULL; + if (r_index_array.size()) { + iw = r_index_array.ptrw(); + } + + int max_bone = 0; + + for (int ai = 0; ai < RS::ARRAY_MAX; ai++) { + + if (!(p_format & (1 << ai))) // no array + continue; + + switch (ai) { + + case RS::ARRAY_VERTEX: { + + if (p_format & RS::ARRAY_FLAG_USE_2D_VERTICES) { + + Vector array = p_arrays[ai]; + ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); + + const Vector2 *src = array.ptr(); + + // setting vertices means regenerating the AABB + Rect2 aabb; + + { + for (int i = 0; i < p_vertex_array_len; i++) { + + float vector[2] = { src[i].x, src[i].y }; + + copymem(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(float) * 2); + + if (i == 0) { + + aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size + } else { + + aabb.expand_to(src[i]); + } + } + } + + r_aabb = AABB(Vector3(aabb.position.x, aabb.position.y, 0), Vector3(aabb.size.x, aabb.size.y, 0)); + + } else { + Vector array = p_arrays[ai]; + ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); + + const Vector3 *src = array.ptr(); + + // setting vertices means regenerating the AABB + AABB aabb; + + { + for (int i = 0; i < p_vertex_array_len; i++) { + + float vector[3] = { src[i].x, src[i].y, src[i].z }; + + copymem(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(float) * 3); + + if (i == 0) { + + aabb = AABB(src[i], SMALL_VEC3); + } else { + + aabb.expand_to(src[i]); + } + } + } + + r_aabb = aabb; + } + + } break; + case RS::ARRAY_NORMAL: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_VECTOR3_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); + + const Vector3 *src = array.ptr(); + + // setting vertices means regenerating the AABB + + if (p_format & ARRAY_COMPRESS_NORMAL) { + + for (int i = 0; i < p_vertex_array_len; i++) { + + int8_t vector[4] = { + (int8_t)CLAMP(src[i].x * 127, -128, 127), + (int8_t)CLAMP(src[i].y * 127, -128, 127), + (int8_t)CLAMP(src[i].z * 127, -128, 127), + 0, + }; + + copymem(&vw[p_offsets[ai] + i * p_stride], vector, 4); + } + + } else { + for (int i = 0; i < p_vertex_array_len; i++) { + + float vector[3] = { src[i].x, src[i].y, src[i].z }; + copymem(&vw[p_offsets[ai] + i * p_stride], vector, 3 * 4); + } + } + + } break; + + case RS::ARRAY_TANGENT: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + + ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER); + + const real_t *src = array.ptr(); + + if (p_format & ARRAY_COMPRESS_TANGENT) { + + for (int i = 0; i < p_vertex_array_len; i++) { + int8_t xyzw[4] = { + (int8_t)CLAMP(src[i * 4 + 0] * 127, -128, 127), + (int8_t)CLAMP(src[i * 4 + 1] * 127, -128, 127), + (int8_t)CLAMP(src[i * 4 + 2] * 127, -128, 127), + (int8_t)CLAMP(src[i * 4 + 3] * 127, -128, 127) + }; + + copymem(&vw[p_offsets[ai] + i * p_stride], xyzw, 4); + } + + } else { + for (int i = 0; i < p_vertex_array_len; i++) { + + float xyzw[4] = { + src[i * 4 + 0], + src[i * 4 + 1], + src[i * 4 + 2], + src[i * 4 + 3] + }; + + copymem(&vw[p_offsets[ai] + i * p_stride], xyzw, 4 * 4); + } + } + + } break; + case RS::ARRAY_COLOR: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_COLOR_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + + ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); + + const Color *src = array.ptr(); + + if (p_format & ARRAY_COMPRESS_COLOR) { + + for (int i = 0; i < p_vertex_array_len; i++) { + + uint8_t colors[4]; + + for (int j = 0; j < 4; j++) { + + colors[j] = CLAMP(int((src[i][j]) * 255.0), 0, 255); + } + + copymem(&vw[p_offsets[ai] + i * p_stride], colors, 4); + } + } else { + + for (int i = 0; i < p_vertex_array_len; i++) { + + copymem(&vw[p_offsets[ai] + i * p_stride], &src[i], 4 * 4); + } + } + + } break; + case RS::ARRAY_TEX_UV: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_VECTOR2_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + + ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); + + const Vector2 *src = array.ptr(); + + if (p_format & ARRAY_COMPRESS_TEX_UV) { + + for (int i = 0; i < p_vertex_array_len; i++) { + + uint16_t uv[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) }; + copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 2); + } + + } else { + for (int i = 0; i < p_vertex_array_len; i++) { + + float uv[2] = { src[i].x, src[i].y }; + + copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 4); + } + } + + } break; + + case RS::ARRAY_TEX_UV2: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_VECTOR2_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + + ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); + + const Vector2 *src = array.ptr(); + + if (p_format & ARRAY_COMPRESS_TEX_UV2) { + + for (int i = 0; i < p_vertex_array_len; i++) { + + uint16_t uv[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) }; + copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 2); + } + + } else { + for (int i = 0; i < p_vertex_array_len; i++) { + + float uv[2] = { src[i].x, src[i].y }; + + copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 4); + } + } + } break; + case RS::ARRAY_WEIGHTS: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + + ERR_FAIL_COND_V(array.size() != p_vertex_array_len * RS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER); + + const real_t *src = array.ptr(); + + { + + for (int i = 0; i < p_vertex_array_len; i++) { + + uint16_t data[RS::ARRAY_WEIGHTS_SIZE]; + for (int j = 0; j < RS::ARRAY_WEIGHTS_SIZE; j++) { + data[j] = CLAMP(src[i * RS::ARRAY_WEIGHTS_SIZE + j] * 65535, 0, 65535); + } + + copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4); + } + } + + } break; + case RS::ARRAY_BONES: { + + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_INT32_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); + + Vector array = p_arrays[ai]; + + ERR_FAIL_COND_V(array.size() != p_vertex_array_len * RS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER); + + const int *src = array.ptr(); + + for (int i = 0; i < p_vertex_array_len; i++) { + + uint16_t data[RS::ARRAY_WEIGHTS_SIZE]; + for (int j = 0; j < RS::ARRAY_WEIGHTS_SIZE; j++) { + data[j] = src[i * RS::ARRAY_WEIGHTS_SIZE + j]; + max_bone = MAX(data[j], max_bone); + } + + copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4); + } + + } break; + case RS::ARRAY_INDEX: { + + ERR_FAIL_NULL_V(iw, ERR_INVALID_DATA); + ERR_FAIL_COND_V(p_index_array_len <= 0, ERR_INVALID_DATA); + ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_INT32_ARRAY, ERR_INVALID_PARAMETER); + + Vector indices = p_arrays[ai]; + ERR_FAIL_COND_V(indices.size() == 0, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(indices.size() != p_index_array_len, ERR_INVALID_PARAMETER); + + /* determine whether using 16 or 32 bits indices */ + + const int *src = indices.ptr(); + + for (int i = 0; i < p_index_array_len; i++) { + + if (p_vertex_array_len < (1 << 16)) { + uint16_t v = src[i]; + + copymem(&iw[i * 2], &v, 2); + } else { + uint32_t v = src[i]; + + copymem(&iw[i * 4], &v, 4); + } + } + } break; + default: { + ERR_FAIL_V(ERR_INVALID_DATA); + } + } + } + + if (p_format & RS::ARRAY_FORMAT_BONES) { + //create AABBs for each detected bone + int total_bones = max_bone + 1; + + bool first = r_bone_aabb.size() == 0; + + r_bone_aabb.resize(total_bones); + + if (first) { + for (int i = 0; i < total_bones; i++) { + r_bone_aabb.write[i].size = Vector3(-1, -1, -1); //negative means unused + } + } + + Vector vertices = p_arrays[RS::ARRAY_VERTEX]; + Vector bones = p_arrays[RS::ARRAY_BONES]; + Vector weights = p_arrays[RS::ARRAY_WEIGHTS]; + + bool any_valid = false; + + if (vertices.size() && bones.size() == vertices.size() * 4 && weights.size() == bones.size()) { + + int vs = vertices.size(); + const Vector3 *rv = vertices.ptr(); + const int *rb = bones.ptr(); + const float *rw = weights.ptr(); + + AABB *bptr = r_bone_aabb.ptrw(); + + for (int i = 0; i < vs; i++) { + + Vector3 v = rv[i]; + for (int j = 0; j < 4; j++) { + + int idx = rb[i * 4 + j]; + float w = rw[i * 4 + j]; + if (w == 0) + continue; //break; + ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA); + + if (bptr[idx].size.x < 0) { + //first + bptr[idx] = AABB(v, SMALL_VEC3); + any_valid = true; + } else { + bptr[idx].expand_to(v); + } + } + } + } + + if (!any_valid && first) { + + r_bone_aabb.clear(); + } + } + return OK; +} + +uint32_t RenderingServer::mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const { + uint32_t offsets[ARRAY_MAX]; + mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets); + return offsets[p_array_index]; +} + +uint32_t RenderingServer::mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const { + uint32_t offsets[ARRAY_MAX]; + return mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets); +} + +uint32_t RenderingServer::mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const { + + int total_elem_size = 0; + + for (int i = 0; i < RS::ARRAY_MAX; i++) { + + r_offsets[i] = 0; //reset + + if (!(p_format & (1 << i))) // no array + continue; + + int elem_size = 0; + + switch (i) { + + case RS::ARRAY_VERTEX: { + + if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { + elem_size = 2; + } else { + elem_size = 3; + } + + { + elem_size *= sizeof(float); + } + + if (elem_size == 6) { + elem_size = 8; + } + + } break; + case RS::ARRAY_NORMAL: { + + if (p_format & ARRAY_COMPRESS_NORMAL) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 3; + } + + } break; + + case RS::ARRAY_TANGENT: { + if (p_format & ARRAY_COMPRESS_TANGENT) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + + } break; + case RS::ARRAY_COLOR: { + + if (p_format & ARRAY_COMPRESS_COLOR) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + } break; + case RS::ARRAY_TEX_UV: { + if (p_format & ARRAY_COMPRESS_TEX_UV) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + + case RS::ARRAY_TEX_UV2: { + if (p_format & ARRAY_COMPRESS_TEX_UV2) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + case RS::ARRAY_WEIGHTS: { + + elem_size = sizeof(uint16_t) * 4; + + } break; + case RS::ARRAY_BONES: { + + elem_size = sizeof(uint16_t) * 4; + + } break; + case RS::ARRAY_INDEX: { + + if (p_index_len <= 0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine whether using 16 or 32 bits indices */ + if (p_vertex_len >= (1 << 16)) { + + elem_size = 4; + + } else { + elem_size = 2; + } + r_offsets[i] = elem_size; + continue; + } + default: { + ERR_FAIL_V(0); + } + } + + r_offsets[i] = total_elem_size; + total_elem_size += elem_size; + } + return total_elem_size; +} + +Error RenderingServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_compress_format) { + + ERR_FAIL_INDEX_V(p_primitive, RS::PRIMITIVE_MAX, ERR_INVALID_PARAMETER); + ERR_FAIL_COND_V(p_arrays.size() != RS::ARRAY_MAX, ERR_INVALID_PARAMETER); + + uint32_t format = 0; + + // validation + int index_array_len = 0; + int array_len = 0; + + for (int i = 0; i < p_arrays.size(); i++) { + + if (p_arrays[i].get_type() == Variant::NIL) + continue; + + format |= (1 << i); + + if (i == RS::ARRAY_VERTEX) { + + Variant var = p_arrays[i]; + switch (var.get_type()) { + case Variant::PACKED_VECTOR2_ARRAY: { + Vector v2 = var; + } break; + case Variant::PACKED_VECTOR3_ARRAY: { + Vector v3 = var; + } break; + default: { + Array v = var; + } break; + } + + array_len = PackedVector3Array(p_arrays[i]).size(); + ERR_FAIL_COND_V(array_len == 0, ERR_INVALID_DATA); + } else if (i == RS::ARRAY_INDEX) { + + index_array_len = PackedInt32Array(p_arrays[i]).size(); + } + } + + ERR_FAIL_COND_V((format & RS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // mandatory + + if (p_blend_shapes.size()) { + //validate format for morphs + for (int i = 0; i < p_blend_shapes.size(); i++) { + + uint32_t bsformat = 0; + Array arr = p_blend_shapes[i]; + for (int j = 0; j < arr.size(); j++) { + + if (arr[j].get_type() != Variant::NIL) + bsformat |= (1 << j); + } + + ERR_FAIL_COND_V((bsformat) != (format & (RS::ARRAY_FORMAT_INDEX - 1)), ERR_INVALID_PARAMETER); + } + } + + uint32_t offsets[RS::ARRAY_MAX]; + + int total_elem_size = 0; + + for (int i = 0; i < RS::ARRAY_MAX; i++) { + + offsets[i] = 0; //reset + + if (!(format & (1 << i))) // no array + continue; + + int elem_size = 0; + + switch (i) { + + case RS::ARRAY_VERTEX: { + + Variant arr = p_arrays[0]; + if (arr.get_type() == Variant::PACKED_VECTOR2_ARRAY) { + elem_size = 2; + p_compress_format |= ARRAY_FLAG_USE_2D_VERTICES; + } else if (arr.get_type() == Variant::PACKED_VECTOR3_ARRAY) { + p_compress_format &= ~ARRAY_FLAG_USE_2D_VERTICES; + elem_size = 3; + } else { + elem_size = (p_compress_format & ARRAY_FLAG_USE_2D_VERTICES) ? 2 : 3; + } + + { + elem_size *= sizeof(float); + } + + } break; + case RS::ARRAY_NORMAL: { + + if (p_compress_format & ARRAY_COMPRESS_NORMAL) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 3; + } + + } break; + + case RS::ARRAY_TANGENT: { + if (p_compress_format & ARRAY_COMPRESS_TANGENT) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + + } break; + case RS::ARRAY_COLOR: { + + if (p_compress_format & ARRAY_COMPRESS_COLOR) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + } break; + case RS::ARRAY_TEX_UV: { + if (p_compress_format & ARRAY_COMPRESS_TEX_UV) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + + case RS::ARRAY_TEX_UV2: { + if (p_compress_format & ARRAY_COMPRESS_TEX_UV2) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + case RS::ARRAY_WEIGHTS: { + + elem_size = sizeof(uint16_t) * 4; + + } break; + case RS::ARRAY_BONES: { + + elem_size = sizeof(uint16_t) * 4; + + } break; + case RS::ARRAY_INDEX: { + + if (index_array_len <= 0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine whether using 16 or 32 bits indices */ + if (array_len >= (1 << 16)) { + + elem_size = 4; + + } else { + elem_size = 2; + } + offsets[i] = elem_size; + continue; + } + default: { + ERR_FAIL_V(ERR_BUG); + } + } + + offsets[i] = total_elem_size; + total_elem_size += elem_size; + } + + uint32_t mask = (1 << ARRAY_MAX) - 1; + format |= (~mask) & p_compress_format; //make the full format + + int array_size = total_elem_size * array_len; + + Vector vertex_array; + vertex_array.resize(array_size); + + int index_array_size = offsets[RS::ARRAY_INDEX] * index_array_len; + + Vector index_array; + index_array.resize(index_array_size); + + AABB aabb; + Vector bone_aabb; + + Error err = _surface_set_data(p_arrays, format, offsets, total_elem_size, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb); + ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Invalid array format for surface."); + + Vector> blend_shape_data; + + for (int i = 0; i < p_blend_shapes.size(); i++) { + + Vector vertex_array_shape; + vertex_array_shape.resize(array_size); + Vector noindex; + + AABB laabb; + Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb); + aabb.merge_with(laabb); + ERR_FAIL_COND_V_MSG(err2 != OK, ERR_INVALID_DATA, "Invalid blend shape array format for surface."); + + blend_shape_data.push_back(vertex_array_shape); + } + Vector lods; + if (index_array_len) { + + List keys; + p_lods.get_key_list(&keys); + for (List::Element *E = keys.front(); E; E = E->next()) { + float distance = E->get(); + ERR_CONTINUE(distance <= 0.0); + Vector indices = p_lods[E->get()]; + ERR_CONTINUE(indices.size() == 0); + uint32_t index_count = indices.size(); + ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller.. + + const int *r = indices.ptr(); + + Vector data; + if (array_len <= 65536) { + //16 bits indices + data.resize(indices.size() * 2); + uint8_t *w = data.ptrw(); + uint16_t *index_ptr = (uint16_t *)w; + for (uint32_t i = 0; i < index_count; i++) { + index_ptr[i] = r[i]; + } + } else { + //32 bits indices + data.resize(indices.size() * 4); + uint8_t *w = data.ptrw(); + uint32_t *index_ptr = (uint32_t *)w; + for (uint32_t i = 0; i < index_count; i++) { + index_ptr[i] = r[i]; + } + } + + SurfaceData::LOD lod; + lod.edge_length = distance; + lod.index_data = data; + lods.push_back(lod); + } + } + + SurfaceData &surface_data = *r_surface_data; + surface_data.format = format; + surface_data.primitive = p_primitive; + surface_data.aabb = aabb; + surface_data.vertex_data = vertex_array; + surface_data.vertex_count = array_len; + surface_data.index_data = index_array; + surface_data.index_count = index_array_len; + surface_data.blend_shapes = blend_shape_data; + surface_data.bone_aabbs = bone_aabb; + surface_data.lods = lods; + + return OK; +} + +void RenderingServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_compress_format) { + + SurfaceData sd; + Error err = mesh_create_surface_data_from_arrays(&sd, p_primitive, p_arrays, p_blend_shapes, p_lods, p_compress_format); + if (err != OK) { + return; + } + mesh_add_surface(p_mesh, sd); +} + +Array RenderingServer::_get_array_from_surface(uint32_t p_format, Vector p_vertex_data, int p_vertex_len, Vector p_index_data, int p_index_len) const { + + uint32_t offsets[ARRAY_MAX]; + + int total_elem_size = 0; + + for (int i = 0; i < RS::ARRAY_MAX; i++) { + + offsets[i] = 0; //reset + + if (!(p_format & (1 << i))) // no array + continue; + + int elem_size = 0; + + switch (i) { + + case RS::ARRAY_VERTEX: { + + if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { + elem_size = 2; + } else { + elem_size = 3; + } + + { + elem_size *= sizeof(float); + } + + } break; + case RS::ARRAY_NORMAL: { + + if (p_format & ARRAY_COMPRESS_NORMAL) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 3; + } + + } break; + + case RS::ARRAY_TANGENT: { + if (p_format & ARRAY_COMPRESS_TANGENT) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + + } break; + case RS::ARRAY_COLOR: { + + if (p_format & ARRAY_COMPRESS_COLOR) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 4; + } + } break; + case RS::ARRAY_TEX_UV: { + if (p_format & ARRAY_COMPRESS_TEX_UV) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + + case RS::ARRAY_TEX_UV2: { + if (p_format & ARRAY_COMPRESS_TEX_UV2) { + elem_size = sizeof(uint32_t); + } else { + elem_size = sizeof(float) * 2; + } + + } break; + case RS::ARRAY_WEIGHTS: { + + elem_size = sizeof(uint16_t) * 4; + + } break; + case RS::ARRAY_BONES: { + + elem_size = sizeof(uint16_t) * 4; + + } break; + case RS::ARRAY_INDEX: { + + if (p_index_len <= 0) { + ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); + break; + } + /* determine whether using 16 or 32 bits indices */ + if (p_vertex_len >= (1 << 16)) { + + elem_size = 4; + + } else { + elem_size = 2; + } + offsets[i] = elem_size; + continue; + } + default: { + ERR_FAIL_V(Array()); + } + } + + offsets[i] = total_elem_size; + total_elem_size += elem_size; + } + + Array ret; + ret.resize(RS::ARRAY_MAX); + + const uint8_t *r = p_vertex_data.ptr(); + + for (int i = 0; i < RS::ARRAY_MAX; i++) { + + if (!(p_format & (1 << i))) + continue; + + switch (i) { + + case RS::ARRAY_VERTEX: { + + if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { + + Vector arr_2d; + arr_2d.resize(p_vertex_len); + + { + + Vector2 *w = arr_2d.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector2(v[0], v[1]); + } + } + + ret[i] = arr_2d; + } else { + + Vector arr_3d; + arr_3d.resize(p_vertex_len); + + { + + Vector3 *w = arr_3d.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector3(v[0], v[1], v[2]); + } + } + + ret[i] = arr_3d; + } + + } break; + case RS::ARRAY_NORMAL: { + Vector arr; + arr.resize(p_vertex_len); + + if (p_format & ARRAY_COMPRESS_NORMAL) { + + Vector3 *w = arr.ptrw(); + const float multiplier = 1.f / 127.f; + + for (int j = 0; j < p_vertex_len; j++) { + + const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector3(float(v[0]) * multiplier, float(v[1]) * multiplier, float(v[2]) * multiplier); + } + } else { + Vector3 *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector3(v[0], v[1], v[2]); + } + } + + ret[i] = arr; + + } break; + + case RS::ARRAY_TANGENT: { + Vector arr; + arr.resize(p_vertex_len * 4); + if (p_format & ARRAY_COMPRESS_TANGENT) { + float *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]]; + for (int k = 0; k < 4; k++) { + w[j * 4 + k] = float(v[k] / 127.0); + } + } + } else { + + float *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + for (int k = 0; k < 4; k++) { + w[j * 4 + k] = v[k]; + } + } + } + + ret[i] = arr; + + } break; + case RS::ARRAY_COLOR: { + + Vector arr; + arr.resize(p_vertex_len); + + if (p_format & ARRAY_COMPRESS_COLOR) { + + Color *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const uint8_t *v = (const uint8_t *)&r[j * total_elem_size + offsets[i]]; + w[j] = Color(float(v[0] / 255.0), float(v[1] / 255.0), float(v[2] / 255.0), float(v[3] / 255.0)); + } + } else { + Color *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + w[j] = Color(v[0], v[1], v[2], v[3]); + } + } + + ret[i] = arr; + } break; + case RS::ARRAY_TEX_UV: { + + Vector arr; + arr.resize(p_vertex_len); + + if (p_format & ARRAY_COMPRESS_TEX_UV) { + + Vector2 *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1])); + } + } else { + + Vector2 *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector2(v[0], v[1]); + } + } + + ret[i] = arr; + } break; + + case RS::ARRAY_TEX_UV2: { + Vector arr; + arr.resize(p_vertex_len); + + if (p_format & ARRAY_COMPRESS_TEX_UV2) { + + Vector2 *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1])); + } + } else { + + Vector2 *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; + w[j] = Vector2(v[0], v[1]); + } + } + + ret[i] = arr; + + } break; + case RS::ARRAY_WEIGHTS: { + + Vector arr; + arr.resize(p_vertex_len * 4); + { + float *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; + for (int k = 0; k < 4; k++) { + w[j * 4 + k] = float(v[k] / 65535.0); + } + } + } + + ret[i] = arr; + + } break; + case RS::ARRAY_BONES: { + + Vector arr; + arr.resize(p_vertex_len * 4); + + int *w = arr.ptrw(); + + for (int j = 0; j < p_vertex_len; j++) { + + const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; + for (int k = 0; k < 4; k++) { + w[j * 4 + k] = v[k]; + } + } + + ret[i] = arr; + + } break; + case RS::ARRAY_INDEX: { + /* determine whether using 16 or 32 bits indices */ + + const uint8_t *ir = p_index_data.ptr(); + + Vector arr; + arr.resize(p_index_len); + if (p_vertex_len < (1 << 16)) { + + int *w = arr.ptrw(); + + for (int j = 0; j < p_index_len; j++) { + + const uint16_t *v = (const uint16_t *)&ir[j * 2]; + w[j] = *v; + } + } else { + + int *w = arr.ptrw(); + + for (int j = 0; j < p_index_len; j++) { + const int *v = (const int *)&ir[j * 4]; + w[j] = *v; + } + } + ret[i] = arr; + } break; + default: { + ERR_FAIL_V(ret); + } + } + } + + return ret; +} + +Array RenderingServer::mesh_surface_get_arrays(RID p_mesh, int p_surface) const { + + SurfaceData sd = mesh_get_surface(p_mesh, p_surface); + return mesh_create_arrays_from_surface_data(sd); +} + +Dictionary RenderingServer::mesh_surface_get_lods(RID p_mesh, int p_surface) const { + + SurfaceData sd = mesh_get_surface(p_mesh, p_surface); + ERR_FAIL_COND_V(sd.vertex_count == 0, Dictionary()); + + Dictionary ret; + + for (int i = 0; i < sd.lods.size(); i++) { + Vector lods; + if (sd.vertex_count <= 65536) { + uint32_t lc = sd.lods[i].index_data.size() / 2; + lods.resize(lc); + const uint8_t *r = sd.lods[i].index_data.ptr(); + const uint16_t *rptr = (const uint16_t *)r; + int *w = lods.ptrw(); + for (uint32_t j = 0; j < lc; j++) { + w[j] = rptr[i]; + } + } else { + uint32_t lc = sd.lods[i].index_data.size() / 4; + lods.resize(lc); + const uint8_t *r = sd.lods[i].index_data.ptr(); + const uint32_t *rptr = (const uint32_t *)r; + int *w = lods.ptrw(); + for (uint32_t j = 0; j < lc; j++) { + w[j] = rptr[i]; + } + } + + ret[sd.lods[i].edge_length] = lods; + } + + return ret; +} + +Array RenderingServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const { + + SurfaceData sd = mesh_get_surface(p_mesh, p_surface); + ERR_FAIL_COND_V(sd.vertex_count == 0, Array()); + + Vector> blend_shape_data = sd.blend_shapes; + + if (blend_shape_data.size() > 0) { + int vertex_len = sd.vertex_count; + + Vector index_data = sd.index_data; + int index_len = sd.index_count; + + uint32_t format = sd.format; + + Array blend_shape_array; + blend_shape_array.resize(blend_shape_data.size()); + for (int i = 0; i < blend_shape_data.size(); i++) { + blend_shape_array.set(i, _get_array_from_surface(format, blend_shape_data[i], vertex_len, index_data, index_len)); + } + + return blend_shape_array; + } else { + return Array(); + } +} + +Array RenderingServer::mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const { + + Vector vertex_data = p_data.vertex_data; + + ERR_FAIL_COND_V(vertex_data.size() == 0, Array()); + int vertex_len = p_data.vertex_count; + + Vector index_data = p_data.index_data; + int index_len = p_data.index_count; + + uint32_t format = p_data.format; + + return _get_array_from_surface(format, vertex_data, vertex_len, index_data, index_len); +} +#if 0 +Array RenderingServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const { + + Vector vec = RS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface); + Array arr; + for (int i = 0; i < vec.size(); i++) { + arr[i] = vec[i]; + } + return arr; +} +#endif +void RenderingServer::_bind_methods() { + + ClassDB::bind_method(D_METHOD("force_sync"), &RenderingServer::sync); + ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &RenderingServer::draw, DEFVAL(true), DEFVAL(0.0)); + +#ifndef _MSC_VER +#warning TODO all texture methods need re-binding +#endif + + ClassDB::bind_method(D_METHOD("texture_2d_create", "image"), &RenderingServer::texture_2d_create); + ClassDB::bind_method(D_METHOD("texture_2d_get", "texture"), &RenderingServer::texture_2d_get); + +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("sky_create"), &RenderingServer::sky_create); + ClassDB::bind_method(D_METHOD("sky_set_material", "sky", "material"), &RenderingServer::sky_set_material); +#endif + ClassDB::bind_method(D_METHOD("shader_create"), &RenderingServer::shader_create); + ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &RenderingServer::shader_set_code); + ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &RenderingServer::shader_get_code); + ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &RenderingServer::_shader_get_param_list_bind); + ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "name", "texture"), &RenderingServer::shader_set_default_texture_param); + ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "name"), &RenderingServer::shader_get_default_texture_param); + ClassDB::bind_method(D_METHOD("shader_get_param_default", "material", "parameter"), &RenderingServer::shader_get_param_default); + + ClassDB::bind_method(D_METHOD("material_create"), &RenderingServer::material_create); + ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &RenderingServer::material_set_shader); + ClassDB::bind_method(D_METHOD("material_set_param", "material", "parameter", "value"), &RenderingServer::material_set_param); + ClassDB::bind_method(D_METHOD("material_get_param", "material", "parameter"), &RenderingServer::material_get_param); + ClassDB::bind_method(D_METHOD("material_set_render_priority", "material", "priority"), &RenderingServer::material_set_render_priority); + + ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &RenderingServer::material_set_next_pass); + + ClassDB::bind_method(D_METHOD("mesh_create"), &RenderingServer::mesh_create); + ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_len", "index_len", "array_index"), &RenderingServer::mesh_surface_get_format_offset); + ClassDB::bind_method(D_METHOD("mesh_surface_get_format_stride", "format", "vertex_len", "index_len"), &RenderingServer::mesh_surface_get_format_stride); + ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "lods", "compress_format"), &RenderingServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); + ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &RenderingServer::mesh_get_blend_shape_count); + ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &RenderingServer::mesh_set_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &RenderingServer::mesh_get_blend_shape_mode); + ClassDB::bind_method(D_METHOD("mesh_surface_update_region", "mesh", "surface", "offset", "data"), &RenderingServer::mesh_surface_update_region); + ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &RenderingServer::mesh_surface_set_material); + ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &RenderingServer::mesh_surface_get_material); + ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &RenderingServer::mesh_surface_get_arrays); + ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &RenderingServer::mesh_surface_get_blend_shape_arrays); + ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &RenderingServer::mesh_get_surface_count); + ClassDB::bind_method(D_METHOD("mesh_set_custom_aabb", "mesh", "aabb"), &RenderingServer::mesh_set_custom_aabb); + ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &RenderingServer::mesh_get_custom_aabb); + ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &RenderingServer::mesh_clear); + + ClassDB::bind_method(D_METHOD("multimesh_create"), &RenderingServer::multimesh_create); + ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &RenderingServer::multimesh_allocate, DEFVAL(false), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &RenderingServer::multimesh_get_instance_count); + ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &RenderingServer::multimesh_set_mesh); + ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &RenderingServer::multimesh_instance_set_transform); + ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform_2d", "multimesh", "index", "transform"), &RenderingServer::multimesh_instance_set_transform_2d); + ClassDB::bind_method(D_METHOD("multimesh_instance_set_color", "multimesh", "index", "color"), &RenderingServer::multimesh_instance_set_color); + ClassDB::bind_method(D_METHOD("multimesh_instance_set_custom_data", "multimesh", "index", "custom_data"), &RenderingServer::multimesh_instance_set_custom_data); + ClassDB::bind_method(D_METHOD("multimesh_get_mesh", "multimesh"), &RenderingServer::multimesh_get_mesh); + ClassDB::bind_method(D_METHOD("multimesh_get_aabb", "multimesh"), &RenderingServer::multimesh_get_aabb); + ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform", "multimesh", "index"), &RenderingServer::multimesh_instance_get_transform); + ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform_2d", "multimesh", "index"), &RenderingServer::multimesh_instance_get_transform_2d); + ClassDB::bind_method(D_METHOD("multimesh_instance_get_color", "multimesh", "index"), &RenderingServer::multimesh_instance_get_color); + ClassDB::bind_method(D_METHOD("multimesh_instance_get_custom_data", "multimesh", "index"), &RenderingServer::multimesh_instance_get_custom_data); + ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &RenderingServer::multimesh_set_visible_instances); + ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &RenderingServer::multimesh_get_visible_instances); + ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &RenderingServer::multimesh_set_buffer); + ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &RenderingServer::multimesh_get_buffer); +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("immediate_create"), &RenderingServer::immediate_create); + ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &RenderingServer::immediate_begin, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("immediate_vertex", "immediate", "vertex"), &RenderingServer::immediate_vertex); + ClassDB::bind_method(D_METHOD("immediate_vertex_2d", "immediate", "vertex"), &RenderingServer::immediate_vertex_2d); + ClassDB::bind_method(D_METHOD("immediate_normal", "immediate", "normal"), &RenderingServer::immediate_normal); + ClassDB::bind_method(D_METHOD("immediate_tangent", "immediate", "tangent"), &RenderingServer::immediate_tangent); + ClassDB::bind_method(D_METHOD("immediate_color", "immediate", "color"), &RenderingServer::immediate_color); + ClassDB::bind_method(D_METHOD("immediate_uv", "immediate", "tex_uv"), &RenderingServer::immediate_uv); + ClassDB::bind_method(D_METHOD("immediate_uv2", "immediate", "tex_uv"), &RenderingServer::immediate_uv2); + ClassDB::bind_method(D_METHOD("immediate_end", "immediate"), &RenderingServer::immediate_end); + ClassDB::bind_method(D_METHOD("immediate_clear", "immediate"), &RenderingServer::immediate_clear); + ClassDB::bind_method(D_METHOD("immediate_set_material", "immediate", "material"), &RenderingServer::immediate_set_material); + ClassDB::bind_method(D_METHOD("immediate_get_material", "immediate"), &RenderingServer::immediate_get_material); +#endif + + ClassDB::bind_method(D_METHOD("skeleton_create"), &RenderingServer::skeleton_create); + ClassDB::bind_method(D_METHOD("skeleton_allocate", "skeleton", "bones", "is_2d_skeleton"), &RenderingServer::skeleton_allocate, DEFVAL(false)); + ClassDB::bind_method(D_METHOD("skeleton_get_bone_count", "skeleton"), &RenderingServer::skeleton_get_bone_count); + ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform", "skeleton", "bone", "transform"), &RenderingServer::skeleton_bone_set_transform); + ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform", "skeleton", "bone"), &RenderingServer::skeleton_bone_get_transform); + ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform_2d", "skeleton", "bone", "transform"), &RenderingServer::skeleton_bone_set_transform_2d); + ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform_2d", "skeleton", "bone"), &RenderingServer::skeleton_bone_get_transform_2d); + +#ifndef _3D_DISABLED + ClassDB::bind_method(D_METHOD("directional_light_create"), &RenderingServer::directional_light_create); + ClassDB::bind_method(D_METHOD("omni_light_create"), &RenderingServer::omni_light_create); + ClassDB::bind_method(D_METHOD("spot_light_create"), &RenderingServer::spot_light_create); + + ClassDB::bind_method(D_METHOD("light_set_color", "light", "color"), &RenderingServer::light_set_color); + ClassDB::bind_method(D_METHOD("light_set_param", "light", "param", "value"), &RenderingServer::light_set_param); + ClassDB::bind_method(D_METHOD("light_set_shadow", "light", "enabled"), &RenderingServer::light_set_shadow); + ClassDB::bind_method(D_METHOD("light_set_shadow_color", "light", "color"), &RenderingServer::light_set_shadow_color); + ClassDB::bind_method(D_METHOD("light_set_projector", "light", "texture"), &RenderingServer::light_set_projector); + ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &RenderingServer::light_set_negative); + ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &RenderingServer::light_set_cull_mask); + ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &RenderingServer::light_set_reverse_cull_face_mode); + ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &RenderingServer::light_set_use_gi); + + ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &RenderingServer::light_omni_set_shadow_mode); + + ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &RenderingServer::light_directional_set_shadow_mode); + ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &RenderingServer::light_directional_set_blend_splits); + ClassDB::bind_method(D_METHOD("light_directional_set_shadow_depth_range_mode", "light", "range_mode"), &RenderingServer::light_directional_set_shadow_depth_range_mode); + + ClassDB::bind_method(D_METHOD("reflection_probe_create"), &RenderingServer::reflection_probe_create); + ClassDB::bind_method(D_METHOD("reflection_probe_set_update_mode", "probe", "mode"), &RenderingServer::reflection_probe_set_update_mode); + ClassDB::bind_method(D_METHOD("reflection_probe_set_intensity", "probe", "intensity"), &RenderingServer::reflection_probe_set_intensity); + ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient", "probe", "color"), &RenderingServer::reflection_probe_set_interior_ambient); + ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_energy", "probe", "energy"), &RenderingServer::reflection_probe_set_interior_ambient_energy); + ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_probe_contribution", "probe", "contrib"), &RenderingServer::reflection_probe_set_interior_ambient_probe_contribution); + ClassDB::bind_method(D_METHOD("reflection_probe_set_max_distance", "probe", "distance"), &RenderingServer::reflection_probe_set_max_distance); + ClassDB::bind_method(D_METHOD("reflection_probe_set_extents", "probe", "extents"), &RenderingServer::reflection_probe_set_extents); + ClassDB::bind_method(D_METHOD("reflection_probe_set_origin_offset", "probe", "offset"), &RenderingServer::reflection_probe_set_origin_offset); + ClassDB::bind_method(D_METHOD("reflection_probe_set_as_interior", "probe", "enable"), &RenderingServer::reflection_probe_set_as_interior); + ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_box_projection", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_box_projection); + ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &RenderingServer::reflection_probe_set_enable_shadows); + ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &RenderingServer::reflection_probe_set_cull_mask); + +#ifndef _MSC_VER +#warning TODO all giprobe methods need re-binding +#endif +#if 0 + ClassDB::bind_method(D_METHOD("gi_probe_create"), &RenderingServer::gi_probe_create); + ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &RenderingServer::gi_probe_set_bounds); + ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &RenderingServer::gi_probe_get_bounds); + ClassDB::bind_method(D_METHOD("gi_probe_set_cell_size", "probe", "range"), &RenderingServer::gi_probe_set_cell_size); + ClassDB::bind_method(D_METHOD("gi_probe_get_cell_size", "probe"), &RenderingServer::gi_probe_get_cell_size); + ClassDB::bind_method(D_METHOD("gi_probe_set_to_cell_xform", "probe", "xform"), &RenderingServer::gi_probe_set_to_cell_xform); + ClassDB::bind_method(D_METHOD("gi_probe_get_to_cell_xform", "probe"), &RenderingServer::gi_probe_get_to_cell_xform); + ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_data", "probe", "data"), &RenderingServer::gi_probe_set_dynamic_data); + ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_data", "probe"), &RenderingServer::gi_probe_get_dynamic_data); + ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_range", "probe", "range"), &RenderingServer::gi_probe_set_dynamic_range); + ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_range", "probe"), &RenderingServer::gi_probe_get_dynamic_range); + ClassDB::bind_method(D_METHOD("gi_probe_set_energy", "probe", "energy"), &RenderingServer::gi_probe_set_energy); + ClassDB::bind_method(D_METHOD("gi_probe_get_energy", "probe"), &RenderingServer::gi_probe_get_energy); + ClassDB::bind_method(D_METHOD("gi_probe_set_bias", "probe", "bias"), &RenderingServer::gi_probe_set_bias); + ClassDB::bind_method(D_METHOD("gi_probe_get_bias", "probe"), &RenderingServer::gi_probe_get_bias); + ClassDB::bind_method(D_METHOD("gi_probe_set_normal_bias", "probe", "bias"), &RenderingServer::gi_probe_set_normal_bias); + ClassDB::bind_method(D_METHOD("gi_probe_get_normal_bias", "probe"), &RenderingServer::gi_probe_get_normal_bias); + ClassDB::bind_method(D_METHOD("gi_probe_set_propagation", "probe", "propagation"), &RenderingServer::gi_probe_set_propagation); + ClassDB::bind_method(D_METHOD("gi_probe_get_propagation", "probe"), &RenderingServer::gi_probe_get_propagation); + ClassDB::bind_method(D_METHOD("gi_probe_set_interior", "probe", "enable"), &RenderingServer::gi_probe_set_interior); + ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &RenderingServer::gi_probe_is_interior); + ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &RenderingServer::gi_probe_set_compress); + ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &RenderingServer::gi_probe_is_compressed); +#endif + + ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &RenderingServer::lightmap_capture_create); + ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &RenderingServer::lightmap_capture_set_bounds); + ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &RenderingServer::lightmap_capture_get_bounds); + ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree", "capture", "octree"), &RenderingServer::lightmap_capture_set_octree); + ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_transform", "capture", "xform"), &RenderingServer::lightmap_capture_set_octree_cell_transform); + ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_transform", "capture"), &RenderingServer::lightmap_capture_get_octree_cell_transform); + ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_subdiv", "capture", "subdiv"), &RenderingServer::lightmap_capture_set_octree_cell_subdiv); + ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_subdiv", "capture"), &RenderingServer::lightmap_capture_get_octree_cell_subdiv); + ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree", "capture"), &RenderingServer::lightmap_capture_get_octree); + ClassDB::bind_method(D_METHOD("lightmap_capture_set_energy", "capture", "energy"), &RenderingServer::lightmap_capture_set_energy); + ClassDB::bind_method(D_METHOD("lightmap_capture_get_energy", "capture"), &RenderingServer::lightmap_capture_get_energy); +#endif + ClassDB::bind_method(D_METHOD("particles_create"), &RenderingServer::particles_create); + ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &RenderingServer::particles_set_emitting); + ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &RenderingServer::particles_get_emitting); + ClassDB::bind_method(D_METHOD("particles_set_amount", "particles", "amount"), &RenderingServer::particles_set_amount); + ClassDB::bind_method(D_METHOD("particles_set_lifetime", "particles", "lifetime"), &RenderingServer::particles_set_lifetime); + ClassDB::bind_method(D_METHOD("particles_set_one_shot", "particles", "one_shot"), &RenderingServer::particles_set_one_shot); + ClassDB::bind_method(D_METHOD("particles_set_pre_process_time", "particles", "time"), &RenderingServer::particles_set_pre_process_time); + ClassDB::bind_method(D_METHOD("particles_set_explosiveness_ratio", "particles", "ratio"), &RenderingServer::particles_set_explosiveness_ratio); + ClassDB::bind_method(D_METHOD("particles_set_randomness_ratio", "particles", "ratio"), &RenderingServer::particles_set_randomness_ratio); + ClassDB::bind_method(D_METHOD("particles_set_custom_aabb", "particles", "aabb"), &RenderingServer::particles_set_custom_aabb); + ClassDB::bind_method(D_METHOD("particles_set_speed_scale", "particles", "scale"), &RenderingServer::particles_set_speed_scale); + ClassDB::bind_method(D_METHOD("particles_set_use_local_coordinates", "particles", "enable"), &RenderingServer::particles_set_use_local_coordinates); + ClassDB::bind_method(D_METHOD("particles_set_process_material", "particles", "material"), &RenderingServer::particles_set_process_material); + ClassDB::bind_method(D_METHOD("particles_set_fixed_fps", "particles", "fps"), &RenderingServer::particles_set_fixed_fps); + ClassDB::bind_method(D_METHOD("particles_set_fractional_delta", "particles", "enable"), &RenderingServer::particles_set_fractional_delta); + ClassDB::bind_method(D_METHOD("particles_is_inactive", "particles"), &RenderingServer::particles_is_inactive); + ClassDB::bind_method(D_METHOD("particles_request_process", "particles"), &RenderingServer::particles_request_process); + ClassDB::bind_method(D_METHOD("particles_restart", "particles"), &RenderingServer::particles_restart); + ClassDB::bind_method(D_METHOD("particles_set_draw_order", "particles", "order"), &RenderingServer::particles_set_draw_order); + ClassDB::bind_method(D_METHOD("particles_set_draw_passes", "particles", "count"), &RenderingServer::particles_set_draw_passes); + ClassDB::bind_method(D_METHOD("particles_set_draw_pass_mesh", "particles", "pass", "mesh"), &RenderingServer::particles_set_draw_pass_mesh); + ClassDB::bind_method(D_METHOD("particles_get_current_aabb", "particles"), &RenderingServer::particles_get_current_aabb); + ClassDB::bind_method(D_METHOD("particles_set_emission_transform", "particles", "transform"), &RenderingServer::particles_set_emission_transform); + + ClassDB::bind_method(D_METHOD("camera_create"), &RenderingServer::camera_create); + ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &RenderingServer::camera_set_perspective); + ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &RenderingServer::camera_set_orthogonal); + ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &RenderingServer::camera_set_frustum); + ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &RenderingServer::camera_set_transform); + ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &RenderingServer::camera_set_cull_mask); + ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &RenderingServer::camera_set_environment); + ClassDB::bind_method(D_METHOD("camera_set_use_vertical_aspect", "camera", "enable"), &RenderingServer::camera_set_use_vertical_aspect); + + ClassDB::bind_method(D_METHOD("viewport_create"), &RenderingServer::viewport_create); + ClassDB::bind_method(D_METHOD("viewport_set_use_arvr", "viewport", "use_arvr"), &RenderingServer::viewport_set_use_arvr); + ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &RenderingServer::viewport_set_size); + ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &RenderingServer::viewport_set_active); + ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &RenderingServer::viewport_set_parent_viewport); + ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &RenderingServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID)); + ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &RenderingServer::viewport_set_render_direct_to_screen); + + ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &RenderingServer::viewport_set_update_mode); + ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &RenderingServer::viewport_set_clear_mode); + ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &RenderingServer::viewport_get_texture); + ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &RenderingServer::viewport_set_hide_scenario); + ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &RenderingServer::viewport_set_hide_canvas); + ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &RenderingServer::viewport_set_disable_environment); + ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &RenderingServer::viewport_attach_camera); + ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &RenderingServer::viewport_set_scenario); + ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &RenderingServer::viewport_attach_canvas); + ClassDB::bind_method(D_METHOD("viewport_remove_canvas", "viewport", "canvas"), &RenderingServer::viewport_remove_canvas); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &RenderingServer::viewport_set_canvas_transform); + ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &RenderingServer::viewport_set_transparent_background); + ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &RenderingServer::viewport_set_global_canvas_transform); + ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &RenderingServer::viewport_set_canvas_stacking); + ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &RenderingServer::viewport_set_shadow_atlas_size); + ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &RenderingServer::viewport_set_shadow_atlas_quadrant_subdivision); + ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &RenderingServer::viewport_set_msaa); + ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &RenderingServer::viewport_get_render_info); + ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &RenderingServer::viewport_set_debug_draw); + + ClassDB::bind_method(D_METHOD("environment_create"), &RenderingServer::environment_create); + ClassDB::bind_method(D_METHOD("environment_set_background", "env", "bg"), &RenderingServer::environment_set_background); + ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &RenderingServer::environment_set_sky); + ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &RenderingServer::environment_set_sky_custom_fov); + ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &RenderingServer::environment_set_sky_orientation); + ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &RenderingServer::environment_set_bg_color); + ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &RenderingServer::environment_set_bg_energy); + ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &RenderingServer::environment_set_canvas_max_layer); + ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &RenderingServer::environment_set_ambient_light, DEFVAL(RS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(RS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color())); + ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "level_flags", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap", "bicubic_upscale"), &RenderingServer::environment_set_glow); + ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &RenderingServer::environment_set_tonemap); + ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &RenderingServer::environment_set_adjustment); + ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance", "roughness"), &RenderingServer::environment_set_ssr); + ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "bias", "light_affect", "ao_channel_affect", "blur", "bilateral_sharpness"), &RenderingServer::environment_set_ssao); + ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "color", "sun_color", "sun_amount"), &RenderingServer::environment_set_fog); + + ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_end", "depth_curve", "transmit", "transmit_curve"), &RenderingServer::environment_set_fog_depth); + + ClassDB::bind_method(D_METHOD("environment_set_fog_height", "env", "enable", "min_height", "max_height", "height_curve"), &RenderingServer::environment_set_fog_height); + + ClassDB::bind_method(D_METHOD("scenario_create"), &RenderingServer::scenario_create); + ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &RenderingServer::scenario_set_debug); + ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &RenderingServer::scenario_set_environment); + ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &RenderingServer::scenario_set_fallback_environment); + +#ifndef _3D_DISABLED + + ClassDB::bind_method(D_METHOD("instance_create2", "base", "scenario"), &RenderingServer::instance_create2); + ClassDB::bind_method(D_METHOD("instance_create"), &RenderingServer::instance_create); + ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &RenderingServer::instance_set_base); + ClassDB::bind_method(D_METHOD("instance_set_scenario", "instance", "scenario"), &RenderingServer::instance_set_scenario); + ClassDB::bind_method(D_METHOD("instance_set_layer_mask", "instance", "mask"), &RenderingServer::instance_set_layer_mask); + ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &RenderingServer::instance_set_transform); + ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &RenderingServer::instance_attach_object_instance_id); + ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &RenderingServer::instance_set_blend_shape_weight); + ClassDB::bind_method(D_METHOD("instance_set_surface_material", "instance", "surface", "material"), &RenderingServer::instance_set_surface_material); + ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &RenderingServer::instance_set_visible); + ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap"), &RenderingServer::instance_set_use_lightmap); + ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &RenderingServer::instance_set_custom_aabb); + ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &RenderingServer::instance_attach_skeleton); + ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &RenderingServer::instance_set_exterior); + ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &RenderingServer::instance_set_extra_visibility_margin); + ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &RenderingServer::instance_geometry_set_flag); + ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &RenderingServer::instance_geometry_set_cast_shadows_setting); + ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &RenderingServer::instance_geometry_set_material_override); + ClassDB::bind_method(D_METHOD("instance_geometry_set_draw_range", "instance", "min", "max", "min_margin", "max_margin"), &RenderingServer::instance_geometry_set_draw_range); + ClassDB::bind_method(D_METHOD("instance_geometry_set_as_instance_lod", "instance", "as_lod_of_instance"), &RenderingServer::instance_geometry_set_as_instance_lod); + + ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &RenderingServer::_instances_cull_aabb_bind, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &RenderingServer::_instances_cull_ray_bind, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("instances_cull_convex", "convex", "scenario"), &RenderingServer::_instances_cull_convex_bind, DEFVAL(RID())); +#endif + ClassDB::bind_method(D_METHOD("canvas_create"), &RenderingServer::canvas_create); + ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &RenderingServer::canvas_set_item_mirroring); + ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &RenderingServer::canvas_set_modulate); +#ifndef _MSC_VER +#warning TODO method bindings need to be fixed +#endif +#if 0 + + ClassDB::bind_method(D_METHOD("canvas_item_create"), &RenderingServer::canvas_item_create); + ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &RenderingServer::canvas_item_set_parent); + ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &RenderingServer::canvas_item_set_visible); + ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &RenderingServer::canvas_item_set_light_mask); + ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &RenderingServer::canvas_item_set_transform); + ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &RenderingServer::canvas_item_set_clip); + ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &RenderingServer::canvas_item_set_distance_field_mode); + ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &RenderingServer::canvas_item_set_custom_rect, DEFVAL(Rect2())); + ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &RenderingServer::canvas_item_set_modulate); + ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &RenderingServer::canvas_item_set_self_modulate); + ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &RenderingServer::canvas_item_set_draw_behind_parent); + ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &RenderingServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &RenderingServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &RenderingServer::canvas_item_add_rect); + ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &RenderingServer::canvas_item_add_circle); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose", "normal_map"), &RenderingServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &RenderingServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()), DEFVAL(true)); + ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &RenderingServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &RenderingServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &RenderingServer::canvas_item_add_polygon, DEFVAL(Vector()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased"), &RenderingServer::canvas_item_add_triangle_array, DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false)); + ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &RenderingServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &RenderingServer::canvas_item_add_multimesh, DEFVAL(RID())); + ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &RenderingServer::canvas_item_add_particles); + ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &RenderingServer::canvas_item_add_set_transform); + ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &RenderingServer::canvas_item_add_clip_ignore); + ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &RenderingServer::canvas_item_set_sort_children_by_y); +#endif + ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &RenderingServer::canvas_item_set_z_index); + ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &RenderingServer::canvas_item_set_z_as_relative_to_parent); + ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &RenderingServer::canvas_item_set_copy_to_backbuffer); + ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &RenderingServer::canvas_item_clear); + ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &RenderingServer::canvas_item_set_draw_index); + ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &RenderingServer::canvas_item_set_material); + ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &RenderingServer::canvas_item_set_use_parent_material); + ClassDB::bind_method(D_METHOD("canvas_light_create"), &RenderingServer::canvas_light_create); + ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &RenderingServer::canvas_light_attach_to_canvas); + ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &RenderingServer::canvas_light_set_scale); + ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &RenderingServer::canvas_light_set_transform); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &RenderingServer::canvas_light_set_texture); + ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &RenderingServer::canvas_light_set_texture_offset); + ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &RenderingServer::canvas_light_set_color); + ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &RenderingServer::canvas_light_set_height); + ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &RenderingServer::canvas_light_set_energy); + ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &RenderingServer::canvas_light_set_z_range); + ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &RenderingServer::canvas_light_set_layer_range); + ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_cull_mask); + ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &RenderingServer::canvas_light_set_item_shadow_cull_mask); + ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &RenderingServer::canvas_light_set_mode); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &RenderingServer::canvas_light_set_shadow_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &RenderingServer::canvas_light_set_shadow_buffer_size); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &RenderingServer::canvas_light_set_shadow_filter); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &RenderingServer::canvas_light_set_shadow_color); + ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &RenderingServer::canvas_light_set_shadow_smooth); + + ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &RenderingServer::canvas_light_occluder_create); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &RenderingServer::canvas_light_occluder_attach_to_canvas); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &RenderingServer::canvas_light_occluder_set_enabled); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &RenderingServer::canvas_light_occluder_set_polygon); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &RenderingServer::canvas_light_occluder_set_transform); + ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &RenderingServer::canvas_light_occluder_set_light_mask); + + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &RenderingServer::canvas_occluder_polygon_create); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &RenderingServer::canvas_occluder_polygon_set_shape); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &RenderingServer::canvas_occluder_polygon_set_shape_as_lines); + ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &RenderingServer::canvas_occluder_polygon_set_cull_mode); + + ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_margins); + ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &RenderingServer::black_bars_set_images); + + ClassDB::bind_method(D_METHOD("free_rid", "rid"), &RenderingServer::free); // shouldn't conflict with Object::free() + + ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &RenderingServer::request_frame_drawn_callback); + ClassDB::bind_method(D_METHOD("has_changed"), &RenderingServer::has_changed); + ClassDB::bind_method(D_METHOD("init"), &RenderingServer::init); + ClassDB::bind_method(D_METHOD("finish"), &RenderingServer::finish); + ClassDB::bind_method(D_METHOD("get_render_info", "info"), &RenderingServer::get_render_info); + ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &RenderingServer::get_video_adapter_name); + ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &RenderingServer::get_video_adapter_vendor); +#ifndef _3D_DISABLED + + ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &RenderingServer::make_sphere_mesh); + ClassDB::bind_method(D_METHOD("get_test_cube"), &RenderingServer::get_test_cube); +#endif + ClassDB::bind_method(D_METHOD("get_test_texture"), &RenderingServer::get_test_texture); + ClassDB::bind_method(D_METHOD("get_white_texture"), &RenderingServer::get_white_texture); + + ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale", "use_filter"), &RenderingServer::set_boot_image, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &RenderingServer::set_default_clear_color); + + ClassDB::bind_method(D_METHOD("has_feature", "feature"), &RenderingServer::has_feature); + ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &RenderingServer::has_os_feature); + ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &RenderingServer::set_debug_generate_wireframes); + + BIND_CONSTANT(NO_INDEX_ARRAY); + BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); + BIND_CONSTANT(CANVAS_ITEM_Z_MIN); + BIND_CONSTANT(CANVAS_ITEM_Z_MAX); + BIND_CONSTANT(MAX_GLOW_LEVELS); + BIND_CONSTANT(MAX_CURSORS); + + BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN); + BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX); + + BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY); + BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP); + BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP_ARRAY); + + BIND_ENUM_CONSTANT(CUBEMAP_LAYER_LEFT); + BIND_ENUM_CONSTANT(CUBEMAP_LAYER_RIGHT); + BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BOTTOM); + BIND_ENUM_CONSTANT(CUBEMAP_LAYER_TOP); + BIND_ENUM_CONSTANT(CUBEMAP_LAYER_FRONT); + BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BACK); + + BIND_ENUM_CONSTANT(SHADER_SPATIAL); + BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); + BIND_ENUM_CONSTANT(SHADER_PARTICLES); + BIND_ENUM_CONSTANT(SHADER_SKY); + BIND_ENUM_CONSTANT(SHADER_MAX); + + BIND_ENUM_CONSTANT(ARRAY_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COLOR); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_BONES); + BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_INDEX); + BIND_ENUM_CONSTANT(ARRAY_MAX); + + BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); + BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); + + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES); + BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE); + BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT); + + BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); + BIND_ENUM_CONSTANT(PRIMITIVE_LINES); + BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); + BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); + BIND_ENUM_CONSTANT(PRIMITIVE_MAX); + + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); + BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); + + BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D); + BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D); + + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL); + BIND_ENUM_CONSTANT(LIGHT_OMNI); + BIND_ENUM_CONSTANT(LIGHT_SPOT); + + BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY); + BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR); + BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION); + BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS); + BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE); + BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX); + + BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID); + BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE); + + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS); + + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); + BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED); + + BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE); + BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS); + + BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_INDEX); + BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_LIFETIME); + BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_VIEW_DEPTH); + + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); + BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); + + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS); + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER); + BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME); + + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_2X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_4X); + + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME); + BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX); + + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_UNSHADED); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_LIGHTING); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO); + BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER); + + BIND_ENUM_CONSTANT(SKY_MODE_QUALITY); + BIND_ENUM_CONSTANT(SKY_MODE_REALTIME); + + BIND_ENUM_CONSTANT(ENV_BG_CLEAR_COLOR); + BIND_ENUM_CONSTANT(ENV_BG_COLOR); + BIND_ENUM_CONSTANT(ENV_BG_SKY); + BIND_ENUM_CONSTANT(ENV_BG_CANVAS); + BIND_ENUM_CONSTANT(ENV_BG_KEEP); + BIND_ENUM_CONSTANT(ENV_BG_CAMERA_FEED); + BIND_ENUM_CONSTANT(ENV_BG_MAX); + + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_BG); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_COLOR); + BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_SKY); + + BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_BG); + BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_DISABLED); + BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_SKY); + + BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_ADDITIVE); + BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_SCREEN); + BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_SOFTLIGHT); + BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_REPLACE); + BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_MIX); + + BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_LINEAR); + BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_REINHARD); + BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_FILMIC); + BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_ACES); + + BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_DISABLED); + BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_1x1); + BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_2x2); + BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_3x3); + + BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_LOW); + BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_MEDIUM); + BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_HIGH); + BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_ULTRA); + + BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_VERY_LOW); + BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_LOW); + BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_MEDIUM); + BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_HIGH); + + BIND_ENUM_CONSTANT(DOF_BOKEH_BOX); + BIND_ENUM_CONSTANT(DOF_BOKEH_HEXAGON); + BIND_ENUM_CONSTANT(DOF_BOKEH_CIRCLE); + + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_DISABLED); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_WIREFRAME); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_OVERDRAW); + BIND_ENUM_CONSTANT(SCENARIO_DEBUG_SHADELESS); + + BIND_ENUM_CONSTANT(INSTANCE_NONE); + BIND_ENUM_CONSTANT(INSTANCE_MESH); + BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH); + BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE); + BIND_ENUM_CONSTANT(INSTANCE_PARTICLES); + BIND_ENUM_CONSTANT(INSTANCE_LIGHT); + BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); + BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP_CAPTURE); + BIND_ENUM_CONSTANT(INSTANCE_MAX); + BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); + + BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_BAKED_LIGHT); + BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_DYNAMIC_GI); + BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE); + BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX); + + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); + BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); + + BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH); + BIND_ENUM_CONSTANT(NINE_PATCH_TILE); + BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT); + + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_DEFAULT); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_NEAREST); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_LINEAR); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_MAX); + + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); + BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK); + + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13); + BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_MAX); + + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED); + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE); + BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE); + + BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME); + BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL); + BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED); + BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED); + BIND_ENUM_CONSTANT(INFO_VERTEX_MEM_USED); + + BIND_ENUM_CONSTANT(FEATURE_SHADERS); + BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED); + + ADD_SIGNAL(MethodInfo("frame_pre_draw")); + ADD_SIGNAL(MethodInfo("frame_post_draw")); +} + +void RenderingServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector &p_margins, const Color &p_modulate) { + + ERR_FAIL_COND(p_margins.size() != 4); + //canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate); +} + +void RenderingServer::_camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) { + + camera_set_orthogonal(p_camera, p_size, p_z_near, p_z_far); +} + +void RenderingServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data) { + + Vector vertices; + Vector normals; + + for (int i = 0; i < p_mesh_data.faces.size(); i++) { + + const Geometry::MeshData::Face &f = p_mesh_data.faces[i]; + + for (int j = 2; j < f.indices.size(); j++) { + +#define _ADD_VERTEX(m_idx) \ + vertices.push_back(p_mesh_data.vertices[f.indices[m_idx]]); \ + normals.push_back(f.plane.normal); + + _ADD_VERTEX(0); + _ADD_VERTEX(j - 1); + _ADD_VERTEX(j); + } + } + + Array d; + d.resize(RS::ARRAY_MAX); + d[ARRAY_VERTEX] = vertices; + d[ARRAY_NORMAL] = normals; + mesh_add_surface_from_arrays(p_mesh, PRIMITIVE_TRIANGLES, d); +} + +void RenderingServer::mesh_add_surface_from_planes(RID p_mesh, const Vector &p_planes) { + + Geometry::MeshData mdata = Geometry::build_convex_mesh(p_planes); + mesh_add_surface_from_mesh_data(p_mesh, mdata); +} + +void RenderingServer::immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex) { + immediate_vertex(p_immediate, Vector3(p_vertex.x, p_vertex.y, 0)); +} + +RID RenderingServer::instance_create2(RID p_base, RID p_scenario) { + + RID instance = instance_create(); + instance_set_base(instance, p_base); + instance_set_scenario(instance, p_scenario); + return instance; +} + +RenderingServer::RenderingServer() { + + //ERR_FAIL_COND(singleton); + singleton = this; + + GLOBAL_DEF_RST("rendering/vram_compression/import_bptc", false); + GLOBAL_DEF_RST("rendering/vram_compression/import_s3tc", true); + GLOBAL_DEF_RST("rendering/vram_compression/import_etc", false); + GLOBAL_DEF_RST("rendering/vram_compression/import_etc2", true); + GLOBAL_DEF_RST("rendering/vram_compression/import_pvrtc", false); + + GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096); + GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384")); + GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096); + GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); + GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_0_subdiv", 1); + GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_1_subdiv", 2); + GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_2_subdiv", 3); + GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_3_subdiv", 4); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); + + GLOBAL_DEF("rendering/quality/shadows/filter_mode", 1); + GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled (Fastest),PCF5,PCF13 (Slowest)")); + + GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 8); + GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true); + GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false); + GLOBAL_DEF("rendering/quality/reflections/ggx_samples", 1024); + GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128); + GLOBAL_DEF("rendering/quality/reflections/fast_filter_high_quality", false); + GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256); + GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128); + GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64); + + GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false); + GLOBAL_DEF("rendering/quality/gi_probes/quality", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Ultra-Low (1 cone - fastest),Medium (4 cones), High (6 cones - slowest)")); + + GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false); + GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true); + GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley", false); + GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley.mobile", true); + GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx", false); + GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true); + + GLOBAL_DEF("rendering/quality/depth_prepass/enable", true); + GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); + + GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); + GLOBAL_DEF("rendering/quality/filters/max_anisotropy", 4); + + GLOBAL_DEF("rendering/quality/filters/depth_of_field_bokeh_shape", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/depth_of_field_bokeh_shape", PropertyInfo(Variant::INT, "rendering/quality/filters/depth_of_field_bokeh_shape", PROPERTY_HINT_ENUM, "Box (Fastest),Hexagon,Circle (Slowest)")); + GLOBAL_DEF("rendering/quality/filters/depth_of_field_bokeh_quality", 2); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/depth_of_field_bokeh_quality", PropertyInfo(Variant::INT, "rendering/quality/filters/depth_of_field_bokeh_quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low,Medium,High (Slow)")); + GLOBAL_DEF("rendering/quality/filters/depth_of_field_use_jitter", false); + + GLOBAL_DEF("rendering/quality/ssao/quality", 1); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/quality", PropertyInfo(Variant::INT, "rendering/quality/ssao/quality", PROPERTY_HINT_ENUM, "Low (Fast),Medium,High (Slow),Ultra (Very Slow)")); + GLOBAL_DEF("rendering/quality/ssao/half_size", false); + + GLOBAL_DEF("rendering/quality/filters/screen_space_roughness_limiter", 0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/screen_space_roughness_limiter", PropertyInfo(Variant::INT, "rendering/quality/filters/screen_space_roughness_limiter", PROPERTY_HINT_ENUM, "Disabled,Enabled (Small Cost)")); + GLOBAL_DEF("rendering/quality/filters/screen_space_roughness_limiter_curve", 1.0); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/screen_space_roughness_limiter_curve", PropertyInfo(Variant::FLOAT, "rendering/quality/filters/screen_space_roughness_limiter_curve", PROPERTY_HINT_EXP_EASING, "0.01,8,0.01")); +} + +RenderingServer::~RenderingServer() { + + singleton = NULL; +} diff --git a/servers/rendering_server.h b/servers/rendering_server.h new file mode 100644 index 0000000000..92820aca21 --- /dev/null +++ b/servers/rendering_server.h @@ -0,0 +1,1157 @@ +/*************************************************************************/ +/* rendering_server.h */ +/*************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/*************************************************************************/ +/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ +/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/*************************************************************************/ + +#ifndef RENDERING_SERVER_H +#define RENDERING_SERVER_H + +#include "core/image.h" +#include "core/math/geometry.h" +#include "core/math/transform_2d.h" +#include "core/object.h" +#include "core/rid.h" +#include "core/variant.h" +#include "servers/display_server.h" + +class RenderingServer : public Object { + + GDCLASS(RenderingServer, Object); + + static RenderingServer *singleton; + + int mm_policy; + + void _camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); + void _canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector &p_margins, const Color &p_modulate = Color(1, 1, 1)); + Array _get_array_from_surface(uint32_t p_format, Vector p_vertex_data, int p_vertex_len, Vector p_index_data, int p_index_len) const; + +protected: + RID _make_test_cube(); + void _free_internal_rids(); + RID test_texture; + RID white_texture; + RID test_material; + + Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, Vector &r_vertex_array, int p_vertex_array_len, Vector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb); + + static RenderingServer *(*create_func)(); + static void _bind_methods(); + +public: + static RenderingServer *get_singleton(); + static RenderingServer *create(); + + enum { + NO_INDEX_ARRAY = -1, + ARRAY_WEIGHTS_SIZE = 4, + CANVAS_ITEM_Z_MIN = -4096, + CANVAS_ITEM_Z_MAX = 4096, + MAX_GLOW_LEVELS = 7, + MAX_CURSORS = 8, + }; + + /* TEXTURE API */ + + enum TextureLayeredType { + TEXTURE_LAYERED_2D_ARRAY, + TEXTURE_LAYERED_CUBEMAP, + TEXTURE_LAYERED_CUBEMAP_ARRAY, + }; + + enum CubeMapLayer { + + CUBEMAP_LAYER_LEFT, + CUBEMAP_LAYER_RIGHT, + CUBEMAP_LAYER_BOTTOM, + CUBEMAP_LAYER_TOP, + CUBEMAP_LAYER_FRONT, + CUBEMAP_LAYER_BACK + }; + + virtual RID texture_2d_create(const Ref &p_image) = 0; + virtual RID texture_2d_layered_create(const Vector> &p_layers, TextureLayeredType p_layered_type) = 0; + virtual RID texture_3d_create(const Vector> &p_slices) = 0; //all slices, then all the mipmaps, must be coherent + virtual RID texture_proxy_create(RID p_base) = 0; + + virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; //mostly used for video and streaming + virtual void texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; + virtual void texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap) = 0; + virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0; + + //these two APIs can be used together or in combination with the others. + virtual RID texture_2d_placeholder_create() = 0; + virtual RID texture_2d_layered_placeholder_create() = 0; + virtual RID texture_3d_placeholder_create() = 0; + + virtual Ref texture_2d_get(RID p_texture) const = 0; + virtual Ref texture_2d_layer_get(RID p_texture, int p_layer) const = 0; + virtual Ref texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const = 0; + + virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; + virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0; +#endif + + virtual void texture_set_path(RID p_texture, const String &p_path) = 0; + virtual String texture_get_path(RID p_texture) const = 0; + + typedef void (*TextureDetectCallback)(void *); + + virtual void texture_set_detect_3d_callback(RID p_texture, TextureDetectCallback p_callback, void *p_userdata) = 0; + virtual void texture_set_detect_normal_callback(RID p_texture, TextureDetectCallback p_callback, void *p_userdata) = 0; + + enum TextureDetectRoughnessChannel { + TEXTURE_DETECT_ROUGNHESS_R, + TEXTURE_DETECT_ROUGNHESS_G, + TEXTURE_DETECT_ROUGNHESS_B, + TEXTURE_DETECT_ROUGNHESS_A, + TEXTURE_DETECT_ROUGNHESS_GRAY, + }; + + typedef void (*TextureDetectRoughnessCallback)(void *, const String &, TextureDetectRoughnessChannel); + virtual void texture_set_detect_roughness_callback(RID p_texture, TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; + + struct TextureInfo { + RID texture; + uint32_t width; + uint32_t height; + uint32_t depth; + Image::Format format; + int bytes; + String path; + }; + + virtual void texture_debug_usage(List *r_info) = 0; + Array _texture_debug_usage_bind(); + + virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; + + /* SHADER API */ + + enum ShaderMode { + + SHADER_SPATIAL, + SHADER_CANVAS_ITEM, + SHADER_PARTICLES, + SHADER_SKY, + SHADER_MAX + }; + + virtual RID shader_create() = 0; + + virtual void shader_set_code(RID p_shader, const String &p_code) = 0; + virtual String shader_get_code(RID p_shader) const = 0; + virtual void shader_get_param_list(RID p_shader, List *p_param_list) const = 0; + Array _shader_get_param_list_bind(RID p_shader) const; + virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0; + + virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; + virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; + + /* COMMON MATERIAL API */ + + enum { + MATERIAL_RENDER_PRIORITY_MIN = -128, + MATERIAL_RENDER_PRIORITY_MAX = 127, + + }; + virtual RID material_create() = 0; + + virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; + + virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; + virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; + + virtual void material_set_render_priority(RID p_material, int priority) = 0; + + virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; + + /* MESH API */ + + enum ArrayType { + + ARRAY_VERTEX = 0, + ARRAY_NORMAL = 1, + ARRAY_TANGENT = 2, + ARRAY_COLOR = 3, + ARRAY_TEX_UV = 4, + ARRAY_TEX_UV2 = 5, + ARRAY_BONES = 6, + ARRAY_WEIGHTS = 7, + ARRAY_INDEX = 8, + ARRAY_MAX = 9 + }; + + enum ArrayFormat { + /* ARRAY FORMAT FLAGS */ + ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory + ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL, + ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT, + ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR, + ARRAY_FORMAT_TEX_UV = 1 << ARRAY_TEX_UV, + ARRAY_FORMAT_TEX_UV2 = 1 << ARRAY_TEX_UV2, + ARRAY_FORMAT_BONES = 1 << ARRAY_BONES, + ARRAY_FORMAT_WEIGHTS = 1 << ARRAY_WEIGHTS, + ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX, + + ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1), + ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE), + ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE), + + ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1, + ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3, + + ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 + + }; + + enum PrimitiveType { + PRIMITIVE_POINTS, + PRIMITIVE_LINES, + PRIMITIVE_LINE_STRIP, + PRIMITIVE_TRIANGLES, + PRIMITIVE_TRIANGLE_STRIP, + PRIMITIVE_MAX, + }; + + struct SurfaceData { + + PrimitiveType primitive = PRIMITIVE_MAX; + + uint32_t format = 0; + Vector vertex_data; + uint32_t vertex_count = 0; + Vector index_data; + uint32_t index_count = 0; + + AABB aabb; + struct LOD { + float edge_length; + Vector index_data; + }; + Vector lods; + Vector bone_aabbs; + + Vector> blend_shapes; + + RID material; + }; + + virtual RID mesh_create_from_surfaces(const Vector &p_surfaces) = 0; + virtual RID mesh_create() = 0; + + virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const; + virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const; + /// Returns stride + virtual uint32_t mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const; + virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT); + Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const; + Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const; + Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const; + Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const; + + virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT); + virtual void mesh_add_surface(RID p_mesh, const SurfaceData &p_surface) = 0; + + virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; + + enum BlendShapeMode { + BLEND_SHAPE_MODE_NORMALIZED, + BLEND_SHAPE_MODE_RELATIVE, + }; + + virtual void mesh_set_blend_shape_mode(RID p_mesh, BlendShapeMode p_mode) = 0; + virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; + + virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data) = 0; + + virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; + virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; + + virtual SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; + + virtual int mesh_get_surface_count(RID p_mesh) const = 0; + + virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; + virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; + + virtual void mesh_clear(RID p_mesh) = 0; + + /* MULTIMESH API */ + + virtual RID multimesh_create() = 0; + + enum MultimeshTransformFormat { + MULTIMESH_TRANSFORM_2D, + MULTIMESH_TRANSFORM_3D, + }; + + virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; + virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; + + virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; + virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; + virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; + virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; + virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; + + virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; + virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; + + virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; + virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; + virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; + + virtual void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) = 0; + virtual Vector multimesh_get_buffer(RID p_multimesh) const = 0; + + virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; + virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; + + /* IMMEDIATE API */ + + virtual RID immediate_create() = 0; + virtual void immediate_begin(RID p_immediate, PrimitiveType p_rimitive, RID p_texture = RID()) = 0; + virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; + virtual void immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex); + virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; + virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; + virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; + virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; + virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; + virtual void immediate_end(RID p_immediate) = 0; + virtual void immediate_clear(RID p_immediate) = 0; + virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; + virtual RID immediate_get_material(RID p_immediate) const = 0; + + /* SKELETON API */ + + virtual RID skeleton_create() = 0; + virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; + virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; + virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0; + virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; + virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; + virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; + + /* Light API */ + + enum LightType { + LIGHT_DIRECTIONAL, + LIGHT_OMNI, + LIGHT_SPOT + }; + + enum LightParam { + + LIGHT_PARAM_ENERGY, + LIGHT_PARAM_INDIRECT_ENERGY, + LIGHT_PARAM_SPECULAR, + LIGHT_PARAM_RANGE, + LIGHT_PARAM_ATTENUATION, + LIGHT_PARAM_SPOT_ANGLE, + LIGHT_PARAM_SPOT_ATTENUATION, + LIGHT_PARAM_CONTACT_SHADOW_SIZE, + LIGHT_PARAM_SHADOW_MAX_DISTANCE, + LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, + LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, + LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, + LIGHT_PARAM_SHADOW_FADE_START, + LIGHT_PARAM_SHADOW_NORMAL_BIAS, + LIGHT_PARAM_SHADOW_BIAS, + LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, + LIGHT_PARAM_MAX + }; + + virtual RID directional_light_create() = 0; + virtual RID omni_light_create() = 0; + virtual RID spot_light_create() = 0; + + virtual void light_set_color(RID p_light, const Color &p_color) = 0; + virtual void light_set_param(RID p_light, LightParam p_param, float p_value) = 0; + virtual void light_set_shadow(RID p_light, bool p_enabled) = 0; + virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0; + virtual void light_set_projector(RID p_light, RID p_texture) = 0; + virtual void light_set_negative(RID p_light, bool p_enable) = 0; + virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; + virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; + virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; + + // omni light + enum LightOmniShadowMode { + LIGHT_OMNI_SHADOW_DUAL_PARABOLOID, + LIGHT_OMNI_SHADOW_CUBE, + }; + + virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0; + + // directional light + enum LightDirectionalShadowMode { + LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, + LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, + LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS + }; + + virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; + virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; + + enum LightDirectionalShadowDepthRangeMode { + LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, + LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, + + }; + + virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0; + + /* PROBE API */ + + virtual RID reflection_probe_create() = 0; + + enum ReflectionProbeUpdateMode { + REFLECTION_PROBE_UPDATE_ONCE, + REFLECTION_PROBE_UPDATE_ALWAYS, + }; + + virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode) = 0; + virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; + virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_color) = 0; + virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0; + virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0; + virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; + virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; + virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; + virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0; + virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; + virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; + + /* GI PROBE API */ + + virtual RID gi_probe_create() = 0; + + virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; + + virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; + virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_octree_cells(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_data_cells(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_distance_field(RID p_gi_probe) const = 0; + virtual Vector gi_probe_get_level_counts(RID p_gi_probe) const = 0; + virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; + virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; + virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; + virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; + virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; + virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; + virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; + virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; + + virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; + virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; + + /* LIGHTMAP CAPTURE */ + + virtual RID lightmap_capture_create() = 0; + virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; + virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) = 0; + virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; + virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; + virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; + virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; + virtual Vector lightmap_capture_get_octree(RID p_capture) const = 0; + virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; + virtual float lightmap_capture_get_energy(RID p_capture) const = 0; + + /* PARTICLES API */ + + virtual RID particles_create() = 0; + + virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; + virtual bool particles_get_emitting(RID p_particles) = 0; + virtual void particles_set_amount(RID p_particles, int p_amount) = 0; + virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; + virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; + virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0; + virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0; + virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0; + virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; + virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0; + virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; + virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; + virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; + virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; + virtual bool particles_is_inactive(RID p_particles) = 0; + virtual void particles_request_process(RID p_particles) = 0; + virtual void particles_restart(RID p_particles) = 0; + + enum ParticlesDrawOrder { + PARTICLES_DRAW_ORDER_INDEX, + PARTICLES_DRAW_ORDER_LIFETIME, + PARTICLES_DRAW_ORDER_VIEW_DEPTH, + }; + + virtual void particles_set_draw_order(RID p_particles, ParticlesDrawOrder p_order) = 0; + + virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; + virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; + + virtual AABB particles_get_current_aabb(RID p_particles) = 0; + + virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; //this is only used for 2D, in 3D it's automatic + + /* CAMERA API */ + + virtual RID camera_create() = 0; + virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; + virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; + virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; + virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0; + virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; + virtual void camera_set_environment(RID p_camera, RID p_env) = 0; + virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0; + virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0; + + /* + enum ParticlesCollisionMode { + PARTICLES_COLLISION_NONE, + PARTICLES_COLLISION_TEXTURE, + PARTICLES_COLLISION_CUBEMAP, + }; + + virtual void particles_set_collision(RID p_particles,ParticlesCollisionMode p_mode,const Transform&, p_xform,const RID p_depth_tex,const RID p_normal_tex)=0; +*/ + /* VIEWPORT TARGET API */ + + virtual RID viewport_create() = 0; + + virtual void viewport_set_use_arvr(RID p_viewport, bool p_use_arvr) = 0; + virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0; + virtual void viewport_set_active(RID p_viewport, bool p_active) = 0; + virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; + + virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0; + virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0; + + enum ViewportUpdateMode { + VIEWPORT_UPDATE_DISABLED, + VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated + VIEWPORT_UPDATE_WHEN_VISIBLE, // default + VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE, + VIEWPORT_UPDATE_ALWAYS + }; + + virtual void viewport_set_update_mode(RID p_viewport, ViewportUpdateMode p_mode) = 0; + + enum ViewportClearMode { + + VIEWPORT_CLEAR_ALWAYS, + VIEWPORT_CLEAR_NEVER, + VIEWPORT_CLEAR_ONLY_NEXT_FRAME + }; + + virtual void viewport_set_clear_mode(RID p_viewport, ViewportClearMode p_clear_mode) = 0; + + virtual RID viewport_get_texture(RID p_viewport) const = 0; + + virtual void viewport_set_hide_scenario(RID p_viewport, bool p_hide) = 0; + virtual void viewport_set_hide_canvas(RID p_viewport, bool p_hide) = 0; + virtual void viewport_set_disable_environment(RID p_viewport, bool p_disable) = 0; + + virtual void viewport_attach_camera(RID p_viewport, RID p_camera) = 0; + virtual void viewport_set_scenario(RID p_viewport, RID p_scenario) = 0; + virtual void viewport_attach_canvas(RID p_viewport, RID p_canvas) = 0; + virtual void viewport_remove_canvas(RID p_viewport, RID p_canvas) = 0; + virtual void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) = 0; + virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0; + + virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0; + virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0; + + virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0; + virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0; + + enum ViewportMSAA { + VIEWPORT_MSAA_DISABLED, + VIEWPORT_MSAA_2X, + VIEWPORT_MSAA_4X, + VIEWPORT_MSAA_8X, + VIEWPORT_MSAA_16X, + VIEWPORT_MSAA_EXT_2X, + VIEWPORT_MSAA_EXT_4X, + }; + + virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0; + + enum ViewportRenderInfo { + + VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME, + VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME, + VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME, + VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME, + VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME, + VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME, + VIEWPORT_RENDER_INFO_MAX + }; + + virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) = 0; + + enum ViewportDebugDraw { + VIEWPORT_DEBUG_DRAW_DISABLED, + VIEWPORT_DEBUG_DRAW_UNSHADED, + VIEWPORT_DEBUG_DRAW_LIGHTING, + VIEWPORT_DEBUG_DRAW_OVERDRAW, + VIEWPORT_DEBUG_DRAW_WIREFRAME, + VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER, + VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO, + VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, + VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, + VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS, + VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, + VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE, + VIEWPORT_DEBUG_DRAW_SSAO, + VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER, + + }; + + virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0; + + virtual void directional_shadow_atlas_set_size(int p_size) = 0; + + /* SKY API */ + + enum SkyMode { + SKY_MODE_QUALITY, + SKY_MODE_REALTIME + }; + + virtual RID sky_create() = 0; + virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; + virtual void sky_set_mode(RID p_sky, SkyMode p_mode) = 0; + virtual void sky_set_material(RID p_sky, RID p_material) = 0; + + /* ENVIRONMENT API */ + + virtual RID environment_create() = 0; + + enum EnvironmentBG { + + ENV_BG_CLEAR_COLOR, + ENV_BG_COLOR, + ENV_BG_SKY, + ENV_BG_CANVAS, + ENV_BG_KEEP, + ENV_BG_CAMERA_FEED, + ENV_BG_MAX + }; + + enum EnvironmentAmbientSource { + ENV_AMBIENT_SOURCE_BG, + ENV_AMBIENT_SOURCE_DISABLED, + ENV_AMBIENT_SOURCE_COLOR, + ENV_AMBIENT_SOURCE_SKY, + }; + + enum EnvironmentReflectionSource { + ENV_REFLECTION_SOURCE_BG, + ENV_REFLECTION_SOURCE_DISABLED, + ENV_REFLECTION_SOURCE_SKY, + }; + + virtual void environment_set_background(RID p_env, EnvironmentBG p_bg) = 0; + virtual void environment_set_sky(RID p_env, RID p_sky) = 0; + virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; + virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; + virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; + virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; + virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; + virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; +// FIXME: Disabled during Vulkan refactoring, should be ported. +#if 0 + virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; +#endif + + enum EnvironmentGlowBlendMode { + ENV_GLOW_BLEND_MODE_ADDITIVE, + ENV_GLOW_BLEND_MODE_SCREEN, + ENV_GLOW_BLEND_MODE_SOFTLIGHT, + ENV_GLOW_BLEND_MODE_REPLACE, + ENV_GLOW_BLEND_MODE_MIX, + }; + virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; + + enum EnvironmentToneMapper { + ENV_TONE_MAPPER_LINEAR, + ENV_TONE_MAPPER_REINHARD, + ENV_TONE_MAPPER_FILMIC, + ENV_TONE_MAPPER_ACES + }; + + virtual void environment_set_tonemap(RID p_env, EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_grey) = 0; + virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; + + virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; + + enum EnvironmentSSAOBlur { + ENV_SSAO_BLUR_DISABLED, + ENV_SSAO_BLUR_1x1, + ENV_SSAO_BLUR_2x2, + ENV_SSAO_BLUR_3x3, + }; + + virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; + + enum EnvironmentSSAOQuality { + ENV_SSAO_QUALITY_LOW, + ENV_SSAO_QUALITY_MEDIUM, + ENV_SSAO_QUALITY_HIGH, + ENV_SSAO_QUALITY_ULTRA, + }; + + virtual void environment_set_ssao_quality(EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; + + virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; + virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; + virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; + + virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; + + /* CAMERA EFFECTS */ + + virtual RID camera_effects_create() = 0; + + enum DOFBlurQuality { + DOF_BLUR_QUALITY_VERY_LOW, + DOF_BLUR_QUALITY_LOW, + DOF_BLUR_QUALITY_MEDIUM, + DOF_BLUR_QUALITY_HIGH, + }; + + virtual void camera_effects_set_dof_blur_quality(DOFBlurQuality p_quality, bool p_use_jitter) = 0; + + enum DOFBokehShape { + DOF_BOKEH_BOX, + DOF_BOKEH_HEXAGON, + DOF_BOKEH_CIRCLE + }; + + virtual void camera_effects_set_dof_blur_bokeh_shape(DOFBokehShape p_shape) = 0; + + virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; + virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; + + /* SCENARIO API */ + + virtual RID scenario_create() = 0; + + enum ScenarioDebugMode { + SCENARIO_DEBUG_DISABLED, + SCENARIO_DEBUG_WIREFRAME, + SCENARIO_DEBUG_OVERDRAW, + SCENARIO_DEBUG_SHADELESS, + + }; + + virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0; + virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0; + virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0; + virtual void scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) = 0; + + /* INSTANCING API */ + + enum InstanceType { + + INSTANCE_NONE, + INSTANCE_MESH, + INSTANCE_MULTIMESH, + INSTANCE_IMMEDIATE, + INSTANCE_PARTICLES, + INSTANCE_LIGHT, + INSTANCE_REFLECTION_PROBE, + INSTANCE_GI_PROBE, + INSTANCE_LIGHTMAP_CAPTURE, + INSTANCE_MAX, + + INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES) + }; + + virtual RID instance_create2(RID p_base, RID p_scenario); + + virtual RID instance_create() = 0; + + virtual void instance_set_base(RID p_instance, RID p_base) = 0; + virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; + virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; + virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0; + virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; + virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; + virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; + virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; + + virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) = 0; + + virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0; + + virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0; + virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0; + + virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0; + + // don't use these in a game! + virtual Vector instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0; + virtual Vector instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0; + virtual Vector instances_cull_convex(const Vector &p_convex, RID p_scenario = RID()) const = 0; + + Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const; + Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; + Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const; + + enum InstanceFlags { + INSTANCE_FLAG_USE_BAKED_LIGHT, + INSTANCE_FLAG_USE_DYNAMIC_GI, + INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, + INSTANCE_FLAG_MAX + }; + + enum ShadowCastingSetting { + SHADOW_CASTING_SETTING_OFF, + SHADOW_CASTING_SETTING_ON, + SHADOW_CASTING_SETTING_DOUBLE_SIDED, + SHADOW_CASTING_SETTING_SHADOWS_ONLY, + }; + + virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0; + virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0; + virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0; + + virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0; + virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0; + + /* CANVAS (2D) */ + + virtual RID canvas_create() = 0; + virtual void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) = 0; + virtual void canvas_set_modulate(RID p_canvas, const Color &p_color) = 0; + virtual void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) = 0; + + virtual void canvas_set_disable_scale(bool p_disable) = 0; + + virtual RID canvas_item_create() = 0; + virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0; + + virtual void canvas_item_set_visible(RID p_item, bool p_visible) = 0; + virtual void canvas_item_set_light_mask(RID p_item, int p_mask) = 0; + + virtual void canvas_item_set_update_when_visible(RID p_item, bool p_update) = 0; + + virtual void canvas_item_set_transform(RID p_item, const Transform2D &p_transform) = 0; + virtual void canvas_item_set_clip(RID p_item, bool p_clip) = 0; + virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable) = 0; + virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()) = 0; + virtual void canvas_item_set_modulate(RID p_item, const Color &p_color) = 0; + virtual void canvas_item_set_self_modulate(RID p_item, const Color &p_color) = 0; + + virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) = 0; + + enum NinePatchAxisMode { + NINE_PATCH_STRETCH, + NINE_PATCH_TILE, + NINE_PATCH_TILE_FIT, + }; + + enum CanvasItemTextureFilter { + CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_FILTER_NEAREST, + CANVAS_ITEM_TEXTURE_FILTER_LINEAR, + CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, + CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, + CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, + CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, + CANVAS_ITEM_TEXTURE_FILTER_MAX + }; + + enum CanvasItemTextureRepeat { + CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item + CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, + CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, + CANVAS_ITEM_TEXTURE_REPEAT_MIRROR, + CANVAS_ITEM_TEXTURE_REPEAT_MAX, + }; + + //takes effect only for new draw commands + virtual void canvas_item_set_default_texture_filter(RID p_item, CanvasItemTextureFilter p_filter) = 0; + virtual void canvas_item_set_default_texture_repeat(RID p_item, CanvasItemTextureRepeat p_repeat) = 0; + + virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0) = 0; + virtual void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0) = 0; + virtual void canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0) = 0; + virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; + virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; + virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_primitive(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_polygon(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; + virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; + virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0; + virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0; + virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0; + virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0; + virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) = 0; + + virtual void canvas_item_attach_skeleton(RID p_item, RID p_skeleton) = 0; + + virtual void canvas_item_clear(RID p_item) = 0; + virtual void canvas_item_set_draw_index(RID p_item, int p_index) = 0; + + virtual void canvas_item_set_material(RID p_item, RID p_material) = 0; + + virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable) = 0; + + virtual RID canvas_light_create() = 0; + virtual void canvas_light_attach_to_canvas(RID p_light, RID p_canvas) = 0; + virtual void canvas_light_set_enabled(RID p_light, bool p_enabled) = 0; + virtual void canvas_light_set_scale(RID p_light, float p_scale) = 0; + virtual void canvas_light_set_transform(RID p_light, const Transform2D &p_transform) = 0; + virtual void canvas_light_set_texture(RID p_light, RID p_texture) = 0; + virtual void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) = 0; + virtual void canvas_light_set_color(RID p_light, const Color &p_color) = 0; + virtual void canvas_light_set_height(RID p_light, float p_height) = 0; + virtual void canvas_light_set_energy(RID p_light, float p_energy) = 0; + virtual void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) = 0; + virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) = 0; + virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask) = 0; + virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) = 0; + + enum CanvasLightMode { + CANVAS_LIGHT_MODE_ADD, + CANVAS_LIGHT_MODE_SUB, + CANVAS_LIGHT_MODE_MIX, + CANVAS_LIGHT_MODE_MASK, + }; + + virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) = 0; + + enum CanvasLightShadowFilter { + CANVAS_LIGHT_FILTER_NONE, + CANVAS_LIGHT_FILTER_PCF5, + CANVAS_LIGHT_FILTER_PCF13, + CANVAS_LIGHT_FILTER_MAX + }; + + virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0; + virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size) = 0; + virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter) = 0; + virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0; + virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0; + + virtual RID canvas_light_occluder_create() = 0; + virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0; + virtual void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) = 0; + virtual void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) = 0; + virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0; + virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0; + + virtual RID canvas_occluder_polygon_create() = 0; + virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector &p_shape, bool p_closed) = 0; + virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector &p_shape) = 0; + + enum CanvasOccluderPolygonCullMode { + CANVAS_OCCLUDER_POLYGON_CULL_DISABLED, + CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE, + CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE, + }; + virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, CanvasOccluderPolygonCullMode p_mode) = 0; + + /* BLACK BARS */ + + virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0; + virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) = 0; + + /* FREE */ + + virtual void free(RID p_rid) = 0; ///< free RIDs associated with the visual server + + virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) = 0; + + /* EVENT QUEUING */ + + virtual void draw(bool p_swap_buffers = true, double frame_step = 0.0) = 0; + virtual void sync() = 0; + virtual bool has_changed() const = 0; + virtual void init() = 0; + virtual void finish() = 0; + + /* STATUS INFORMATION */ + + enum RenderInfo { + + INFO_OBJECTS_IN_FRAME, + INFO_VERTICES_IN_FRAME, + INFO_MATERIAL_CHANGES_IN_FRAME, + INFO_SHADER_CHANGES_IN_FRAME, + INFO_SURFACE_CHANGES_IN_FRAME, + INFO_DRAW_CALLS_IN_FRAME, + INFO_USAGE_VIDEO_MEM_TOTAL, + INFO_VIDEO_MEM_USED, + INFO_TEXTURE_MEM_USED, + INFO_VERTEX_MEM_USED, + }; + + virtual int get_render_info(RenderInfo p_info) = 0; + virtual String get_video_adapter_name() const = 0; + virtual String get_video_adapter_vendor() const = 0; + + struct FrameProfileArea { + String name; + float gpu_msec; + float cpu_msec; + }; + + virtual void set_frame_profiling_enabled(bool p_enable) = 0; + virtual Vector get_frame_profile() = 0; + virtual uint64_t get_frame_profile_frame() = 0; + + /* Materials for 2D on 3D */ + + /* TESTING */ + + virtual RID get_test_cube() = 0; + + virtual RID get_test_texture(); + virtual RID get_white_texture(); + + virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius); + + virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data); + virtual void mesh_add_surface_from_planes(RID p_mesh, const Vector &p_planes); + + virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0; + virtual void set_default_clear_color(const Color &p_color) = 0; + + enum Features { + FEATURE_SHADERS, + FEATURE_MULTITHREADED, + }; + + virtual bool has_feature(Features p_feature) const = 0; + + virtual bool has_os_feature(const String &p_feature) const = 0; + + virtual void set_debug_generate_wireframes(bool p_generate) = 0; + + virtual void call_set_use_vsync(bool p_enable) = 0; + + virtual bool is_low_end() const = 0; + + RenderingServer(); + virtual ~RenderingServer(); +}; + +// make variant understand the enums +VARIANT_ENUM_CAST(RenderingServer::TextureLayeredType); +VARIANT_ENUM_CAST(RenderingServer::CubeMapLayer); +VARIANT_ENUM_CAST(RenderingServer::ShaderMode); +VARIANT_ENUM_CAST(RenderingServer::ArrayType); +VARIANT_ENUM_CAST(RenderingServer::ArrayFormat); +VARIANT_ENUM_CAST(RenderingServer::PrimitiveType); +VARIANT_ENUM_CAST(RenderingServer::BlendShapeMode); +VARIANT_ENUM_CAST(RenderingServer::MultimeshTransformFormat); +VARIANT_ENUM_CAST(RenderingServer::LightType); +VARIANT_ENUM_CAST(RenderingServer::LightParam); +VARIANT_ENUM_CAST(RenderingServer::LightOmniShadowMode); +VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowMode); +VARIANT_ENUM_CAST(RenderingServer::LightDirectionalShadowDepthRangeMode); +VARIANT_ENUM_CAST(RenderingServer::ReflectionProbeUpdateMode); +VARIANT_ENUM_CAST(RenderingServer::ParticlesDrawOrder); +VARIANT_ENUM_CAST(RenderingServer::ViewportUpdateMode); +VARIANT_ENUM_CAST(RenderingServer::ViewportClearMode); +VARIANT_ENUM_CAST(RenderingServer::ViewportMSAA); +VARIANT_ENUM_CAST(RenderingServer::ViewportRenderInfo); +VARIANT_ENUM_CAST(RenderingServer::ViewportDebugDraw); +VARIANT_ENUM_CAST(RenderingServer::SkyMode); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentBG); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentAmbientSource); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentReflectionSource); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentGlowBlendMode); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentToneMapper); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOQuality); +VARIANT_ENUM_CAST(RenderingServer::EnvironmentSSAOBlur); +VARIANT_ENUM_CAST(RenderingServer::DOFBlurQuality); +VARIANT_ENUM_CAST(RenderingServer::DOFBokehShape); +VARIANT_ENUM_CAST(RenderingServer::ScenarioDebugMode); +VARIANT_ENUM_CAST(RenderingServer::InstanceType); +VARIANT_ENUM_CAST(RenderingServer::InstanceFlags); +VARIANT_ENUM_CAST(RenderingServer::ShadowCastingSetting); +VARIANT_ENUM_CAST(RenderingServer::NinePatchAxisMode); +VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureFilter); +VARIANT_ENUM_CAST(RenderingServer::CanvasItemTextureRepeat); +VARIANT_ENUM_CAST(RenderingServer::CanvasLightMode); +VARIANT_ENUM_CAST(RenderingServer::CanvasLightShadowFilter); +VARIANT_ENUM_CAST(RenderingServer::CanvasOccluderPolygonCullMode); +VARIANT_ENUM_CAST(RenderingServer::RenderInfo); +VARIANT_ENUM_CAST(RenderingServer::Features); + +//typedef RenderingServer VS; // makes it easier to use +#define RS RenderingServer + +#endif diff --git a/servers/visual/SCsub b/servers/visual/SCsub deleted file mode 100644 index fca18bfea0..0000000000 --- a/servers/visual/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -env.add_source_files(env.servers_sources, "*.cpp") - -SConscript("rasterizer_rd/SCsub") diff --git a/servers/visual/rasterizer.cpp b/servers/visual/rasterizer.cpp deleted file mode 100644 index a3f93a3f8c..0000000000 --- a/servers/visual/rasterizer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************/ -/* rasterizer.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer.h" - -#include "core/os/os.h" -#include "core/print_string.h" - -Rasterizer *(*Rasterizer::_create_func)() = NULL; - -void RasterizerScene::InstanceDependency::instance_notify_changed(bool p_aabb, bool p_dependencies) { - for (Map::Element *E = instances.front(); E; E = E->next()) { - E->key()->dependency_changed(p_aabb, p_dependencies); - } -} -void RasterizerScene::InstanceDependency::instance_notify_deleted(RID p_deleted) { - for (Map::Element *E = instances.front(); E; E = E->next()) { - E->key()->dependency_deleted(p_deleted); - } - for (Map::Element *E = instances.front(); E; E = E->next()) { - E->key()->dependencies.erase(this); - } - - instances.clear(); -} - -RasterizerScene::InstanceDependency::~InstanceDependency() { -#ifdef DEBUG_ENABLED - if (instances.size()) { - WARN_PRINT("Leaked instance dependency: Bug - did not call instance_notify_deleted when freeing."); - for (Map::Element *E = instances.front(); E; E = E->next()) { - E->key()->dependencies.erase(this); - } - } -#endif -} - -Rasterizer *Rasterizer::create() { - - return _create_func(); -} - -RasterizerCanvas *RasterizerCanvas::singleton = NULL; - -RasterizerStorage *RasterizerStorage::base_singleton = NULL; - -RasterizerStorage::RasterizerStorage() { - - base_singleton = this; -} diff --git a/servers/visual/rasterizer.h b/servers/visual/rasterizer.h deleted file mode 100644 index d5d32c8d47..0000000000 --- a/servers/visual/rasterizer.h +++ /dev/null @@ -1,1307 +0,0 @@ -/*************************************************************************/ -/* rasterizer.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_H -#define RASTERIZER_H - -#include "core/math/camera_matrix.h" -#include "servers/visual_server.h" - -#include "core/pair.h" -#include "core/self_list.h" - -class RasterizerScene { - -public: - /* SHADOW ATLAS API */ - - virtual RID shadow_atlas_create() = 0; - virtual void shadow_atlas_set_size(RID p_atlas, int p_size) = 0; - virtual void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) = 0; - virtual bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) = 0; - - virtual void directional_shadow_atlas_set_size(int p_size) = 0; - virtual int get_directional_light_shadow_size(RID p_light_intance) = 0; - virtual void set_directional_shadow_count(int p_count) = 0; - - /* SKY API */ - - virtual RID sky_create() = 0; - virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; - virtual void sky_set_mode(RID p_sky, VS::SkyMode p_samples) = 0; - virtual void sky_set_material(RID p_sky, RID p_material) = 0; - - /* ENVIRONMENT API */ - - virtual RID environment_create() = 0; - - virtual void environment_set_background(RID p_env, VS::EnvironmentBG p_bg) = 0; - virtual void environment_set_sky(RID p_env, RID p_sky) = 0; - virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; - virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; - virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; - virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; - virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; -#endif - - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; - virtual void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) = 0; - - virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; - - virtual void environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; - - virtual void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) = 0; - - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; - - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; - virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; - virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; - - virtual bool is_environment(RID p_env) const = 0; - virtual VS::EnvironmentBG environment_get_background(RID p_env) const = 0; - virtual int environment_get_canvas_max_layer(RID p_env) const = 0; - - virtual RID camera_effects_create() = 0; - - virtual void camera_effects_set_dof_blur_quality(VS::DOFBlurQuality p_quality, bool p_use_jitter) = 0; - virtual void camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape p_shape) = 0; - - virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; - virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; - - struct InstanceBase; - - struct InstanceDependency { - - void instance_notify_changed(bool p_aabb, bool p_dependencies); - void instance_notify_deleted(RID p_deleted); - - ~InstanceDependency(); - - private: - friend struct InstanceBase; - Map instances; - }; - - struct InstanceBase { - - VS::InstanceType base_type; - RID base; - - RID skeleton; - RID material_override; - - RID instance_data; - - Transform transform; - - int depth_layer; - uint32_t layer_mask; - uint32_t instance_version; - - //RID sampled_light; - - Vector materials; - Vector light_instances; - Vector reflection_probe_instances; - Vector gi_probe_instances; - - Vector blend_values; - - VS::ShadowCastingSetting cast_shadows; - - //fit in 32 bits - bool mirror : 8; - bool receive_shadows : 8; - bool visible : 8; - bool baked_light : 2; //this flag is only to know if it actually did use baked light - bool dynamic_gi : 2; //this flag is only to know if it actually did use baked light - bool redraw_if_visible : 4; - - float depth; //used for sorting - - SelfList dependency_item; - - InstanceBase *lightmap_capture; - RID lightmap; - Vector lightmap_capture_data; //in a array (12 values) to avoid wasting space if unused. Alpha is unused, but needed to send to shader - - AABB aabb; - AABB transformed_aabb; - - virtual void dependency_deleted(RID p_dependency) = 0; - virtual void dependency_changed(bool p_aabb, bool p_dependencies) = 0; - - Set dependencies; - - void instance_increase_version() { - instance_version++; - } - - void update_dependency(InstanceDependency *p_dependency) { - dependencies.insert(p_dependency); - p_dependency->instances[this] = instance_version; - } - - void clean_up_dependencies() { - List::Element *>> to_clean_up; - for (Set::Element *E = dependencies.front(); E; E = E->next()) { - InstanceDependency *dep = E->get(); - Map::Element *F = dep->instances.find(this); - ERR_CONTINUE(!F); - if (F->get() != instance_version) { - Pair::Element *> p; - p.first = dep; - p.second = F; - to_clean_up.push_back(p); - } - } - - while (to_clean_up.size()) { - to_clean_up.front()->get().first->instances.erase(to_clean_up.front()->get().second); - to_clean_up.pop_front(); - } - } - - void clear_dependencies() { - for (Set::Element *E = dependencies.front(); E; E = E->next()) { - InstanceDependency *dep = E->get(); - dep->instances.erase(this); - } - dependencies.clear(); - } - - InstanceBase() : - dependency_item(this) { - - base_type = VS::INSTANCE_NONE; - cast_shadows = VS::SHADOW_CASTING_SETTING_ON; - receive_shadows = true; - visible = true; - depth_layer = 0; - layer_mask = 1; - instance_version = 0; - baked_light = false; - dynamic_gi = false; - redraw_if_visible = false; - lightmap_capture = NULL; - } - - virtual ~InstanceBase() { - clear_dependencies(); - } - }; - - virtual RID light_instance_create(RID p_light) = 0; - virtual void light_instance_set_transform(RID p_light_instance, const Transform &p_transform) = 0; - virtual void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0) = 0; - virtual void light_instance_mark_visible(RID p_light_instance) = 0; - virtual bool light_instances_can_render_shadow_cube() const { return true; } - - virtual RID reflection_atlas_create() = 0; - virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) = 0; - - virtual RID reflection_probe_instance_create(RID p_probe) = 0; - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) = 0; - virtual void reflection_probe_release_atlas_index(RID p_instance) = 0; - virtual bool reflection_probe_instance_needs_redraw(RID p_instance) = 0; - virtual bool reflection_probe_instance_has_reflection(RID p_instance) = 0; - virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) = 0; - virtual bool reflection_probe_instance_postprocess_step(RID p_instance) = 0; - - virtual RID gi_probe_instance_create(RID p_gi_probe) = 0; - virtual void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) = 0; - virtual bool gi_probe_needs_update(RID p_probe) const = 0; - virtual void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) = 0; - - virtual void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) = 0; - - virtual void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) = 0; - virtual void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; - - virtual void set_scene_pass(uint64_t p_pass) = 0; - virtual void set_time(double p_time, double p_step) = 0; - virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) = 0; - - virtual RID render_buffers_create() = 0; - virtual void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0; - - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; - virtual bool screen_space_roughness_limiter_is_active() const = 0; - - virtual bool free(RID p_rid) = 0; - - virtual void update() = 0; - virtual ~RasterizerScene() {} -}; - -class RasterizerStorage { - - Color default_clear_color; - -public: - /* TEXTURE API */ - - virtual RID texture_2d_create(const Ref &p_image) = 0; - virtual RID texture_2d_layered_create(const Vector> &p_layers, VS::TextureLayeredType p_layered_type) = 0; - virtual RID texture_3d_create(const Vector> &p_slices) = 0; //all slices, then all the mipmaps, must be coherent - virtual RID texture_proxy_create(RID p_base) = 0; //all slices, then all the mipmaps, must be coherent - - virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; //mostly used for video and streaming - virtual void texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap) = 0; - virtual void texture_proxy_update(RID p_proxy, RID p_base) = 0; - - //these two APIs can be used together or in combination with the others. - virtual RID texture_2d_placeholder_create() = 0; - virtual RID texture_2d_layered_placeholder_create() = 0; - virtual RID texture_3d_placeholder_create() = 0; - - virtual Ref texture_2d_get(RID p_texture) const = 0; - virtual Ref texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Ref texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const = 0; - - virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0; -#endif - - virtual void texture_set_path(RID p_texture, const String &p_path) = 0; - virtual String texture_get_path(RID p_texture) const = 0; - - virtual void texture_set_detect_3d_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_normal_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_roughness_callback(RID p_texture, VS::TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; - - virtual void texture_debug_usage(List *r_info) = 0; - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - - virtual Size2 texture_size_with_proxy(RID p_proxy) = 0; - - /* SHADER API */ - - virtual RID shader_create() = 0; - - virtual void shader_set_code(RID p_shader, const String &p_code) = 0; - virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List *p_param_list) const = 0; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; - virtual Variant shader_get_param_default(RID p_material, const StringName &p_param) const = 0; - - /* COMMON MATERIAL API */ - - virtual RID material_create() = 0; - - virtual void material_set_render_priority(RID p_material, int priority) = 0; - virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; - - virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; - virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; - - virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; - - virtual bool material_is_animated(RID p_material) = 0; - virtual bool material_casts_shadows(RID p_material) = 0; - - virtual void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) = 0; - - /* MESH API */ - - virtual RID mesh_create() = 0; - - /// Returns stride - virtual void mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface) = 0; - - virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) = 0; - virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data) = 0; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; - - virtual VS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; - - virtual int mesh_get_surface_count(RID p_mesh) const = 0; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; - virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()) = 0; - - virtual void mesh_clear(RID p_mesh) = 0; - - /* MULTIMESH API */ - - virtual RID multimesh_create() = 0; - - virtual void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; - - virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; - virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; - virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; - - virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; - virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - - virtual void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) = 0; - virtual Vector multimesh_get_buffer(RID p_multimesh) const = 0; - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; - virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; - - virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; - - /* IMMEDIATE API */ - - virtual RID immediate_create() = 0; - virtual void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID()) = 0; - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; - virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_end(RID p_immediate) = 0; - virtual void immediate_clear(RID p_immediate) = 0; - virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; - virtual RID immediate_get_material(RID p_immediate) const = 0; - virtual AABB immediate_get_aabb(RID p_immediate) const = 0; - - /* SKELETON API */ - - virtual RID skeleton_create() = 0; - virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; - virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; - virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0; - virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; - virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - - /* Light API */ - - virtual RID light_create(VS::LightType p_type) = 0; - - RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); } - RID omni_light_create() { return light_create(VS::LIGHT_OMNI); } - RID spot_light_create() { return light_create(VS::LIGHT_SPOT); } - - virtual void light_set_color(RID p_light, const Color &p_color) = 0; - virtual void light_set_param(RID p_light, VS::LightParam p_param, float p_value) = 0; - virtual void light_set_shadow(RID p_light, bool p_enabled) = 0; - virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0; - virtual void light_set_projector(RID p_light, RID p_texture) = 0; - virtual void light_set_negative(RID p_light, bool p_enable) = 0; - virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; - virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; - virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; - - virtual void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) = 0; - - virtual void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) = 0; - virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; - virtual bool light_directional_get_blend_splits(RID p_light) const = 0; - virtual void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) = 0; - virtual VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const = 0; - - virtual VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light) = 0; - virtual VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light) = 0; - - virtual bool light_has_shadow(RID p_light) const = 0; - - virtual VS::LightType light_get_type(RID p_light) const = 0; - virtual AABB light_get_aabb(RID p_light) const = 0; - virtual float light_get_param(RID p_light, VS::LightParam p_param) = 0; - virtual Color light_get_color(RID p_light) = 0; - virtual bool light_get_use_gi(RID p_light) = 0; - virtual uint64_t light_get_version(RID p_light) const = 0; - - /* PROBE API */ - - virtual RID reflection_probe_create() = 0; - - virtual void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) = 0; - virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; - virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; - virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) = 0; - virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0; - virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0; - virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; - virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; - virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; - - virtual AABB reflection_probe_get_aabb(RID p_probe) const = 0; - virtual VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const = 0; - virtual uint32_t reflection_probe_get_cull_mask(RID p_probe) const = 0; - virtual Vector3 reflection_probe_get_extents(RID p_probe) const = 0; - virtual Vector3 reflection_probe_get_origin_offset(RID p_probe) const = 0; - virtual float reflection_probe_get_origin_max_distance(RID p_probe) const = 0; - virtual bool reflection_probe_renders_shadows(RID p_probe) const = 0; - - virtual void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; - virtual void skeleton_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) = 0; - - /* GI PROBE API */ - - virtual RID gi_probe_create() = 0; - - virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; - - virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; - virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_octree_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_data_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_distance_field(RID p_gi_probe) const = 0; - - virtual Vector gi_probe_get_level_counts(RID p_gi_probe) const = 0; - virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; - virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; - virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; - virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; - - virtual uint32_t gi_probe_get_version(RID p_probe) = 0; - - /* LIGHTMAP CAPTURE */ - - struct LightmapCaptureOctree { - - enum { - CHILD_EMPTY = 0xFFFFFFFF - }; - - uint16_t light[6][3]; //anisotropic light - float alpha; - uint32_t children[8]; - }; - - virtual RID lightmap_capture_create() = 0; - virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; - virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) = 0; - virtual Vector lightmap_capture_get_octree(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; - virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; - virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; - virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; - virtual float lightmap_capture_get_energy(RID p_capture) const = 0; - virtual const Vector *lightmap_capture_get_octree_ptr(RID p_capture) const = 0; - - /* PARTICLES */ - - virtual RID particles_create() = 0; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; - virtual bool particles_get_emitting(RID p_particles) = 0; - - virtual void particles_set_amount(RID p_particles, int p_amount) = 0; - virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; - virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; - virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0; - virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0; - virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0; - virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; - virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0; - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; - virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; - virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; - virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; - virtual void particles_restart(RID p_particles) = 0; - - virtual bool particles_is_inactive(RID p_particles) const = 0; - - virtual void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) = 0; - - virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; - virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; - - virtual void particles_request_process(RID p_particles) = 0; - virtual AABB particles_get_current_aabb(RID p_particles) = 0; - virtual AABB particles_get_aabb(RID p_particles) const = 0; - - virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; - - virtual int particles_get_draw_passes(RID p_particles) const = 0; - virtual RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const = 0; - - /* RENDER TARGET */ - - enum RenderTargetFlags { - RENDER_TARGET_TRANSPARENT, - RENDER_TARGET_DIRECT_TO_SCREEN, - RENDER_TARGET_FLAG_MAX - }; - - virtual RID render_target_create() = 0; - virtual void render_target_set_position(RID p_render_target, int p_x, int p_y) = 0; - virtual void render_target_set_size(RID p_render_target, int p_width, int p_height) = 0; - virtual RID render_target_get_texture(RID p_render_target) = 0; - virtual void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) = 0; - virtual void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) = 0; - virtual bool render_target_was_used(RID p_render_target) = 0; - virtual void render_target_set_as_unused(RID p_render_target) = 0; - - virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color) = 0; - virtual bool render_target_is_clear_requested(RID p_render_target) = 0; - virtual Color render_target_get_clear_request_color(RID p_render_target) = 0; - virtual void render_target_disable_clear_request(RID p_render_target) = 0; - virtual void render_target_do_clear_request(RID p_render_target) = 0; - - virtual VS::InstanceType get_base_type(RID p_rid) const = 0; - virtual bool free(RID p_rid) = 0; - - virtual bool has_os_feature(const String &p_feature) const = 0; - - virtual void update_dirty_resources() = 0; - - virtual void set_debug_generate_wireframes(bool p_generate) = 0; - - virtual void render_info_begin_capture() = 0; - virtual void render_info_end_capture() = 0; - virtual int get_captured_render_info(VS::RenderInfo p_info) = 0; - - virtual int get_render_info(VS::RenderInfo p_info) = 0; - virtual String get_video_adapter_name() const = 0; - virtual String get_video_adapter_vendor() const = 0; - - static RasterizerStorage *base_singleton; - - void set_default_clear_color(const Color &p_color) { - default_clear_color = p_color; - } - - Color get_default_clear_color() const { - return default_clear_color; - } -#define TIMESTAMP_BEGIN() \ - { \ - if (VSG::storage->capturing_timestamps) VSG::storage->capture_timestamps_begin(); \ - } - -#define RENDER_TIMESTAMP(m_text) \ - { \ - if (VSG::storage->capturing_timestamps) VSG::storage->capture_timestamp(m_text); \ - } - - bool capturing_timestamps = false; - - virtual void capture_timestamps_begin() = 0; - virtual void capture_timestamp(const String &p_name) = 0; - virtual uint32_t get_captured_timestamps_count() const = 0; - virtual uint64_t get_captured_timestamps_frame() const = 0; - virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0; - virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0; - virtual String get_captured_timestamp_name(uint32_t p_index) const = 0; - - RasterizerStorage(); - virtual ~RasterizerStorage() {} -}; - -class RasterizerCanvas { -public: - static RasterizerCanvas *singleton; - - enum CanvasRectFlags { - - CANVAS_RECT_REGION = 1, - CANVAS_RECT_TILE = 2, - CANVAS_RECT_FLIP_H = 4, - CANVAS_RECT_FLIP_V = 8, - CANVAS_RECT_TRANSPOSE = 16, - CANVAS_RECT_CLIP_UV = 32 - }; - - struct Light { - - bool enabled; - Color color; - Transform2D xform; - float height; - float energy; - float scale; - int z_min; - int z_max; - int layer_min; - int layer_max; - int item_mask; - int item_shadow_mask; - VS::CanvasLightMode mode; - RID texture; - Vector2 texture_offset; - RID canvas; - bool use_shadow; - int shadow_buffer_size; - VS::CanvasLightShadowFilter shadow_filter; - Color shadow_color; - float shadow_smooth; - - //void *texture_cache; // implementation dependent - Rect2 rect_cache; - Transform2D xform_cache; - float radius_cache; //used for shadow far plane - //CameraMatrix shadow_matrix_cache; - - Transform2D light_shader_xform; - //Vector2 light_shader_pos; - - Light *shadows_next_ptr; - Light *filter_next_ptr; - Light *next_ptr; - Light *mask_next_ptr; - - RID light_internal; - uint64_t version; - - int32_t render_index_cache; - - Light() { - version = 0; - enabled = true; - color = Color(1, 1, 1); - shadow_color = Color(0, 0, 0, 0); - height = 0; - z_min = -1024; - z_max = 1024; - layer_min = 0; - layer_max = 0; - item_mask = 1; - scale = 1.0; - energy = 1.0; - item_shadow_mask = -1; - mode = VS::CANVAS_LIGHT_MODE_ADD; - // texture_cache = NULL; - next_ptr = NULL; - mask_next_ptr = NULL; - filter_next_ptr = NULL; - use_shadow = false; - shadow_buffer_size = 2048; - shadow_filter = VS::CANVAS_LIGHT_FILTER_NONE; - shadow_smooth = 0.0; - render_index_cache = -1; - } - }; - - typedef uint64_t TextureBindingID; - - virtual TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) = 0; - virtual void free_texture_binding(TextureBindingID p_binding) = 0; - - //easier wrap to avoid mistakes - - struct Item; - - struct TextureBinding { - - TextureBindingID binding_id; - - _FORCE_INLINE_ void create(VS::CanvasItemTextureFilter p_item_filter, VS::CanvasItemTextureRepeat p_item_repeat, RID p_texture, RID p_normalmap, RID p_specular, VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { - if (p_filter == VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - p_filter = p_item_filter; - } - if (p_repeat == VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - p_repeat = p_item_repeat; - } - if (p_texture != RID() || p_normalmap != RID() || p_specular != RID() || p_filter != VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT || p_repeat != VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT || p_multimesh.is_valid()) { - ERR_FAIL_COND(binding_id != 0); - binding_id = singleton->request_texture_binding(p_texture, p_normalmap, p_specular, p_filter, p_repeat, p_multimesh); - } - } - - _FORCE_INLINE_ TextureBinding() { binding_id = 0; } - _FORCE_INLINE_ ~TextureBinding() { - if (binding_id) singleton->free_texture_binding(binding_id); - } - }; - - typedef uint64_t PolygonID; - virtual PolygonID request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()) = 0; - virtual void free_polygon(PolygonID p_polygon) = 0; - - //also easier to wrap to avoid mistakes - struct Polygon { - - PolygonID polygon_id; - Rect2 rect_cache; - - _FORCE_INLINE_ void create(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()) { - ERR_FAIL_COND(polygon_id != 0); - { - uint32_t pc = p_points.size(); - const Vector2 *v2 = p_points.ptr(); - rect_cache.position = *v2; - for (uint32_t i = 1; i < pc; i++) { - rect_cache.expand_to(v2[i]); - } - } - polygon_id = singleton->request_polygon(p_indices, p_points, p_colors, p_uvs, p_bones, p_weights); - } - - _FORCE_INLINE_ Polygon() { polygon_id = 0; } - _FORCE_INLINE_ ~Polygon() { - if (polygon_id) singleton->free_polygon(polygon_id); - } - }; - - //item - - struct Item { - - //commands are allocated in blocks of 4k to improve performance - //and cache coherence. - //blocks always grow but never shrink. - - struct CommandBlock { - enum { - MAX_SIZE = 4096 - }; - uint32_t usage; - uint8_t *memory; - }; - - struct Command { - - enum Type { - - TYPE_RECT, - TYPE_NINEPATCH, - TYPE_POLYGON, - TYPE_PRIMITIVE, - TYPE_MESH, - TYPE_MULTIMESH, - TYPE_PARTICLES, - TYPE_TRANSFORM, - TYPE_CLIP_IGNORE, - }; - - Command *next; - Type type; - virtual ~Command() {} - }; - - struct CommandRect : public Command { - - Rect2 rect; - Color modulate; - Rect2 source; - uint8_t flags; - Color specular_shininess; - - TextureBinding texture_binding; - - CommandRect() { - flags = 0; - type = TYPE_RECT; - } - }; - - struct CommandNinePatch : public Command { - - Rect2 rect; - Rect2 source; - float margin[4]; - bool draw_center; - Color color; - VS::NinePatchAxisMode axis_x; - VS::NinePatchAxisMode axis_y; - Color specular_shininess; - TextureBinding texture_binding; - CommandNinePatch() { - draw_center = true; - type = TYPE_NINEPATCH; - } - }; - - struct CommandPolygon : public Command { - - VS::PrimitiveType primitive; - Polygon polygon; - Color specular_shininess; - TextureBinding texture_binding; - CommandPolygon() { - type = TYPE_POLYGON; - } - }; - - struct CommandPrimitive : public Command { - - uint32_t point_count; - Vector2 points[4]; - Vector2 uvs[4]; - Color colors[4]; - Color specular_shininess; - TextureBinding texture_binding; - CommandPrimitive() { - type = TYPE_PRIMITIVE; - } - }; - - struct CommandMesh : public Command { - - RID mesh; - Transform2D transform; - Color modulate; - Color specular_shininess; - TextureBinding texture_binding; - CommandMesh() { type = TYPE_MESH; } - }; - - struct CommandMultiMesh : public Command { - - RID multimesh; - Color specular_shininess; - TextureBinding texture_binding; - CommandMultiMesh() { type = TYPE_MULTIMESH; } - }; - - struct CommandParticles : public Command { - - RID particles; - Color specular_shininess; - TextureBinding texture_binding; - CommandParticles() { type = TYPE_PARTICLES; } - }; - - struct CommandTransform : public Command { - - Transform2D xform; - CommandTransform() { type = TYPE_TRANSFORM; } - }; - - struct CommandClipIgnore : public Command { - - bool ignore; - CommandClipIgnore() { - type = TYPE_CLIP_IGNORE; - ignore = false; - } - }; - - struct ViewportRender { - VisualServer *owner; - void *udata; - Rect2 rect; - }; - - Transform2D xform; - bool clip; - bool visible; - bool behind; - bool update_when_visible; - //VS::MaterialBlendMode blend_mode; - int light_mask; - int z_final; - - mutable bool custom_rect; - mutable bool rect_dirty; - mutable Rect2 rect; - RID material; - RID skeleton; - - Item *next; - - struct CopyBackBuffer { - Rect2 rect; - Rect2 screen_rect; - bool full; - }; - CopyBackBuffer *copy_back_buffer; - - Color final_modulate; - Transform2D final_transform; - Rect2 final_clip_rect; - Item *final_clip_owner; - Item *material_owner; - ViewportRender *vp_render; - bool distance_field; - bool light_masked; - - Rect2 global_rect_cache; - - const Rect2 &get_rect() const { - if (custom_rect || (!rect_dirty && !update_when_visible)) - return rect; - - //must update rect - - if (commands == NULL) { - - rect = Rect2(); - rect_dirty = false; - return rect; - } - - Transform2D xf; - bool found_xform = false; - bool first = true; - - const Item::Command *c = commands; - - while (c) { - - Rect2 r; - - switch (c->type) { - case Item::Command::TYPE_RECT: { - - const Item::CommandRect *crect = static_cast(c); - r = crect->rect; - - } break; - case Item::Command::TYPE_NINEPATCH: { - - const Item::CommandNinePatch *style = static_cast(c); - r = style->rect; - } break; - - case Item::Command::TYPE_POLYGON: { - - const Item::CommandPolygon *polygon = static_cast(c); - r = polygon->polygon.rect_cache; - } break; - case Item::Command::TYPE_PRIMITIVE: { - - const Item::CommandPrimitive *primitive = static_cast(c); - for (uint32_t j = 0; j < primitive->point_count; j++) { - if (j == 0) { - r.position = primitive->points[0]; - } else { - r.expand_to(primitive->points[j]); - } - } - } break; - case Item::Command::TYPE_MESH: { - - const Item::CommandMesh *mesh = static_cast(c); - AABB aabb = RasterizerStorage::base_singleton->mesh_get_aabb(mesh->mesh, RID()); - - r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); - - } break; - case Item::Command::TYPE_MULTIMESH: { - - const Item::CommandMultiMesh *multimesh = static_cast(c); - AABB aabb = RasterizerStorage::base_singleton->multimesh_get_aabb(multimesh->multimesh); - - r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); - - } break; - case Item::Command::TYPE_PARTICLES: { - - const Item::CommandParticles *particles_cmd = static_cast(c); - if (particles_cmd->particles.is_valid()) { - AABB aabb = RasterizerStorage::base_singleton->particles_get_aabb(particles_cmd->particles); - r = Rect2(aabb.position.x, aabb.position.y, aabb.size.x, aabb.size.y); - } - - } break; - case Item::Command::TYPE_TRANSFORM: { - - const Item::CommandTransform *transform = static_cast(c); - xf = transform->xform; - found_xform = true; - [[fallthrough]]; - } - default: { - c = c->next; - continue; - } - } - - if (found_xform) { - r = xf.xform(r); - found_xform = false; - } - - if (first) { - rect = r; - first = false; - } else { - rect = rect.merge(r); - } - c = c->next; - } - - rect_dirty = false; - return rect; - } - - Command *commands; - Command *last_command; - Vector blocks; - uint32_t current_block; - - template - T *alloc_command() { - T *command; - if (commands == NULL) { - // As the most common use case of canvas items is to - // use only one command, the first is done with it's - // own allocation. The rest of them use blocks. - command = memnew(T); - command->next = NULL; - commands = command; - last_command = command; - } else { - //Subsequent commands go into a block. - - while (true) { - if (unlikely(current_block == (uint32_t)blocks.size())) { - // If we need more blocks, we allocate them - // (they won't be freed until this CanvasItem is - // deleted, though). - CommandBlock cb; - cb.memory = (uint8_t *)memalloc(CommandBlock::MAX_SIZE); - cb.usage = 0; - blocks.push_back(cb); - } - - CommandBlock *c = &blocks.write[current_block]; - size_t space_left = CommandBlock::MAX_SIZE - c->usage; - if (space_left < sizeof(T)) { - current_block++; - continue; - } - - //allocate block and add to the linked list - void *memory = c->memory + c->usage; - command = memnew_placement(memory, T); - command->next = NULL; - last_command->next = command; - last_command = command; - c->usage += sizeof(T); - break; - } - } - - rect_dirty = true; - return command; - } - - struct CustomData { - - virtual ~CustomData() {} - }; - - mutable CustomData *custom_data; //implementation dependent - - void clear() { - Command *c = commands; - while (c) { - Command *n = c->next; - if (c == commands) { - memdelete(commands); - commands = NULL; - } else { - c->~Command(); - } - c = n; - } - { - uint32_t cbc = MIN((current_block + 1), (uint32_t)blocks.size()); - CommandBlock *blockptr = blocks.ptrw(); - for (uint32_t i = 0; i < cbc; i++) { - blockptr[i].usage = 0; - } - } - - last_command = NULL; - commands = NULL; - current_block = 0; - clip = false; - rect_dirty = true; - final_clip_owner = NULL; - material_owner = NULL; - light_masked = false; - } - Item() { - commands = NULL; - last_command = NULL; - current_block = 0; - light_mask = 1; - vp_render = NULL; - next = NULL; - final_clip_owner = NULL; - clip = false; - final_modulate = Color(1, 1, 1, 1); - visible = true; - rect_dirty = true; - custom_rect = false; - behind = false; - material_owner = NULL; - copy_back_buffer = NULL; - distance_field = false; - light_masked = false; - update_when_visible = false; - z_final = 0; - custom_data = NULL; - } - virtual ~Item() { - clear(); - for (int i = 0; i < blocks.size(); i++) { - memfree(blocks[i].memory); - } - if (copy_back_buffer) memdelete(copy_back_buffer); - if (custom_data) { - memdelete(custom_data); - } - } - }; - - virtual void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) = 0; - virtual void canvas_debug_viewport_shadows(Light *p_lights_with_shadow) = 0; - - struct LightOccluderInstance { - - bool enabled; - RID canvas; - RID polygon; - RID occluder; - Rect2 aabb_cache; - Transform2D xform; - Transform2D xform_cache; - int light_mask; - VS::CanvasOccluderPolygonCullMode cull_cache; - - LightOccluderInstance *next; - - LightOccluderInstance() { - enabled = true; - next = NULL; - light_mask = 1; - cull_cache = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; - } - }; - - virtual RID light_create() = 0; - virtual void light_set_texture(RID p_rid, RID p_texture) = 0; - virtual void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) = 0; - virtual void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) = 0; - - virtual RID occluder_polygon_create() = 0; - virtual void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines) = 0; - virtual void occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode) = 0; - - virtual void draw_window_margins(int *p_margins, RID *p_margin_textures) = 0; - - virtual bool free(RID p_rid) = 0; - virtual void update() = 0; - - RasterizerCanvas() { singleton = this; } - virtual ~RasterizerCanvas() {} -}; - -class Rasterizer { -protected: - static Rasterizer *(*_create_func)(); - -public: - static Rasterizer *create(); - - virtual RasterizerStorage *get_storage() = 0; - virtual RasterizerCanvas *get_canvas() = 0; - virtual RasterizerScene *get_scene() = 0; - - virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0; - - virtual void initialize() = 0; - virtual void begin_frame(double frame_step) = 0; - - struct BlitToScreen { - RID render_target; - Rect2i rect; - //lens distorted parameters for VR should go here - }; - - virtual void prepare_for_blitting_render_targets() = 0; - virtual void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) = 0; - - virtual void end_frame(bool p_swap_buffers) = 0; - virtual void finalize() = 0; - - virtual bool is_low_end() const = 0; - - virtual ~Rasterizer() {} -}; - -#endif // RASTERIZER_H diff --git a/servers/visual/rasterizer_rd/SCsub b/servers/visual/rasterizer_rd/SCsub deleted file mode 100644 index cc17feeb05..0000000000 --- a/servers/visual/rasterizer_rd/SCsub +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -env.add_source_files(env.servers_sources, "*.cpp") - -SConscript("shaders/SCsub") diff --git a/servers/visual/rasterizer_rd/cubemap_coeffs.h b/servers/visual/rasterizer_rd/cubemap_coeffs.h deleted file mode 100644 index 1db03ce7c4..0000000000 --- a/servers/visual/rasterizer_rd/cubemap_coeffs.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2016 Activision Publishing, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef CUBEMAP_COEFFS_H -#define CUBEMAP_COEFFS_H - -const float low_quality_coeffs[7][5][6][4] = { { { { 0.0002037563, 0.0045063655, -0.0016408688, 0.00012037493 }, { -9.1834951e-05, -0.008947532, -8.1524405e-05, -3.9080094e-05 }, { -2.6038267e-05, -6.8409667e-05, 7.2175702e-05, 0.25492775 }, { -9.9426044e-05, 0.0025427756, -0.00074437925, 1.1773191e-05 }, { -3.2668211e-05, 0.0026930659, -4.824934e-05, -0.0006835048 }, { -0.0002864144, -0.0032220854, 0.0021558286, -0.00014573736 } }, { { 0.00030683201, 0.0026819548, -0.00060011756, -0.0067169226 }, { -0.0030993251, 0.0098575575, 0.0022416671, -8.9075401e-05 }, { 0.00052405626, 0.00057860515, 0.00011654518, -0.048018609 }, { 0.00010850967, -0.0088443512, -0.0018168095, 8.6633128e-05 }, { 0.003333989, -0.0050956447, -8.0414612e-05, 0.0049721239 }, { -4.0961436e-05, -8.5486984e-05, 0.0058683066, 2.2978359e-05 } }, { { 0.99999993, 0.99998625, 0.99999847, 0.99997743 }, { 0.99999519, 0.99991138, 0.99999748, 1 }, { 0.99999986, 0.99999983, 0.99999999, 0.96576708 }, { 0.99999999, 0.99995765, 0.99999807, 1 }, { 0.99999444, 0.99998339, 1, 0.99998741 }, { 0.99999996, 0.99999481, 0.99998046, 0.99999999 } }, { { -0.32267524, -0.65409377, -1.4666488, 0.87153305 }, { -1.264365, 0.89880861, -1.2245906, -0.88501403 }, { -0.31118682, -0.086150323, -0.58811532, 1.1317711 }, { -1.2193493, 1.250379, -1.0871569, -0.12694096 }, { -0.4012249, -0.47436307, -0.59661001, 2.7313005 }, { -1.3109856, 0.60929855, 0.55672643, -0.39880018 } }, { { 0.93273157, 0.59530745, 1.1994788, 0.19102276 }, { 1.2272239, 0.23245736, 1.2577607, 2.5491008 }, { 1.1210098, 0.83074953, 1.3049282, -0.001940633 }, { 1.5839111, 0.10520816, 1.150458, 2.3251789 }, { 0.688692, 0.59807498, 1.3374877, 0.095746692 }, { 1.3054173, 0.36604721, 0.065870226, 1.6496907 } } }, { { { 0.10348445, -4.6771514e-07, -0.011513131, 8.8921052e-05 }, { -0.042152043, 0.013143535, 0.00029120107, 0.036661611 }, { -0.04516036, 0.011438473, -0.0099289792, -0.011707897 }, { -0.034779497, 0.0090981166, -5.4202726e-05, 0.038592793 }, { -0.0071967376, -0.0056614418, -0.012278945, 0.0056867462 }, { -0.037678514, 0.011570177, 0.00029044557, 0.038583909 } }, { { 0.048320869, 1.4603673e-05, 0.0092672368, 0.00033289199 }, { 0.0071001761, -0.0090106091, -0.0027305905, -0.00221479 }, { -0.0027204116, 0.00017921587, 0.015296357, -0.00010306185 }, { 0.0079350203, -0.014772431, -1.2410913e-05, -0.0062296897 }, { 0.025087691, 0.00086046427, 0.015034685, -0.00078224706 }, { 0.00074587265, -0.014602074, 0.00027338224, -0.012848552 } }, { { 0.99345662, 1, 0.99989078, 0.99999994 }, { 0.99908598, 0.99987302, 0.99999623, 0.99932528 }, { 0.99897605, 0.99993456, 0.9998337, 0.99993145 }, { 0.99936351, 0.99984949, 1, 0.9992356 }, { 0.99965935, 0.9999836, 0.99981158, 0.99998352 }, { 0.99928963, 0.99982644, 0.99999992, 0.99917276 } }, { { 3.6882765, 0.15963861, 0.55983965, 0.4075649 }, { 2.1169304, 0.56463157, 0.52957047, 2.0117964 }, { 3.1080461, 0.09682931, 0.42125986, 0.089254784 }, { 1.4247315, 0.48411378, -0.17039102, 1.7431674 }, { 4.0339531, 0.14046159, 0.89848909, 0.011661811 }, { 1.9787852, 0.61750145, 0.63514194, 1.9359003 } }, { { 0.030848793, 1.4472743, 1.4356825, 1.4078009 }, { 0.37639678, 1.0793106, 1.1945413, 0.43983395 }, { 0.27451605, 1.5256415, 1.016769, 1.4850575 }, { 0.54580883, 1.1332879, 3.1331784, 0.60772955 }, { 0.11785158, 1.3928946, 0.94998805, 1.0377182 }, { 0.2842108, 1.0026911, 1.9064553, 0.27147854 } } }, { { { -0.096789259, 0.10326967, 0.0011799959, -0.03077328 }, { 0.08342021, 0.033260738, -0.00045864451, -0.021450568 }, { -0.093369441, -0.05807574, -0.033745214, 0.023817208 }, { 0.056747754, 0.031140512, 0.00019362509, -0.023727797 }, { -0.084538386, -0.040545412, -0.0076838784, 0.03424599 }, { 0.074312056, 0.027619787, 0.0015509082, -0.031043528 } }, { { -0.0085160473, -0.012179292, 0.0049910118, 0.020224799 }, { 0.022559343, -0.016273333, -0.0069382139, 0.00058083224 }, { -0.001115062, 0.035002846, -0.0038974773, -0.039378629 }, { 0.0014921617, -0.00058523872, -0.0011606685, 0.02807528 }, { -0.021454809, 0.052957852, -0.0022083677, -0.027956663 }, { -0.016486487, -0.0040233682, 0.00029949558, 0.021924605 } }, { { 0.99526846, 0.99457883, 0.99998685, 0.99932175 }, { 0.99625908, 0.99931422, 0.99997583, 0.99976974 }, { 0.99563091, 0.99769836, 0.99942287, 0.99894047 }, { 0.99838743, 0.99951485, 0.99999931, 0.99932416 }, { 0.99618922, 0.99777329, 0.99996804, 0.99902234 }, { 0.99709875, 0.9996104, 0.99999875, 0.99927754 } }, { { 3.0342011, 4.8022834, 1.3814123, 1.5280754 }, { 2.9043837, 1.7325954, 1.422223, 2.0569263 }, { 3.0358722, 5.3331504, 1.5680146, 1.6079289 }, { 3.2062833, 1.5368069, 1.0484709, 1.5399477 }, { 2.4471653, 4.0916696, 1.5060688, 1.5807009 }, { 2.6932695, 1.5161537, 1.3991175, 1.6301918 } }, { { 0.50787578, 0.17735471, 1.4006765, 1.0878482 }, { 0.69514518, 1.6765187, 1.2224869, 1.3461327 }, { 0.71381288, 0.17509216, 1.2712934, 0.94575821 }, { 1.1817337, 1.796984, 1.8671538, 1.5708691 }, { 0.55621228, 0.38291359, 1.4128781, 0.82625349 }, { 0.72441647, 1.005794, 1.5522327, 1.6032524 } } }, { { { -0.00041301094, -0.095882618, 0.26932618, -0.25137214 }, { 0.13737415, -0.12694293, -0.0090389663, 0.07227623 }, { -0.005236407, -0.0072961249, 0.27776083, -0.19536433 }, { 0.12781899, -0.042881667, -0.095979169, 0.088937396 }, { 0.037496084, -0.090547583, 0.22112334, -0.21930294 }, { 0.13353408, -0.084346121, -0.011365728, 0.043459312 } }, { { -0.05799135, -0.048612281, 0.02422989, 0.015536268 }, { -0.083144241, 0.039381032, 0.018705957, 0.029297922 }, { 0.026364989, -0.041927591, 0.036718516, 0.0050376168 }, { -0.11562256, 0.043521976, -0.014481644, 0.01529188 }, { -0.047859898, -0.057779647, -0.053171395, -0.0063193506 }, { -0.028781196, 0.041145059, -0.00018523142, 0.053524246 } }, { { 0.998317, 0.99420489, 0.96274416, 0.96776581 }, { 0.98702349, 0.99112796, 0.99978417, 0.99695425 }, { 0.99963867, 0.99909401, 0.95994827, 0.9807178 }, { 0.98503489, 0.99813175, 0.99527799, 0.99591983 }, { 0.99815003, 0.99421459, 0.97379529, 0.97563635 }, { 0.99062621, 0.99558667, 0.99993539, 0.99762039 } }, { { 2.3221943, 2.5383575, 4.3177232, 4.2016467 }, { 3.1936529, 3.0443024, 2.548962, 2.7636456 }, { 2.5923827, 2.3497949, 4.2471014, 4.1975975 }, { 3.3748785, 3.2836577, 2.9220414, 2.7175317 }, { 2.3290083, 2.5560991, 4.3572168, 4.4372585 }, { 3.1512055, 3.2863613, 2.4475378, 2.3620003 } }, { { 0.62833231, 0.52378061, 0.55845033, 0.64883444 }, { 0.76905594, 1.1017801, 1.8714048, 1.5664383 }, { 1.5283278, 1.2423369, 0.62247385, 1.0341956 }, { 0.77484548, 1.6866409, 1.0307399, 1.4224643 }, { 0.85627405, 0.72516079, 0.70094339, 0.7547877 }, { 1.202842, 1.7650605, 1.5938526, 0.97031337 } } }, { { { -0.078108035, -0.049518839, 0.26950139, -0.51522828 }, { 0.43015518, -0.045354216, 0.094550359, -0.2395012 }, { -0.079900522, -0.082582235, 0.24464909, -0.5234896 }, { 0.38422945, -0.023833644, 0.07334288, -0.22827313 }, { -0.075370379, -0.05156594, 0.19883182, -0.45064193 }, { 0.46285395, 0.021899343, 0.10155287, -0.25974773 } }, { { 0.068681419, -0.32175988, 0.15143274, -0.0066205388 }, { -0.17060226, 0.31051319, -0.080511981, -0.1593209 }, { 0.08167251, -0.32517768, 0.10937023, -0.06941926 }, { -0.14580685, 0.32474959, -0.081718057, -0.11068378 }, { 0.053961394, -0.29322836, 0.10408839, -0.02243046 }, { -0.030598471, 0.34332821, -0.091528353, -0.16299796 } }, { { 0.99457629, 0.9455255, 0.95101899, 0.85702741 }, { 0.88648824, 0.94948647, 0.99225906, 0.95773484 }, { 0.99345131, 0.94204015, 0.96342357, 0.84919939 }, { 0.9116513, 0.94549969, 0.99395321, 0.96728511 }, { 0.99569447, 0.95465076, 0.97449039, 0.89242295 }, { 0.88590629, 0.93896015, 0.99061071, 0.95182077 } }, { { 3.6380949, 4.1749529, 4.1351439, 4.8389883 }, { 5.256362, 4.2027959, 3.6096892, 3.9848645 }, { 3.5689427, 3.8620869, 4.0023981, 4.8268584 }, { 5.1128497, 4.468934, 3.5851596, 4.047485 }, { 3.7014988, 4.1310058, 4.2446872, 5.3049323 }, { 4.8659881, 4.3133002, 3.4582876, 3.8863853 } }, { { 1.6276316, 0.7747672, 1.0485958, 0.73900224 }, { 0.72010795, 0.65403093, 1.3179681, 0.65610074 }, { 1.5881174, 0.55108527, 1.0509725, 0.72153362 }, { 1.1389053, 1.0905142, 1.6661598, 0.9987548 }, { 1.977914, 0.83001686, 1.0571479, 0.80249183 }, { 0.94107069, 0.80840873, 0.95379751, 0.50386367 } } }, { { { 0.015525428, -0.48038019, -0.021799698, 0.43629156 }, { 0.045681247, -0.55039024, -0.54573329, 0.57817853 }, { -0.045869129, -0.42209953, -0.14040829, 0.37787106 }, { 0.66327604, -0.70070311, -0.55261635, 0.63446196 }, { 0.015397585, -0.43515767, -0.021927897, 0.4203714 }, { 0.85681772, -0.65394729, -0.67557236, 0.60104142 } }, { { -0.31503888, -0.26745648, 0.26817896, 0.26548747 }, { -0.93282124, -0.033621213, 0.68374802, -0.10858524 }, { -0.21723689, -0.17935495, 0.38521982, 0.2578335 }, { -0.39913153, 0.23555359, 0.59589456, -0.19075103 }, { -0.28851798, -0.24142459, 0.28279261, 0.24766617 }, { -0.29435977, -0.25850549, 0.57790878, -0.200546 } }, { { 0.94895177, 0.83528552, 0.96312243, 0.85974768 }, { 0.35743218, 0.8342303, 0.48442112, 0.80865248 }, { 0.97504059, 0.88863029, 0.9120807, 0.88923301 }, { 0.63305523, 0.67344611, 0.58268761, 0.74904744 }, { 0.95735066, 0.86738225, 0.9589304, 0.87289711 }, { 0.42333878, 0.71100482, 0.45784651, 0.77364753 } }, { { 5.3641275, 5.2550422, 5.3103777, 5.2851215 }, { 5.2657045, 6.2095784, 6.9549598, 4.9205516 }, { 5.163385, 5.3141038, 4.9907618, 5.3583852 }, { 6.1257061, 6.1102338, 6.9549598, 5.3129951 }, { 5.3138838, 5.3257842, 5.3133783, 5.2687156 }, { 5.8915091, 6.153324, 6.9549598, 4.9568971 } }, { { 3.1221918, 1.1882615, 2.6991784, 1.1185048 }, { -0.2322432, -0.16590163, 0.088416958, 0.057399579 }, { 3.4395383, 1.5836276, 2.6242352, 1.2873336 }, { -0.23767634, -0.79425452, 0.20477899, 0.40461516 }, { 2.2521751, 1.1933374, 2.3309484, 1.0185309 }, { -0.099258385, -0.2173726, 0.0736866, 0.15470436 } } }, { { { 0.066050217, -0.33053278, -0.13771479, 0.33278465 }, { 0.00084467977, -0.50077778, -0.30083482, 0.6494273 }, { 0.24880159, -0.30354993, -0.15417892, 0.38203296 }, { -0.073325098, -0.4778777, 0.10779844, 0.66683723 }, { 0.15703809, -0.36335455, -0.15657631, 0.35926503 }, { 0.26127617, -0.29524368, -0.14490804, 0.65461301 } }, { { -0.57970022, -0.33939622, 0.72169742, 0.320959 }, { -0.38698206, -0.12730306, 0.65810895, 0.026509232 }, { -0.6199708, -0.34745658, 0.68683659, 0.34547285 }, { -0.3613378, -0.14006845, 0.65917895, 0.038446867 }, { -0.57778101, -0.35057776, 0.57837882, 0.36488991 }, { -0.50051482, -0.019174387, 0.50816239, 0.02682636 } }, { { 0.8121484, 0.88065787, 0.67837119, 0.88670158 }, { 0.92208686, 0.85616327, 0.69021085, -0.75996148 }, { 0.74413303, 0.88720424, 0.71027063, 0.85714604 }, { 0.92954743, 0.86718726, 0.74421946, -0.74421095 }, { 0.80094204, 0.86317363, 0.8006009, 0.85894353 }, { 0.82536033, 0.95522956, 0.8489833, -0.75548802 } }, { { 5.7725061, 5.1565901, 5.6224483, 5.0847054 }, { 5.7717118, 6.4180057, 6.9797014, -0.03290957 }, { 5.7847117, 5.2015529, 5.614561, 5.2019388 }, { 6.2613999, 6.5807982, 6.9797014, -0.032764603 }, { 5.823775, 5.2332343, 5.826694, 5.197143 }, { 6.3463188, 5.8174311, 6.9797014, -0.032766769 } }, { { 2.96787, 1.3557735, 2.0749129, 1.3066609 }, { -0.92782801, 0.0079162579, -0.33479446, 2.699659e-05 }, { 2.1997063, 3.1083252, 2.6810949, 1.8276262 }, { -0.48654719, -0.10954189, -0.32175132, 5.490092e-05 }, { 3.1970446, 1.787085, 3.062849, 1.6274811 }, { -0.78882801, -0.34050184, -0.59962127, 3.6554198e-05 } } } }; - -const float high_quality_coeffs[7][5][3][24][4] = { { { { { -4.8355339e-06, -4.4902569e-05, -9.2632249e-05, -0.00053773136 }, { 0.0040143823, -0.00060900339, -0.0095301923, -0.0053956011 }, { -0.0005923892, -3.6901978e-05, -5.6694857e-06, -0.00017018564 }, { 0.0012441402, 0.02236187, 0.022751769, 0.0062788948 }, { 0.00013810055, -2.2709815e-05, 0.0054849671, -1.6599195e-05 }, { -0.020320408, -0.017066319, -0.017457746, 0.022910628 }, { 0.00024171724, 9.7419073e-05, -0.00047804272, -0.00010093683 }, { 7.6988167e-05, 1.8551597e-05, -5.7692813e-05, -3.332362e-05 }, { -0.00062766208, 2.713742e-05, 0.00026511682, 2.3841873e-05 }, { -0.00043656844, 0.0028645469, 0.0049817085, 0.0080221478 }, { -3.3210444e-05, -8.0852386e-05, -2.2111492e-06, -8.4430827e-05 }, { 0.010967284, 0.018811225, 0.017569463, -0.0046944996 }, { -0.00018391248, -0.00010462174, -0.00017726, -0.00018490133 }, { 0.00012591989, 0.015965386, 0.015964059, -0.0078018431 }, { -0.006125333, -8.2224165e-05, -0.00020500151, -0.00025207244 }, { -0.00016320041, -0.0001279242, 0.00014038799, 8.1359421e-05 }, { -0.00064341098, -0.0011265496, -0.0011634792, -0.00081607159 }, { 0.00089294825, 0.0061923653, 0.0052662392, -0.00058227469 }, { -2.4001308e-05, -1.3534224e-05, -1.4720478e-05, -2.5120827e-05 }, { 0.00029964918, -0.0045658543, -0.0045581938, 0.0017106208 }, { 7.5790173e-05, -1.8265415e-05, 1.5918205e-05, 5.8524021e-05 }, { 0.0011669872, -0.00017571882, -0.00017190275, -0.0023833977 }, { 0.0033487264, -0.0066535821, -0.0066413786, -0.0032332601 }, { -3.6468807e-05, -0.00068145131, -9.8190714e-05, -8.7169435e-05 } }, { { -0.0010440653, -8.9750644e-05, 4.971182e-05, 0.0044618878 }, { 0.0078333883, -0.00090884312, -0.00046920549, -0.002465051 }, { -0.0058778609, 0.0026554895, -0.00031880506, -0.00010649091 }, { -0.0015095448, 0.0094026506, 0.009492703, 0.0024572848 }, { 0.0047331786, 0.00070722401, 0.0028798817, -0.00039779892 }, { -0.0089878107, -0.0095474878, -0.0097187652, 0.008765907 }, { -4.0435321e-05, -0.00061813281, -0.0060490143, 0.0016259965 }, { -0.00014720558, -1.0601876e-05, 0.00014757138, 0.00016227641 }, { -0.010428289, -0.00031812813, -0.0016172213, -0.00012022134 }, { 0.0040517131, 0.0072972763, 0.0060433905, 0.0025041645 }, { 0.00014090924, 0.00027612853, 0.00015961665, 0.0002605418 }, { -0.00020653783, -0.00048482867, -0.00058472338, 0.00026413759 }, { 0.00056712638, 0.00026385353, 0.00035484947, 0.00033212447 }, { -0.00094663094, 0.0029891757, 0.0029887838, -0.0026583585 }, { -0.0017400246, 0.00042350567, 0.00086128207, 0.00039863587 }, { 0.00059604848, 0.00027495434, -0.00059956434, -4.4981673e-05 }, { -0.010211343, -0.0080580409, -0.0085333216, 0.0023258717 }, { 0.00042832593, 0.0056750222, 0.0048059635, -0.0092168281 }, { 3.0214612e-05, 4.540924e-06, 1.7239937e-05, 2.783598e-05 }, { 0.00029393335, -4.5128636e-05, -4.3089017e-05, 0.00030682556 }, { -4.7077735e-05, -1.3596835e-05, -0.0015338149, -7.4957991e-05 }, { -0.00097136844, 0.00018564298, 0.00021815754, 0.0015095577 }, { 0.00043929849, -0.0014691094, -0.0014671742, -0.00029365954 }, { 8.8554045e-05, 0.0062500772, 0.0001495049, 0.00021007601 } }, { { 0.0020307077, 0.0020947445, 0.0017438295, 0.0084822342 }, { -0.0069727503, -0.0010131005, 0.0055261321, -0.0020442588 }, { 0.00031035611, 0.00010839441, 3.7359209e-06, 4.3112837e-05 }, { 9.1207794e-05, 0.0050148169, 0.0051071455, 0.0033679057 }, { -0.00090101737, -0.00053793176, -0.0025829621, 0.0003241927 }, { -0.0019244714, -0.0033690472, -0.0035193497, 0.0027653636 }, { -0.00065476293, -0.00017787403, 0.00040383136, -0.00018123957 }, { -0.00030640434, -0.00018961553, -0.00011036218, -0.00015793049 }, { 0.001110592, -0.00021252645, 0.00015849587, -3.7758317e-05 }, { 0.00077967828, -0.0051765235, -0.0078505592, -0.010796339 }, { -1.2024951e-05, 6.48806e-05, -3.9409005e-05, 7.4639306e-05 }, { -0.00017352424, -0.00037802595, -0.00045639468, 0.00016843169 }, { -4.2866244e-05, -4.3730932e-06, 7.3574276e-05, 5.6076779e-05 }, { 0.00024802387, 0.0018053101, 0.0018042994, -0.0016700716 }, { 0.0082698262, -0.00014605077, 0.0004377682, 8.1585074e-05 }, { -4.494343e-06, 0.00019781519, -0.00058910268, -0.00027360572 }, { 0.0013016934, 0.0021020456, 0.0022718598, -0.0059377824 }, { 0.002185371, -0.0080788056, -0.0071952836, 0.0039688918 }, { 0.00013048617, 0.0001738124, 0.00012978924, 0.00013813358 }, { 0.00032386518, 0.00023046021, 0.00023064714, 0.00033762343 }, { 0.00023643771, 0.00019652953, 0.0013083597, 0.00024739959 }, { -0.0063957036, -0.0055319023, -0.0054742301, -0.0037204932 }, { -0.0005510683, -0.0007715413, -0.00077385934, -0.001009415 }, { 0.00017904616, -0.00096137522, 0.00030252599, -2.2478138e-05 } } }, { { { -0.00038948583, -0.00040817153, -0.00041280315, -0.0010985631 }, { 0.0025695337, 0.00042904308, 0.0054649973, -0.0055079106 }, { 0.00052050672, 2.2618679e-05, 0.00024058975, -0.00012632201 }, { -0.013468886, 0.0079396715, 0.0079402246, 0.026283756 }, { -7.922122e-05, -3.4761763e-06, -0.0041716347, 0.0001478739 }, { 0.023716381, -0.016415262, -0.015296927, -0.021050827 }, { 3.7654391e-05, 0.00012765816, -0.0001337099, 0.00051483398 }, { 0.00015671907, 0.00010686796, 2.1421097e-05, -2.2281569e-05 }, { 3.1779413e-06, 0.00010449913, -0.00018303614, 7.5382489e-05 }, { -0.00020526765, -0.0011333575, -0.0050720108, 0.0051482782 }, { 4.0450357e-05, 1.0808158e-05, -2.3316095e-05, 9.7767333e-06 }, { -0.019107229, 0.010907324, 0.0048969594, 0.017851514 }, { 7.4048796e-05, -7.041835e-06, 8.0226174e-05, 5.1714105e-05 }, { -0.016564627, 0.0023486944, 0.0023601429, 0.016005248 }, { -0.004528284, 3.6291049e-05, 2.4229636e-05, 0.0024853948 }, { 5.6882054e-05, 6.8805135e-05, 0.00013119897, 0.00010339801 }, { 0.00021183341, 0.0008203137, -7.204401e-05, 0.00062599728 }, { -0.00099314707, 0.0030198762, -0.0038989955, 0.00055571214 }, { -7.4247984e-05, -8.3993373e-05, -5.9133252e-05, -7.7411989e-05 }, { 0.0054296732, -0.00057858871, -0.00058417754, -0.005072911 }, { -0.00019259782, -0.00018772532, -4.2959783e-05, -0.0001827295 }, { -0.00029351865, 0.00013736372, 0.00016666048, 0.00020873447 }, { 0.0069341659, 0.0027612928, 0.0027538377, -0.0061770317 }, { 4.2584714e-05, -0.00037063589, -9.0693123e-06, 0.00011845784 } }, { { 0.0028834168, 0.0031807308, 0.0031352582, 0.01064051 }, { 0.0049297987, -4.2149356e-05, -0.0014926841, -0.0002300371 }, { 0.0020396303, -0.00066042794, -6.4359283e-05, 0.00017835163 }, { -0.0025767816, 0.0025148152, 0.0025224779, 0.0043006543 }, { -0.00042084416, -0.00013534305, 0.002453623, -4.0707749e-05 }, { -0.0001803055, -0.0010450606, -0.00084380806, 0.00014843677 }, { -0.0064067107, 0.00011012652, -0.0022552747, -0.00080508294 }, { -0.00017778763, -4.296789e-05, 0.00015343883, 0.00025036711 }, { 0.002825978, -0.00031945362, -0.00031987612, -0.00021117763 }, { 0.00032791249, -0.00049524542, 0.0049368722, -0.0017186408 }, { -0.0001685943, -0.00016766033, -0.0001755097, -0.00017067307 }, { 0.00023939157, -0.00011793706, -6.0620575e-05, -0.0002706595 }, { -2.9718673e-05, 3.5950879e-05, 1.839844e-05, -2.8718148e-05 }, { -0.0017260981, 0.00012145435, 0.0001236679, 0.0018292155 }, { 0.0036086706, 0.0001026898, -2.5518889e-05, -0.00019830236 }, { -0.00031546808, -0.00042107458, -0.00059963868, -0.00061472497 }, { -0.0074719522, 0.0015719596, -0.0033624165, -0.0092664101 }, { -0.0011285776, 0.0018601435, 0.00052060704, -1.5554679e-05 }, { 4.9853171e-05, 7.3650922e-05, 3.4080107e-05, 5.4255445e-05 }, { 0.00015102779, -2.58105e-05, -2.5851018e-05, -4.5185316e-05 }, { 0.0002057452, 0.00019037765, 0.0040052198, 0.00020046579 }, { 0.0027727314, 0.0040749211, 0.0036050794, 0.0034635222 }, { 0.00042503689, 0.00056027382, 0.00056052971, -8.2485044e-05 }, { -5.6309634e-05, 0.0019722025, 6.4267434e-05, -0.00020376412 } }, { { 0.0051607661, 0.0047835358, 0.0047658352, 0.0054281814 }, { -0.0040939561, 0.0012119183, -0.0023408179, -0.00055891234 }, { -0.0031939804, -0.0015954053, -0.00018570689, 0.00028849431 }, { -0.0075625096, 0.0033878734, 0.0033797415, 0.010242674 }, { -0.002293562, 0.00024245282, 0.0019455622, 0.0039550747 }, { 0.0090386754, -0.0086947671, -0.0082684939, -0.0075613346 }, { -0.00085735117, 3.4822634e-05, -0.0024653972, -0.00090964985 }, { -0.00013750587, -0.00010089501, 6.3555498e-05, 0.0002758494 }, { 0.0060496328, -0.00032664426, 0.0005979723, -0.00018819024 }, { 0.00072724184, 0.00082242885, 0.0045668772, -0.0054557456 }, { -9.6167811e-05, 7.9856612e-05, 0.00015672473, 8.0901183e-05 }, { 0.00038859448, -0.00025360755, -0.00017624981, -0.00049125519 }, { -8.8277361e-05, 2.4159527e-05, -0.00016014627, -2.7854246e-05 }, { -0.0037308647, 0.00041434141, 0.0004167221, 0.0037190244 }, { 0.00050696744, -4.6752715e-05, 0.00033183668, -0.0025882828 }, { -0.00015915702, -0.0002325901, -0.00036157415, -0.00016391937 }, { 0.00012320153, 0.0026711886, 0.0018414591, -0.0058215223 }, { -0.0029409983, -0.00015460743, 0.0031951665, 0.0074654329 }, { 9.9084813e-05, 9.1785865e-05, 5.9300007e-05, 0.00010463304 }, { 0.00024773341, -2.5723276e-05, -2.5709769e-05, -0.00015357475 }, { 0.000416633, 0.00028749584, -0.0038632071, 0.00039869488 }, { 0.00018344152, 3.0811778e-05, -0.00010240082, 0.00059301197 }, { 0.0019217461, 0.00034404024, 0.00034318823, -0.0015867375 }, { -0.00011928879, 0.001178769, -5.8655983e-05, -0.00028461439 } } }, { { { 0.99999992, 0.99999992, 0.99999991, 0.99999925 }, { 0.99998864, 0.99999972, 0.99993965, 0.99997027 }, { 0.99999969, 1, 0.99999997, 0.99999998 }, { 0.99990852, 0.99971841, 0.99970961, 0.9996348 }, { 0.99999999, 1, 0.99997626, 0.99999999 }, { 0.99951219, 0.9997196, 0.99973058, 0.99951587 }, { 0.99999997, 0.99999999, 0.99999988, 0.99999986 }, { 0.99999998, 0.99999999, 1, 1 }, { 0.9999998, 0.99999999, 0.99999995, 1 }, { 0.99999988, 0.99999525, 0.99997473, 0.99995457 }, { 1, 1, 1, 1 }, { 0.99975729, 0.99976356, 0.99983365, 0.99982963 }, { 0.99999998, 0.99999999, 0.99999998, 0.99999998 }, { 0.99986279, 0.99986979, 0.99986978, 0.99984147 }, { 0.99997099, 1, 0.99999998, 0.99999688 }, { 0.99999999, 0.99999999, 0.99999998, 0.99999999 }, { 0.99999977, 0.99999903, 0.99999932, 0.99999947 }, { 0.99999911, 0.99997627, 0.99997853, 0.99999968 }, { 1, 1, 1, 1 }, { 0.99998521, 0.99998941, 0.99998944, 0.99998567 }, { 0.99999998, 0.99999998, 1, 0.99999998 }, { 0.99999928, 0.99999998, 0.99999997, 0.99999714 }, { 0.99997035, 0.99997405, 0.99997415, 0.99997569 }, { 1, 0.9999997, 1, 0.99999999 } }, { { 0.00015966941, 0.00014262676, 0.00020165066, 0.00021618914 }, { 2.8140907e-06, -0.00020325872, 0.00017736728, 6.0386679e-05 }, { -0.0003187876, 5.8862288e-05, 6.2281085e-05, 1.7339908e-05 }, { -2.6587911e-05, -0.00011609007, -0.00011725093, -7.6114852e-05 }, { 0.00013665042, 5.2703844e-06, -0.00031293536, 3.8693931e-05 }, { -9.8143069e-05, -0.00012816332, -0.00012926252, -0.00010623032 }, { 0.00032342312, -1.9200091e-06, -0.00010691485, 6.3541059e-05 }, { -8.0643542e-06, 9.7622933e-06, 2.9924822e-05, -1.988333e-05 }, { 0.00025318464, 1.2588649e-05, 1.4665927e-05, 9.3294806e-06 }, { 2.6875391e-06, -2.4928123e-05, 2.251878e-05, 0.00011026808 }, { 1.767638e-05, 1.0309044e-05, 2.4765648e-05, 1.4397941e-05 }, { 6.9000935e-06, 1.0637078e-05, 1.087637e-05, 6.3065784e-06 }, { 5.532953e-05, 1.6231463e-05, 4.9564371e-05, 3.6623041e-05 }, { -1.6958729e-05, -3.1627491e-05, -3.1524511e-05, -2.9954116e-05 }, { 8.9045086e-05, 2.1005026e-05, 1.3016463e-05, 8.7863053e-05 }, { -2.75035e-05, -3.0440427e-05, -3.5356286e-05, 5.9609261e-06 }, { 0.0001586274, 4.0711165e-05, 3.1563135e-05, 0.0001385483 }, { 8.5548316e-06, 7.4531928e-05, -3.7017413e-05, 2.6874037e-05 }, { -1.3750655e-05, -8.2756032e-06, -2.7214983e-07, -1.4830115e-05 }, { -7.0798362e-07, -3.3187173e-07, -3.3266762e-07, -5.7113855e-07 }, { 4.3615512e-05, -4.4076433e-06, 8.9239586e-06, 3.7278531e-05 }, { -7.7366773e-06, 4.610399e-06, 4.3762687e-06, -5.64067e-06 }, { -3.2666125e-06, -1.0773146e-05, -1.0861965e-05, -1.3327232e-06 }, { -9.1178305e-06, 0.00030171207, -1.5395234e-05, -2.0695425e-07 } }, { { 0.00017159464, 0.00014699558, 0.00018752678, 0.0002227926 }, { -4.6524822e-05, -0.00010460271, 0.00034735325, 0.00010082238 }, { -6.8269006e-05, 1.4343751e-05, 7.7283393e-06, 2.5347136e-05 }, { -6.6149546e-05, -7.1168993e-05, -7.0621016e-05, -0.00015246746 }, { 7.12022e-05, 3.8790461e-05, -0.00023994449, 6.6792921e-05 }, { -0.00014735813, -0.00012658353, -0.00012162488, -0.00012106777 }, { 0.00015161388, -1.4439153e-05, -3.7629923e-06, 8.3140788e-06 }, { 4.0175416e-05, 2.5380268e-05, -2.2894421e-06, 4.6374378e-06 }, { 0.00028906023, 1.7695243e-05, 5.3790587e-06, 1.631859e-05 }, { 1.8890685e-05, -1.6898275e-05, 2.1007663e-05, 6.5179363e-05 }, { -3.9142595e-06, 2.5745488e-05, 1.0803197e-05, 2.7099749e-05 }, { 9.4245546e-06, 1.0010075e-05, 9.058324e-06, 9.8703427e-06 }, { -2.3441863e-06, 2.5490323e-05, -1.0097654e-05, 4.0554798e-05 }, { -4.1443921e-05, -1.996316e-05, -2.0000841e-05, -4.7495655e-05 }, { 0.00012591695, 5.6179903e-05, -1.8415869e-05, -3.8697972e-05 }, { 2.6719505e-05, 2.4195362e-06, 2.4287424e-05, 3.4703059e-05 }, { 7.3804931e-05, 4.9784871e-05, 3.1159931e-06, 0.00015857197 }, { -0.00010634331, -1.6427658e-05, -7.4874306e-05, -6.2620255e-05 }, { -4.2561214e-06, -1.6123179e-05, -1.5507273e-05, -1.2909924e-05 }, { -1.2210463e-06, 1.1546399e-06, 1.1413892e-06, -1.3465856e-06 }, { 3.4909884e-05, -1.2677793e-05, 0.00011543701, 2.413091e-05 }, { -2.1953323e-05, -4.6244252e-06, -3.5624435e-06, 4.2293671e-06 }, { -1.1392936e-05, -4.3970369e-06, -4.4264864e-06, -1.208518e-05 }, { -4.4002617e-05, 0.00020912348, -3.9617824e-05, -4.1725112e-05 } } }, { { { -0.32504349, -0.32502096, -0.32501094, -0.32423576 }, { -0.65602876, -0.65622598, -0.65567173, -0.65525128 }, { -1.4666488, -1.4666488, -1.4666488, -1.4666488 }, { 0.87168363, 0.87181364, 0.87181792, 0.8718169 }, { -1.264365, -1.264365, -1.264365, -1.264365 }, { 0.89917968, 0.89916889, 0.89916525, 0.89927374 }, { -1.2245906, -1.2245906, -1.2245906, -1.2245906 }, { -0.8885678, -0.88856217, -0.88856327, -0.88855044 }, { -0.31799095, -0.31916566, -0.31907669, -0.31918911 }, { -0.08987958, -0.090342401, -0.090004674, -0.090222398 }, { -0.59425693, -0.59433999, -0.59429118, -0.59433553 }, { 1.1317575, 1.1317475, 1.1317412, 1.1317494 }, { -1.2193493, -1.2193493, -1.2193493, -1.2193493 }, { 1.2506981, 1.250675, 1.250675, 1.2506569 }, { -1.08782, -1.0877793, -1.0878022, -1.0878025 }, { -0.13925598, -0.13932948, -0.13919658, -0.13913403 }, { -0.40394684, -0.4042314, -0.40436178, -0.40402218 }, { -0.47762966, -0.47745572, -0.47767784, -0.47713093 }, { -0.60177181, -0.60176862, -0.60177347, -0.60177079 }, { 2.7311956, 2.7311911, 2.7311911, 2.731191 }, { -1.3109856, -1.3109856, -1.3109856, -1.3109856 }, { 0.60942644, 0.60941369, 0.6094123, 0.60944198 }, { 0.55675448, 0.55672275, 0.55672303, 0.5567542 }, { -0.40637059, -0.4057945, -0.40635768, -0.40636681 } }, { { -0.0016154222, -0.0015930079, -0.0015828998, -0.00087447165 }, { -0.0011262472, -0.001324462, -0.00094895016, -0.00062188189 }, { 0, 0, 0, 0 }, { 9.7616744e-05, 0.00010718899, 0.00010718606, 0.00012665246 }, { 0, 0, 0, 0 }, { 0.00013476236, 6.982272e-05, 6.8208505e-05, 0.00014604742 }, { 0, 0, 0, 0 }, { -0.0031089951, -0.0031071196, -0.0031207245, -0.0031097054 }, { -0.0027808116, -0.0035049857, -0.0034100135, -0.0035192661 }, { -0.0018291474, -0.0019603285, -0.0018919656, -0.0019656229 }, { -0.0034301741, -0.0034912573, -0.0034474395, -0.0034893985 }, { -6.156701e-06, -9.8568527e-06, -1.2383692e-05, -9.9984205e-06 }, { 0, 0, 0, 0 }, { 0.00011838153, 0.00011008679, 0.00011008878, 0.00010536608 }, { -0.0006246638, -0.00058479459, -0.00061327452, -0.00061085433 }, { -0.0059197749, -0.0059778169, -0.0059586015, -0.0058798299 }, { -0.0013246996, -0.0016061786, -0.0016081246, -0.0014374546 }, { -0.001593227, -0.0014706843, -0.0015974008, -0.001341579 }, { -0.0027930604, -0.0027920013, -0.0027939865, -0.0027928528 }, { -1.8908723e-06, -4.266382e-06, -4.2210172e-06, -5.0155215e-06 }, { 0, 0, 0, 0 }, { 0.00018508026, 0.00019774537, 0.00019744661, 0.00019538593 }, { 2.3243747e-05, 1.7291398e-05, 1.7309712e-05, 2.9261396e-05 }, { -0.0041402471, -0.0037085946, -0.0041294876, -0.0041316136 } }, { { -0.0018899732, -0.0018719182, -0.0018661076, -0.0012234594 }, { -0.0012968123, -0.0012971446, -0.00093522854, -0.00066475268 }, { 0, 0, 0, 0 }, { 9.1054464e-05, 0.00014124217, 0.00014156806, 0.00012014953 }, { 0, 0, 0, 0 }, { 0.00017026995, 0.00010528413, 0.00010537941, 0.00015698848 }, { 0, 0, 0, 0 }, { -0.0025812972, -0.0025835894, -0.0025789321, -0.002554949 }, { -0.0035568863, -0.0042988014, -0.0042155548, -0.004312546 }, { -0.0024184575, -0.0025111277, -0.0024654994, -0.0023980076 }, { -0.0036993386, -0.0037113013, -0.0036987284, -0.0037094875 }, { -5.074861e-06, -1.1367399e-05, -1.4819989e-05, -9.2705899e-06 }, { 0, 0, 0, 0 }, { 0.00012570403, 0.00012150272, 0.00012149179, 0.00010579599 }, { -0.00062162762, -0.00058131015, -0.00060837583, -0.00060795256 }, { -0.00775735, -0.0077198081, -0.0078365948, -0.0077749317 }, { -0.0015325554, -0.0017125784, -0.001703195, -0.0015662859 }, { -0.0018130784, -0.00177106, -0.001858095, -0.0015845058 }, { -0.003668417, -0.0036659688, -0.0036693421, -0.0036680526 }, { -9.5804016e-06, -9.6276607e-06, -9.630607e-06, -1.2159056e-05 }, { 0, 0, 0, 0 }, { 0.00017930618, 0.00020084683, 0.00020150104, 0.00020810787 }, { 2.3869269e-05, 1.1024793e-05, 1.1041937e-05, 1.6467357e-05 }, { -0.004690782, -0.0044656761, -0.0046782065, -0.0046921455 } } }, { { { 0.23047932, 0.23043226, 0.23041471, 0.22922185 }, { 0.14990977, 0.15703656, 0.15110771, 0.15149153 }, { 0.30629171, 0.30426701, 0.30400037, 0.30403889 }, { 0.03476576, 0.036188528, 0.036216719, 0.037322097 }, { 0.31066251, 0.31090363, 0.31041565, 0.31057779 }, { 0.04875259, 0.046468595, 0.046486323, 0.046584523 }, { 0.31745458, 0.31874472, 0.32086369, 0.31880207 }, { 0.64054942, 0.64062862, 0.64051973, 0.64059059 }, { 0.27309038, 0.27480819, 0.27477284, 0.27486762 }, { 0.196647, 0.19687982, 0.19607604, 0.1957915 }, { 0.32867362, 0.32858008, 0.32856702, 0.328555 }, { -0.0026873031, -0.0042393446, -0.0057894907, -0.0041858859 }, { 0.40254624, 0.4024247, 0.4025598, 0.40243731 }, { 0.019362807, 0.018146218, 0.018146051, 0.019656613 }, { 0.29328089, 0.29403937, 0.29435036, 0.29403094 }, { 0.57111506, 0.57118505, 0.57099608, 0.57099266 }, { 0.16966612, 0.16993739, 0.17069399, 0.16991136 }, { 0.14989055, 0.1489484, 0.14995985, 0.15015916 }, { 0.33606014, 0.33606294, 0.33606393, 0.33605429 }, { 0.015421206, 0.015180692, 0.01518037, 0.015431139 }, { 0.33165237, 0.33185282, 0.33162592, 0.33166981 }, { 0.078137018, 0.078153855, 0.078165152, 0.078332343 }, { 0.002896946, 0.0026038621, 0.0026029604, 0.0022081151 }, { 0.41064398, 0.40987685, 0.41065341, 0.41059166 } }, { { -0.0024316111, -0.0024732789, -0.0024922144, -0.0035874346 }, { 0.0013306961, 0.004171802, 0.0027660627, 0.0023671465 }, { 0.0034411091, 0.0020878413, 0.0020874456, 0.0022028237 }, { -0.0032873976, -0.0021351911, -0.0021071363, -0.0028424534 }, { 0.0017995208, 0.0022319618, 0.0039270256, 0.0021249365 }, { -0.0019590835, -0.0012526895, -0.0012347747, -0.0021069943 }, { 0.0012319531, 0.002255621, 0.0030193583, 0.0020970822 }, { 0.0015144077, 0.0015110104, 0.0014803089, 0.0015340007 }, { -0.0036679996, -0.0028160114, -0.0028586497, -0.0027953731 }, { -0.005445786, -0.0052624873, -0.0054843188, -0.0053271749 }, { 0.00067154572, 0.0007530775, 0.00067974516, 0.00074462315 }, { -0.0035626119, -0.0034186877, -0.0038720517, -0.0040088745 }, { 0.003455851, 0.0035040061, 0.0034671486, 0.0035069881 }, { -0.0047789747, -0.0047994804, -0.0047996451, -0.0044008337 }, { 0.0032403482, 0.0033627856, 0.003429619, 0.0031153117 }, { -0.005027022, -0.0049812, -0.0049604573, -0.0050556194 }, { -0.0020728991, -0.0014784158, -0.001216894, -0.0019213729 }, { -0.00013808007, -0.00067270623, -0.00024001574, -0.00030691077 }, { 0.0004367104, 0.00043390709, 0.00043548166, 0.00043425516 }, { -0.00082746467, -0.00088151411, -0.00088152334, -0.0008043643 }, { 0.0030277712, 0.003133577, 0.0028529862, 0.0030362271 }, { -0.0058721937, -0.0059816331, -0.0059799345, -0.0058882832 }, { -0.0057032562, -0.0057401855, -0.0057416619, -0.0062417688 }, { -0.0014357888, -0.0020782049, -0.0014346823, -0.0014513767 } }, { { -0.0027051235, -0.0027087245, -0.0027052303, -0.0033594951 }, { 0.0028036195, 0.0030416572, 0.0014306948, 0.0017897371 }, { 0.0031113166, 0.0026432303, 0.0025937824, 0.0025394463 }, { -0.0036032904, -0.003447065, -0.0034344406, -0.0024163572 }, { 0.0023912799, 0.0025281229, 0.0038665087, 0.0024214034 }, { -0.0023543827, -0.0024294943, -0.0024539784, -0.0027742617 }, { 0.0020903896, 0.0026617586, 0.003395249, 0.0026261065 }, { 0.0019031008, 0.0019405475, 0.0019426085, 0.0019404325 }, { -0.0040413326, -0.0030964835, -0.0031020735, -0.0030826754 }, { -0.0064568993, -0.0062342438, -0.0064704698, -0.0065636744 }, { 0.0010788406, 0.0010092051, 0.0010264121, 0.00099891228 }, { -0.0040759201, -0.0059224283, -0.0066809927, -0.0049099348 }, { 0.0042962009, 0.0041909175, 0.0043195236, 0.0041900138 }, { -0.0062728983, -0.0070256154, -0.007025641, -0.0061758746 }, { 0.0036210401, 0.0039723998, 0.0042232048, 0.0042757707 }, { -0.0058693852, -0.0058583303, -0.0058544016, -0.005887725 }, { -0.0023099876, -0.0021136245, -0.0017298078, -0.0022483337 }, { -0.00017851962, -0.00014956209, 8.5676316e-05, -0.00024971669 }, { 0.0003734781, 0.00037078986, 0.00037364181, 0.00037070594 }, { -0.00030648905, -0.00038230535, -0.00038223043, -0.00028623253 }, { 0.0032871423, 0.0034163052, 0.0028276655, 0.0032991918 }, { -0.0061331695, -0.0063319797, -0.0063340119, -0.0064390374 }, { -0.0062172888, -0.0059787106, -0.0059793294, -0.0060406701 }, { -0.0018276142, -0.0022170788, -0.0018293949, -0.0018222824 } } } }, { { { { 0.13218089, -0.11654637, -0.11622196, -0.044208736 }, { 0.0074579257, 0.0038503609, 0.0013201096, 4.0415784e-05 }, { -0.025474487, -0.01209255, -0.016535858, 0.012704547 }, { -0.0016894103, -0.0081312144, -0.0033264609, 0.0011923269 }, { -0.068044876, 0.018276873, -0.074833897, 0.01308348 }, { 0.02665691, 0.013515118, 0.026440814, -0.0077037816 }, { 0.0023286096, -0.0025782652, 0.0021644694, -0.0042955294 }, { 0.051356261, -0.031058382, -0.085382962, -0.033103269 }, { -0.081609229, 0.0035270199, -0.015722417, 0.048773789 }, { 0.0023928418, -0.001243811, 0.011910492, -0.011621478 }, { -0.028953904, -0.029335777, -0.0057891432, 0.013874136 }, { -0.012473582, 0.001772629, -0.013983442, 0.014846792 }, { -0.016111661, 0.0018902323, 0.025910586, 0.042848276 }, { 0.026200626, 0.024007879, 0.0017667146, -0.016394032 }, { -0.0067006429, -0.0017968936, 0.009028659, 0.0044060413 }, { 0.019280611, 0.0449581, -0.042852227, -0.066012332 }, { -0.014451123, -0.047772741, -0.047475406, 0.098434178 }, { -0.0028954635, 0.010521833, -0.015741597, -0.00091666191 }, { 0.0020291956, -0.057966746, -0.04525094, 0.032711614 }, { 0.020563445, -0.0078684621, -0.015282237, -0.0019830466 }, { -0.019504171, 0.071338511, 0.0033729474, -0.0095772339 }, { 0.013056103, 0.018719519, 0.0096002937, -0.028774366 }, { -0.00038728577, -0.0010662982, -0.0014333502, 0.00059135695 }, { 0.073844752, -0.05666013, -0.1007151, -0.030440738 } }, { { 0.00017766639, -9.2398532e-05, -3.9442682e-05, -3.9559848e-05 }, { -0.0043956477, 0.00044042277, -0.00047491077, 9.4171117e-05 }, { -0.0042095545, -0.00910753, -0.0014295282, 0.0042595844 }, { 0.00070989004, -0.0009623012, 0.00084162653, -0.00015925965 }, { -0.0017587638, 0.0033199811, -0.00025544613, 0.00083644978 }, { 0.0051797987, 0.0015691893, -0.002324397, 0.0050776381 }, { 0.003911779, 0.00072639703, 2.102924e-05, -0.0029529332 }, { 0.0050240476, -0.00041452319, 3.1730448e-06, -0.0072697591 }, { -1.5023048e-05, 0.00032491246, -9.2151952e-05, 0.0035851726 }, { 0.0030984373, 0.0016428856, 0.0032974124, -0.0036034289 }, { -0.00044578206, -0.0035916409, 0.0028146658, 0.0068013321 }, { 0.00025716711, -0.0024772152, 0.0029660992, -0.0008783244 }, { -0.005543602, -0.00046453249, 0.006815884, 0.0069207512 }, { -0.0033541738, -0.0015140333, -0.004071746, -0.0020908789 }, { 0.0027932918, -0.0012517158, -0.0033509184, -0.001271572 }, { 0.0043481525, -0.00088858735, -0.0081538059, 0.00027985077 }, { 7.4017523e-05, -7.0080388e-05, -7.1766386e-05, 0.00020468758 }, { 0.00044507396, 0.010179106, -0.0048087449, 0.0013487105 }, { 0.00082148695, -0.00042640153, -0.0024255173, 0.0044486011 }, { -0.00026383509, -0.0031871528, -0.008203704, -0.00053957093 }, { -0.0002996462, 0.00070789605, 7.9300612e-05, -0.00024002209 }, { 0.0013722116, 0.0049176054, 0.0029283062, -0.000849108 }, { 0.00026545039, 0.0011783443, 0.00072103548, -0.0007355776 }, { 0.002192273, -0.00294318, 1.5452606e-05, -0.0020953993 } }, { { 2.4074136e-05, -2.4931598e-05, -1.0893587e-05, 1.080951e-05 }, { -0.0061635883, -0.0042963493, -0.00177783, -0.00080292808 }, { 0.0047868795, -0.0050472436, 0.0082439123, -0.0090979713 }, { 0.0017221077, 0.0067285193, 0.0031011872, -0.0019932567 }, { 0.0010926271, -0.0012170693, 0.00012875612, 0.00016441623 }, { -0.0048786273, -0.0041225634, -0.005591426, 0.0043469593 }, { -0.0070664098, -0.0012625813, -0.00022220241, -0.0026120468 }, { -0.0026689917, 0.00030860545, 1.9297947e-05, 0.001274799 }, { 0.0026769559, 0.00016106032, 0.00013829246, -0.0017239107 }, { -0.0042495789, 0.0010270326, -0.00078224804, -0.0019210019 }, { 0.0072385804, 0.0086418476, 0.0061428272, -0.0027142827 }, { 0.0019768127, -0.00057957046, 0.0047464783, -0.004599565 }, { 0.0093618867, -0.0010476542, -0.0038681572, -0.0065219521 }, { -0.0076406673, -0.0036729355, -0.0068804827, 0.0077571478 }, { 0.0012706397, -0.00042567505, -0.002521821, 6.0288127e-05 }, { -0.002041411, 0.000430125, 0.0073620925, 0.0021579456 }, { 0.00012145466, 4.1276616e-05, 4.2449608e-05, 9.8351262e-05 }, { 0.0014376278, -0.007439719, 0.0039006971, 0.00051135138 }, { -7.1665367e-05, 0.00023856335, 0.00015274881, -0.0096946274 }, { -0.00076804256, 0.0040182915, 0.012603411, -0.00059669891 }, { -0.00010641981, -0.00052355992, 0.00057481361, 0.00016456343 }, { -0.0027623375, -0.0036761364, -0.010480297, 0.0066006902 }, { 0.00049081404, 0.00077264749, 0.0021355718, -0.00029188425 }, { 0.00028566818, 0.00097678458, 0.00089022281, -0.00013760767 } } }, { { { -0.0098123577, 0.11017117, 0.11245143, -0.01173447 }, { 0.0036188505, -0.0025878518, -0.00043343726, -0.0038813197 }, { 0.013109746, -0.016775181, -0.0011093308, 0.00083465721 }, { -0.0042515898, -0.0028159364, 0.00027829209, -0.002907578 }, { -0.0081027554, -0.0019330574, 0.061872524, -0.037539524 }, { -0.012923735, 0.021011524, 0.002680406, 0.0034369108 }, { 0.0027819214, 0.0028657905, -0.0034177203, -0.0037322329 }, { -0.0036178174, 0.065792163, 0.13263475, 0.0055427994 }, { 0.027832309, -0.083372016, -0.058757582, 0.016164879 }, { -0.0082343898, 0.011782416, 0.011496052, -0.0027847616 }, { 0.0012516658, -0.014686832, -0.025073035, -0.020700577 }, { 0.0055718234, -0.011543219, -0.012867689, -0.0049474286 }, { 0.028869265, -0.035431559, 0.024976635, -0.01063055 }, { -0.0010657662, 0.014977146, 0.027109, 0.01612865 }, { -0.0021697493, 0.0044220507, 0.0055654161, -0.0032373397 }, { -0.018500666, -0.01979267, -0.0068480612, 0.03908391 }, { 0.063306878, 0.01934691, 0.019254616, -0.099824471 }, { 7.0580666e-05, -0.0015082457, -0.0056893693, 0.00022726294 }, { 0.0077067654, -0.014018834, -0.021406454, -0.0076589993 }, { -0.0013072394, 2.6765854e-05, 0.0028400803, 0.0037431063 }, { -0.025369581, -0.064039908, -0.020594137, -0.086807367 }, { -0.033639351, 0.010434758, 0.00082983507, 0.013145885 }, { 0.00029373395, 7.8193614e-05, 0.00048496415, 0.00062972215 }, { -0.0041597628, 0.024283117, -0.030148407, 0.011456515 } }, { { -1.3484857e-05, -3.7204145e-05, -1.5660577e-05, -2.4497955e-05 }, { -0.0068070249, 0.0041035892, 0.0034647689, 0.0035918321 }, { -0.0053613309, 0.0080593503, 0.0028507084, -0.0023104987 }, { 0.0048581064, 0.0039720065, -0.0019058129, 0.0047295789 }, { -0.00030675956, -0.0007787587, -0.00025201217, 0.00020777843 }, { -0.00026433336, -0.0093672701, -0.0053201627, -0.0059632173 }, { -0.0063062815, 0.0011995204, 0.0001870407, 0.0028197877 }, { -0.00053247524, -0.00066138217, -1.4959372e-05, -0.00036023628 }, { 0.00027591427, 0.00011309835, 2.2453632e-05, -0.00075736359 }, { 0.0015654886, 0.0018114616, -0.0004503446, -8.5866048e-05 }, { 0.003501393, 0.0037179893, 0.008328543, 0.013411108 }, { -0.0035136609, -0.0015054003, 0.0011903964, 0.0022551358 }, { -0.0083723767, 0.0061303554, -0.008056962, 0.0035035183 }, { -0.0023715655, -0.0070468331, -0.010219655, -0.0057856465 }, { -0.0011406634, -0.00021204595, -0.001693195, 0.0011051597 }, { 0.0011643412, 0.00037557194, 0.0048567739, -0.00063996433 }, { -3.1728174e-05, -2.9073903e-06, -3.0243209e-06, 2.579239e-05 }, { 0.00053152589, 0.0029635352, 0.0040743289, -0.00051381046 }, { -0.0017253584, 0.00012081524, 0.00012243664, -0.00063598215 }, { 0.0026711847, -0.0020733972, -0.0027860744, 0.0017065643 }, { 5.7762902e-05, 0.00092043577, -0.0035278882, 0.0007846087 }, { 0.0056127705, -0.0051893669, -0.0027072408, -0.0025630045 }, { -0.00059289151, -0.0004168408, -8.8118696e-05, -0.00073538101 }, { 0.0003388606, -0.00094234652, 3.013109e-05, -0.0010532484 } }, { { -2.9013996e-05, 6.1983083e-05, 2.8401438e-05, -3.4901557e-05 }, { 0.0045230474, -0.0021369843, -0.00422706, -0.0018918027 }, { 0.00017586142, 0.005389053, 0.0071352982, -0.0018278685 }, { -0.0012135723, -0.0035970727, 0.00078957165, -0.0017065397 }, { -0.00067051937, -1.9501585e-05, 4.1968766e-05, -0.0010958091 }, { -0.0015277626, -0.0039952533, -0.00049631478, 0.0018042745 }, { 0.0039376754, -0.00097834328, 6.5894634e-06, -0.0044189106 }, { -0.00067623039, 0.0004690807, 1.4532105e-07, 0.0032984829 }, { 0.0020787449, -0.0016586579, -0.00062367064, 0.0021545362 }, { 0.0016427801, 2.6710288e-05, 0.0016011535, -0.00077649869 }, { 0.0039999622, -0.0014968097, -0.0025647576, 0.0022783424 }, { 0.001558454, -0.00083803058, 0.0018955692, 0.0010432376 }, { 0.010555722, -0.010395022, 0.0050354965, -0.0016177699 }, { 0.00011370745, -0.009328355, -0.0063009522, 0.0024377458 }, { -0.00024433189, 0.00052920244, -0.0013213352, -0.0013503982 }, { -0.0057620093, 0.00095391746, -0.0034768563, 0.00093990705 }, { 0.00012108024, 4.1007202e-05, 4.2193381e-05, -0.00011043617 }, { 0.0038593696, -0.00074282979, -0.0093457897, 0.00027311164 }, { 0.0021514797, -7.8742315e-05, -0.0018813077, -0.0017625098 }, { 0.0038491118, 0.00022570776, -0.0061331041, 0.00014956617 }, { -0.00014676603, -0.00025053931, 0.003376287, -0.00014730695 }, { 0.0016439646, 0.0060569792, 0.00063058918, -0.0034810156 }, { 0.00011722835, 0.00032237223, -0.0012556553, -0.0006887808 }, { 0.00060814722, 0.0003708376, -0.00056515636, -0.00016801817 } } }, { { { 0.99117704, 0.98705585, 0.98683693, 0.9989534 }, { 0.99996564, 0.99998924, 0.99999903, 0.99999247 }, { 0.99958951, 0.99978616, 0.99986266, 0.99991895 }, { 0.99998953, 0.99996298, 0.99999443, 0.99999506 }, { 0.99764936, 0.9998311, 0.99527468, 0.99920949 }, { 0.9995611, 0.99968788, 0.99964679, 0.99996442 }, { 0.99999342, 0.99999257, 0.99999182, 0.99998381 }, { 0.99867384, 0.99734987, 0.98748052, 0.99943657 }, { 0.99627571, 0.99651225, 0.99814846, 0.99867903 }, { 0.99996323, 0.99992981, 0.99986298, 0.99992859 }, { 0.99957996, 0.99946171, 0.99966886, 0.99968945 }, { 0.99990668, 0.9999318, 0.99981943, 0.99987754 }, { 0.99945334, 0.99937032, 0.99935219, 0.99902503 }, { 0.99965614, 0.99959957, 0.99963092, 0.99973552 }, { 0.9999752, 0.99998861, 0.99994375, 0.99998505 }, { 0.99964293, 0.99879278, 0.99905795, 0.99705307 }, { 0.99788947, 0.99867085, 0.99868681, 0.99012413 }, { 0.99999581, 0.99994351, 0.99985991, 0.99999955 }, { 0.99996824, 0.99822008, 0.99874627, 0.99943549 }, { 0.9997877, 0.99996904, 0.99987919, 0.99999103 }, { 0.99948785, 0.99539425, 0.99978223, 0.99617908 }, { 0.99934875, 0.99977032, 0.99995357, 0.99949949 }, { 0.99999988, 0.99999943, 0.99999886, 0.99999963 }, { 0.99726107, 0.99809817, 0.99445842, 0.99947091 } }, { { -2.3481737e-05, -6.7307406e-06, -2.8605869e-06, -2.0372001e-06 }, { 6.6885689e-05, 4.5630281e-06, 3.5788218e-05, 1.0842484e-05 }, { -4.9278613e-05, -2.4660601e-05, 3.1625301e-06, 0.00019708279 }, { 1.2439158e-05, 3.0347865e-05, 8.6153947e-06, 1.0887256e-05 }, { -0.00012454598, -6.513709e-05, -3.5853483e-06, -3.4708286e-06 }, { -0.00013746339, 0.00013516333, 8.4535039e-05, 5.693766e-05 }, { -2.3674091e-05, -3.4690053e-06, 5.3812265e-07, -1.7613197e-05 }, { -0.00025790043, 3.0475251e-05, 2.1174795e-06, -0.00023630753 }, { -8.8624748e-06, 7.9175589e-06, -2.4258477e-07, -0.00017288313 }, { 4.0061469e-05, 0.00069846663, -0.00060299476, -0.00015396968 }, { 5.0667108e-06, 2.306363e-05, 0.00028636884, 3.6246633e-05 }, { 0.00032740524, -0.00037985037, -0.00014841039, -0.00012676016 }, { 8.7000758e-05, 0.00018530207, 1.7669124e-05, -0.00023199594 }, { 9.2332094e-05, 0.00013487652, 0.00034587506, -3.8853378e-05 }, { 6.9809868e-05, -0.00015411544, 0.0013505166, 1.4531796e-06 }, { -6.3782301e-05, 4.8545135e-05, -0.00027083794, 4.5129465e-05 }, { 3.0912438e-06, -3.2982361e-06, -3.3551612e-06, -1.7781589e-05 }, { 9.872609e-06, -2.9944213e-05, -4.5592652e-05, 1.5950681e-05 }, { 1.4767773e-05, -2.2486726e-05, -0.00010613341, -0.00015794394 }, { 2.4386215e-05, -1.1610334e-05, -4.4456294e-05, -5.0215596e-06 }, { -4.2741558e-06, 8.7714242e-06, -6.6343322e-05, 6.7010735e-05 }, { 0.00016489767, -3.3636771e-05, 5.1610504e-05, 5.2803593e-06 }, { 1.1649256e-05, 2.1169993e-05, 1.9755999e-05, 1.3389438e-05 }, { -0.00015815197, -0.00014316145, 2.6536218e-06, -4.6846396e-05 } }, { { -3.5109783e-06, -9.8530632e-06, -4.5020804e-06, 6.9233235e-08 }, { 9.9938991e-06, -2.0914089e-06, 3.5717699e-05, 3.2813664e-06 }, { 0.00012938219, 1.111062e-05, 8.0858608e-05, 0.00018147439 }, { 4.8657525e-06, 8.6580257e-06, 3.6742927e-06, 3.5828406e-06 }, { 6.9905696e-05, 2.0985073e-05, 6.8866215e-06, -4.2552499e-05 }, { 0.00012100208, 9.7821801e-05, 0.00013576456, 6.3686234e-05 }, { 1.954525e-06, -1.0727343e-06, 5.2332444e-07, -5.4034988e-06 }, { 0.00013699813, -2.226833e-05, 1.4994043e-06, 1.7110377e-05 }, { 0.0001678261, -0.00013844113, -3.4281745e-05, 5.3854072e-05 }, { -1.3018868e-05, 0.00022176303, 0.00016983401, 0.00038109805 }, { 0.00019016068, 0.00023448876, 2.643329e-05, 4.6842203e-05 }, { -1.2492528e-05, -0.00059486605, 0.00012427061, 8.1876965e-05 }, { 8.400564e-05, -0.00029859163, -4.884214e-05, 0.0002631806 }, { 0.00019907281, 0.00014046808, 0.00015482448, 4.0461099e-05 }, { -0.00024349239, 0.00081298441, 0.00084294728, 7.9617963e-05 }, { -6.0040835e-05, 3.2352918e-07, 0.00024295599, 0.00011067283 }, { -6.0027092e-06, 1.1975092e-06, 1.2248893e-06, -2.1293392e-05 }, { 1.4478736e-05, 6.8326918e-05, -7.8693614e-06, 9.2888155e-06 }, { -1.6982828e-05, 1.2094341e-05, -3.1693808e-05, 0.00028574477 }, { 3.4480942e-05, 2.6556008e-05, 0.00016193956, -1.8966503e-06 }, { -5.7726961e-06, 2.1091148e-05, 5.8963955e-05, -1.0834372e-05 }, { 0.0001214393, 1.4174882e-05, 0.0001371836, 0.00021757165 }, { 1.0140226e-05, 6.1641031e-06, 1.0590727e-05, 1.0893212e-05 }, { -1.7442656e-05, 4.2353331e-05, 7.4324714e-05, -1.9484775e-06 } } }, { { { 3.7217719, 3.6900797, 3.6899881, 3.6670816 }, { 0.067826319, 0.16468028, 0.083129199, 0.1336756 }, { 0.66338737, 0.23883566, 0.093361469, 0.10095622 }, { 0.27185537, 0.20781392, 0.32216624, 0.29876595 }, { 2.0776462, 2.0006156, 2.0243138, 2.080345 }, { 0.57695783, 0.18015147, -0.11440889, 0.14229144 }, { 0.63833683, 0.41431062, 0.44752994, 0.47594414 }, { 1.7890608, 1.962584, 1.9322155, 1.6588331 }, { 3.0538128, 3.108267, 3.1001573, 2.9593433 }, { -0.28383051, -0.27708376, -0.042513902, -0.085181891 }, { 0.3873435, 0.41697884, 0.39625427, 0.33250735 }, { -0.33498881, -0.40206929, -0.028905862, -0.48179632 }, { 1.1875033, 1.3535177, 1.2526197, 1.3337495 }, { 0.42579488, 0.24951727, 0.18976118, 0.20605317 }, { -0.53212666, -0.3861028, -0.75685995, -0.23411882 }, { 1.6910165, 1.686815, 1.5906473, 1.6528217 }, { 4.0570657, 4.0349492, 4.0350332, 4.0498099 }, { -0.017225465, -0.032503897, 0.46003211, 0.21602109 }, { 1.1196901, 1.00885, 0.91675568, 0.99635794 }, { -0.093891275, 0.0809352, -0.13783332, 0.27130678 }, { 1.9925136, 1.9829394, 1.8820721, 1.9542026 }, { 0.84563763, 0.48476746, 0.37907152, 0.70267878 }, { 0.37054708, 0.4228574, 0.6329822, 0.26197064 }, { 1.9618393, 1.8405969, 1.9440918, 1.901629 } }, { { -5.6047186e-06, 6.0454847e-06, 2.8365975e-06, 6.0894367e-06 }, { -0.00069876506, -0.00029642785, -0.00059516082, -0.00025400441 }, { -0.00020850504, -0.00012959593, -0.00032902532, -0.00058117893 }, { -0.00037901964, -0.00038062016, -0.00023777964, -0.00033714679 }, { -5.9894351e-05, -9.820791e-05, -5.9867157e-06, -6.258549e-06 }, { -0.00035424038, -8.7146215e-05, 3.0398362e-05, -0.00061406521 }, { 0.00014971442, 4.5936211e-05, -5.6259869e-06, 0.00013567035 }, { -0.00016180211, 3.1840487e-06, 3.8979157e-07, -0.00017131994 }, { -1.9877193e-05, 2.5768261e-05, 9.0577543e-06, -0.00013927462 }, { -0.0012323564, -0.00042892846, 7.2082106e-05, 0.00010999853 }, { -0.00034618449, -0.00017058897, -0.00016535057, -0.00096982024 }, { -0.00028039653, -7.155747e-05, -0.00075796707, 0.00062756458 }, { 6.6596276e-05, -7.9730809e-05, -8.0686754e-05, -2.9532397e-05 }, { -0.00084106867, -0.00036762453, 0.00012523548, -0.00052789663 }, { 7.6718268e-05, -0.0010042005, -0.00042802983, -0.0011951304 }, { -3.6972258e-05, 2.1447505e-06, -0.00035448623, -1.0620008e-05 }, { 2.8326169e-05, 2.2049468e-05, 2.2640575e-05, 1.7574827e-05 }, { -0.00014318496, -0.0004811524, -0.00049293303, -0.00067646484 }, { -2.7469144e-05, -5.9653763e-06, -1.3998899e-05, -0.00018475323 }, { -0.00017314302, -0.00010954727, -0.00040004932, 3.31106e-05 }, { -3.6093435e-06, -1.6125243e-05, -4.9195648e-05, 1.5586886e-05 }, { 0.0002059631, -0.0004024722, -0.00047984678, -9.8485329e-05 }, { -0.00094100913, -0.00073046048, -0.00052500163, -0.00068196784 }, { -2.2820197e-05, -5.9454557e-05, -6.2505468e-06, -2.6569804e-05 } }, { { 2.6015883e-05, 8.5398335e-06, 3.8473185e-06, 9.1409625e-06 }, { -0.00041459247, -0.0001855224, -0.00030529542, -0.00016322166 }, { -8.8427847e-05, -0.0002302048, -0.00038072959, -0.00076801295 }, { -0.00027717792, -0.00028594346, -0.00017910208, -0.00027291164 }, { 2.8409311e-05, -3.8005817e-05, -4.2266878e-06, -1.4520383e-05 }, { -0.0001088827, -0.00021924377, 3.9307406e-05, -0.00032488556 }, { 0.00027997916, 3.5103699e-05, -5.7448764e-06, 0.00010259251 }, { -4.7807894e-06, -2.9470863e-05, 2.6656233e-07, -0.00014346393 }, { 0.00015527098, -6.8528726e-05, -1.1206714e-05, 2.3422595e-05 }, { -0.0012763247, -0.00051503472, 0.00058055106, -0.00068688488 }, { -6.1232076e-06, -1.7073841e-05, -0.00033533389, -0.00078769935 }, { -0.00044113485, -0.00027577451, -0.0012008622, 0.00013071136 }, { 1.834948e-05, -0.00015615102, -0.00016449385, 3.6685217e-05 }, { -0.00063618257, -0.00032641968, -5.0281118e-05, -0.00041378992 }, { -0.0010181884, -0.0003871932, -0.00050061147, -0.0018967455 }, { -5.7650067e-05, -5.1145774e-06, -0.00017409773, 1.9512036e-05 }, { 1.5838743e-05, 2.503655e-05, 2.5679098e-05, 2.0053218e-05 }, { -0.00018055811, -0.00044345237, -7.9049557e-05, -0.00095669161 }, { -4.98611e-05, -1.1320605e-06, 3.7756645e-06, -8.7299215e-05 }, { -0.00011794063, -0.00015778552, -0.00036514881, 4.7288704e-05 }, { -5.1753817e-06, -1.5040527e-06, -2.836739e-05, -9.4945229e-06 }, { 0.00016873335, -0.00031983601, -0.00052281245, 0.00019034815 }, { -0.0011988594, -0.0010684975, -0.00057577023, -0.0009143845 }, { 5.0336006e-05, -1.356148e-05, 1.5582694e-05, -2.0666272e-05 } } }, { { { 0.012207721, 0.0044164612, 0.0022704542, 0.0042008503 }, { 0.29516302, 0.139976, 0.35038027, 0.13748343 }, { 0.1462123, 0.12114907, 0.28473665, 0.45762717 }, { 0.17976664, 0.19141553, 0.1209483, 0.16393769 }, { 0.044254492, 0.11383095, 0.0062726904, 0.023550537 }, { 0.14785458, 0.10151341, 0.045717467, 0.42243971 }, { -0.24205201, -0.033590842, 0.0032064617, -0.093924041 }, { 0.10866955, 0.016299431, 0.00081631108, 0.15856447 }, { 0.10108337, 0.057931152, 0.024463589, 0.21514346 }, { 0.47967783, 0.75472932, 0.5653649, 0.64752457 }, { 0.30082544, 0.15124922, 0.23567284, 0.47161499 }, { 0.54286166, 0.61049777, 0.61641378, 0.51181399 }, { 0.39328762, 0.25557559, 0.25875912, 0.22436901 }, { 0.45699569, 0.16989563, 0.2429263, 0.3924359 }, { 0.92996797, 1.1024806, 0.78045387, 1.2298879 }, { 0.19029829, -0.022675055, 0.28113642, 0.034941166 }, { 0.013203939, 0.013034069, 0.013414649, 0.011688038 }, { 0.076026927, 0.13838472, 0.29961655, 0.31531564 }, { 0.089182386, 0.010401684, 0.029374547, 0.22995838 }, { 0.052198894, 0.039866726, 0.11570972, -0.013818992 }, { 0.0062380932, 0.01788119, -0.20765047, 0.013339281 }, { 0.12436441, 0.17318651, 0.21554136, 0.18600144 }, { 0.38005287, 0.32135548, 0.28632777, 0.29211902 }, { 0.03798742, 0.0450845, 0.010912505, 0.039060104 } }, { { 0.00077914246, 0.00011130803, 8.1110229e-05, -0.00035312557 }, { 0.00051711901, 0.00029701387, 0.00040733345, 0.00034149723 }, { 0.00063893978, -0.00013702086, 0.00030866699, -0.00020070677 }, { 7.5899443e-05, 9.7456273e-05, -4.5352178e-05, 7.6172703e-06 }, { 0.00066250814, -0.00073033349, 0.00015225542, -0.0010197351 }, { 0.00040931533, -0.00043022747, 0.00093333285, 0.0002579685 }, { -0.00067488578, -0.0003706974, -0.00044487256, -0.00056555959 }, { 0.00075838366, -0.0021903789, -0.0026744174, -0.00047135202 }, { -0.00081050821, -0.0010297809, -0.00099480849, -0.00074914246 }, { 0.00063637392, 5.248783e-05, 0.00044645091, 0.00018028446 }, { 0.00067430392, 0.0004762628, -0.00032736685, 0.00041933609 }, { 6.2324555e-05, -1.6709531e-06, 0.00057418116, -0.0010360999 }, { -0.00038256183, -0.0010104012, -0.00045533693, -1.3888404e-05 }, { 0.00068274628, 0.00068411875, -0.00091273333, 0.00016211145 }, { -0.00039440715, 0.00027665323, -0.00035895503, 0.00013423207 }, { -0.00061939017, 0.00012140102, 0.00024178233, 0.00064755788 }, { -0.00052441128, -0.00050994483, -0.00051126044, 0.00066320373 }, { 0.00085915332, 0.0013567332, -0.00014328466, 0.00056098523 }, { -0.0012682676, 0.0029139719, 0.0019812291, -0.00053863027 }, { 0.0021895869, 0.00062956835, 0.0018161156, 0.00011699452 }, { -0.0010337306, 0.00016880497, -0.0014942346, -0.0034402453 }, { -0.0025336946, -0.00019468865, -0.00018045349, -5.4312149e-05 }, { 0.00021491979, 4.7651714e-05, -0.00044921151, 0.00046742044 }, { 0.0019408125, 0.00044842687, 0.0026003265, -0.00090116109 } }, { { -0.0006591255, 0.00022873584, 0.00026313866, -0.00060151354 }, { 0.00027198127, 0.00034252944, 0.00033246896, 0.00035232159 }, { -0.00034460639, -5.9085725e-05, 7.836454e-05, -0.00018946388 }, { 0.00018790551, 0.0001918358, 9.7031467e-05, 0.00015259869 }, { -0.0023033429, -0.0012945186, -0.00080964072, -0.00030432514 }, { -0.001359781, 0.00055828912, -0.00041912301, 0.00019263336 }, { -0.00042789448, -0.00018313775, -0.00030217124, -0.00028437496 }, { -0.0018340159, 0.00030654336, -0.00010781402, -0.0011985455 }, { -0.002103478, 0.00029492518, -0.00042283946, -0.001472689 }, { 0.00064558079, 0.00049703204, -0.00018932594, -0.00038268301 }, { -0.00097813334, -0.00057838807, 0.00079268109, 0.00039650774 }, { -0.00017335252, 0.00074363734, 0.0008194423, -0.00065923207 }, { -0.00075344545, -0.00026114262, -0.00054658657, -0.0013814943 }, { -0.00028279346, 0.00055730283, 0.00048990213, -0.00022186466 }, { 0.00013438509, -0.0001962818, -0.00036195953, 0.00042669461 }, { -0.00089003585, -0.0011600794, -0.0012554286, -0.0012892408 }, { -0.00067007058, -0.0010597247, -0.0010590421, 0.00044132516 }, { 0.0011626727, 0.001261033, -0.00072912018, 0.00076332442 }, { -0.001204702, -0.00011230019, 0.00036178615, -0.0017559004 }, { 0.00096282849, 0.001025959, 0.0011696947, 0.00046633555 }, { -0.00082328571, -0.00075771669, -0.0011629302, 0.00073458863 }, { -0.0016869269, -0.00035239862, -0.0004024204, -0.0016276971 }, { 0.00029053123, 0.00013409355, -0.00049087974, 0.00061969429 }, { -0.0013198997, -0.0018615784, -0.0025724061, -0.0015563017 } } } }, { { { { -0.072246889, -0.043157285, 0.043289306, 0.095998047 }, { 0.12597079, 0.24289541, -0.10930005, -0.24150539 }, { 0.031889347, -0.036238337, -0.014521983, -0.018963885 }, { -0.044155351, -0.0077170425, -0.043781059, 0.047982339 }, { 0.093995001, -0.0079510758, -0.04688882, -0.11125523 }, { 0.01700754, -0.0034361033, 0.055252382, -0.053119426 }, { -0.0014957087, -0.00063057103, 0.037930463, 0.017656646 }, { -0.017388477, -0.084085888, -0.067726647, 0.061397079 }, { -0.070625168, -0.061293011, -0.077366932, 0.11518646 }, { -0.14771316, -0.12543895, 0.052150789, 0.10530462 }, { -0.03609139, 0.001131616, -0.039549928, 0.03805765 }, { 0.064364205, 0.066758929, 0.045537002, -0.05510954 }, { 0.049051369, 0.098312455, -0.01079726, -0.11202623 }, { 0.033012208, -0.0013996988, -0.0049458824, -0.028981527 }, { 0.008617177, -0.00017670863, -0.0052380282, -0.0023438457 }, { -0.05901498, -0.050754807, -0.00011829844, 0.037297411 }, { -0.056264446, -0.03645315, -0.066412698, 0.019549244 }, { -0.11401603, -0.11856524, 0.12275022, 0.11635143 }, { -0.0011999881, -0.0016334327, -0.0056868938, 0.013393766 }, { 0.054526972, 0.033632235, 0.062591094, -0.0025531074 }, { 0.073041316, 0.073735243, -0.06935254, -0.11214186 }, { 0.034872822, -0.015473423, 0.037359975, -0.026829465 }, { -0.015137592, -0.0064462553, 0.011771178, 0.0025042048 }, { -0.038708904, -0.033968131, -0.044070885, 0.024422773 } }, { { -0.047895007, -0.016535938, 0.04855533, 0.018341613 }, { 0.004310087, 0.01519838, -0.0033290683, -0.013597406 }, { 0.0015859181, 0.016869623, -0.019279963, -0.01426933 }, { -0.0061048976, 0.031131561, 0.018085381, -0.017927117 }, { 0.052590378, 0.0066156852, -0.0025756141, -0.037241705 }, { 0.0083512619, 0.0046235666, 0.024122126, -0.013443654 }, { 0.0010672274, 0.00053123301, -0.0016276029, -0.04221993 }, { -0.0048754166, -0.021474788, -0.0039993317, 0.011831691 }, { -0.054685347, -0.050242732, -0.007606251, 0.043061893 }, { -7.5644942e-05, 0.00086632318, 0.0001960729, 0.0013264286 }, { 0.0042413724, -0.0057181522, 0.0065940983, -0.0078263328 }, { 0.0031260881, -0.0013520907, 0.025073658, -0.010841673 }, { 0.038353769, 0.06620308, -0.0072105562, -0.079188681 }, { 0.003099559, -0.0022927921, 0.021982683, -0.018991144 }, { 0.012285675, 0.0091834074, -0.0041874571, -0.032253924 }, { -0.014563556, 0.009843969, -0.010490279, 0.012979866 }, { -0.005492286, 0.064109426, -0.034795617, -0.020395732 }, { -0.023364141, -0.059336321, 0.080710391, 0.038948527 }, { 0.0028384819, 0.001822471, 0.0012903958, 0.012781079 }, { -0.004510518, -0.0020008272, 0.0017752876, 0.0077607089 }, { 0.032279653, 0.0041906079, -0.034682371, 0.0061335907 }, { -0.0082992317, -0.025250117, -0.017026845, -0.028345042 }, { -0.013132125, -0.026688493, -0.0014827793, -0.003236826 }, { 0.01650781, 0.002313574, -0.012897922, 0.026077933 } }, { { 0.062668058, 0.0081578851, 0.018952049, -0.012267283 }, { 0.0008567722, 0.0033246009, -0.0037620102, -0.0096317368 }, { -0.0083012273, 0.01184624, -0.01209373, 0.020208536 }, { 0.013862003, 0.019166381, 0.013235471, -0.026788736 }, { -0.021904217, -0.051018749, 0.0020330268, 0.006626371 }, { -0.015856131, 0.0028024655, -0.032825412, -0.018920906 }, { 0.0020870233, 0.0011616727, -0.0032704368, -0.027327141 }, { 0.01934969, 0.002427195, 0.049925128, -0.0061414889 }, { 0.013158375, 0.022248445, 0.040266734, -0.017583455 }, { 1.9024812e-05, 0.00071602053, 0.0012622199, 0.0018791611 }, { -0.0011857767, 0.0023417924, 0.026237548, -0.014687892 }, { -0.041419782, 0.024942194, -0.029143101, 0.036590943 }, { -0.015470651, -0.035208671, -0.038530514, 0.037434376 }, { -0.0029356279, 0.0023358079, 0.017641055, 0.0038203652 }, { -0.0030449623, -0.010187444, 0.0066142145, 0.0037433206 }, { 0.0080034603, 0.011463159, -0.0058129532, 0.011831147 }, { -0.0091743137, 0.045949289, 0.022412137, -0.0067531419 }, { 0.00069946656, -0.0068974782, 0.0091806954, 0.0022160793 }, { -0.0027530077, 0.00089797627, 0.0066153093, -0.010355635 }, { -0.019399018, -0.0085762573, 0.0208003, -0.027739023 }, { -0.014354809, -0.011971089, -0.0031124986, 0.044710091 }, { -0.011411144, 0.0073253411, -0.0087561348, -0.014838738 }, { 0.018837992, 0.00231775, -0.013982978, -0.0020044658 }, { 0.0012069362, 0.0012202952, 0.029106153, 0.00062793994 } } }, { { { 0.054154158, -0.11603661, -0.025631275, 0.054671866 }, { -0.2359715, 0.093194255, 0.21874866, -0.08378526 }, { 0.0089903397, 0.0087113885, -0.015445726, 0.011142042 }, { -0.0055372249, -0.0041494086, -0.033355186, -0.010136823 }, { -0.015010227, -0.0077144008, 0.13058394, -0.016779666 }, { -0.015855009, 0.014090685, 0.026549575, 0.025677527 }, { -0.00065423811, -0.0011506403, 0.028628751, 0.0086359197 }, { -0.010571292, 0.035861454, -0.025871285, -0.024827688 }, { 0.00010603924, 0.011433504, -0.052819957, -0.020208661 }, { 0.12243361, -0.14574398, -0.10091072, 0.054524772 }, { -0.014659734, -0.02291001, 0.010102434, -0.0099333349 }, { -0.0079939087, 0.023468399, 0.044548395, 0.04568814 }, { -0.048188816, 0.016469102, 0.084818672, -0.040634065 }, { 0.015089138, 0.025396216, 0.017000121, 0.010820807 }, { -0.0098155552, -0.00080001495, 0.0020122754, -0.00046896909 }, { -0.0018906417, -0.03909342, -0.020339049, -0.024007559 }, { -0.0012744487, -0.027829333, -0.05202457, -0.024366779 }, { 0.10406956, -0.092281421, -0.050420166, 0.10716663 }, { -0.0049603976, -0.0055370076, -0.0016910106, 0.012172389 }, { -0.0026486448, 0.038673757, -0.0016176887, 0.052692494 }, { -0.03722357, 0.055455783, 0.067738953, -0.0087990582 }, { -0.0026491637, 0.017275247, 0.010687117, 0.020312052 }, { -0.0016032469, 0.0090272843, -0.0079027514, -0.0050039898 }, { -0.0073653412, -0.033150577, 0.0082912493, -0.021457881 } }, { { -0.0059001999, 0.033600833, 0.066374213, -0.018058548 }, { -0.0037864945, -0.0064946131, 0.0018627774, 0.0044899139 }, { 0.0048961861, -0.0034770968, -0.0002311598, -0.0053935761 }, { 0.0090090757, 0.012149811, 0.0029969663, 0.0049403543 }, { -0.042874682, -0.0083455851, -0.0064437344, 0.0010579362 }, { 0.011866873, -0.017157526, -0.014724976, 0.0054373752 }, { -0.0006329516, -0.00024834697, 0.0015416168, -0.014246989 }, { 0.031530357, -0.052715858, -0.0063186617, -0.0070200141 }, { -0.0082273844, 0.053856605, 0.0096812384, 0.01684635 }, { -0.00017150577, 0.00097354737, 0.0013944706, 0.00085166684 }, { -0.013604545, 0.0089329355, -0.013809086, 0.0025044469 }, { -0.020284731, 0.0004724419, -0.045697697, -0.01844702 }, { 0.017874081, -0.0040537465, -0.023316716, -0.026344708 }, { 0.0092557469, -0.014456327, -0.0092919835, 0.0091758924 }, { 0.016058873, 0.0019220807, 0.0031692823, 0.0024577167 }, { -0.021184352, 0.021287579, -0.0048442696, 0.0095799112 }, { 0.035229915, -0.054291919, -0.013871324, 0.035585241 }, { 0.001275203, 0.011513119, 0.020184769, -0.0061701639 }, { 0.011353237, 0.0052697685, 0.0047637419, -0.020278005 }, { 0.0068266296, -0.01173749, 0.037482577, -0.0083236299 }, { 0.025699221, -0.03651135, -0.032342446, -0.0059784486 }, { 0.0029540635, -0.0021598269, 0.0028168477, 0.0044577193 }, { 0.0038274002, -0.0050806333, 0.007628551, 0.0027461742 }, { 0.0056567464, 0.006846664, -0.031161558, -0.0040832656 } }, { { 0.025668431, 0.0093723617, 7.4324163e-05, -0.023051436 }, { -0.010148124, 0.0018159908, 0.0072269566, 0.00082671261 }, { 0.0069741056, 0.023493533, 0.028507618, -0.026874125 }, { 0.0083316277, -0.024891629, 0.013623217, 0.0038373532 }, { -0.020992516, 0.070912136, -0.0014634877, -0.015680371 }, { 0.02178962, -0.003772636, -0.024578501, -0.047467019 }, { 0.0028586275, 0.0033445767, 0.0049576063, -0.017365739 }, { 0.0075721122, 0.010652219, -0.024031886, -0.0001146548 }, { 0.016381176, -0.044765924, -0.038036229, -0.014041395 }, { -0.00082564842, 0.00033107944, 0.00073792054, 0.0005712734 }, { 0.0080934887, 0.014534447, -0.0071347609, 0.0085413493 }, { -0.018211778, 0.0064443848, 0.017393403, 0.011490985 }, { -0.071531366, 0.030059694, 0.049103287, 0.0074609412 }, { 0.00770209, -0.017999995, -0.040048679, -0.0029073853 }, { 0.020442166, 0.0019454488, -0.019644905, 0.021793285 }, { 0.035171271, 0.0080192155, -0.023151504, 0.014168348 }, { -0.048901887, -0.0039613606, 0.0021703807, 0.030275152 }, { 0.044666116, -0.029756153, -0.015570779, 0.034470632 }, { -0.0078700362, 0.0037551741, 0.0003070052, -0.0031237403 }, { 0.015288427, -0.01284757, -0.0075319169, 0.026981487 }, { -0.0093872483, 0.013517073, -0.030221944, 0.058356065 }, { 0.0042326205, -0.016381154, 0.021475001, 0.01008732 }, { 0.0034929117, 0.020531314, -0.0085114063, 0.004821913 }, { 0.014314413, 0.01127037, -0.017197896, 0.0046932185 } } }, { { { 0.99591552, 0.99230689, 0.99873374, 0.99387895 }, { 0.96356049, 0.96556546, 0.96964041, 0.96677566 }, { 0.99945097, 0.99930521, 0.99977525, 0.99975808 }, { 0.99900933, 0.99996161, 0.99848418, 0.99879675 }, { 0.99545951, 0.99993863, 0.99032786, 0.9936502 }, { 0.99972964, 0.99989482, 0.99811938, 0.99825798 }, { 0.99999867, 0.99999914, 0.9988702, 0.99980681 }, { 0.99979292, 0.99581299, 0.99736843, 0.99780458 }, { 0.99750292, 0.99805433, 0.99560254, 0.9931383 }, { 0.98142286, 0.98133774, 0.99352772, 0.9929441 }, { 0.99924096, 0.99973689, 0.99916652, 0.99922617 }, { 0.99789446, 0.9974931, 0.99796885, 0.99743448 }, { 0.9976331, 0.99501931, 0.9963379, 0.99287411 }, { 0.99934104, 0.99967648, 0.99984325, 0.99952138 }, { 0.9999147, 0.99999966, 0.99998426, 0.99999714 }, { 0.99825531, 0.99794572, 0.99979313, 0.99901579 }, { 0.99841509, 0.99894779, 0.99643504, 0.99951192 }, { 0.98801309, 0.98864879, 0.99115599, 0.98740957 }, { 0.99998698, 0.99998334, 0.9999824, 0.99983621 }, { 0.99850879, 0.99868574, 0.99803794, 0.99860752 }, { 0.99663402, 0.99573479, 0.99528974, 0.99365325 }, { 0.99938825, 0.99973103, 0.99924472, 0.99943364 }, { 0.99988413, 0.99993848, 0.99989949, 0.99998434 }, { 0.99922338, 0.99887297, 0.998994, 0.9994714 } }, { { -0.0050599833, 0.003362263, 0.0035202243, -0.00056864904 }, { -0.0014675187, -0.0029154981, -0.00077796172, -0.0027392627 }, { -0.0010916411, 0.00078232803, 0.0014339533, -0.0020166729 }, { 0.011183745, 0.008298699, 0.011631254, 0.00030693508 }, { -0.0012964861, -0.00028098882, 0.00098513135, -0.0052243577 }, { 0.0091119501, 0.002780703, 0.011045274, 0.00334383 }, { 4.1103001e-05, 5.5767744e-05, 0.0030605577, 0.0022152241 }, { 0.00085375099, 0.0026952672, 0.0071937971, 0.0056504112 }, { -0.003773118, 0.0047936307, -4.5743022e-05, -0.0038357994 }, { 2.3815581e-05, 0.0002468657, 0.00013492048, -0.00018410816 }, { 0.0070959632, -0.00205589, 0.0056417297, 0.0030702073 }, { 0.010671769, 0.0074346008, 0.0012867659, 0.0075437523 }, { -0.0013037272, -0.0058374269, 0.0025899757, -0.0071565118 }, { 0.0030041304, 0.0018011397, 0.0093160386, 0.0082062863 }, { 0.0053156934, 0.0036543193, 0.0048724246, 0.0035118324 }, { -0.0053866158, 0.0024053442, 0.00052459148, 0.0090970513 }, { 0.011239324, -0.0010327051, -0.00097551594, 0.0044180668 }, { -0.0024379533, -0.0088232426, -0.012355568, -0.0031875953 }, { 0.0026244123, 0.0011858999, 0.0028110843, -0.001005442 }, { 0.0059514328, 0.0018892606, 0.0050231625, 0.0046700575 }, { 0.00050741664, 0.0096547476, -0.00079618251, 0.0024532112 }, { 0.0058717468, -0.0017457656, 0.0080261577, -0.00048009588 }, { 0.0025457914, 0.0016788968, 0.0013982313, 0.00073909928 }, { 0.0075035778, 0.011234409, 0.0079271096, 0.006672353 } }, { { 0.0095152396, 0.0011785006, -0.00081996856, 0.0018904938 }, { -0.0025430397, -0.0010236291, -0.0020168276, -0.0021827861 }, { 0.0036295778, 0.005406882, 0.0040788276, -0.0057729163 }, { -0.00029952998, 0.0024548208, 0.0088548836, 0.0019084209 }, { 0.0034184324, -0.0088925589, 0.00023040452, 0.00017437939 }, { 0.0037804595, 0.012156355, 0.0041276361, 0.012721488 }, { 7.4846461e-05, 0.00010580108, 0.013483417, 0.0024239851 }, { 0.00026411032, -0.00059353627, 0.0093564271, 0.0061507538 }, { 0.0016065383, -0.0027764641, 0.0013620195, 0.0010062065 }, { 9.7127925e-05, 0.00017275393, 1.0814607e-05, -0.00022627793 }, { 0.0048710612, -0.00014794569, 0.0082832436, -0.00072595412 }, { -0.0027392579, 0.0066783951, 0.00087397132, 0.001567366 }, { -0.003378151, 0.0025916338, -0.0025553201, 0.0030152022 }, { 0.0096818399, 0.0012695523, 0.0072489949, 0.016881099 }, { 0.0022796191, 0.0051693266, 0.0023373397, -0.0041448561 }, { -0.0002074582, 0.0035962454, -0.0007460719, 0.0025086317 }, { 0.0035784996, 0.003162753, 0.0022592918, 0.00024595998 }, { -0.0051294944, -0.0041428868, -0.0027597, -0.0039539398 }, { 0.0022410392, 0.00031263884, 0.0016376751, -0.0022787113 }, { 0.0025647038, 0.0074733037, 0.0051722028, 0.0024463612 }, { 0.0011787227, 0.0071159753, 0.0017217143, 0.0062717989 }, { 0.0046836737, 0.0038976423, 0.00062832002, 0.0027638154 }, { 0.0014142926, 0.0024903802, 0.0015757227, 0.0011628587 }, { 0.0016928585, 0.0043828548, 0.001653268, 0.011450696 } } }, { { { 2.8886078, 2.8900127, 2.7925705, 2.7895874 }, { 4.5455217, 4.5284714, 4.7042338, 4.6915273 }, { 0.96672505, 0.99303664, 0.98927606, 1.0351588 }, { 1.2743756, 1.2525364, 0.99649566, 0.94572778 }, { 2.6910679, 2.6922168, 2.8503404, 2.8246076 }, { 1.256075, 1.2325025, 1.5911826, 1.6091223 }, { 1.3601759, 1.3606869, 1.2793533, 1.240925 }, { 2.0291828, 2.0506809, 1.7341658, 1.6555689 }, { 2.6663531, 2.6921882, 3.1290975, 3.11849 }, { 5.3676887, 5.3663279, 5.3848664, 5.3852162 }, { 1.0586431, 1.0865889, 0.8196623, 0.8076665 }, { 1.6967251, 1.7305944, 1.5450413, 1.6347879 }, { 3.0908857, 3.0706775, 3.2974343, 3.3053965 }, { 1.2172073, 1.3839086, 1.5086796, 1.4295506 }, { 0.97676668, 1.0856738, 0.98747912, 1.0385491 }, { 1.5662275, 1.4603538, 1.784278, 1.6575438 }, { 2.1085757, 2.2092885, 2.1410448, 2.1518347 }, { 4.0214776, 4.006424, 3.7686967, 3.7771354 }, { 1.2089239, 1.2116036, 1.1244311, 1.0901017 }, { 1.1827246, 1.1472796, 1.7516784, 1.7833976 }, { 2.2113439, 2.197512, 2.2692963, 2.2787751 }, { 0.98819531, 1.057833, 1.3587301, 1.3890421 }, { 1.208957, 1.2247867, 1.2301205, 1.2325178 }, { 1.0499613, 1.1319197, 1.4067885, 1.3209087 } }, { { -0.002860931, -0.0033581281, -0.0047612075, -0.0030481839 }, { -0.0017370907, -0.0065700936, -0.0011051926, -0.0046915938 }, { -0.0006126207, 0.0010791181, -0.022876686, -0.015937275 }, { -0.010040922, -0.016433531, -0.0044976975, -0.029838315 }, { 0.00056888968, -0.0093450028, -0.00041549218, -0.0069079656 }, { -0.029781683, -0.019722587, 0.019472312, 0.0016798037 }, { -0.0015128736, -0.0012250172, -0.0091568262, -0.0091368119 }, { 0.0010846814, 0.0017189068, 0.012975603, -0.0051530971 }, { -0.026042808, -0.0090684857, -0.0021498742, -0.0032938309 }, { -0.0012792901, -0.0010431731, -0.0021366737, -0.0025526365 }, { -0.03218779, -0.013848893, -0.021872476, -0.029443623 }, { 0.008300061, 0.011951182, -0.011139414, 0.0098292843 }, { -0.0065854884, -0.020955083, -9.3843515e-05, -0.0078425688 }, { -0.054726229, -0.0073673428, -0.019267231, -0.03383648 }, { -0.049769726, 0.0065482059, -0.010189395, -0.0050480393 }, { 0.022565943, -0.020311569, 0.0091512717, -0.015600752 }, { -0.014418429, 0.0060070592, -0.0055296743, -0.003361885 }, { 8.8146509e-05, -0.0082609252, 0.0036746024, 0.0040108321 }, { 0.0010230427, 4.8153189e-06, 0.0052893378, -0.0096303521 }, { 0.0032909351, -0.010982824, 0.003880027, 0.0097699095 }, { -0.006528317, -0.012608887, -0.0057088008, -0.003867806 }, { -0.046599771, -0.024701737, -0.001078321, -0.0041018649 }, { -0.021680777, -0.021120711, 0.0055144734, -0.0031337995 }, { -0.030559213, 0.0089872726, -0.011166202, -0.0077587071 } }, { { -0.0059548858, -0.0040070313, -0.0062572119, -0.0047711065 }, { -0.0031938803, -0.005431389, -0.0026376521, -0.0046119366 }, { 0.0064917253, 0.013030824, -0.027850471, -0.011824849 }, { -0.032644485, -0.025045016, -0.0034396539, -0.039827623 }, { -0.007691681, -0.014095643, -0.0008171964, -0.0051336386 }, { -0.035626586, -0.021424668, 0.00035790929, 0.0099705685 }, { -0.0019006762, -0.0014887089, -0.0050782898, -0.0096835564 }, { -0.00087496879, 0.0052586834, 0.017041675, -0.00046753956 }, { -0.022489507, -0.0084834888, 0.0017184219, -0.0023910992 }, { -0.0010618265, -0.00085888729, -0.0020035777, -0.0024245283 }, { -0.029245834, -0.038977066, -0.013385246, -0.030312138 }, { -0.0028497869, 0.014205986, -0.0125692, 0.0037959624 }, { -0.0086377959, -0.019175965, -0.007684309, -0.005037677 }, { -0.063945685, -0.0060751259, -0.0057457302, -0.019079575 }, { -0.043745147, 0.013651906, -0.034067394, 0.0012111497 }, { 0.0086647574, -0.019171418, 0.020745219, -0.0055629951 }, { -0.024541273, 0.0072112135, -0.0078821942, -0.0085072621 }, { -0.0018227939, -0.0021153099, 0.008577002, 0.0043865151 }, { -0.013984752, -0.012209334, 0.00023638151, -0.0085025952 }, { -0.0099800075, -0.0095390578, 0.0081328135, 0.012673433 }, { -0.0099975551, -0.0028467616, -0.010712056, -0.0045012212 }, { -0.011329139, -0.0084709831, -0.0070232966, 0.0015504012 }, { -0.015334801, -0.0075637633, -0.01107439, -0.0094188163 }, { -0.017505269, -0.00013701888, -0.033955823, -0.034192649 } } }, { { { 0.16413327, 0.084074422, 0.10646123, 0.18806073 }, { 0.039511019, 0.058967072, 0.035166958, 0.052296507 }, { 0.26970995, 0.21576211, 0.2954278, 0.29870678 }, { 0.40442043, 0.38744132, 0.14502571, 0.24076804 }, { 0.22655046, 0.20912486, 0.015295019, 0.16442957 }, { 0.69235319, 0.6080183, 0.36756076, 0.23314717 }, { 0.085565328, 0.075535626, 0.22162979, 0.33140596 }, { 0.16109547, 0.11961895, 0.26619212, 0.25941009 }, { 0.27077686, 0.23481238, 0.063446408, 0.11614487 }, { 0.026116057, 0.027491327, 0.030421883, 0.039965345 }, { 0.33922592, 0.38039792, 0.27167385, 0.31510976 }, { 0.32744968, 0.22567102, 0.23116584, 0.18867836 }, { 0.29783431, 0.28054079, 0.26752139, 0.23889932 }, { 0.61721263, 0.60602797, 0.51283622, 0.47601102 }, { 0.51383952, 0.53111455, 0.44519064, 0.42875877 }, { 0.3485879, 0.35374178, 0.53292055, 0.53995494 }, { 0.4366997, 0.35554257, 0.14878367, 0.22083288 }, { 0.12855375, 0.16718264, 0.17583661, 0.11125895 }, { 0.35898096, 0.37222307, 0.35439108, 0.35956111 }, { 0.16773044, 0.25668894, 0.23246756, 0.1506316 }, { 0.36172813, 0.26938211, 0.20069185, 0.1714591 }, { 0.3998571, 0.23607244, 0.34121623, 0.29126696 }, { 0.31471307, 0.29500525, 0.39451396, 0.40013999 }, { 0.29554399, 0.28083636, 0.47190649, 0.47892938 } }, { { 0.01419653, -0.061214452, -0.032506906, 0.0078227125 }, { -0.015799432, 0.0136148, -0.0090824684, 0.013638505 }, { 0.023848919, 0.022034707, 0.022812846, 0.022790329 }, { -0.0026324255, -0.0053566952, 0.00027470228, 0.050203583 }, { 0.0035659857, -0.02015272, -0.039043616, 0.054511651 }, { 0.0052075445, 0.0051043119, -0.011801097, -0.0074336577 }, { 0.020735195, 0.01811747, 0.00808952, 0.01140964 }, { -0.0073139049, 0.011075347, 0.0057685988, 0.010251582 }, { 0.024813488, -0.01629986, -0.012536791, -0.01110061 }, { -0.014508648, -0.021444084, -0.023836972, -0.014258253 }, { 0.0079687141, -0.00092011446, 0.060249601, 0.033199468 }, { -0.020822483, -0.013924875, -0.005068391, -0.016928794 }, { -0.030059, -0.013887475, -0.045329289, -0.04449219 }, { 0.007264541, 0.0015213919, -0.0066322618, -0.0036449174 }, { 0.0057175046, 0.0012159867, -0.00054271896, 0.0020625484 }, { 0.0027083179, -0.0012554897, -0.0044854592, -0.0045242423 }, { -0.017906563, -0.028301884, -0.010139427, 0.0035851304 }, { -0.020245794, 0.01149232, 0.011320484, -0.013561794 }, { 0.0068048997, 0.011957759, 0.0046962412, -0.0015476541 }, { -0.0022514613, 0.019996868, 0.0051520398, -0.023405604 }, { 0.0055213198, 0.0070384134, 0.024405643, -0.02050399 }, { 0.039987541, 0.021127504, -0.012323503, -0.0041538161 }, { 0.0072321478, 0.0053097351, 0.0039966161, 0.013617175 }, { 0.030470642, 0.0044694115, -0.0024591651, -0.0027274707 } }, { { -0.040500402, -0.039657034, -0.017497359, -0.017857145 }, { -0.0015646885, -0.020957371, -0.0057356498, -0.0060587007 }, { 0.0070388709, -0.013205178, -0.00033412934, 0.02192306 }, { -0.0042317723, 0.020620857, -0.012309167, 0.065948811 }, { -0.016686589, 0.013616667, 0.030139062, -0.019023551 }, { 0.015181564, 0.008673659, -0.0014559576, -0.025916054 }, { 0.031630671, 0.027030197, -0.026982415, 0.025214731 }, { -0.003845127, -0.00062884599, -0.029488655, -0.0051457939 }, { -0.0032476351, 0.0021153707, -0.033110808, -0.033629213 }, { -0.0064637077, -0.010805748, -0.014982403, -0.0084641529 }, { 0.0087766042, 0.017780238, 0.026838871, 0.032580257 }, { 0.0010700985, -0.037414784, -0.0053773565, 0.0040969752 }, { -0.02637392, -0.050236074, -0.048422986, -0.069357813 }, { -0.0089483588, 0.0026259727, 0.0040142797, -0.010752754 }, { -0.0025658872, 0.0071106029, 0.015467367, 0.0012536589 }, { -0.0037247444, -0.0036991733, -0.015429566, -0.016148852 }, { -0.024788221, -0.045938054, -0.028679471, 0.011593494 }, { -0.032699114, -0.036800967, -0.033870575, -0.031842203 }, { 0.018156047, 0.02457546, 0.0209432, 0.015057433 }, { 0.0043152638, 0.025831372, -0.019608349, -0.026614397 }, { -0.0057047815, -0.013831909, 0.027613211, -0.043616864 }, { 0.014124478, -0.010786326, 0.010775415, -0.023241344 }, { 0.018337827, 0.0048735321, 0.018371717, 0.022106807 }, { 0.013619207, 0.022051384, 0.0082720974, -0.0030262071 } } } }, { { { { 0.083322661, 0.079807165, 0.03660117, -0.051657142 }, { -0.099216074, -0.0080141573, 0.10637241, 0.0367403 }, { 0.20813681, -0.0001361621, -0.20762563, -0.085913357 }, { -0.22091149, 0.10003156, -0.16122219, 0.31542901 }, { 0.16226908, 0.02665194, -0.012123307, -0.16559939 }, { -0.14025496, 0.025804505, 0.076174345, 0.20548591 }, { 0.0035713609, -0.0092551928, -0.099937652, 0.0038879391 }, { 0.12405732, -0.0053373497, -0.030865175, -0.060934551 }, { -0.0060175826, -0.026583926, -0.075326797, -0.0063155886 }, { 0.036389362, 0.054175433, 0.06490927, -0.038784258 }, { 0.30604876, -0.030813476, 0.011402956, -0.21074796 }, { -0.31769497, 0.046793931, -0.038212559, 0.21137297 }, { 0.12952945, 0.20720126, 0.08525845, -0.14568109 }, { -0.09735197, -0.17799099, -0.12256082, 0.038889119 }, { 0.002114572, 0.026037779, -0.0036772795, 0.13478173 }, { 0.094577863, 0.0057382415, -0.087017736, -0.059444148 }, { 0.054953104, 0.071323301, 0.097417831, 8.3254475e-05 }, { -0.11005534, 0.027214076, 0.0059378205, 0.02443999 }, { 0.27096654, 0.1864966, 0.034810947, -0.25886676 }, { -0.35626794, 0.037256657, -0.17795321, 0.52988269 }, { 0.14913899, -0.0086988732, -0.028760192, -0.21779266 }, { -0.16010301, -0.17699785, 0.017269826, 0.17878541 }, { -0.0049504093, -0.02387924, -0.04034852, -0.060461173 }, { 0.10405347, 0.0072745723, -0.10244372, -0.072981984 } }, { { 0.019363393, 5.327311e-05, 0.0075925373, 0.0019542034 }, { -0.051707557, 0.06554253, 0.0050626046, -0.0061857803 }, { 0.022891698, 0.014872273, -0.020436928, 0.0069081531 }, { -0.044566611, 0.019854557, 0.023600607, -0.0055387351 }, { 0.02283957, -0.067086756, 0.088865856, -0.033915007 }, { 0.0020254431, -0.16422426, 0.032495902, 0.012460808 }, { -0.017316175, 0.023440087, 0.011459595, 0.0043887872 }, { 0.027714908, -0.06907548, 0.013578806, -0.009848884 }, { 0.0044782488, 0.0079432606, 0.010143137, 0.023589488 }, { 0.014325082, 0.0075465848, -0.0079373813, -0.0056032635 }, { 0.025123579, 0.01904807, -0.0092328848, -0.019002052 }, { -0.02633985, -0.019560519, -0.065544737, 0.0073352606 }, { 0.044308433, -0.0032233834, 0.01324206, -0.00047128106 }, { -0.076577611, -0.021853603, -0.020190543, 0.0026420865 }, { -0.0029799448, -0.0083566545, 0.14896601, 0.0078617095 }, { 0.021033237, -0.08234711, -0.020642328, -0.0089829962 }, { 0.043793881, 0.0096494147, 0.035831274, -0.01294602 }, { -0.014064874, 0.066144489, 0.0143429, 0.015113964 }, { 0.043111732, 0.0029232804, -0.016912145, 0.012142059 }, { 0.0014186333, -0.0078590166, 0.065781153, -0.038375123 }, { 0.02255714, -0.030191796, -0.078373164, -0.0017593196 }, { -0.033878798, 0.016266579, 0.013539653, 0.043519216 }, { 0.019046482, 0.0080403173, -0.0010755939, 0.03305222 }, { 0.023206448, -0.054323067, -0.035173093, -0.010873592 } }, { { 0.014068291, -0.026418786, 0.016375695, 0.0048801469 }, { 0.024404214, 0.0073572002, -0.027247654, 0.00093849398 }, { 0.012741523, -0.012913063, 0.0054881373, -0.021780769 }, { -0.020497215, 0.057437717, 0.0031122704, 0.014713732 }, { 0.012765254, -0.052846334, 0.048042201, 0.0016578534 }, { 0.031245254, -0.0469321, -0.057199738, 0.012436479 }, { -0.0022837759, 0.0068501747, 0.010541107, -0.0005227683 }, { -0.0187059, 0.0025631581, -0.0082184266, 0.0026294483 }, { 0.0053899388, -0.0199458, 0.0023448066, 0.016215236 }, { 0.021117204, 0.010868775, -0.016412681, -0.016399297 }, { -0.0026199223, -0.011436548, 0.0031355049, 0.011933919 }, { 0.017940023, 0.090292392, -0.061029038, 0.016388845 }, { 0.0074493061, -0.045849358, -0.082612855, 0.025851315 }, { 0.061276666, -0.024654813, 0.035447334, -0.025952766 }, { -0.0068267167, -0.02207426, 0.003724368, 0.0070458116 }, { 0.021714649, -0.017552721, -0.037105408, 0.024398534 }, { 0.0092901891, -0.021559075, 0.009034776, -0.016574279 }, { -0.017218595, -0.041930302, 0.003369899, 0.017959363 }, { -0.0022510875, 0.028106616, -0.042936548, -0.041948028 }, { -0.017145551, -0.032331654, 0.021486923, -0.020295391 }, { -0.023196465, -0.088353584, 0.010086154, 0.018689553 }, { -0.024508386, -0.00058959302, -0.02867958, 0.019018994 }, { 0.0088748911, 0.012528454, -0.016636351, 0.0078166115 }, { 0.00066772723, 0.001693912, 0.032066885, 0.016951148 } } }, { { { 0.015200105, 0.071414961, -0.020616434, 0.0063982643 }, { -0.084578144, -0.12318522, -0.035470756, 0.057833574 }, { 0.19487946, 0.44043059, 0.10981527, -0.31907303 }, { -0.17774238, -0.30460726, -0.53133003, 0.31186606 }, { -0.1172677, 0.3183613, 0.10375266, -0.066515168 }, { 0.054176263, -0.12382077, -0.033807438, 0.039809238 }, { -5.3634009e-05, 0.004084452, 0.005103199, -0.060697866 }, { 0.06093199, 0.060355274, 0.049176467, -0.060579228 }, { 0.054611799, 9.0520863e-05, -0.048891261, -0.047609349 }, { -0.036428706, 0.06336736, 0.0020843807, 0.033254378 }, { 0.26975732, 0.51328693, 0.29976157, 0.049031141 }, { -0.28383516, -0.48219276, -0.27898799, -0.033028759 }, { -0.078976834, 0.14077934, 0.098587186, 0.051336328 }, { 0.076281206, -0.074223398, -0.053178835, -0.099578331 }, { -0.056377095, -0.00066113896, -0.11597726, 0.058805777 }, { -0.0027130032, 0.12007881, 0.0081935835, -0.10415807 }, { -0.019349408, 0.06206561, -0.0079099126, 0.079363093 }, { -0.059959607, -0.0591041, -0.047505451, -0.0031496967 }, { -0.11419194, 0.20904287, 0.53960104, 0.10467592 }, { -0.21312862, -0.34770872, -0.54593093, 0.23230512 }, { -0.073229448, 0.12913, 0.27728133, -0.050627706 }, { 0.082312471, -0.24529296, -0.12381516, 0.05577292 }, { 0.03015389, -0.0015805638, 0.024306632, -0.080697961 }, { 0.061367564, 0.056058289, 0.041197211, -0.015551356 } }, { { -0.029269776, -0.030251548, 0.01352869, 0.0084860712 }, { 0.053983187, 0.047657625, -0.026379004, 0.022474039 }, { 0.011898439, 0.045120742, -0.024430477, -0.081318878 }, { -0.0012641508, -0.018495044, -0.030127865, -0.0088483264 }, { 0.040728292, 0.010691761, -0.023566342, 0.028045232 }, { 0.014593998, 0.0047006468, -0.049032498, -0.011446808 }, { 0.00045433705, -0.0030610749, -0.010359449, -0.0026455857 }, { -0.0026794352, -0.032142744, 0.010153936, -0.0034586152 }, { 0.0097198782, 0.0051005644, 0.03482872, -0.0043676475 }, { -0.0012381415, -0.025746274, -0.0081178021, 0.0041481596 }, { -0.01598781, 0.0048815642, 0.06313106, -0.0062291669 }, { 0.072970618, -0.041153529, -0.007457013, 0.059776924 }, { 0.0024768493, 0.0093018711, 0.024827984, 0.043842172 }, { -0.012927661, -0.023256709, -0.0035951539, -0.069710027 }, { 0.0064149713, 0.0019783425, 0.010135188, 0.019449636 }, { -0.0071551675, 0.015761815, 0.0086309278, 0.038854386 }, { 0.020978109, -0.0056696814, 0.0025526797, -0.017352926 }, { -0.010711116, -0.0097050903, 0.0022304504, -0.0039308489 }, { 0.036904234, 0.025927127, 0.028330671, 0.051193417 }, { -0.00076391153, -0.077528792, -0.029763477, 0.0033945843 }, { -0.01775202, 0.034507636, 0.065392848, -0.017840909 }, { -0.019567742, -0.019880035, 0.055214211, -0.02206159 }, { 0.01110111, 0.0022938832, -0.011417507, 0.017692635 }, { 0.050208493, -0.028178909, 0.0065276591, -0.0056267473 } }, { { 0.0065622702, -0.0012303136, -0.0081183663, 0.00079383048 }, { 0.030775912, 0.052260356, -0.019758331, -0.020044147 }, { 0.019016537, -0.043070451, 0.035298744, -0.040592775 }, { 0.010468089, 0.00057085185, 0.0081761984, 0.0033382478 }, { 0.047189462, -0.052695409, 0.021849623, 0.033585939 }, { 0.0012065616, -0.050287476, -0.065085924, -0.039012886 }, { -0.012294892, 0.006839242, 0.0051165438, -2.0711078e-05 }, { -0.03292822, 0.015299577, 0.0029119931, 0.0073040242 }, { -0.0086784873, 0.0085910164, -0.0059378411, -0.010259049 }, { -0.014191355, -0.011172486, -0.01299927, 0.015386671 }, { 0.040453224, -0.041489173, 0.015047889, 0.064340197 }, { -0.020000046, 0.058477092, -0.0018150465, 0.048536972 }, { -0.006105982, 0.03437044, 0.0087640339, 0.032868283 }, { -0.027120362, 0.016579996, -0.01708524, 0.011178424 }, { 0.030535528, 0.0058718219, -0.031240404, 0.024241052 }, { 0.003729958, -0.055735848, -0.0055392842, 0.03447519 }, { -0.04084502, -0.01227488, 0.0062970198, -0.021996031 }, { 0.053671675, -0.067787009, 0.0053426012, -0.0080796738 }, { -0.021911856, 0.038395527, -0.07713235, 0.024805484 }, { -0.0034319194, 0.0052741327, 0.026402991, 0.0012916612 }, { -0.033119652, -0.0046506889, 0.045613946, -0.050230593 }, { -0.0054612035, -0.033482221, 0.084267507, -0.0224334 }, { -0.0063348693, -0.0074524817, -0.0029629355, 0.035493958 }, { -0.0073519185, 0.045139911, 0.0022901735, -0.041385515 } } }, { { { 0.99640669, 0.99424882, 0.99911727, 0.99864438 }, { 0.99146493, 0.99235134, 0.99369348, 0.99764995 }, { 0.95848895, 0.89778665, 0.9720248, 0.943828 }, { 0.95896077, 0.9472107, 0.83168251, 0.89623886 }, { 0.97975356, 0.94759472, 0.99452924, 0.98394744 }, { 0.98863213, 0.99196902, 0.99652121, 0.97785007 }, { 0.99999362, 0.99994883, 0.99498061, 0.99814861 }, { 0.99040248, 0.99816269, 0.99831309, 0.99630173 }, { 0.99848953, 0.99964658, 0.9959596, 0.99884607 }, { 0.9986735, 0.99651874, 0.99788899, 0.99869411 }, { 0.91299789, 0.85766372, 0.953946, 0.97631002 }, { 0.90471405, 0.87481454, 0.959534, 0.97684726 }, { 0.9884254, 0.96811612, 0.9914694, 0.98799879 }, { 0.99232241, 0.98122887, 0.99103524, 0.99426948 }, { 0.99840731, 0.99966074, 0.99324506, 0.98912879 }, { 0.99551377, 0.99274778, 0.99617307, 0.9927827 }, { 0.99830144, 0.99552039, 0.99521214, 0.99684577 }, { 0.99211525, 0.9978808, 0.99885333, 0.99969634 }, { 0.95579147, 0.95995838, 0.84120087, 0.96022443 }, { 0.90975235, 0.9368621, 0.81871367, 0.8156339 }, { 0.98610091, 0.99158952, 0.96035822, 0.97468107 }, { 0.98366238, 0.9531543, 0.99215501, 0.98230604 }, { 0.99953301, 0.9997136, 0.99888998, 0.99490315 }, { 0.99267663, 0.998401, 0.99388534, 0.99721201 } }, { { -0.0021537732, 0.010607958, -0.0066166595, -0.0027390442 }, { -0.0069401807, 0.0053215201, 0.0062121114, 0.013403291 }, { -0.0035740125, -0.021839368, 0.00042431197, -0.029478899 }, { -0.007886159, -0.0087705321, -0.010570968, 0.0040635318 }, { -0.0021772698, 0.00025306776, -0.0092725896, -0.0075657706 }, { -0.010438319, -0.0072866821, 0.009272756, 0.0043932916 }, { -0.00058203184, 0.0081284104, 0.027749999, 0.0035426599 }, { -0.003604276, -0.012244348, 0.0072177908, 0.0026686264 }, { 0.011192179, 0.0069527119, 0.017278396, -0.0053058312 }, { -0.020276487, -0.0063228657, 0.013968347, -0.0021534789 }, { -0.0037534313, 0.00061399133, -0.02126817, 0.0085256452 }, { 0.015620795, -0.022637876, 0.00069280338, 0.0054369037 }, { 0.0095244184, -0.0026896982, -0.0057963534, 0.0067237437 }, { -0.0085689961, -0.004816024, -0.00088793436, -0.0034021999 }, { 0.015428153, 0.019777562, -0.011217833, 0.0095744159 }, { -0.003802304, 0.0022643577, 0.0054254827, 0.025560756 }, { -0.0053298651, 0.021621993, -0.01864184, 0.019120967 }, { 0.015380344, -0.0027384467, 0.0010235928, 0.0062792725 }, { -0.001166873, -0.0049586656, -0.014850883, 0.00057841904 }, { 0.0032865456, -0.033386196, 0.0032068954, 0.02854738 }, { 0.010308266, -0.000233004, -0.020287643, 0.0044441043 }, { -0.0040523345, 0.0050367711, 0.01627907, -0.010032412 }, { 0.0073463987, 0.00073274858, 0.002814661, 0.030221018 }, { 0.0057509063, -0.011441338, 0.01894259, 0.0077856453 } }, { { -0.0053054924, 0.0037677068, 0.0066263851, 0.0011220287 }, { -0.02212139, 0.013769097, -0.0013834097, 0.014152363 }, { -0.0008493126, 0.021473024, -0.0039313241, -0.017764981 }, { -0.00081897848, -0.0074161164, 0.0038179092, -0.0035760615 }, { 0.014045643, 0.015317904, 0.0045966739, 0.0075917156 }, { 0.0035574126, -0.00017773424, -0.0010937491, -0.0017762282 }, { 0.0072018344, 0.012586227, 0.0138702, -0.0085424173 }, { -0.0055783456, -0.019909385, 0.01190919, -0.0065821489 }, { 1.7402026e-05, 0.0094513341, 0.015333305, -0.0072158969 }, { -0.0063049905, 0.0021776758, 0.014376378, 0.0072426401 }, { -0.0078049673, 0.028764242, -0.0024169449, 0.0077604105 }, { 0.00047536469, 0.029806623, 0.0017798261, 0.00087410198 }, { -0.0030498401, 0.0044874501, 0.0020382571, -0.0011101062 }, { -0.0057084397, -0.0013428994, -0.001024136, 0.0066188614 }, { 0.039201052, 0.015120258, -0.0082642793, 0.0051985023 }, { -0.0091203243, 0.020790215, 0.0025270937, 0.020092044 }, { -0.0029830063, 0.006602841, -0.00833601, 0.044852353 }, { 0.025206353, -0.0038915173, 0.00045914851, 0.0037840538 }, { 0.0014814254, -0.011573911, 0.046232337, -0.015228958 }, { -0.0071984443, 0.0090004063, 0.022942838, 0.016019787 }, { 0.0050929336, 0.0060892107, -0.0061771339, 0.0047850766 }, { -0.011634853, 0.0010276548, 0.022396644, -0.0021248711 }, { -0.012943002, 0.0016430074, 0.02034928, 0.024289705 }, { 0.0051047037, 0.010052556, 0.0020923265, -0.019043181 } } }, { { { 2.1627647, 2.1788232, 1.9290264, 1.8457806 }, { 2.526488, 2.3020441, 2.538915, 2.03484 }, { 3.9987521, 4.3952121, 3.906821, 4.1693278 }, { 4.0400466, 4.1069844, 5.2512999, 5.4283264 }, { 3.0141968, 3.3306035, 3.2224806, 3.2473051 }, { 2.9840674, 3.1294685, 3.2964833, 3.2929246 }, { 1.8346741, 1.8637353, 2.3037966, 2.0860888 }, { 2.691236, 2.6068079, 1.9349032, 2.1632935 }, { 1.9231956, 1.7251627, 2.1609654, 2.1155629 }, { 2.165771, 2.1908952, 1.777038, 2.0223741 }, { 4.5166991, 4.8674508, 3.918546, 3.378087 }, { 4.4502295, 4.5429338, 3.9552598, 3.3580272 }, { 3.0973598, 3.3953852, 2.2704362, 2.6488177 }, { 3.2110537, 3.3104376, 2.515002, 2.3267785 }, { 1.8303675, 1.7094345, 3.1787979, 2.5960104 }, { 2.4391795, 2.8730077, 2.3730261, 2.1545299 }, { 2.2130903, 2.1899209, 2.4997355, 1.9058674 }, { 2.6472893, 2.5455636, 2.1164596, 1.8341163 }, { 3.9428283, 4.0433678, 4.5430063, 4.2482776 }, { 4.1941673, 4.28852, 4.64044, 4.6644567 }, { 3.0873642, 2.649364, 3.6026133, 3.2426354 }, { 3.2415154, 3.5406745, 3.2976852, 3.3100246 }, { 1.8400289, 1.8404692, 1.889289, 2.0125184 }, { 2.7063995, 2.7229173, 2.6289878, 2.4313709 } }, { { -0.015335928, -0.043382119, -0.0054163805, -0.028249934 }, { -0.017200109, 0.0027582413, -0.079612821, -0.0013966663 }, { -0.027233584, -0.018783395, -0.01183278, -0.020918937 }, { -0.0036358348, -0.015712206, -0.0089146421, -0.0057117233 }, { 0.020392865, 0.017743746, -0.068597326, -0.030425581 }, { -0.041123673, -0.020767538, -0.0087941887, -0.0065248183 }, { -0.0055478408, -0.00082196865, 0.0088521402, -0.045916836 }, { -0.010506485, 0.0078523247, -0.030002306, -0.0015085765 }, { 0.01894068, -0.012424968, -0.034837214, -0.045009941 }, { -0.045299587, 0.02630478, -0.017175711, -0.043601235 }, { -0.046003661, -0.020588165, 0.034398873, -0.054653787 }, { -0.0042534368, 0.01325834, -0.0036369576, -0.079162988 }, { -0.028728556, 0.0051289128, 0.012104313, 0.010686997 }, { -0.066337767, 0.00059928728, -0.080303668, 0.011318772 }, { -0.031879871, 0.0011317962, -0.050259029, 0.0031596552 }, { -0.090121238, -0.011196084, -0.072456123, -0.00079731072 }, { -0.024243475, 0.021401076, -0.018209385, -0.0083196072 }, { -0.079888701, 0.0032806631, -0.12762259, -0.04652308 }, { 0.031806075, -0.034165157, -0.015255921, -0.049164663 }, { -0.0012051123, 0.030788487, 0.022291919, 0.0025694519 }, { 0.035836509, 0.0055365388, 0.026704836, 0.0001547235 }, { -0.012129747, -0.0094322145, -0.040637935, -0.12125388 }, { -0.027044986, 0.04531553, -0.033484589, -0.0059927923 }, { 0.0067188802, -0.051166351, -0.048822794, -0.025926988 } }, { { 0.022049053, 0.021265778, -0.040370641, -0.036232952 }, { -0.0058098424, -0.0042264198, -0.077428509, -0.04241654 }, { -0.0026825379, -0.029453318, -0.016181275, -0.028320229 }, { -0.012541692, -0.01345735, 0.00037814888, -0.0046052489 }, { -0.026527394, 0.020033638, -0.025683861, -0.084207169 }, { -0.0010459945, -0.036745215, -0.039772051, 0.024810839 }, { 0.012134618, 0.0068515798, -0.035286972, 0.043129595 }, { -0.077093357, -0.026872688, 0.032800133, -0.090326706 }, { 0.13930909, 0.0081274014, -0.08349188, -0.012200005 }, { -0.091693797, -0.012567011, -0.069736822, -0.0061444184 }, { -0.053061301, 0.003642159, 0.0052515175, -0.036957472 }, { 0.0043493933, -0.013069332, -0.014708126, -0.032765039 }, { -0.016116105, -0.022907609, -0.043503106, -0.013266465 }, { -0.072759977, -0.077354585, 0.0043827591, -0.013821612 }, { -0.032399073, -0.045305037, -0.021840791, 0.073996542 }, { -0.057239255, -0.056581235, -0.038880927, 0.044102943 }, { -0.026951489, -0.088667645, -0.013659704, 0.033527579 }, { 0.034815442, -0.028634059, -0.036666529, 0.011546036 }, { 0.026688447, -0.0081892129, -0.031138092, -0.041739155 }, { 0.0015665701, -0.012701682, 0.0013533943, -0.002849785 }, { 0.032994636, 0.008802974, 0.019032649, 0.0039042621 }, { -0.044544917, 0.0093201326, -0.017968915, 0.01936344 }, { -0.034794535, 0.043032983, -0.051072531, -0.040148303 }, { -0.0030398597, -0.027112065, -0.064007483, -0.01798277 } } }, { { { 0.22040906, 0.24911942, 0.41660708, 0.23632869 }, { 0.25894466, 0.1416669, 0.41902981, 0.35717608 }, { 0.26918091, 0.14566759, 0.2147652, 0.15769391 }, { 0.22500921, 0.12113361, 0.11151768, 0.12348609 }, { 0.25699055, 0.056819107, 0.3859882, 0.4585378 }, { 0.7304995, 0.20719358, 0.44455636, 0.42226989 }, { 0.43602897, 0.51049581, 0.41978824, 0.62521039 }, { 0.42004119, 0.52912054, 0.33314238, 0.38257921 }, { 0.55092562, 0.43085653, 0.31149977, 0.34391138 }, { 0.40391149, 0.48820255, 0.13569806, 0.36060266 }, { 0.13647907, 0.12061002, 0.20668806, 0.30221394 }, { 0.15583476, 0.13133696, 0.22775202, 0.35653823 }, { 0.56336195, 0.25684627, 0.11118383, 0.23109245 }, { 0.45430401, 0.42843367, 0.25496534, 0.097473509 }, { 0.3420223, 0.39418925, 0.26458947, 0.30588082 }, { 0.51345558, 0.3612731, 0.41151773, 0.25269512 }, { 0.29195176, 0.42659964, 0.47971993, 0.32714756 }, { 0.49222777, 0.28477645, 0.74993827, 0.43781271 }, { 0.098434481, 0.31164923, 0.14486345, 0.11466693 }, { 0.070833248, 0.20569754, 0.10233576, 0.047352701 }, { 0.51050902, 0.15597643, 0.1417112, 0.35581415 }, { 0.48261165, 0.14592221, 0.62554576, 0.5209765 }, { 0.33562628, 0.39920067, 0.28183433, 0.297464 }, { 0.366851, 0.59278666, 0.59095922, 0.48385165 } }, { { 0.13792051, 0.072076744, 0.094800532, 0.026318377 }, { 0.13607414, -0.061382542, 0.061800151, -0.020060553 }, { 0.028096406, 0.069282616, 0.010195109, -0.010461141 }, { 0.018651237, 0.02642439, 0.0077552848, -0.051151646 }, { 0.098299803, -0.0085081153, -0.011764584, 0.087405711 }, { 0.064082346, -0.04626424, -0.071480607, 0.064447268 }, { 0.022766233, 0.0167542, -0.021285286, -0.071637286 }, { -0.0202445, 0.011692601, 0.048325551, 0.0097755172 }, { -0.027775183, 0.016463115, 0.060050391, -0.034226107 }, { 0.019412547, 0.059977501, -0.0041737169, 0.031539317 }, { 0.013192979, 0.036015595, -0.049943198, 0.014112312 }, { -0.013272349, 0.035821037, -0.060503687, 0.095316821 }, { 0.038338785, -0.059038809, -0.044954172, -0.00051347307 }, { -0.039594082, 0.018205882, 0.13413799, 0.012292954 }, { 0.015177594, -0.0082493854, 0.00029420179, 0.010356248 }, { 0.100271, -0.13623174, 0.1121235, 0.068902399 }, { 0.025189636, 0.0014918434, 0.0088847718, -0.053714493 }, { 0.06487698, -0.097217547, -0.069537353, 0.032490984 }, { -0.030729608, 0.048956315, 0.016036034, 0.022485239 }, { 0.049839618, 0.01148525, -0.021032427, -0.019665817 }, { -0.0037762817, -0.030422275, -0.062343207, 0.057994884 }, { 0.014035184, -0.021387762, -0.080846143, -0.020681511 }, { -0.03594567, 0.026862531, 0.078975557, -0.034056659 }, { -0.014490672, 0.026128902, 0.045617611, 0.090192953 } }, { { 0.011904288, -0.014624471, 0.042023114, 0.019592867 }, { 0.032705848, 0.00038558691, 0.031901745, 0.027208951 }, { -0.044369719, -0.039761364, -0.013366816, -0.019308126 }, { -0.019051023, -0.00015767269, -0.082968285, -0.035266053 }, { -0.004775162, 0.010889271, 0.0089521094, 0.027037104 }, { 0.005616143, -0.00099668486, 0.0068716426, -0.12649184 }, { 0.018531199, 0.023881776, -0.053798787, -0.041912909 }, { -0.0036187094, 0.11590788, 0.025140733, 0.022280209 }, { -0.02994342, -0.026293799, -0.017204658, 0.044901944 }, { 0.079892089, 0.10816526, 0.14667807, 0.027301352 }, { -0.045296738, -0.066748968, -0.0099354431, -0.070369692 }, { -0.08357374, -0.043311901, 0.013163375, -0.0881777 }, { -0.065923811, -0.10382274, 0.090440302, -0.013617198 }, { -0.092578587, -0.010178017, -0.01416593, 0.0432333 }, { 0.055172515, 0.10021805, -0.0062782668, -0.11791805 }, { -0.039684132, -0.08934283, 0.020686084, -0.0013788117 }, { 0.064624676, 0.051773746, 0.0045383964, -0.037696971 }, { -0.066296373, 0.020570689, -0.017742721, -0.022651449 }, { -0.0061572447, -0.094510525, -0.094775804, -0.038022514 }, { 0.0055683313, 0.039513342, -0.096815654, -0.0065483011 }, { -0.03311602, -0.018395457, 0.0028464434, -0.088048272 }, { -0.073106109, -0.055187863, -0.093209932, -0.10155137 }, { 0.042841842, -0.005778703, 0.074069607, -0.025841052 }, { -0.018569637, 0.063144303, 0.02291584, 0.005525742 } } } }, { { { { -0.20809663, -0.18346453, -0.072140694, -0.0078104407 }, { -0.19490097, 0.25712922, 0.37640771, 0.11563399 }, { 0.26894915, -0.33477877, -0.093739129, -0.55078405 }, { -0.65794103, 0.09211629, -0.19166986, 0.5574327 }, { 0.45579532, 0.23202083, 0.19626303, -0.64130523 }, { -0.018763975, -0.24981569, -0.32514026, -0.11121342 }, { 0.22376238, 0.09515938, 0.071728264, -0.02790747 }, { -0.3053338, 0.34023365, 0.099862481, 0.26163964 }, { -0.21722968, -0.094881958, -0.086364431, -0.0081863581 }, { -0.16090709, 0.23527698, 0.28947119, 0.11309742 }, { 0.26447184, -0.33536416, -0.096418234, -0.26201294 }, { -0.56343769, -0.041662822, -0.24873841, 0.67122901 }, { 0.35362642, 0.2577592, 0.2009013, -0.74233681 }, { -0.047956299, -0.54973418, -0.4958485, -0.12453303 }, { 0.06917425, 0.080509853, 0.0090863722, -0.023518805 }, { -0.27000602, 0.083167162, 0.12715558, 0.12397839 }, { -0.11376964, -0.079199259, 0.019676685, -0.0094352472 }, { -0.19185851, 0.22193112, 0.28110877, -0.06422845 }, { 0.084091992, -0.16151548, 0.091400556, -0.28257376 }, { -0.53821376, 0.21718328, -0.2234907, 0.52302804 }, { 0.71322306, 0.042728493, 0.13229522, -0.61892094 }, { 0.15270046, -0.26304886, -0.33110633, -0.052728951 }, { 0.072398971, 0.25829764, 0.25881687, -0.020942042 }, { -0.26788161, 0.055822039, 0.33817103, 0.42061402 } }, { { 0.088248648, 0.091306255, 0.020476927, 0.0030144802 }, { 0.0087376707, 0.043816157, 0.0022807168, 0.016745414 }, { -0.13412414, 0.12686539, 0.060531476, 0.044582027 }, { 0.019204757, -0.0070891897, 0.091194602, 0.065258927 }, { -0.10429513, -0.027665602, -0.064350626, 0.0053147478 }, { 0.069218141, -0.035018324, -0.088257571, 0.019279642 }, { -0.073137338, 0.040764456, -0.022352804, 0.031743288 }, { 0.040325697, -0.12840825, -0.009582113, 0.034509657 }, { 0.081971224, -0.0035223125, -0.051728499, 0.0038899717 }, { 0.050968435, 0.022254651, 0.18781134, -0.032392139 }, { 0.024342518, 0.13929014, -0.019175435, -0.0011608234 }, { -0.0021942487, -0.01251222, 0.024263454, -0.063179344 }, { -0.13071776, -0.059221747, -0.034153238, 0.036561209 }, { 0.054124093, 0.070495803, 0.081441614, 0.051900357 }, { 0.027480327, 0.028940343, -0.01469313, 0.032388411 }, { -0.039696828, -0.0069393798, -0.011361641, 0.035031025 }, { -0.039730763, 0.0085971581, -0.0077461932, -0.040735188 }, { 0.10893368, 0.00014757217, 0.025489178, -0.11388774 }, { -0.0013816669, 0.0031148929, 0.10281666, -0.019860642 }, { -0.065093128, -0.11495815, 0.041783056, -0.091373461 }, { -0.044985581, 0.0012713031, -0.16078032, 0.17303747 }, { -0.038132358, -0.02995975, -0.037612782, 0.012575173 }, { 0.0042976619, 0.027014275, 0.017518808, 0.030405184 }, { -0.0015298607, 0.029297664, -0.1034349, 0.023450502 } }, { { 0.028785558, -0.028708377, -0.010459636, 2.8360915e-05 }, { 0.091634877, 0.021214811, 0.12282079, 0.080617943 }, { -0.29287977, 0.045481846, 0.014712563, 0.057317576 }, { -0.10728772, 0.03268482, 0.015167285, -0.011256231 }, { 0.09337321, 0.037150859, 0.052549202, -0.042671474 }, { -0.0041288689, -0.024299997, -0.11357403, -0.022045772 }, { -0.041469935, -0.0071353646, -0.0086607538, 0.008536762 }, { 0.033629272, -0.0070042955, -0.037864853, -0.0055907778 }, { 0.016404597, -0.0055321059, -0.020989839, -0.013771265 }, { 0.042552435, 0.04428518, 0.0030587466, 0.044894182 }, { -0.027600219, 0.026831779, 0.051120849, -0.032184808 }, { 0.13870554, 0.15273282, 0.049260112, 0.043371121 }, { -0.018453269, -0.18061413, 0.24805649, -0.031741165 }, { -0.085137374, 0.025935867, 0.015978067, 0.067726486 }, { 0.072393868, 0.0050430488, 0.0016664585, 0.0072097064 }, { 0.033840162, 0.082225764, -0.079387016, 0.033165625 }, { 0.033170766, 0.0012231618, -0.066984982, 0.051671704 }, { 0.017894231, -0.012267532, 0.045536123, -0.07327109 }, { 0.0073109731, -0.063797898, -0.13446413, 0.1408986 }, { -0.045702456, -0.1647051, -0.14336468, 0.054543693 }, { 0.0042448876, -0.13234456, 0.092181719, -0.10440841 }, { -0.060020212, -0.011098469, -0.030257182, -0.030922037 }, { -0.018118661, 0.00067983745, -0.0061776598, -0.031721273 }, { -0.019885189, 0.094157888, 0.014017961, -0.051373389 } } }, { { { 0.12415319, -0.13611564, -0.029441661, -0.14143497 }, { -0.26074418, 0.011913326, -0.033328425, 0.43248793 }, { 0.19336432, 0.37269586, 0.36803538, -0.51720719 }, { -0.15185913, -0.47431781, -0.6593667, 0.23163184 }, { 0.18276216, 0.19248743, 0.65453332, 0.54748087 }, { 0.17751443, -0.0020337696, 0.08506463, -0.40147769 }, { -0.11370932, 0.11523476, -0.010573025, 0.082295392 }, { -0.13666335, -0.32747478, -0.16897386, 0.15359006 }, { 0.11716326, -0.12259922, 0.0033396256, -0.13240653 }, { -0.27776876, -0.10222241, -0.039920479, 0.35499708 }, { 0.090003723, 0.3313923, 0.1871549, 0.003163675 }, { -0.51626118, -0.76341562, -0.56326874, 0.20153559 }, { -0.34172723, 0.26975563, 0.67520079, -0.1252004 }, { 0.45758078, -0.19142179, 0.064180031, -0.48748431 }, { -0.12800789, 0.1399912, 0.0077954775, 0.14379741 }, { -0.13042104, -0.45670817, -0.18831095, 0.0032738639 }, { 0.12446807, -0.11504524, -0.027331682, 0.03861758 }, { -0.31337986, -0.11842668, 0.033415325, 0.45344231 }, { 0.11463107, 0.077427841, 0.060880794, -0.069619455 }, { -0.37772106, -0.59628905, -0.65426572, 0.065297039 }, { 0.29532991, 0.75920243, 0.53294265, -0.15002562 }, { 0.3618333, 0.10488387, 0.36007528, -0.30963565 }, { -0.13738196, 0.20795596, 0.029274703, 0.18017599 }, { -0.10290023, -0.48517535, -0.33278584, 0.56477854 } }, { { -0.0047891472, 0.024629901, 0.015256654, -0.0084462001 }, { 0.056227746, -0.048057782, -0.15671312, 0.06418471 }, { -0.070093217, -0.018057199, 0.062026545, -0.051053726 }, { -0.0091221476, 0.0020547295, -0.087729813, -0.10164738 }, { 0.098917091, -0.066835916, 0.083151519, 0.006342544 }, { 0.0013540606, 0.038719082, 0.036333261, -0.053178668 }, { 0.0083787438, 0.0028359378, 0.0089872852, 0.031308249 }, { 0.014379686, -0.079563474, -0.079160006, -0.016352226 }, { 0.0091376645, -0.016678006, -0.044636785, -0.0011035265 }, { 0.0099146109, 0.027589302, -0.09494437, 0.07451767 }, { 0.017453983, 0.080674871, 0.06341808, 0.048820473 }, { 0.02794057, 0.058230195, -0.010793601, 0.091813872 }, { -0.049633232, -0.1142016, 0.036984283, 0.0034294865 }, { 0.047712957, 0.10161366, 0.13774722, 0.039503136 }, { 0.014194782, -0.014555183, -0.00053182909, 0.0019143477 }, { 0.0014900262, 0.0056176356, -0.034517871, -0.0010707988 }, { 0.013287784, -0.0073967933, -0.019271341, 0.016354896 }, { -0.10345626, 0.023536634, 0.027943639, -0.015686972 }, { -0.025193395, -0.10224801, 0.078686884, -0.048574399 }, { 0.15797878, -0.0012322757, -0.036096649, -0.23983963 }, { -0.10455507, -0.056368102, -0.06570944, 0.29104616 }, { 0.05155239, -0.040940824, -0.038367594, 0.058174485 }, { 0.010471732, -0.066952904, -0.047763843, -0.021124742 }, { -0.033555686, 0.0049111983, -0.026592789, 0.014438586 } }, { { -0.0048440946, 0.025915095, -0.018325403, 0.022133613 }, { 0.059240081, -0.031272176, -0.12967647, -0.17957913 }, { 0.0574837, 0.067005152, 0.024644254, 0.10786296 }, { 0.067084865, 0.008513386, 0.04077659, 0.10587924 }, { 0.026332643, 0.1072618, -0.098375042, -0.001724609 }, { -0.021386362, -0.0020174921, 0.16800158, 0.081359882 }, { -0.018204146, -0.026432136, -0.0068153455, -0.029997667 }, { -0.043221501, -0.016869967, -0.067406967, -0.024965804 }, { -0.0033879999, 0.031310818, -0.010853802, 0.00088944004 }, { -0.068991006, 0.087874253, -0.15737392, -0.088870044 }, { 0.061763806, -0.00072874343, -0.009915009, -0.0178225 }, { -0.07340717, 0.080339271, -0.0027124572, -0.13078641 }, { -0.023682834, 0.16512313, -0.15784472, 0.047978827 }, { 0.0063250439, -0.09953777, 0.094180888, 0.010565041 }, { 0.010047311, -0.042999009, -0.012483998, -0.016966759 }, { -0.048612679, 0.051708319, 0.015059148, 0.0036776472 }, { -0.011737015, -0.0027276603, 0.026535075, -0.065453876 }, { 0.056388137, 0.061461073, -0.12726984, -0.025578248 }, { 0.0016833003, 0.10878558, 0.13254828, -0.017098914 }, { -0.031606282, -0.072245098, 0.12724789, -0.21852899 }, { -0.062502612, -0.073402771, -0.049624729, 0.069066032 }, { -0.075837195, -0.10297347, -0.07249237, -0.11538062 }, { -0.015644005, 0.039474396, 0.074415075, -0.038881161 }, { -0.040175911, 0.034030267, 0.03947059, 0.014167463 } } }, { { { 0.97019677, 0.97355703, 0.99695983, 0.98991674 }, { 0.94552952, 0.96630359, 0.92585444, 0.89419404 }, { 0.9435447, 0.86545998, 0.92507456, 0.65508294 }, { 0.73759908, 0.87552111, 0.72697883, 0.79725496 }, { 0.87111918, 0.95347518, 0.73011435, 0.53758004 }, { 0.9839393, 0.96829127, 0.94183216, 0.90909143 }, { 0.96798791, 0.98876976, 0.99736817, 0.99621717 }, { 0.9423876, 0.88147679, 0.98054848, 0.95286662 }, { 0.96906348, 0.98791034, 0.99625801, 0.99116169 }, { 0.94707625, 0.9665378, 0.9563539, 0.9280011 }, { 0.96018435, 0.88187869, 0.97758711, 0.96505917 }, { 0.64499021, 0.64456248, 0.78794513, 0.71332673 }, { 0.87073007, 0.92778882, 0.70974824, 0.65822558 }, { 0.88787388, 0.81311133, 0.86603417, 0.86420517 }, { 0.98935782, 0.98687417, 0.99992833, 0.98932764 }, { 0.95398485, 0.88572054, 0.97384313, 0.99227952 }, { 0.98567955, 0.99019799, 0.99943274, 0.99920952 }, { 0.93004482, 0.96784384, 0.95909399, 0.88896838 }, { 0.98984254, 0.98382807, 0.99395144, 0.95671584 }, { 0.75342733, 0.77283296, 0.72248756, 0.84981055 }, { 0.63568318, 0.6494505, 0.83574524, 0.77099234 }, { 0.91965169, 0.95906448, 0.87218942, 0.94939213 }, { 0.98786871, 0.94341754, 0.96548269, 0.98341143 }, { 0.95794101, 0.87263324, 0.8802806, 0.71000638 } }, { { -0.0064390277, 0.051629953, -0.011423447, 0.032337826 }, { 0.055030538, 0.061305324, -0.016012659, 0.083766345 }, { 0.052467122, 0.018425134, -0.00054737782, 0.048038459 }, { 0.076436505, 0.016815709, -0.024174832, -0.00829119 }, { 0.057903371, 0.068822104, -0.0064003131, 0.00010695928 }, { 0.067104151, 0.067284611, 0.0074295447, 0.024215238 }, { 0.073380541, 0.01486405, 0.01523157, 0.012966612 }, { -0.0002536971, 0.010628632, 0.00045031869, 0.041891438 }, { 0.055922922, 0.0090823157, 0.011101162, 0.033807592 }, { -0.040264953, 0.022318628, -0.013682045, -0.016112502 }, { -0.034286564, 4.7089727e-05, -0.013030079, -0.012231424 }, { 0.027756308, 0.084041595, 0.018308393, 0.11564334 }, { 0.0026690817, 0.058149333, -0.013682964, 0.052975934 }, { -0.03852481, 0.063493354, 0.059460027, 0.047740976 }, { 0.026410264, -0.0073902435, 0.022353771, 0.012987341 }, { 0.035217135, -0.0023455309, -0.0055505614, 0.010102857 }, { 0.00075590283, 0.038624793, -0.0040614962, 0.070039437 }, { -0.02318411, 0.04527054, 0.013119286, 0.025335215 }, { 0.021268391, 0.044855911, 0.012622905, 0.04827088 }, { -0.0046678346, -0.01934799, 0.018393432, 0.09750434 }, { 0.12480373, 0.059151139, 0.055196092, 0.26701338 }, { -0.0096669036, 0.065624767, 0.016918517, 0.028425135 }, { 0.026488514, -0.0037618693, 0.0077028717, 0.041713399 }, { 0.018628451, 0.033145064, 0.029067918, -0.000924258 } }, { { -0.043525781, 0.028119778, -0.011653105, -0.020930158 }, { -0.028099186, 0.017594088, -0.099226445, 0.10408808 }, { 0.11750066, -0.0010629746, 0.018381448, 0.096538552 }, { 0.0010069446, 0.013799541, 0.1325137, 0.020820734 }, { -0.053571928, -0.0066793785, 0.14596488, -0.03272949 }, { 0.028507895, 0.015474376, -0.025411653, 0.037264272 }, { 0.033698911, 0.018088387, 0.0038898537, 0.03163178 }, { 0.0057766828, 0.015879322, 0.012557033, 0.071771631 }, { -0.0044521866, 0.0083963511, -0.0020426175, 0.023784146 }, { -0.011508765, 0.0075020051, 0.0018808294, 0.040843424 }, { 0.0085150894, 0.0056891711, 0.010134672, 0.046224768 }, { 0.040825446, 0.10099754, 0.021853299, 0.024507528 }, { -0.0055958303, -0.0060958, 0.1115321, -0.021701014 }, { 0.010487817, -0.010033143, -0.031203025, 0.054265436 }, { 0.0040500672, 0.0053935875, 0.018233022, 0.018797311 }, { 0.064057639, 0.014318185, 0.0199119, 0.014366235 }, { 0.02411682, 0.045454692, 0.0030084434, 0.019464939 }, { 0.012500289, 0.027734846, 0.0025097372, 0.047343669 }, { 0.037625829, -0.00064472688, 0.0557556, 0.04785655 }, { 0.0020433437, 0.019929208, 0.087936103, -0.036738471 }, { 0.020811556, 0.0915387, 0.055445303, -0.065132763 }, { 0.03911814, 0.043721622, 0.0074336204, -0.031370424 }, { 0.014072509, -0.014795458, 0.010517063, 0.022409628 }, { -0.0054107234, 0.055313602, 0.053556404, 0.048574319 } } }, { { { 3.4224197, 3.3162336, 3.1136621, 3.3189801 }, { 4.0715355, 3.5614196, 4.1797877, 4.0959601 }, { 4.3979407, 4.1858272, 4.3116447, 4.5467451 }, { 4.4920032, 4.0716439, 4.6107962, 4.5268016 }, { 5.6570832, 4.9036495, 4.7373547, 4.7259419 }, { 3.3277827, 3.6015237, 4.226646, 3.7939772 }, { 3.4893058, 3.3260638, 3.0626103, 3.1798705 }, { 3.6423735, 4.1092281, 3.3264203, 3.7325301 }, { 3.4756581, 3.2550256, 3.224671, 3.4093307 }, { 3.8511362, 3.4821381, 4.3232597, 3.7357164 }, { 3.6688024, 4.0797971, 3.4140927, 3.6881261 }, { 4.5298469, 4.7472506, 4.4046473, 4.7279944 }, { 4.1614448, 4.1242955, 4.6741969, 5.0037875 }, { 4.3148703, 4.3815566, 4.1976536, 3.9032858 }, { 3.2640506, 3.3214728, 2.9463564, 3.3562068 }, { 3.6729325, 3.9218642, 3.4550701, 3.4833871 }, { 3.435975, 3.3079446, 3.3432341, 3.3632985 }, { 3.8404619, 3.4716915, 3.858149, 3.8677391 }, { 3.3181827, 3.8403872, 4.0363918, 3.9604287 }, { 5.0916792, 5.2773748, 4.5404255, 4.377031 }, { 4.6514614, 4.7569957, 4.1233238, 4.4022582 }, { 3.6884833, 3.6283543, 4.1874612, 4.2963913 }, { 3.456705, 3.6250566, 3.5292789, 3.1420033 }, { 3.5986317, 4.0596074, 4.0696874, 4.5327067 } }, { { -0.12592901, -0.14780788, -0.11051274, -0.18767653 }, { -0.020435093, 0.0055221209, -0.021183195, -0.15159792 }, { 0.022498629, -0.025100789, -0.30939177, 0.016420202 }, { 0.21296442, -0.042976575, 0.082118132, 0.14574735 }, { -0.13608022, 0.16141834, -0.015091164, 0.044951541 }, { -0.08235774, -0.10333151, 0.089785432, -0.036620639 }, { -0.17664465, -0.015842477, -0.083075331, -0.15660828 }, { -0.11292423, -0.072894494, -0.068901923, -0.2283674 }, { -0.19063437, -0.071954393, 0.091375283, -0.26993547 }, { 0.042798331, -0.06495575, 0.050221766, 0.024602586 }, { -0.026228614, 0.0049810367, 0.046584088, -0.13067577 }, { 0.072779737, -0.023369437, -0.030275791, 0.19591126 }, { -0.018649072, 0.029208952, 0.012033439, 0.00094798196 }, { -0.094599446, 0.0070746366, -0.0007115864, -0.040175552 }, { -0.027599009, -0.068747365, 0.19480498, -0.19423733 }, { -0.076671551, 0.0075475135, 0.019853903, -0.012984601 }, { 0.064371855, -0.24044027, -0.043765356, 0.0016424127 }, { -0.076744435, 0.035881398, 0.12967612, 0.081825243 }, { -0.15224256, 0.032665115, -0.027927205, 0.076091133 }, { -0.0057973613, -0.14914213, -0.047678749, -0.037214457 }, { 0.10060085, -0.099197666, -0.22704457, -0.0020812401 }, { -0.070664558, -0.13179176, -0.014217065, -0.030410253 }, { -0.12286487, -0.046623366, -0.10695394, -0.0081383175 }, { -0.14561788, 0.02765909, 0.10439783, 0.033139041 } }, { { 0.0063171031, -0.0047223477, -0.056312039, -0.065065766 }, { -0.0059575982, -0.062348475, 0.069540315, -0.090331962 }, { 0.10218203, 0.050383376, -0.0089914697, -0.037837343 }, { -0.0037657879, 0.18278082, 0.079014627, -0.052587294 }, { -0.33929282, 0.018522098, 0.0078923893, 0.042545349 }, { 0.027294929, -0.086490439, -0.0057363347, -0.035932082 }, { -0.061716003, -0.14470599, 0.033117786, -0.08112808 }, { 0.16414856, 0.082471596, -0.058497326, 0.050552718 }, { -0.07627083, -0.0064181717, -0.031179581, -0.075705068 }, { -0.057808009, -0.00074561624, -0.23990956, 0.018671772 }, { 0.1677602, 0.10757253, 0.028015134, -0.23923178 }, { 0.078827365, 0.068682485, 0.056277532, -0.069749241 }, { 0.079502977, 0.05526585, 0.0089767144, -0.15319341 }, { -0.038594242, -0.055488998, -0.043132461, 0.054313031 }, { 0.12890592, -0.082639555, 0.22520491, -0.026781096 }, { -0.071292391, 0.064592881, -0.050368563, -0.072488866 }, { 0.092998671, 0.12152394, 0.033318795, -0.039691417 }, { -0.0049706273, -0.0014175115, -0.11634604, 0.15219284 }, { -0.012414906, 0.035583927, -0.072463074, -0.058394705 }, { -0.071558898, -0.00093653835, 0.013149622, 0.01495775 }, { -0.057103279, 0.013702583, -0.020242751, 0.04649072 }, { -0.083398977, -0.20123674, 0.062758815, -0.043671819 }, { 0.084479675, 0.17868517, -0.021185269, 0.15711776 }, { 0.11862504, 0.079985297, 0.063556911, 0.14639069 } } }, { { { 0.48018566, 0.17712962, 0.45065949, 0.76214707 }, { 0.37788335, 0.385421, 0.24766167, 0.3647243 }, { 0.45095873, 0.2634498, 0.37824131, 0.10713483 }, { 0.18808611, 0.27852978, 0.23671202, 0.23174978 }, { 0.39404781, -0.7399413, 0.28511918, 0.026007027 }, { 0.46587668, 0.46802177, 0.36697974, 0.23706778 }, { 0.48925391, 0.42086488, 0.49570155, 0.45137287 }, { 0.30655255, 0.35196398, 0.23019387, 0.50586011 }, { 0.45798975, 0.34137244, 0.33289763, 0.54218519 }, { 0.42271216, 0.38700914, 0.48791862, 0.15025833 }, { 0.7282781, 0.37956244, 0.25156645, 0.51632504 }, { 0.084933462, 0.15576738, 0.16469359, 0.29684651 }, { 0.34570877, 0.34912791, 0.26663435, 0.11188061 }, { 0.48552914, 0.19012867, 0.12677402, 0.1234341 }, { 0.2190939, 0.41431469, 0.64823269, 0.51846746 }, { 0.49289149, 0.29829354, 0.29090992, 0.36465152 }, { 0.50568056, 0.64150077, 0.40217634, 0.53523743 }, { 0.24945735, 0.47058801, 0.29099852, 0.25452114 }, { 0.49039753, 0.26327736, 0.39431507, 0.50632023 }, { 0.19678915, 0.031547614, 0.22295107, 0.26300048 }, { 0.12409997, 0.11506147, 0.19327618, 0.2174585 }, { 0.15319333, 0.39177705, 0.38498586, 0.25972804 }, { 0.69027161, 0.37279682, 0.31143504, 0.23440833 }, { 0.39682066, 0.3156927, 0.36369313, 0.14308402 } }, { { 0.15030994, 0.15410005, 0.0072554408, -0.22242826 }, { -0.032421729, 0.22531436, 0.22185899, -0.022703209 }, { 0.070341052, 0.30237173, 0.047916387, 0.03629681 }, { -0.024283222, 0.075614195, 0.013940033, -0.016841468 }, { 0.077729482, 0.19455394, -0.02162282, -0.018761003 }, { -0.22986895, 0.18914992, 0.14483608, 0.11173921 }, { 0.14132894, -0.0081864768, -0.11405791, 0.031777789 }, { 0.38775389, 0.0085565642, -0.057167843, 0.09784167 }, { 0.079102739, 0.030530894, 0.041954967, 0.02957611 }, { 0.076915126, 0.18656729, 0.044218872, 0.22478833 }, { 0.017173879, 0.11961351, -0.085099523, 0.22720323 }, { 0.030466202, 0.095221887, -0.042982583, -0.069264747 }, { 0.041170442, -0.090598444, -0.021082598, -0.028016784 }, { -0.082581617, -0.023712106, 0.32427665, 0.1010696 }, { 0.19197752, 0.10900527, -0.0053794951, 0.068553764 }, { 0.18674269, 0.028895321, -0.053421028, 0.063918058 }, { 0.044090722, -0.054247791, 0.05585954, -0.13406746 }, { 0.08358642, -0.032301886, 0.010371619, 0.099505528 }, { 0.16467816, 0.044994571, -0.0045949279, 0.0626774 }, { 0.12942209, 0.092097891, 0.019866495, 0.10340014 }, { 0.037094903, 0.13829877, 0.15116473, -0.048632499 }, { 0.10749044, 0.14329542, -0.061272024, -0.1536028 }, { 0.097716907, 0.044246181, 0.056664419, 0.15804873 }, { 0.031819999, 0.10132976, 0.079198524, 0.017871462 } }, { { 0.056219172, 0.08683492, -0.061488015, 0.065746152 }, { 0.088983664, 0.19773741, -0.096766599, 0.16352101 }, { -0.0097043787, -0.040925999, 0.097458334, 0.032319634 }, { -0.024873518, 0.057873123, -0.0059256291, -0.057498398 }, { -0.13355098, 0.39190863, 0.017449142, -0.0076009344 }, { 0.10319658, 0.22069551, -0.098795717, 0.10603434 }, { 0.090765308, 0.13803326, -0.070647945, 0.14557561 }, { -0.068457348, 0.058955208, -0.050501105, 0.02914144 }, { 0.10363866, 0.060231993, 0.027681685, 0.079659088 }, { 0.01269983, 0.11977996, -0.049648315, 0.089882363 }, { -0.072877286, 0.019348792, 0.13977764, 0.055396044 }, { 0.028834456, -0.1084196, -0.0043985215, -0.072640844 }, { -0.040232522, 0.051835989, -0.02198193, 0.016421295 }, { -0.087848469, -0.04621504, 0.099259188, -0.0025909067 }, { 0.3000131, 0.10526775, 0.016890366, 0.12892588 }, { -0.021028821, -0.024429075, 0.088067677, -0.084594075 }, { 0.086861805, -0.045902006, 0.0058222123, -0.0075466204 }, { 0.14411905, 0.036488937, 0.05091815, 0.16385101 }, { 0.1576814, 0.043890956, -0.064244298, -0.087234754 }, { -0.071100004, 0.16782304, -0.10860149, -0.1601076 }, { 0.032634641, -0.0025068263, -0.093802703, -0.076176546 }, { 0.1121451, 0.15584236, 0.070074778, 0.083736091 }, { 0.16981897, -0.078106227, 0.12480295, -0.0056807652 }, { -0.20300117, -0.017467249, 0.035504155, 0.056546123 } } } }, { { { { 0.014994926, 0.3118252, 0.12179235, -0.2013765 }, { -0.2622824, 0.28086607, 0.018805882, 0.72058929 }, { -0.0081002049, -0.28176506, -0.592214, -0.15032918 }, { 0.18913426, -0.24000825, 0.0020279072, -0.54749128 }, { 0.010237954, 0.76905205, 0.80173664, -0.016024595 }, { -0.53448318, 0.31204229, -0.16183732, 0.76857439 }, { -0.57639279, -0.63719194, -0.71354849, 0.56346054 }, { 0.49443258, 0.15067585, 0.31864726, -0.30570933 }, { -0.20756322, 0.2544828, -0.005298245, 0.0073796841 }, { -0.61822672, 0.21508574, 0.6362534, 0.30433278 }, { -0.0050327191, -0.278054, -0.3460806, 0.29967778 }, { 0.33983098, -0.11715664, -0.21761592, -0.068273894 }, { 0.5550354, 0.44369709, 0.64019993, -0.026032291 }, { -0.72587268, -0.33528197, -0.33592445, 0.53027141 }, { -0.47623191, -0.61767624, -0.61525655, 0.37823554 }, { 0.82869964, 0.219401, -0.018181789, -0.56937955 }, { -0.051792934, 0.3461701, 0.20915925, 0.078166496 }, { -0.26705611, 0.14439061, 0.0055054648, 0.463243 }, { -0.0019649711, -0.34119962, -0.29306531, -0.040223173 }, { 0.29285811, -0.32824753, -0.24768208, -0.29676955 }, { 0.87604898, 0.25374435, 0.2341931, -0.77851996 }, { -0.80404697, 0.011122158, 0.18899178, 0.55592668 }, { -0.78397618, -0.53690406, -0.59931185, 0.62348293 }, { 0.54613799, 0.080819658, 0.12590931, -0.60614071 } }, { { -0.12307869, -0.20242175, 0.21530167, -0.15608553 }, { 0.00052208688, 0.09998365, -0.067550225, -0.14009319 }, { 0.12621699, -0.089024022, 0.022656689, 0.18947331 }, { 0.34838897, -0.04936051, 0.25527451, -0.18942819 }, { 0.013210249, -0.043957685, -0.19088103, -0.034189573 }, { -0.0027790938, -0.026595097, 0.087083287, -0.12513839 }, { -0.038231564, 0.013328425, -0.0091503894, -0.005743873 }, { 0.17205702, -0.14956835, -0.0088915291, 0.18720588 }, { -0.049670195, 0.39532325, 0.080260299, 0.01811245 }, { 0.043555003, -0.30289197, -0.50878196, 0.27306166 }, { 0.02555972, -0.0068359476, 0.061097702, -0.43822038 }, { -0.10926471, 0.1870906, 0.12419548, 0.1245213 }, { -0.012443149, 0.040036941, 0.18601483, 0.02310445 }, { -0.10442982, 0.057455632, 0.13475314, -0.0019859122 }, { -0.068181593, -0.0033655904, 0.01922998, -0.020393828 }, { -0.10660626, 0.0020812455, 0.081209707, 0.077131932 }, { 0.088733212, -0.10430986, 0.45554817, -0.17113078 }, { 0.0046831409, 0.13247549, -0.1077727, 0.15382275 }, { 0.022346595, 0.022924261, -0.35016323, 0.2437608 }, { 0.029795657, 0.23046877, -0.020493651, -0.33214749 }, { -0.016101582, 0.042296203, 0.046779444, 0.037412394 }, { -0.02214903, -0.025218605, 0.14797485, -0.051723623 }, { 0.021321783, 0.010405115, 0.0075476201, 0.0082410917 }, { 0.040559796, 0.027927916, -0.012812736, -0.0096642379 } }, { { -0.055647079, 0.017595207, 0.34495838, -0.03055759 }, { -0.058415094, 0.027416036, 0.18568916, 0.13044498 }, { 0.01482217, -0.17300703, 0.027540135, -0.2744944 }, { 0.25558424, -0.15324455, -0.29751197, -0.11422984 }, { -0.068936732, -0.11425403, 0.094767025, -0.0020892558 }, { 0.040887892, 0.031622148, -0.095292456, -0.02460001 }, { -0.0026237665, 0.017734103, 0.01213911, 0.0056586962 }, { -0.052138375, 0.052245567, 0.04608449, -0.043004468 }, { -0.17693366, 0.0021023738, 0.13167397, -0.14062006 }, { -0.20900333, 0.0057695127, 0.13057243, 0.046715668 }, { -0.020569928, -0.08439655, -0.09683347, 0.038139385 }, { 0.18196242, 0.44461908, -0.11388512, -0.12413082 }, { 0.072801844, -0.0017236427, -0.0026756083, 0.049805114 }, { -0.092195952, -0.0076195172, -0.22763849, -0.11320887 }, { 0.016234922, 0.007258942, 0.078535592, -0.084829275 }, { -0.15320003, 0.057490618, -0.16065455, -0.17063675 }, { -0.012856124, 0.024818957, 0.097529739, 0.11569844 }, { -0.11141243, 0.26677735, 0.1319403, -0.15699502 }, { -0.021128161, -0.12370585, 0.056198856, -0.1836225 }, { -0.01871806, 0.025525037, 0.063822152, 0.066517944 }, { -0.013759301, 0.11401068, -0.04701374, -0.021321516 }, { 0.032714649, -3.161284e-06, 0.026930697, 0.00019593482 }, { 0.10575127, 0.016956425, 0.016873291, 0.0049304377 }, { -0.11938883, 0.31242334, 0.29347156, -0.19514533 } } }, { { { -0.17374661, -0.028781395, -0.25993234, 0.27242277 }, { -0.13675759, -0.62291002, -0.80742781, 0.54260546 }, { 0.16876581, -0.052588487, 0.22415557, -0.59669887 }, { 0.1769234, 0.64210979, 0.81157479, -0.2718564 }, { -0.99873125, -0.013258174, 0.58939675, 0.99930085 }, { -0.30883355, -0.71116337, -0.76218623, 0.096388818 }, { 0.65749012, -0.54533843, -0.57508599, -0.70359398 }, { -0.27406769, 0.61006308, 0.1873512, 0.2563151 }, { -0.78453523, -0.13585943, -0.048534939, 0.02085237 }, { 0.40938527, -0.76981396, -0.42506866, 0.22362984 }, { 0.29003079, -0.20624421, 0.1151133, -0.50558933 }, { 0.0070051806, 0.20763719, 0.59485798, -0.61562639 }, { -0.4371111, 0.48314196, 0.72981069, 0.99889301 }, { 0.58257878, -0.8603979, -0.94188892, -0.83140889 }, { 0.71858167, -0.49534538, -0.63421799, -0.84488463 }, { 0.016158248, 0.65330502, 0.82883727, -0.127372 }, { -0.50292264, -0.14848746, -0.20836533, 0.2471481 }, { -0.15815031, -0.63472031, -0.79826416, 0.15325573 }, { -0.010424343, -0.022843894, 0.099730136, -0.26040744 }, { 0.15069433, 0.31188588, 0.63836617, -0.25234477 }, { -0.36946506, 0.92093529, 0.96548808, 0.62354203 }, { -0.57070465, -0.99847512, -0.47855156, -0.079970605 }, { 0.077467525, -0.71134336, -0.67172579, -0.66364974 }, { -0.27299386, 0.89512951, 0.61598356, 0.49577277 } }, { { 0.070458859, -0.28774455, 0.21287043, -0.094689772 }, { 0.0029548085, -0.31404605, -0.039280892, -0.3652277 }, { -0.033729607, 0.041215792, 0.065844258, -0.21509418 }, { 0.39270582, 0.067526811, 0.15655351, 0.053346856 }, { 0.052704394, -0.087801294, 0.18655104, 0.056114808 }, { -0.074582751, -0.055177669, -0.22165519, 0.13272162 }, { -0.027850171, 0.0029849066, -0.0062314784, -0.010484316 }, { 0.20753796, -0.0087111988, -0.13875075, -0.06137521 }, { 0.089744421, 0.07271039, 0.099417029, -0.22157272 }, { -0.013209094, 0.048633419, -0.26528065, -0.15253703 }, { 0.052922007, 0.24859103, 0.14406684, 0.13857649 }, { 0.00096142813, 0.32643367, 0.17939549, -0.39761314 }, { 0.013505803, -0.036986517, -0.12729111, 0.15459921 }, { -0.00049722057, -0.047063275, -0.0018666598, 0.1067114 }, { -0.074221027, -0.00927958, -0.029535811, -0.024240068 }, { -0.12387933, 0.06626829, 0.16422781, 0.077740779 }, { 0.14560404, -0.082132455, 0.027268021, 0.18857832 }, { 0.10470732, -0.29519533, -0.23666419, 0.10917064 }, { 0.042550279, 0.02436036, -0.31865644, -0.024987356 }, { -0.030434576, 0.082115299, 0.17770796, 0.020944092 }, { -0.17365377, 0.13807361, 0.12476029, 0.072738061 }, { -0.11503962, -0.04022554, 0.028018434, -0.070211356 }, { -0.043677907, 0.0053361863, 0.0039019898, 0.0027489647 }, { 0.27060899, -0.0016552279, 0.14166067, -0.25461265 } }, { { 0.014703402, 0.094752279, -0.32162049, 0.082335322 }, { -0.31539882, 0.44394592, 0.44316202, -0.031456167 }, { -0.024148679, 0.082370612, -0.0031744796, 0.098610537 }, { 0.46130367, -0.19989896, -0.56118891, 0.11979937 }, { 0.11784636, 0.079971516, -0.16977121, 0.014922099 }, { 0.018367216, -0.076519762, 0.13801492, 0.039682415 }, { -0.0027614728, 0.0010389006, -0.023126227, 0.0027068473 }, { 0.22249856, -0.071302328, 0.23721977, 0.10734273 }, { 0.41478408, -0.36611101, 0.18031261, -0.11176768 }, { 0.15800457, 0.23829725, -0.0016193556, 0.2112867 }, { -0.14793833, -0.15378785, 0.0082778301, 0.27105519 }, { -0.064743588, 0.44794816, -0.12599819, 0.4310022 }, { 0.092725214, 0.033947737, 0.19969884, 0.0072363359 }, { -0.074190657, 0.005985921, 0.300818, -0.090919095 }, { 0.024238118, -0.010955859, -0.068086841, -0.021137349 }, { 0.12196721, -0.19977338, -0.64428422, -0.30808722 }, { 0.46567096, -0.042072501, -0.1778338, 0.34294059 }, { -0.32528695, 0.25699981, 0.49346557, -0.20743316 }, { 0.10422458, 0.049488574, 0.49098274, -0.34871439 }, { 0.16431875, -0.050748897, -0.18464312, -0.61695364 }, { -0.1753479, 0.033238479, -0.046267845, -0.012339883 }, { -0.16098841, 0.080519992, -0.11793031, 0.036790025 }, { 0.017193144, -0.0029212372, -0.0044153187, -0.0057094316 }, { 0.23481771, -0.1556448, -0.18775429, -0.013697353 } } }, { { { 0.98467622, 0.94970347, 0.95791534, 0.9408684 }, { 0.95525144, 0.73013516, 0.58966657, 0.43166004 }, { 0.98562289, 0.95804118, 0.77397471, 0.78825859 }, { 0.96588112, 0.72807352, 0.58424502, 0.79142113 }, { -0.049305848, 0.63904864, 0.099145551, -0.03377918 }, { 0.78673348, 0.62998117, 0.62680207, 0.63245759 }, { 0.48526085, 0.544603, 0.40015579, 0.43297544 }, { 0.82487776, 0.77789448, 0.92917353, 0.91697567 }, { 0.58431326, 0.95748667, 0.99880743, 0.99975533 }, { 0.67096902, 0.60093643, 0.64381538, 0.92594344 }, { 0.95700408, 0.93816272, 0.93111608, 0.80905665 }, { 0.94046044, 0.97116483, 0.77381347, 0.78507504 }, { 0.7077214, 0.7547892, 0.23983411, -0.039180128 }, { 0.3656649, 0.38379871, -0.00015338393, 0.16604667 }, { 0.50679735, 0.6108265, 0.46821675, 0.37829596 }, { 0.55946029, 0.72460731, 0.55919425, 0.81214734 }, { 0.86277825, 0.92634645, 0.95542467, 0.96581976 }, { 0.95061533, 0.75913205, 0.60228234, 0.87287949 }, { 0.99994373, 0.93971324, 0.95087677, 0.96466059 }, { 0.9442062, 0.89161694, 0.72879505, 0.92100486 }, { 0.30989313, 0.29579046, 0.11395771, 0.071428407 }, { 0.16674735, -0.054071458, 0.85747916, 0.82737551 }, { 0.61593841, 0.45356879, 0.43544204, 0.41332561 }, { 0.79196443, 0.43841915, 0.77763172, 0.62193473 } }, { { 0.028699614, 0.071974788, -0.028868668, 0.030119772 }, { -0.16988515, -0.35713152, 0.36877151, 0.37172103 }, { 0.024472009, 0.10373643, 0.052160621, -0.12998364 }, { 0.051999909, -0.1688679, 0.05813266, -0.11063347 }, { 0.026373007, 0.067310776, 0.34433164, 0.0017481699 }, { -0.017659611, -0.10215276, -0.23736187, 0.12678732 }, { -0.0019097928, 0.02067204, -0.030447136, -0.0093192388 }, { 0.10615435, 0.11124023, 0.04473958, 0.14369936 }, { 0.14791062, -0.034502091, 0.041456555, 0.06737059 }, { 0.22389399, 0.2668048, 0.25742349, 0.03724758 }, { 0.0046009946, 0.066632032, 0.097957775, 0.22969631 }, { 0.043253167, -0.013638494, 0.071328387, -0.19249903 }, { -0.023561087, 0.011490741, 0.19824644, -0.04133258 }, { -0.057507532, -0.039265903, 0.060469313, 0.37300659 }, { 0.027051207, -0.0086784396, -0.0055877341, -0.0315352 }, { 0.15724931, 0.0099485187, 0.22462997, 0.14112999 }, { 0.13909905, 0.026199511, -0.12430815, -0.076900423 }, { -0.022327596, -0.1975812, 0.49862652, -0.096026553 }, { 0.076782007, 0.041598482, 0.0033451155, 0.039947963 }, { 0.005353589, 0.070993946, 0.0068174778, -0.17805261 }, { -0.059912765, -0.17027417, -0.060069718, 0.1561139 }, { 0.017122435, 0.048532637, -0.05315926, 0.066962855 }, { 0.058014377, 0.021874362, 0.017248667, -0.0069413843 }, { 0.099274028, 0.040622241, 0.040435904, 0.14191123 } }, { { -0.13453832, 0.071519908, -0.1597656, -0.030758273 }, { -0.13511715, 0.32373425, 0.35851035, -0.18685481 }, { 0.021440457, 0.034442875, 0.14324368, 0.15754565 }, { -0.061440371, 0.16837735, 0.47887644, -0.036265812 }, { 0.55060811, 0.14095672, 0.13077418, 0.25515565 }, { -0.084599968, -0.084002143, 0.1542308, 0.044223437 }, { 0.0017727822, 0.025149715, -0.025479364, -0.0023658361 }, { 0.1619123, 0.069159159, -0.016343512, 0.026108175 }, { 0.3296525, 0.029456656, 0.039715069, 0.015958704 }, { -0.093419591, 0.37051381, -0.063182977, -0.017764112 }, { 0.11962535, 0.062511772, -0.070445145, 0.27768911 }, { 0.07458833, -0.16218828, 0.064111239, 0.43889373 }, { -0.0326486, -0.03666828, -0.17597139, 0.34213144 }, { 0.061334301, -0.0099525239, 0.21497301, 0.0074569296 }, { -0.016749445, 0.00054557189, 0.040331287, 0.066200794 }, { 0.20620866, 0.25268529, 0.46594276, 0.059651923 }, { 0.15170896, 0.041438057, 0.021708506, -0.15049245 }, { -0.14317538, 0.13548996, 0.37297491, 0.13718874 }, { 0.053339004, 0.015014013, -0.10418356, -0.13598877 }, { -0.02227412, 0.045548464, 0.21534467, -0.23828118 }, { -0.055326885, 0.11851609, 0.28938409, 0.041373996 }, { -0.1219532, 0.57338554, -0.094571555, 0.025008596 }, { 0.070380772, 0.016993506, 0.018073937, -0.015404818 }, { 0.17033841, 0.12449473, 0.10847869, -0.11141982 } } }, { { { 4.409738, 4.5071479, 5.4761817, 5.3214091 }, { 5.3741435, 4.6270256, 5.4786338, 5.323679 }, { 4.305776, 4.4890731, 4.6894257, 4.6068436 }, { 5.4930574, 4.9116386, 5.4097636, 4.9225404 }, { 5.1861828, 5.5144226, 5.1307797, 5.0804212 }, { 6.1194597, 6.0655136, 5.7369562, 6.1076578 }, { 6.9549598, 6.9281578, 6.9549598, 6.9549598 }, { 4.5030565, 4.5849566, 4.4830953, 4.4904323 }, { 5.3629211, 5.5524848, 4.5719135, 4.9103175 }, { 4.8906163, 5.3972226, 4.8806206, 5.1834202 }, { 4.5047396, 4.5984947, 4.7039612, 4.3422371 }, { 4.5956963, 5.6294962, 4.46025, 4.4827131 }, { 5.8454206, 6.000743, 5.4594428, 4.9952614 }, { 6.09642, 6.3979283, 4.9784963, 5.6878449 }, { 6.9549598, 6.9752898, 6.9549598, 6.9549598 }, { 6.2053562, 4.9984547, 5.3887395, 4.6221036 }, { 4.5265196, 4.3684629, 5.5819288, 5.4957366 }, { 5.2220057, 4.6118907, 5.5046208, 4.9190037 }, { 4.3408178, 4.4980303, 5.4937404, 5.6154153 }, { 4.4802186, 4.4666194, 4.8546878, 5.1764252 }, { 5.7384024, 5.9048089, 5.4636107, 5.0807017 }, { 5.1013817, 5.2237041, 6.0338955, 5.8869417 }, { 6.9414339, 6.9549598, 6.9549598, 6.9549598 }, { 4.3368412, 4.9692663, 4.7090567, 4.9023075 } }, { { 0.0093525884, -0.33796029, -0.4366682, -0.18161326 }, { -0.34446047, 0.10854359, -0.61563912, -0.16514117 }, { 0.055849315, 0.093045585, 0.36722184, 0.085665647 }, { -0.21881508, -0.036846235, -0.25226403, -0.012790033 }, { -0.14697546, -0.026656628, 0.2559775, 0.026279081 }, { 0.073189287, -0.074472165, -0.15439557, 0.020907645 }, { 0, -0.015078298, 0, 0 }, { 0.027540893, -0.30876053, -0.15680794, -0.18470107 }, { -0.072547269, -0.019227086, -0.26735769, -0.1362069 }, { 0.36907279, -0.28005156, 0.01966203, -0.10277819 }, { -0.26755862, 0.066747173, 0.60834173, -0.23356165 }, { -0.12357338, -0.41742338, 0.081840746, -0.14596222 }, { -0.068599762, -0.004402392, -0.17192993, -0.15797464 }, { -0.072923207, -0.02555551, -0.21075071, 0.047272919 }, { 0, 0.0115085, 0, 0 }, { 0.32527558, 0.066048741, -0.28639187, 0.45171914 }, { -0.158086, -0.049098981, -0.17226122, -0.50289857 }, { -0.39456648, 0.031970902, -0.74883626, 0.20536003 }, { 0.22864705, -0.0095988927, -0.1155595, -0.06240073 }, { 0.12336497, -0.34128076, 0.34341316, 0.083678547 }, { -0.032718317, 0.076359349, -0.30099369, -0.016865529 }, { -0.23491753, -0.17228011, -0.044893186, -0.057411459 }, { -0.0077848677, 0, 0, 0 }, { -0.18713605, -0.11612415, 0.30907006, 0.064707406 } }, { { -0.20768494, -0.15642062, -0.079474216, -0.020948121 }, { -0.18767308, -0.013722599, 0.15827086, -0.27421942 }, { -0.11484158, -0.29325715, 0.24426149, 0.34598577 }, { -0.095599056, 0.16784413, 0.23369965, 0.15036114 }, { 0.058496274, -0.064565923, -0.076598803, -0.11988702 }, { -0.03406356, -0.010863931, -0.036116475, 0.0077051595 }, { 0, -0.015078298, 0, 0 }, { -0.21271534, 0.31678528, 0.084310434, -0.039787477 }, { 0.057420352, -0.60894321, -0.14275706, -0.29178151 }, { -0.21477227, 0.091254596, -0.053659362, -0.13299553 }, { -0.24972574, 0.22261101, -0.59415755, -0.13299464 }, { -0.406027, 0.15018847, 0.33281927, 0.28006105 }, { -0.033198856, 0.013081228, 0.0098634494, -0.18858267 }, { -0.16914457, -0.014917022, -0.15618156, 0.038961385 }, { 0, 0.0115085, 0, 0 }, { 0.047340338, -0.052961301, 0.30193278, 0.38564757 }, { -0.2009302, -0.15247105, -0.32333852, 0.22878398 }, { -0.22934017, 0.022888443, 0.30911154, -0.12420416 }, { 0.21191356, -0.33281926, -0.13523708, -0.038546557 }, { 0.28507859, -0.012777666, 0.16285544, -0.12612215 }, { -0.057034227, 0.01719448, -0.037892291, -0.13064036 }, { -0.075888865, 0.041589292, 0.0089100653, -0.10775402 }, { 0.0075560462, 0, 0, 0 }, { -0.18120766, 0.16485298, 0.58949587, 0.072313493 } } }, { { { 0.60381773, 0.64633179, 0.92301353, 0.23720177 }, { 1.1128727, 0.42172315, 1.6605811, 0.22066721 }, { 0.55829912, 0.7107351, 0.47437673, 0.53646626 }, { 0.75684406, 0.65607146, 1.5264507, 0.12817954 }, { -0.25070514, 0.30263175, -0.21070678, -0.2264813 }, { -0.24745858, -0.26801252, 0.2750925, 0.055035565 }, { -0.018769156, -0.066023008, 0.10111114, 0.0089232736 }, { 0.41152465, 0.52508091, 0.4161358, 0.39058287 }, { 0.90919582, 1.2448772, 0.61547497, 0.51303689 }, { 0.2973136, 1.2348603, 0.24154398, 0.76087607 }, { 0.23369317, 0.68368068, 0.81024353, 0.35451079 }, { 0.69272073, 0.47014545, 0.61401877, 0.43768641 }, { -0.44449894, -0.10123077, -0.19173956, -0.15811184 }, { -0.089717, -0.068601549, -0.16704813, -0.29761406 }, { 0.0055968308, -0.089855929, -0.087150641, 0.2244144 }, { 0.38902787, 0.62620686, 1.3314901, 0.26038797 }, { 0.16776511, 0.32722251, 0.71914611, 0.53556119 }, { 0.63106992, 0.46256454, 1.785895, 0.17339911 }, { 0.72516261, 0.44941094, 0.81174974, 0.61247129 }, { 0.56877815, 0.20989179, 0.7607991, 0.017998645 }, { 0.016372087, 0.26062407, -0.32771461, -0.075930098 }, { -0.11957223, -0.22579003, -0.42587945, -0.0015549589 }, { 0.0049992009, 0.053511694, 0.00053268274, 0.022778575 }, { 0.19356675, 0.5564623, 0.74981777, 0.28733119 } }, { { 0.017029304, 0.22690356, 0.25927682, -0.048136042 }, { 0.52936856, -0.26082526, 0.12568074, -0.046727529 }, { 0.08949554, -0.019090555, 0.31477592, -0.067513409 }, { 0.056302335, -0.011819435, -0.063621104, 0.27092306 }, { 0.053971592, -0.17913246, -0.14991651, -0.044263405 }, { 0.29037749, -0.040498369, -0.33600753, 0.16250066 }, { -0.067102844, -0.17843768, 0.033172168, 0.13638573 }, { 0.057127881, -0.044468822, 0.33005778, 0.34775491 }, { -0.14300931, 0.022121077, -0.045281831, -0.065216583 }, { 0.084931489, 0.06688461, 0.15758114, -0.091330485 }, { -0.014274888, 0.29139103, 0.089163749, -0.18005467 }, { -0.2191522, -0.1333803, -0.31948964, -0.28536602 }, { 0.20298891, -0.0031882515, -0.15749696, -0.014977715 }, { -0.14016857, -0.17278064, 0.01369474, 0.10971499 }, { 0.018219806, 0.080447764, 0.0056022696, -0.043028475 }, { -0.076556403, -0.13038184, -0.23788273, 0.5849635 }, { 0.1038427, 0.18199702, 0.35294355, -0.0023601311 }, { 0.22294845, -0.37427713, 0.2907529, 0.26234219 }, { 0.40809306, 0.12982813, 0.42857338, 0.14064303 }, { 0.4265028, 0.18710053, 0.15310514, 0.067551813 }, { -0.18986488, -0.029676062, -0.087045959, -0.14788626 }, { -0.07865478, 0.011558295, -0.018262356, 0.38992629 }, { 0.22297641, 0.072192947, 0.064119712, 0.12862555 }, { -0.069262467, -0.14990585, 0.31342655, -0.15002022 } }, { { 0.25288162, -0.096551539, 0.051695506, 0.20925392 }, { 0.23093904, 0.096712594, 0.19826434, 0.32530694 }, { 0.14114785, 0.071010138, -0.17642029, 0.092260082 }, { 0.39001648, -0.17666595, 0.088397252, 0.1462816 }, { 0.12484597, 0.066920676, -0.16116194, 0.21758387 }, { 0.15625272, -0.00043631439, -0.07868976, -0.19261141 }, { -0.0142415, 0.06356153, 0.026276923, -0.024546668 }, { 0.097089221, 0.085426402, 0.11936115, 0.012042542 }, { 0.52509109, -0.22465399, -0.11490612, 0.023562122 }, { -0.12418278, 0.11985465, 0.087804943, 0.25283464 }, { 0.10716753, -0.036426901, 0.2469409, -0.095816257 }, { -0.095364501, 0.14001518, -0.068636804, -0.082487255 }, { 0.074490355, 0.25323233, 0.17863748, 0.12482145 }, { -0.019616587, -0.0053326518, 0.047558858, 0.066104462 }, { 0.12647102, 0.25712368, 0.12306783, -0.050252261 }, { -0.13375041, 0.17825067, 0.026649645, -0.33338076 }, { 0.16384463, -0.022241979, 0.17817325, 0.6808721 }, { 0.42075944, -0.024292721, -0.11323318, 0.45027063 }, { -0.023953485, 0.25719992, 0.28680108, 0.33600529 }, { 0.013445546, 0.22504275, 0.17408162, 0.52860686 }, { -0.098839039, -0.27017244, 0.10293505, -0.012472685 }, { 0.074267375, -0.0056418849, 0.17632358, 0.21754089 }, { 0.1491061, 0.017927571, -0.0217757, -0.0039381966 }, { 0.067239102, -0.74624136, 0.12992555, -0.058866581 } } } }, { { { { 0.1270204, 0.7650174, 0.55252173, 0.05956498 }, { -0.36870832, 0.31227245, 0.52167466, 0.4282174 }, { -0.036761861, -0.5477415, -0.76091563, -0.37583127 }, { 0.17129434, -0.14281209, -0.40463148, -0.56367877 }, { 0.07429238, 0.45420144, 0.41919765, 0.019225986 }, { -0.44125436, -0.05567539, 0.080551064, 0.54444995 }, { -0.36600455, -0.55359309, -0.3290331, 0.33946169 }, { 0.65253747, 0.015186649, 0.0665303, -0.64649501 }, { 0.05392469, 0.54355001, 0.7539307, -0.41089455 }, { -0.29264863, 0.49684721, 0.39184208, 0.47737193 }, { 0.10885354, -0.80803227, -0.7443769, -0.3736688 }, { 0.1939378, -0.079590275, -0.42241709, -0.75536039 }, { 0.44776697, 0.44884546, 0.427965, 0.3297221 }, { -0.34595785, 0.27723463, 0.12245317, 0.43884357 }, { 0.18467758, -0.55582608, -0.99421464, -0.0096027817 }, { 0.6672057, -0.038103784, -0.048616141, -0.68508055 }, { -0.016615937, 0.62001729, 0.50530563, -0.22211425 }, { -0.16823123, 0.31934529, 0.47092187, 0.4884373 }, { 0.03194189, -0.5624624, -0.44688229, 0.223814 }, { 0.17828041, -0.080017082, -0.44239439, -0.46726625 }, { 0.19895649, 0.82568772, 0.47859751, 0.064443297 }, { -0.47464217, 0.011895223, 0.01123465, -0.010697203 }, { -0.17670677, -0.66931423, -0.5814681, -0.01325001 }, { 0.65193874, -0.010713062, -0.007915928, -0.65520853 } }, { { -0.01027431, -0.0019056004, 0.0020213958, 0.0064495753 }, { 0.0058416688, 0.0051314639, 0.021497114, 0.005870592 }, { -0.00035518612, -0.00087553938, -0.0029318969, 0.0087577986 }, { -0.0048770476, -0.015949665, -0.034816051, -0.006104917 }, { 0.0015371362, -0.0012591621, 0.01241148, 0.00096621463 }, { 0.0032416133, 0.021025709, 0.0036344622, 0.0015436078 }, { -0.0093946276, 0.0046564763, 0.028177476, -0.01022744 }, { 0.00014675555, 0.030031482, -0.0092302407, -0.001999398 }, { -0.049980321, 0.024752279, 0.016684689, -0.0045230976 }, { 0.0067493834, 0.014071508, 0.0079316435, 0.034593704 }, { 0.01971715, -0.0037227013, -0.013430278, -0.024257585 }, { -0.004342319, 0.024001878, -0.013356442, -0.022792018 }, { -0.0051709665, -0.017029547, 0.040567567, 0.0052520812 }, { 0.0090399102, 0.0079604733, 0.00018765016, -0.0092868977 }, { -0.020304032, 0.0056590257, -0.0045373063, -0.018653318 }, { -9.9636934e-05, 0.002001886, 0.0046843544, 0.0055608043 }, { 0.0018025744, -0.0025962216, 0.0068285574, -0.014851062 }, { 0.00041645221, 0.0054738242, 0.0076769026, -0.013419208 }, { 0.0038347099, -0.0042555066, -0.0066470075, 0.0039146778 }, { -0.009084153, 0.024461537, 0.0034578066, -0.0054827001 }, { 0.0033463477, 0.0045594748, 0.00037604935, -0.01571513 }, { -0.012589588, 0.029678359, -0.019924871, -0.004708459 }, { -0.0002642682, -0.0051057336, -0.0042867302, -0.00041141781 }, { -0.00086487068, -0.0025170841, 0.0030062196, -0.0030385417 } }, { { -0.01027431, -0.0019056004, 0.0020213958, 0.0064495753 }, { 0.0058416688, 0.0051314639, 0.021497114, 0.005870592 }, { -0.00035518612, -0.00087553938, -0.0029318969, 0.0087577986 }, { -0.0048770476, -0.015949665, -0.034816051, -0.006104917 }, { 0.0015371362, -0.0012591621, 0.01241148, 0.00096621463 }, { 0.0032416133, 0.021025709, 0.0036344622, 0.0015436078 }, { -0.0093946276, 0.0046564763, 0.028177476, -0.01022744 }, { 0.00014675555, 0.030031482, -0.0092302407, -0.001999398 }, { -0.049980321, 0.024752279, 0.016684689, -0.0045230976 }, { 0.0067493834, 0.014071508, 0.0079316435, 0.034593704 }, { 0.01971715, -0.0037227013, -0.013430278, -0.024257585 }, { -0.004342319, 0.024001878, -0.013356442, -0.022792018 }, { -0.0051709665, -0.017029547, 0.040567567, 0.0052520812 }, { 0.0090399102, 0.0079604733, 0.00018765016, -0.0092868977 }, { -0.020304032, 0.0056590257, -0.0045373063, -0.018653318 }, { -9.9636934e-05, 0.002001886, 0.0046843544, 0.0055608043 }, { 0.0018025744, -0.0025962216, 0.0068285574, -0.014851062 }, { 0.00041645221, 0.0054738242, 0.0076769026, -0.013419208 }, { 0.0038347099, -0.0042555066, -0.0066470075, 0.0039146778 }, { -0.009084153, 0.024461537, 0.0034578066, -0.0054827001 }, { 0.0033463477, 0.0045594748, 0.00037604935, -0.01571513 }, { -0.012589588, 0.029678359, -0.019924871, -0.004708459 }, { -0.0002642682, -0.0051057336, -0.0042867302, -0.00041141781 }, { -0.00086487068, -0.0025170841, 0.0030062196, -0.0030385417 } } }, { { { -0.68772793, 0.19029367, -0.17427646, 0.60300616 }, { -0.29980532, -0.22397537, -0.4071009, 0.36277983 }, { 0.75628069, -0.13426242, 0.13645381, -0.74653491 }, { 0.14891408, -0.13497977, 0.36807879, -0.39814386 }, { -0.20608987, -0.076497863, -0.19510375, 0.34604256 }, { -0.02421123, -0.4588774, -0.64965351, 0.083039161 }, { 0.51918764, -0.30614677, -0.25791921, -0.40837612 }, { 0.028860181, 0.63152733, 0.5876224, -0.033139773 }, { -0.63418144, 0.046874151, 0.24431924, 0.71662556 }, { -0.29088451, -0.21455586, -0.73980807, 0.65038559 }, { 0.78663226, 0.00020858525, 0.40361403, -0.75720144 }, { 0.1998276, 0.54590973, 0.1773378, -0.35464319 }, { -0.40236144, 0.31362578, -0.34406026, 0.38120073 }, { -0.27845549, -0.46862161, -0.47141499, 0.095899189 }, { 0.6004921, 0.28051621, -0.011378178, -0.98141078 }, { 0.032724674, 0.66798127, 0.66430425, -0.05209965 }, { -0.59603974, -0.083198329, 0.34616224, 0.42082916 }, { -0.14262632, -0.21418442, -0.37504914, 0.32676687 }, { 0.58204273, 0.0067537174, -0.35923481, -0.40792038 }, { 0.15607366, 0.17215007, 0.34414936, -0.33566945 }, { -0.44862333, 0.004919013, 0.0076768115, 0.41897935 }, { -0.022062848, -0.39695079, -0.0062786656, 0.042925103 }, { 0.65953535, -0.15521993, 0.011867978, -0.57721165 }, { 0.031305912, 0.65627006, 0.66779002, -0.029815636 } }, { { 0.011457792, -0.011774949, -0.012205337, 0.0048139052 }, { -0.024024566, 0.018313023, -0.023210623, -0.0046351547 }, { 0.0039133571, 0.0046801024, -0.020590099, -0.0018568631 }, { -0.015369931, -0.0092621276, -0.026149742, 0.0010335971 }, { 0.032555144, -0.01336897, -0.022733265, -0.027997469 }, { -0.028161537, -0.00073877629, -0.023989631, 0.0055660453 }, { -0.012966193, 0.003944376, 0.025685982, -0.0017458044 }, { 0.00015626641, -0.009524206, 0.0083025026, -0.00049753811 }, { -0.02358661, 0.006370149, 0.00087066462, -0.00054248544 }, { -0.0024571244, -0.023218369, -0.010895303, -0.0095647684 }, { 0.0069970393, -0.00093403301, -0.0081922371, -0.00026359768 }, { 0.0065921354, 0.028846533, -0.045676337, 0.006070217 }, { 0.0045248423, -0.0084676847, 0.028756195, 0.020612871 }, { 0.0037691244, -0.0069385161, -0.00029501448, -0.0017839033 }, { -0.0048675353, -0.011930456, 0.0044251285, -0.00016323616 }, { -0.0012291164, -0.0019575288, 0.0078250029, -0.0011151155 }, { 0.00503333, -0.0094538968, 0.0092375183, 0.018207648 }, { 0.0080615812, -0.0073583459, -0.0166794, 0.016416158 }, { 0.002192959, -0.01153759, -0.0048668362, -0.0071123281 }, { -0.010116143, -0.010224552, 0.010897731, 0.00093792816 }, { 0.017199359, -0.0087516179, 0.0021169251, -0.020946959 }, { -0.01570063, 0.020087246, 0.014492818, -0.016014018 }, { 0.0023484072, 0.0015070243, -0.00045616273, -0.001211882 }, { 0.0018090492, -0.0012261901, 0.0012809284, 0.00096488905 } }, { { 0.011457792, -0.011774949, -0.012205337, 0.0048139052 }, { -0.024024566, 0.018313023, -0.023210623, -0.0046351547 }, { 0.0039133571, 0.0046801024, -0.020590099, -0.0018568631 }, { -0.015369931, -0.0092621276, -0.026149742, 0.0010335971 }, { 0.032555144, -0.01336897, -0.022733265, -0.027997469 }, { -0.028161537, -0.00073877629, -0.023989631, 0.0055660453 }, { -0.012966193, 0.003944376, 0.025685982, -0.0017458044 }, { 0.00015626641, -0.009524206, 0.0083025026, -0.00049753811 }, { -0.02358661, 0.006370149, 0.00087066462, -0.00054248544 }, { -0.0024571244, -0.023218369, -0.010895303, -0.0095647684 }, { 0.0069970393, -0.00093403301, -0.0081922371, -0.00026359768 }, { 0.0065921354, 0.028846533, -0.045676337, 0.006070217 }, { 0.0045248423, -0.0084676847, 0.028756195, 0.020612871 }, { 0.0037691244, -0.0069385161, -0.00029501448, -0.0017839033 }, { -0.0048675353, -0.011930456, 0.0044251285, -0.00016323616 }, { -0.0012291164, -0.0019575288, 0.0078250029, -0.0011151155 }, { 0.00503333, -0.0094538968, 0.0092375183, 0.018207648 }, { 0.0080615812, -0.0073583459, -0.0166794, 0.016416158 }, { 0.002192959, -0.01153759, -0.0048668362, -0.0071123281 }, { -0.010116143, -0.010224552, 0.010897731, 0.00093792816 }, { 0.017199359, -0.0087516179, 0.0021169251, -0.020946959 }, { -0.01570063, 0.020087246, 0.014492818, -0.016014018 }, { 0.0023484072, 0.0015070243, -0.00045616273, -0.001211882 }, { 0.0018090492, -0.0012261901, 0.0012809284, 0.00096488905 } } }, { { { 0.71476997, 0.61525336, 0.81507512, 0.79550964 }, { 0.87986984, 0.9232123, 0.74974956, 0.82765975 }, { 0.65321366, 0.82580437, 0.63434042, 0.54903231 }, { 0.97390084, 0.98050251, 0.83713283, 0.72370416 }, { 0.97570877, 0.88760866, 0.88668363, 0.9380218 }, { 0.89705541, 0.88675351, 0.75595095, 0.83467284 }, { 0.77232433, 0.77447327, 0.9084134, 0.84734569 }, { -0.75720667, -0.77520488, -0.80639546, -0.76219811 }, { 0.77130152, 0.83806694, 0.60983327, 0.56357207 }, { 0.91090229, 0.84089752, 0.54694041, 0.59085922 }, { 0.60775044, 0.58913818, 0.53197627, 0.53574024 }, { 0.96044628, 0.83405513, 0.88888419, 0.55105253 }, { 0.79850486, 0.83676557, 0.83574428, 0.86369517 }, { 0.89597751, 0.83876978, 0.87336884, 0.8934314 }, { 0.77801249, 0.78253947, 0.10680725, 0.19167855 }, { -0.74415432, -0.74320194, -0.74587957, -0.72660186 }, { 0.802783, 0.78016447, 0.79046691, 0.87952719 }, { 0.97537479, 0.92311625, 0.79848027, 0.80910594 }, { 0.8125306, 0.82679528, 0.81929639, 0.88516002 }, { 0.97152309, 0.98181547, 0.82815966, 0.81791703 }, { 0.87129411, 0.56410602, 0.87800085, 0.905706 }, { 0.87990229, 0.91776281, 0.99991718, 0.99902102 }, { 0.73060786, 0.72658464, 0.81348263, 0.81648708 }, { -0.75762512, -0.75445002, -0.74430762, -0.75485946 } }, { { 0.018332644, 0.0084005452, -0.0018937689, -0.0035491975 }, { 0.0016556654, 0.0049261013, -0.021796869, 0.0025973591 }, { -0.0019671758, 0.00051947074, 0.0071261223, 0.0056689139 }, { 0.00041901024, -0.0023903288, -0.0035639711, -0.0036673013 }, { 0.009963464, 0.00099195429, -0.0042516892, 0.0092605531 }, { 0.0034813664, 0.0028575465, -0.016343415, -0.0014475905 }, { 0.0053571039, 0.0051116063, 0.016171091, -0.00052744238 }, { 0.00013272575, -0.0095491849, 0.0070156475, 0.0017057538 }, { 0.028067438, -0.0086835729, -0.0087852674, 0.0035321054 }, { 0.0025007808, -0.0075654884, -0.012551417, -0.0068823899 }, { -0.00017607308, 0.002636122, -0.011272055, -0.010314896 }, { 0.010646599, 0.00042804331, 0.013900837, -0.01279076 }, { 0.0059898286, 0.012331371, -0.0073125296, 0.016248603 }, { 0.031579315, -0.0057840222, -0.00018304192, 0.005171422 }, { 0.010928513, 0.0092660887, 0.030404621, 0.0053167707 }, { -0.00014899672, -0.0035246494, 0.0075862845, -0.005861723 }, { 0.0067791918, 0.0021224495, -0.0071755505, -0.010370936 }, { 0.0015352958, -0.0025785166, -0.0092688001, 0.003966373 }, { 0.0036915074, -0.002306452, -0.005736452, -0.0033594125 }, { 0.0065128512, 0.006188005, 0.00088322638, -0.0016227066 }, { 0.0092720771, -0.0046684631, -7.3769604e-05, 0.013807013 }, { -0.0031421984, 0.010622679, 0.00041591214, 0.0032786075 }, { -0.0021421613, -0.0041675589, -0.0029529994, -0.00085350449 }, { -0.00069204344, -0.0010785124, 0.00097549628, 0.0025280456 } }, { { 0.018332644, 0.0084005452, -0.0018937689, -0.0035491975 }, { 0.0016556654, 0.0049261013, -0.021796869, 0.0025973591 }, { -0.0019671758, 0.00051947074, 0.0071261223, 0.0056689139 }, { 0.00041901024, -0.0023903288, -0.0035639711, -0.0036673013 }, { 0.009963464, 0.00099195429, -0.0042516892, 0.0092605531 }, { 0.0034813664, 0.0028575465, -0.016343415, -0.0014475905 }, { 0.0053571039, 0.0051116063, 0.016171091, -0.00052744238 }, { 0.00013272575, -0.0095491849, 0.0070156475, 0.0017057538 }, { 0.028067438, -0.0086835729, -0.0087852674, 0.0035321054 }, { 0.0025007808, -0.0075654884, -0.012551417, -0.0068823899 }, { -0.00017607308, 0.002636122, -0.011272055, -0.010314896 }, { 0.010646599, 0.00042804331, 0.013900837, -0.01279076 }, { 0.0059898286, 0.012331371, -0.0073125296, 0.016248603 }, { 0.031579315, -0.0057840222, -0.00018304192, 0.005171422 }, { 0.010928513, 0.0092660887, 0.030404621, 0.0053167707 }, { -0.00014899672, -0.0035246494, 0.0075862845, -0.005861723 }, { 0.0067791918, 0.0021224495, -0.0071755505, -0.010370936 }, { 0.0015352958, -0.0025785166, -0.0092688001, 0.003966373 }, { 0.0036915074, -0.002306452, -0.005736452, -0.0033594125 }, { 0.0065128512, 0.006188005, 0.00088322638, -0.0016227066 }, { 0.0092720771, -0.0046684631, -7.3769604e-05, 0.013807013 }, { -0.0031421984, 0.010622679, 0.00041591214, 0.0032786075 }, { -0.0021421613, -0.0041675589, -0.0029529994, -0.00085350449 }, { -0.00069204344, -0.0010785124, 0.00097549628, 0.0025280456 } } }, { { { 5.3792285, 5.1960477, 5.5112916, 5.6615254 }, { 5.0489877, 5.2428834, 5.1752035, 5.1109826 }, { 5.5205204, 5.7511938, 5.0202917, 4.9168865 }, { 4.9522523, 4.8880256, 5.1015936, 5.2858816 }, { 5.7256502, 5.7919759, 5.645241, 5.6035708 }, { 6.4076931, 6.4822111, 6.2642633, 6.3925959 }, { 6.9797014, 6.981436, 7.0028674, 6.9976464 }, { -0.03290957, -0.03290957, -0.03290957, -0.03290957 }, { 5.4977854, 5.7684965, 5.3463095, 4.8810492 }, { 4.9869047, 5.4896416, 4.9647805, 4.884877 }, { 5.3141219, 5.3357788, 4.7695434, 4.8709631 }, { 5.2056063, 5.407802, 5.2123857, 4.9428208 }, { 6.2188218, 6.17756, 6.2751008, 6.3672109 }, { 6.9105856, 6.7986798, 6.5712335, 6.5907061 }, { 6.9797014, 6.9797014, 5.6859993, 5.5642483 }, { -0.032764603, -0.032764603, -0.032764603, -0.032764603 }, { 5.7724142, 6.0929556, 5.99581, 5.9265164 }, { 4.9363192, 4.9823732, 5.1732995, 5.2475265 }, { 5.8365191, 5.9972902, 5.9778441, 5.9270668 }, { 4.8706768, 5.0194503, 5.155585, 5.2188041 }, { 6.1569904, 6.0563989, 6.0989699, 6.2139837 }, { 5.8727399, 5.8948086, 5.5734095, 5.5536103 }, { 6.9797014, 6.9797014, 6.9797014, 6.9797014 }, { -0.032766769, -0.032766769, -0.032766769, -0.032766769 } }, { { 0.0011802354, -0.006546101, -0.02103972, 0.0008654047 }, { -0.015460534, 0.017874544, 0.0029121134, 0.023511773 }, { -0.040909245, 0.011927691, 0.011991588, 0.01677931 }, { -0.015633544, -0.0042321141, 0.026623034, 0.0080414514 }, { 0.012614382, 0.0065080145, 0.035716738, -0.0080665814 }, { -0.0057849744, -0.017478461, -0.031219642, 0.00016446523 }, { 0, 0.00032235028, 0, 0 }, { 0, 0, 0, 0 }, { -0.068586697, -0.024228236, -0.012857221, -0.039493706 }, { -0.018078201, -0.015140979, 0.00072119173, -0.051249859 }, { -0.054228277, 0.0097895101, 0.0019832646, -0.011715411 }, { -0.042326208, -0.010160072, 0.037088052, -0.031848667 }, { 0.00067130897, -0.013966717, -0.017268559, -0.0074614576 }, { 0.070515961, 0.012848107, -0.0008396517, 0.0049006506 }, { 0, 0, -0.063014256, -0.0085124986 }, { 0, 0, 0, 0 }, { -0.040302299, 0.0048936307, 0.0064406394, 0.0034044871 }, { -0.010453589, 0.0035820836, -0.017384391, -0.038199947 }, { -0.044968611, -0.0088322127, 0.020303819, 0.0058131005 }, { -0.0056838535, 0.010211409, -0.010999927, -0.027621859 }, { 0.0064753811, -0.0059341242, -0.014902755, 0.0082868118 }, { -0.0013222735, 0.0028492181, -0.023523273, -0.02576271 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }, { { 0.0011802354, -0.006546101, -0.02103972, 0.00086540469 }, { -0.015460534, 0.017874544, 0.0029121134, 0.023511773 }, { -0.040909245, 0.011927691, 0.011991588, 0.01677931 }, { -0.015633544, -0.0042321141, 0.026623034, 0.0080414514 }, { 0.012614382, 0.0065080145, 0.035716738, -0.0080665814 }, { -0.0057849744, -0.017478461, -0.031219642, 0.00016446523 }, { 0, 0.00032235028, 0, 0 }, { 0, 0, 0, 0 }, { -0.068586697, -0.024228236, -0.012857221, -0.039493706 }, { -0.018078201, -0.015140979, 0.00072119173, -0.051249859 }, { -0.054228277, 0.0097895101, 0.0019832646, -0.011715411 }, { -0.042326208, -0.010160072, 0.037088052, -0.031848667 }, { 0.00067130897, -0.013966717, -0.017268559, -0.0074614576 }, { 0.070515961, 0.012848107, -0.0008396517, 0.0049006506 }, { 0, 0, -0.063014256, -0.0085124986 }, { 0, 0, 0, 0 }, { -0.040302299, 0.0048936307, 0.0064406394, 0.0034044871 }, { -0.010453589, 0.0035820836, -0.017384391, -0.038199947 }, { -0.044968611, -0.0088322127, 0.020303819, 0.0058131005 }, { -0.0056838535, 0.010211409, -0.010999927, -0.027621859 }, { 0.0064753811, -0.0059341242, -0.014902755, 0.0082868118 }, { -0.0013222735, 0.0028492181, -0.023523273, -0.02576271 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 } } }, { { { 0.72189984, 0.22069996, 0.71952927, 0.77725949 }, { 0.4054405, 0.20582059, 0.2747016, 0.37612563 }, { 0.58887422, 0.27441131, 0.19468101, 0.21480554 }, { 0.46814145, 0.34317, 0.46068212, 0.13962064 }, { -0.18134132, -0.26668789, -0.60984999, -0.67879259 }, { -0.47870351, -0.34453227, 0.32494779, 0.10292971 }, { 0.087252967, 0.066950358, 0.31813819, 0.071094818 }, { -0.0031436256, 0.038245091, -0.0076651913, -0.015389479 }, { 1.2668531, 1.2894974, 0.40584018, 0.51755806 }, { 1.3207257, 1.3403747, 0.54924634, 0.40282713 }, { 0.78581828, 0.56379328, 0.27901993, 0.56429306 }, { 0.8748226, 1.0271253, 1.0085726, 0.3888545 }, { -0.22577636, -0.32895071, -0.2846317, -0.11679531 }, { 0.26477285, 0.3179447, -0.063393238, 0.024059773 }, { -0.15463395, -0.22721468, -0.20680404, -0.15700788 }, { 0.012107106, -0.0061245949, -0.024224367, 0.005040693 }, { 0.97943693, 0.64840429, 0.45106998, 0.40771935 }, { 0.49907853, 0.1562184, 0.34338458, 0.39710628 }, { 0.95047709, 0.53336107, 0.38318275, 0.44919148 }, { 0.41892697, 0.069965886, 0.45831656, 0.38821529 }, { -0.20216736, -0.43209441, -0.57684857, -0.40189427 }, { -0.63992377, -0.40683032, -0.59207903, -0.57251716 }, { -0.047117438, -0.1880015, -0.12265155, 0.00059988607 }, { -0.011836442, -0.010049497, -0.0026152072, 0.016137736 } }, { { 0.092068993, 0.0045466749, 0.0054574031, 0.02582156 }, { 0.022115456, -0.015664041, -0.022004653, 0.041431654 }, { 0.029951298, -0.0004408542, 0.0087496069, 0.017850027 }, { 0.029086373, 0.022116039, 0.044010315, 0.001644876 }, { 0.016256387, 0.0083249367, 0.019570849, -0.0021276222 }, { 0.0079070076, -0.024696939, 0.044311101, 0.023671132 }, { -0.0081796119, -0.0024995551, 0.033501743, -0.031958988 }, { 0.0065005403, -0.076642001, 0.015736477, 0.030966939 }, { 0.029110717, 0.039154477, -0.074376619, 0.025532063 }, { -0.10980761, 0.0038346834, 0.014449171, -0.030702653 }, { -0.00068350423, -0.037251569, -0.008409224, -0.026322878 }, { 0.035406012, 0.064176275, 0.031437854, -0.0344642 }, { 0.037145809, -0.024909212, 0.041030386, 0.035216105 }, { -0.093276646, -0.013904083, -0.019536023, -0.023834405 }, { 0.042751846, -0.03620164, 0.081115921, 0.018379967 }, { -0.023909625, 0.012833691, 0.048086442, -0.0097340268 }, { 0.039552712, -0.00026806514, 0.011646753, 0.0065939486 }, { 0.058985248, 0.020165701, 0.0076721521, 0.033274221 }, { 0.052889871, 0.0042520093, 0.016490396, 0.009287973 }, { 0.044305975, -0.0016263469, 0.041390177, 0.033541355 }, { 0.014595133, -0.004801042, -0.0049517302, 0.015714264 }, { 0.00075086205, 0.0080838736, -0.037611057, -0.030488441 }, { 0.0019178075, -0.0082517768, -0.002525773, 0.0043993022 }, { 0.023774971, 0.020335611, 0.0056643868, -0.032100338 } }, { { 0.092068993, 0.0045466749, 0.0054574031, 0.02582156 }, { 0.022115456, -0.015664041, -0.022004653, 0.041431654 }, { 0.029951298, -0.0004408542, 0.0087496069, 0.017850027 }, { 0.029086373, 0.022116039, 0.044010315, 0.001644876 }, { 0.016256387, 0.0083249367, 0.019570849, -0.0021276222 }, { 0.0079070076, -0.024696939, 0.044311101, 0.023671132 }, { -0.0081796119, -0.0024995551, 0.033501743, -0.031958988 }, { 0.0065005403, -0.076642001, 0.015736477, 0.030966939 }, { 0.029110717, 0.039154477, -0.074376619, 0.025532063 }, { -0.10980761, 0.0038346834, 0.014449171, -0.030702653 }, { -0.00068350423, -0.037251569, -0.008409224, -0.026322878 }, { 0.035406012, 0.064176275, 0.031437854, -0.0344642 }, { 0.037145809, -0.024909212, 0.041030386, 0.035216105 }, { -0.093276646, -0.013904083, -0.019536023, -0.023834405 }, { 0.042751846, -0.03620164, 0.081115921, 0.018379967 }, { -0.023909625, 0.012833691, 0.048086442, -0.0097340268 }, { 0.039552712, -0.00026806514, 0.011646753, 0.0065939486 }, { 0.058985248, 0.020165701, 0.0076721521, 0.033274221 }, { 0.052889871, 0.0042520093, 0.016490396, 0.009287973 }, { 0.044305975, -0.0016263469, 0.041390177, 0.033541355 }, { 0.014595133, -0.004801042, -0.0049517303, 0.015714264 }, { 0.00075086205, 0.0080838736, -0.037611057, -0.030488441 }, { 0.0019178075, -0.0082517768, -0.002525773, 0.0043993022 }, { 0.023774971, 0.020335611, 0.0056643868, -0.032100338 } } } } }; - -#endif diff --git a/servers/visual/rasterizer_rd/light_cluster_builder.cpp b/servers/visual/rasterizer_rd/light_cluster_builder.cpp deleted file mode 100644 index 943ef1c7fa..0000000000 --- a/servers/visual/rasterizer_rd/light_cluster_builder.cpp +++ /dev/null @@ -1,255 +0,0 @@ -/*************************************************************************/ -/* light_cluster_builder.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "light_cluster_builder.h" - -void LightClusterBuilder::begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection) { - view_xform = p_view_transform; - projection = p_cam_projection; - z_near = -projection.get_z_near(); - z_far = -projection.get_z_far(); - - //reset counts - light_count = 0; - refprobe_count = 0; - item_count = 0; - sort_id_count = 0; -} - -void LightClusterBuilder::bake_cluster() { - - float slice_depth = (z_near - z_far) / depth; - - uint8_t *cluster_dataw = cluster_data.ptrw(); - Cell *cluster_data_ptr = (Cell *)cluster_dataw; - //clear the cluster - zeromem(cluster_data_ptr, (width * height * depth * sizeof(Cell))); - - /* Step 1, create cell positions and count them */ - - for (uint32_t i = 0; i < item_count; i++) { - - const Item &item = items[i]; - - int from_slice = Math::floor((z_near - (item.aabb.position.z + item.aabb.size.z)) / slice_depth); - int to_slice = Math::floor((z_near - item.aabb.position.z) / slice_depth); - - if (from_slice >= (int)depth || to_slice < 0) { - continue; //sorry no go - } - - from_slice = MAX(0, from_slice); - to_slice = MIN((int)depth - 1, to_slice); - - for (int j = from_slice; j <= to_slice; j++) { - - Vector3 min = item.aabb.position; - Vector3 max = item.aabb.position + item.aabb.size; - - float limit_near = MIN((z_near - slice_depth * j), max.z); - float limit_far = MAX((z_near - slice_depth * (j + 1)), min.z); - - max.z = limit_near; - min.z = limit_near; - - Vector3 proj_min = projection.xform(min); - Vector3 proj_max = projection.xform(max); - - int near_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width)); - int near_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height)); - int near_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width)); - int near_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height)); - - max.z = limit_far; - min.z = limit_far; - - proj_min = projection.xform(min); - proj_max = projection.xform(max); - - int far_from_x = int(Math::floor((proj_min.x * 0.5 + 0.5) * width)); - int far_from_y = int(Math::floor((-proj_max.y * 0.5 + 0.5) * height)); - int far_to_x = int(Math::floor((proj_max.x * 0.5 + 0.5) * width)); - int far_to_y = int(Math::floor((-proj_min.y * 0.5 + 0.5) * height)); - - //print_line(itos(j) + " near - " + Vector2i(near_from_x, near_from_y) + " -> " + Vector2i(near_to_x, near_to_y)); - //print_line(itos(j) + " far - " + Vector2i(far_from_x, far_from_y) + " -> " + Vector2i(far_to_x, far_to_y)); - - int from_x = MIN(near_from_x, far_from_x); - int from_y = MIN(near_from_y, far_from_y); - int to_x = MAX(near_to_x, far_to_x); - int to_y = MAX(near_to_y, far_to_y); - - if (from_x >= (int)width || to_x < 0 || from_y >= (int)height || to_y < 0) { - continue; - } - - int sx = MAX(0, from_x); - int sy = MAX(0, from_y); - int dx = MIN((int)width - 1, to_x); - int dy = MIN((int)height - 1, to_y); - - //print_line(itos(j) + " - " + Vector2i(sx, sy) + " -> " + Vector2i(dx, dy)); - - for (int x = sx; x <= dx; x++) { - for (int y = sy; y <= dy; y++) { - uint32_t offset = j * (width * height) + y * width + x; - - if (unlikely(sort_id_count == sort_id_max)) { - sort_id_max = nearest_power_of_2_templated(sort_id_max + 1); - sort_ids = (SortID *)memrealloc(sort_ids, sizeof(SortID) * sort_id_max); - if (ids.size()) { - - ids.resize(sort_id_max); - RD::get_singleton()->free(items_buffer); - items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * sort_id_max); - } - } - - sort_ids[sort_id_count].cell_index = offset; - sort_ids[sort_id_count].item_index = item.index; - sort_ids[sort_id_count].item_type = item.type; - - sort_id_count++; - - //for now, only count - cluster_data_ptr[offset].item_pointers[item.type]++; - //print_line("at offset " + itos(offset) + " value: " + itos(cluster_data_ptr[offset].item_pointers[item.type])); - } - } - } - } - - /* Step 2, Assign pointers (and reset counters) */ - - uint32_t offset = 0; - for (uint32_t i = 0; i < (width * height * depth); i++) { - for (int j = 0; j < ITEM_TYPE_MAX; j++) { - uint32_t count = cluster_data_ptr[i].item_pointers[j]; //save count - cluster_data_ptr[i].item_pointers[j] = offset; //replace count by pointer - offset += count; //increase offset by count; - } - } - - //print_line("offset: " + itos(offset)); - /* Step 3, Place item lists */ - - uint32_t *ids_ptr = ids.ptrw(); - - for (uint32_t i = 0; i < sort_id_count; i++) { - const SortID &id = sort_ids[i]; - Cell &cell = cluster_data_ptr[id.cell_index]; - uint32_t pointer = cell.item_pointers[id.item_type] & POINTER_MASK; - uint32_t counter = cell.item_pointers[id.item_type] >> COUNTER_SHIFT; - ids_ptr[pointer + counter] = id.item_index; - - cell.item_pointers[id.item_type] = pointer | ((counter + 1) << COUNTER_SHIFT); - } - - RD::get_singleton()->texture_update(cluster_texture, 0, cluster_data, true); - RD::get_singleton()->buffer_update(items_buffer, 0, offset * sizeof(uint32_t), ids_ptr, true); -} - -void LightClusterBuilder::setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth) { - - if (width == p_width && height == p_height && depth == p_depth) { - return; - } - if (cluster_texture.is_valid()) { - RD::get_singleton()->free(cluster_texture); - } - - width = p_width; - height = p_height; - depth = p_depth; - - cluster_data.resize(width * height * depth * sizeof(Cell)); - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - tf.type = RD::TEXTURE_TYPE_3D; - tf.width = width; - tf.height = height; - tf.depth = depth; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - - cluster_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } -} - -RID LightClusterBuilder::get_cluster_texture() const { - return cluster_texture; -} -RID LightClusterBuilder::get_cluster_indices_buffer() const { - return items_buffer; -} - -LightClusterBuilder::LightClusterBuilder() { - //initialize accumulators to something - lights = (LightData *)memalloc(sizeof(LightData) * 1024); - light_max = 1024; - - refprobes = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024); - refprobe_max = 1024; - - decals = (OrientedBoxData *)memalloc(sizeof(OrientedBoxData) * 1024); - decal_max = 1024; - - items = (Item *)memalloc(sizeof(Item) * 1024); - item_max = 1024; - - sort_ids = (SortID *)memalloc(sizeof(SortID) * 1024); - ids.resize(2014); - items_buffer = RD::get_singleton()->storage_buffer_create(sizeof(uint32_t) * 1024); - item_max = 1024; -} -LightClusterBuilder::~LightClusterBuilder() { - - if (cluster_data.size()) { - RD::get_singleton()->free(cluster_texture); - } - - if (lights) { - memfree(lights); - } - if (refprobes) { - memfree(refprobes); - } - if (decals) { - memfree(decals); - } - if (items) { - memfree(items); - } - if (sort_ids) { - memfree(sort_ids); - RD::get_singleton()->free(items_buffer); - } -} diff --git a/servers/visual/rasterizer_rd/light_cluster_builder.h b/servers/visual/rasterizer_rd/light_cluster_builder.h deleted file mode 100644 index 83014a7dd0..0000000000 --- a/servers/visual/rasterizer_rd/light_cluster_builder.h +++ /dev/null @@ -1,291 +0,0 @@ -/*************************************************************************/ -/* light_cluster_builder.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef LIGHT_CLUSTER_BUILDER_H -#define LIGHT_CLUSTER_BUILDER_H - -#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" - -class LightClusterBuilder { -public: - enum LightType { - LIGHT_TYPE_OMNI, - LIGHT_TYPE_SPOT - }; - - enum ItemType { - ITEM_TYPE_OMNI_LIGHT, - ITEM_TYPE_SPOT_LIGHT, - ITEM_TYPE_REFLECTION_PROBE, - ITEM_TYPE_DECAL, - ITEM_TYPE_MAX //should always be 4 - }; - - enum { - COUNTER_SHIFT = 20, //one million total ids - POINTER_MASK = (1 << COUNTER_SHIFT) - 1, - COUNTER_MASK = 0xfff // 4096 items per cell - }; - -private: - struct LightData { - float position[3]; - uint32_t type; - float radius; - float spot_aperture; - uint32_t pad[2]; - }; - - uint32_t light_count = 0; - uint32_t light_max = 0; - LightData *lights = nullptr; - - struct OrientedBoxData { - float position[3]; - uint32_t pad; - float x_axis[3]; - uint32_t pad2; - float y_axis[3]; - uint32_t pad3; - float z_axis[3]; - uint32_t pad4; - }; - - uint32_t refprobe_count = 0; - uint32_t refprobe_max = 0; - OrientedBoxData *refprobes = nullptr; - - uint32_t decal_count = 0; - uint32_t decal_max = 0; - OrientedBoxData *decals = nullptr; - - struct Item { - AABB aabb; - ItemType type; - uint32_t index; - }; - - Item *items = nullptr; - uint32_t item_count = 0; - uint32_t item_max = 0; - - uint32_t width = 0; - uint32_t height = 0; - uint32_t depth = 0; - - struct Cell { - uint32_t item_pointers[ITEM_TYPE_MAX]; - }; - - Vector cluster_data; - RID cluster_texture; - - struct SortID { - uint32_t cell_index; - uint32_t item_index; - ItemType item_type; - }; - - SortID *sort_ids = nullptr; - Vector ids; - uint32_t sort_id_count = 0; - uint32_t sort_id_max = 0; - RID items_buffer; - - Transform view_xform; - CameraMatrix projection; - float z_far = 0; - float z_near = 0; - - _FORCE_INLINE_ void _add_item(const AABB &p_aabb, ItemType p_type, uint32_t p_index) { - if (unlikely(item_count == item_max)) { - item_max = nearest_power_of_2_templated(item_max + 1); - items = (Item *)memrealloc(items, sizeof(Item) * item_max); - } - - Item &item = items[item_count]; - item.aabb = p_aabb; - item.index = p_index; - item.type = p_type; - item_count++; - } - -public: - void begin(const Transform &p_view_transform, const CameraMatrix &p_cam_projection); - - _FORCE_INLINE_ void add_light(LightType p_type, const Transform &p_transform, float p_radius, float p_spot_aperture) { - if (unlikely(light_count == light_max)) { - light_max = nearest_power_of_2_templated(light_max + 1); - lights = (LightData *)memrealloc(lights, sizeof(LightData) * light_max); - } - - LightData &ld = lights[light_count]; - ld.type = p_type; - ld.position[0] = p_transform.origin.x; - ld.position[1] = p_transform.origin.y; - ld.position[2] = p_transform.origin.z; - ld.radius = p_radius; - ld.spot_aperture = p_spot_aperture; - - Transform xform = view_xform * p_transform; - - ld.radius *= xform.basis.get_uniform_scale(); - - AABB aabb; - - switch (p_type) { - case LIGHT_TYPE_OMNI: { - aabb.position = xform.origin; - aabb.size = Vector3(ld.radius, ld.radius, ld.radius); - aabb.position -= aabb.size; - aabb.size *= 2.0; - - _add_item(aabb, ITEM_TYPE_OMNI_LIGHT, light_count); - } break; - case LIGHT_TYPE_SPOT: { - Vector3 v(0, 0, -1); - v.rotated(Vector3(0, 1, 0), Math::deg2rad(ld.spot_aperture)); //rotate in x-z - v.normalize(); - v *= ld.radius; - v.y = v.x; - - aabb.position = xform.origin; - aabb.expand_to(xform.xform(v)); - aabb.expand_to(xform.xform(Vector3(-v.x, v.y, v.z))); - aabb.expand_to(xform.xform(Vector3(-v.x, -v.y, v.z))); - aabb.expand_to(xform.xform(Vector3(v.x, -v.y, v.z))); - _add_item(aabb, ITEM_TYPE_SPOT_LIGHT, light_count); - } break; - } - - light_count++; - } - - _FORCE_INLINE_ void add_reflection_probe(const Transform &p_transform, const Vector3 &p_half_extents) { - - if (unlikely(refprobe_count == refprobe_max)) { - refprobe_max = nearest_power_of_2_templated(refprobe_max + 1); - refprobes = (OrientedBoxData *)memrealloc(refprobes, sizeof(OrientedBoxData) * refprobe_max); - } - - OrientedBoxData &rp = refprobes[refprobe_count]; - Vector3 origin = p_transform.origin; - rp.position[0] = origin.x; - rp.position[1] = origin.y; - rp.position[2] = origin.z; - - Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x; - rp.x_axis[0] = x_axis.x; - rp.x_axis[1] = x_axis.y; - rp.x_axis[2] = x_axis.z; - - Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y; - rp.y_axis[0] = y_axis.x; - rp.y_axis[1] = y_axis.y; - rp.y_axis[2] = y_axis.z; - - Vector3 z_axis = p_transform.basis.get_axis(2) * p_half_extents.z; - rp.z_axis[0] = z_axis.x; - rp.z_axis[1] = z_axis.y; - rp.z_axis[2] = z_axis.z; - - AABB aabb; - - aabb.position = origin + x_axis + y_axis + z_axis; - aabb.expand_to(origin + x_axis + y_axis - z_axis); - aabb.expand_to(origin + x_axis - y_axis + z_axis); - aabb.expand_to(origin + x_axis - y_axis - z_axis); - aabb.expand_to(origin - x_axis + y_axis + z_axis); - aabb.expand_to(origin - x_axis + y_axis - z_axis); - aabb.expand_to(origin - x_axis - y_axis + z_axis); - aabb.expand_to(origin - x_axis - y_axis - z_axis); - - _add_item(aabb, ITEM_TYPE_REFLECTION_PROBE, refprobe_count); - - refprobe_count++; - } - - _FORCE_INLINE_ void add_decal(const Transform &p_transform, const Vector2 &p_half_extents, float p_depth) { - - if (unlikely(decal_count == decal_max)) { - decal_max = nearest_power_of_2_templated(decal_max + 1); - decals = (OrientedBoxData *)memrealloc(decals, sizeof(OrientedBoxData) * decal_max); - } - - OrientedBoxData &dc = decals[decal_count]; - - Vector3 z_axis = -p_transform.basis.get_axis(2) * p_depth * 0.5; - dc.z_axis[0] = z_axis.x; - dc.z_axis[1] = z_axis.y; - dc.z_axis[2] = z_axis.z; - - Vector3 origin = p_transform.origin - z_axis; - dc.position[0] = origin.x; - dc.position[1] = origin.y; - dc.position[2] = origin.z; - - Vector3 x_axis = p_transform.basis.get_axis(0) * p_half_extents.x; - dc.x_axis[0] = x_axis.x; - dc.x_axis[1] = x_axis.y; - dc.x_axis[2] = x_axis.z; - - Vector3 y_axis = p_transform.basis.get_axis(1) * p_half_extents.y; - dc.y_axis[0] = y_axis.x; - dc.y_axis[1] = y_axis.y; - dc.y_axis[2] = y_axis.z; - - AABB aabb; - - aabb.position = origin + x_axis + y_axis + z_axis; - aabb.expand_to(origin + x_axis + y_axis - z_axis); - aabb.expand_to(origin + x_axis - y_axis + z_axis); - aabb.expand_to(origin + x_axis - y_axis - z_axis); - aabb.expand_to(origin - x_axis + y_axis + z_axis); - aabb.expand_to(origin - x_axis + y_axis - z_axis); - aabb.expand_to(origin - x_axis - y_axis + z_axis); - aabb.expand_to(origin - x_axis - y_axis - z_axis); - - _add_item(aabb, ITEM_TYPE_DECAL, decal_count); - - decal_count++; - } - - void bake_cluster(); - - void setup(uint32_t p_width, uint32_t p_height, uint32_t p_depth); - - RID get_cluster_texture() const; - RID get_cluster_indices_buffer() const; - - LightClusterBuilder(); - ~LightClusterBuilder(); -}; - -#endif // LIGHT_CLUSTER_BUILDER_H diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp deleted file mode 100644 index 38b1e3b3a6..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.cpp +++ /dev/null @@ -1,2558 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_canvas_rd.h" -#include "core/math/math_funcs.h" -#include "core/project_settings.h" -#include "rasterizer_rd.h" - -void RasterizerCanvasRD::_update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4) { - - p_mat4[0] = p_transform.elements[0][0]; - p_mat4[1] = p_transform.elements[0][1]; - p_mat4[2] = 0; - p_mat4[3] = 0; - p_mat4[4] = p_transform.elements[1][0]; - p_mat4[5] = p_transform.elements[1][1]; - p_mat4[6] = 0; - p_mat4[7] = 0; - p_mat4[8] = 0; - p_mat4[9] = 0; - p_mat4[10] = 1; - p_mat4[11] = 0; - p_mat4[12] = p_transform.elements[2][0]; - p_mat4[13] = p_transform.elements[2][1]; - p_mat4[14] = 0; - p_mat4[15] = 1; -} - -void RasterizerCanvasRD::_update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4) { - - p_mat2x4[0] = p_transform.elements[0][0]; - p_mat2x4[1] = p_transform.elements[1][0]; - p_mat2x4[2] = 0; - p_mat2x4[3] = p_transform.elements[2][0]; - - p_mat2x4[4] = p_transform.elements[0][1]; - p_mat2x4[5] = p_transform.elements[1][1]; - p_mat2x4[6] = 0; - p_mat2x4[7] = p_transform.elements[2][1]; -} - -void RasterizerCanvasRD::_update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3) { - - p_mat2x3[0] = p_transform.elements[0][0]; - p_mat2x3[1] = p_transform.elements[0][1]; - p_mat2x3[2] = p_transform.elements[1][0]; - p_mat2x3[3] = p_transform.elements[1][1]; - p_mat2x3[4] = p_transform.elements[2][0]; - p_mat2x3[5] = p_transform.elements[2][1]; -} - -void RasterizerCanvasRD::_update_transform_to_mat4(const Transform &p_transform, float *p_mat4) { - - p_mat4[0] = p_transform.basis.elements[0][0]; - p_mat4[1] = p_transform.basis.elements[1][0]; - p_mat4[2] = p_transform.basis.elements[2][0]; - p_mat4[3] = 0; - p_mat4[4] = p_transform.basis.elements[0][1]; - p_mat4[5] = p_transform.basis.elements[1][1]; - p_mat4[6] = p_transform.basis.elements[2][1]; - p_mat4[7] = 0; - p_mat4[8] = p_transform.basis.elements[0][2]; - p_mat4[9] = p_transform.basis.elements[1][2]; - p_mat4[10] = p_transform.basis.elements[2][2]; - p_mat4[11] = 0; - p_mat4[12] = p_transform.origin.x; - p_mat4[13] = p_transform.origin.y; - p_mat4[14] = p_transform.origin.z; - p_mat4[15] = 1; -} - -void RasterizerCanvasRD::_update_specular_shininess(const Color &p_transform, uint32_t *r_ss) { - - *r_ss = uint32_t(CLAMP(p_transform.a * 255.0, 0, 255)) << 24; - *r_ss |= uint32_t(CLAMP(p_transform.b * 255.0, 0, 255)) << 16; - *r_ss |= uint32_t(CLAMP(p_transform.g * 255.0, 0, 255)) << 8; - *r_ss |= uint32_t(CLAMP(p_transform.r * 255.0, 0, 255)); -} - -RID RasterizerCanvasRD::_create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { - - Vector uniform_set; - - { // COLOR TEXTURE - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; - RID texture = storage->texture_get_rd_texture(p_texture); - if (!texture.is_valid()) { - //use default white texture - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - } - u.ids.push_back(texture); - uniform_set.push_back(u); - } - - { // NORMAL TEXTURE - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - RID texture = storage->texture_get_rd_texture(p_normalmap); - if (!texture.is_valid()) { - //use default normal texture - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); - } - u.ids.push_back(texture); - uniform_set.push_back(u); - } - - { // SPECULAR TEXTURE - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 3; - RID texture = storage->texture_get_rd_texture(p_specular); - if (!texture.is_valid()) { - //use default white texture - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - } - u.ids.push_back(texture); - uniform_set.push_back(u); - } - - { // SAMPLER - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 4; - RID sampler = storage->sampler_rd_get_default(p_filter, p_repeat); - ERR_FAIL_COND_V(sampler.is_null(), RID()); - u.ids.push_back(sampler); - uniform_set.push_back(u); - } - - { // MULTIMESH TEXTURE BUFFER - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; - u.binding = 5; - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER)); - uniform_set.push_back(u); - } - - return RD::get_singleton()->uniform_set_create(uniform_set, shader.default_version_rd_shader, 0); -} - -RasterizerCanvas::TextureBindingID RasterizerCanvasRD::request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh) { - - if (p_filter == VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT) { - p_filter = default_samplers.default_filter; - } - - if (p_repeat == VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) { - p_repeat = default_samplers.default_repeat; - } - - TextureBindingKey key; - key.texture = p_texture; - key.normalmap = p_normalmap; - key.specular = p_specular; - key.multimesh = p_multimesh; - key.texture_filter = p_filter; - key.texture_repeat = p_repeat; - - TextureBinding *binding; - TextureBindingID id; - { - TextureBindingID *idptr = bindings.texture_key_bindings.getptr(key); - - if (!idptr) { - id = bindings.id_generator++; - bindings.texture_key_bindings[key] = id; - binding = memnew(TextureBinding); - binding->key = key; - binding->id = id; - - bindings.texture_bindings[id] = binding; - - } else { - id = *idptr; - binding = bindings.texture_bindings[id]; - } - } - - binding->reference_count++; - - if (binding->to_dispose.in_list()) { - //was queued for disposal previously, but ended up reused. - bindings.to_dispose_list.remove(&binding->to_dispose); - } - - if (binding->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) { - binding->uniform_set = _create_texture_binding(p_texture, p_normalmap, p_specular, p_filter, p_repeat, p_multimesh); - } - - return id; -} - -void RasterizerCanvasRD::free_texture_binding(TextureBindingID p_binding) { - - TextureBinding **binding_ptr = bindings.texture_bindings.getptr(p_binding); - ERR_FAIL_COND(!binding_ptr); - TextureBinding *binding = *binding_ptr; - ERR_FAIL_COND(binding->reference_count == 0); - binding->reference_count--; - if (binding->reference_count == 0) { - bindings.to_dispose_list.add(&binding->to_dispose); - } -} - -void RasterizerCanvasRD::_dispose_bindings() { - - while (bindings.to_dispose_list.first()) { - TextureBinding *binding = bindings.to_dispose_list.first()->self(); - if (binding->uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(binding->uniform_set)) { - RD::get_singleton()->free(binding->uniform_set); - } - - bindings.texture_key_bindings.erase(binding->key); - bindings.texture_bindings.erase(binding->id); - bindings.to_dispose_list.remove(&binding->to_dispose); - memdelete(binding); - } -} - -RasterizerCanvas::PolygonID RasterizerCanvasRD::request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, const Vector &p_bones, const Vector &p_weights) { - - // Care must be taken to generate array formats - // in ways where they could be reused, so we will - // put single-occuring elements first, and repeated - // elements later. This way the generated formats are - // the same no matter the length of the arrays. - // This dramatically reduces the amount of pipeline objects - // that need to be created for these formats. - - uint32_t vertex_count = p_points.size(); - uint32_t stride = 2; //vertices always repeat - if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { - stride += 4; - } - if ((uint32_t)p_uvs.size() == vertex_count) { - stride += 2; - } - if ((uint32_t)p_bones.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) { - stride += 4; - } - - uint32_t buffer_size = stride * p_points.size(); - - Vector polygon_buffer; - polygon_buffer.resize(buffer_size * sizeof(float)); - Vector descriptions; - descriptions.resize(4); - Vector buffers; - buffers.resize(4); - - { - const uint8_t *r = polygon_buffer.ptr(); - float *fptr = (float *)r; - uint32_t *uptr = (uint32_t *)r; - uint32_t base_offset = 0; - { //vertices - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - vd.offset = base_offset * sizeof(float); - vd.location = VS::ARRAY_VERTEX; - vd.stride = stride * sizeof(float); - - descriptions.write[0] = vd; - - const Vector2 *points_ptr = p_points.ptr(); - - for (uint32_t i = 0; i < vertex_count; i++) { - fptr[base_offset + i * stride + 0] = points_ptr[i].x; - fptr[base_offset + i * stride + 1] = points_ptr[i].y; - } - - base_offset += 2; - } - - //colors - if ((uint32_t)p_colors.size() == vertex_count || p_colors.size() == 1) { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - vd.offset = base_offset * sizeof(float); - vd.location = VS::ARRAY_COLOR; - vd.stride = stride * sizeof(float); - - descriptions.write[1] = vd; - - if (p_colors.size() == 1) { - Color color = p_colors[0]; - for (uint32_t i = 0; i < vertex_count; i++) { - fptr[base_offset + i * stride + 0] = color.r; - fptr[base_offset + i * stride + 1] = color.g; - fptr[base_offset + i * stride + 2] = color.b; - fptr[base_offset + i * stride + 3] = color.a; - } - } else { - const Color *color_ptr = p_colors.ptr(); - - for (uint32_t i = 0; i < vertex_count; i++) { - fptr[base_offset + i * stride + 0] = color_ptr[i].r; - fptr[base_offset + i * stride + 1] = color_ptr[i].g; - fptr[base_offset + i * stride + 2] = color_ptr[i].b; - fptr[base_offset + i * stride + 3] = color_ptr[i].a; - } - } - base_offset += 4; - } else { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - vd.offset = 0; - vd.location = VS::ARRAY_COLOR; - vd.stride = 0; - - descriptions.write[1] = vd; - buffers.write[1] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_COLOR); - } - - //uvs - if ((uint32_t)p_uvs.size() == vertex_count) { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - vd.offset = base_offset * sizeof(float); - vd.location = VS::ARRAY_TEX_UV; - vd.stride = stride * sizeof(float); - - descriptions.write[2] = vd; - - const Vector2 *uv_ptr = p_uvs.ptr(); - - for (uint32_t i = 0; i < vertex_count; i++) { - fptr[base_offset + i * stride + 0] = uv_ptr[i].x; - fptr[base_offset + i * stride + 1] = uv_ptr[i].y; - } - base_offset += 2; - } else { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - vd.offset = 0; - vd.location = VS::ARRAY_TEX_UV; - vd.stride = 0; - - descriptions.write[2] = vd; - buffers.write[2] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_TEX_UV); - } - - //bones - if ((uint32_t)p_indices.size() == vertex_count * 4 && (uint32_t)p_weights.size() == vertex_count * 4) { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - vd.offset = base_offset * sizeof(float); - vd.location = VS::ARRAY_BONES; - vd.stride = stride * sizeof(float); - - descriptions.write[3] = vd; - - const int *bone_ptr = p_bones.ptr(); - const float *weight_ptr = p_weights.ptr(); - - for (uint32_t i = 0; i < vertex_count; i++) { - - uint16_t *bone16w = (uint16_t *)&uptr[base_offset + i * stride]; - uint16_t *weight16w = (uint16_t *)&uptr[base_offset + i * stride + 2]; - - bone16w[0] = bone_ptr[i * 4 + 0]; - bone16w[1] = bone_ptr[i * 4 + 1]; - bone16w[2] = bone_ptr[i * 4 + 2]; - bone16w[3] = bone_ptr[i * 4 + 3]; - - weight16w[0] = CLAMP(weight_ptr[i * 4 + 0] * 65535, 0, 65535); - weight16w[1] = CLAMP(weight_ptr[i * 4 + 1] * 65535, 0, 65535); - weight16w[2] = CLAMP(weight_ptr[i * 4 + 2] * 65535, 0, 65535); - weight16w[3] = CLAMP(weight_ptr[i * 4 + 3] * 65535, 0, 65535); - } - - base_offset += 4; - } else { - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - vd.offset = 0; - vd.location = VS::ARRAY_BONES; - vd.stride = 0; - - descriptions.write[3] = vd; - buffers.write[3] = storage->mesh_get_default_rd_buffer(RasterizerStorageRD::DEFAULT_RD_BUFFER_BONES); - } - - //check that everything is as it should be - ERR_FAIL_COND_V(base_offset != stride, 0); //bug - } - - RD::VertexFormatID vertex_id = RD::get_singleton()->vertex_format_create(descriptions); - ERR_FAIL_COND_V(vertex_id == RD::INVALID_ID, 0); - - PolygonBuffers pb; - pb.vertex_buffer = RD::get_singleton()->vertex_buffer_create(polygon_buffer.size(), polygon_buffer); - for (int i = 0; i < descriptions.size(); i++) { - if (buffers[i] == RID()) { //if put in vertex, use as vertex - buffers.write[i] = pb.vertex_buffer; - } - } - - pb.vertex_array = RD::get_singleton()->vertex_array_create(p_points.size(), vertex_id, buffers); - - if (p_indices.size()) { - //create indices, as indices were requested - Vector index_buffer; - index_buffer.resize(p_indices.size() * sizeof(int32_t)); - { - uint8_t *w = index_buffer.ptrw(); - copymem(w, p_indices.ptr(), sizeof(int32_t) * p_indices.size()); - } - pb.index_buffer = RD::get_singleton()->index_buffer_create(p_indices.size(), RD::INDEX_BUFFER_FORMAT_UINT32, index_buffer); - pb.indices = RD::get_singleton()->index_array_create(pb.index_buffer, 0, p_indices.size()); - } - - pb.vertex_format_id = vertex_id; - - PolygonID id = polygon_buffers.last_id++; - - polygon_buffers.polygons[id] = pb; - - return id; -} - -void RasterizerCanvasRD::free_polygon(PolygonID p_polygon) { - - PolygonBuffers *pb_ptr = polygon_buffers.polygons.getptr(p_polygon); - ERR_FAIL_COND(!pb_ptr); - - PolygonBuffers &pb = *pb_ptr; - - if (pb.indices.is_valid()) { - RD::get_singleton()->free(pb.indices); - } - if (pb.index_buffer.is_valid()) { - RD::get_singleton()->free(pb.index_buffer); - } - - RD::get_singleton()->free(pb.vertex_array); - RD::get_singleton()->free(pb.vertex_buffer); - - polygon_buffers.polygons.erase(p_polygon); -} - -Size2i RasterizerCanvasRD::_bind_texture_binding(TextureBindingID p_binding, RD::DrawListID p_draw_list, uint32_t &flags) { - - TextureBinding **texture_binding_ptr = bindings.texture_bindings.getptr(p_binding); - ERR_FAIL_COND_V(!texture_binding_ptr, Size2i()); - TextureBinding *texture_binding = *texture_binding_ptr; - - if (texture_binding->key.normalmap.is_valid()) { - flags |= FLAGS_DEFAULT_NORMAL_MAP_USED; - } - if (texture_binding->key.specular.is_valid()) { - flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - if (!RD::get_singleton()->uniform_set_is_valid(texture_binding->uniform_set)) { - //texture may have changed (erased or replaced, see if we can fix) - texture_binding->uniform_set = _create_texture_binding(texture_binding->key.texture, texture_binding->key.normalmap, texture_binding->key.specular, texture_binding->key.texture_filter, texture_binding->key.texture_repeat, texture_binding->key.multimesh); - ERR_FAIL_COND_V(!texture_binding->uniform_set.is_valid(), Size2i(1, 1)); - } - - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, texture_binding->uniform_set, 0); - if (texture_binding->key.texture.is_valid()) { - return storage->texture_2d_get_size(texture_binding->key.texture); - } else { - return Size2i(1, 1); - } -} - -//////////////////// -void RasterizerCanvasRD::_render_item(RD::DrawListID p_draw_list, const Item *p_item, RD::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants) { - - //create an empty push constant - - PushConstant push_constant; - Transform2D base_transform = p_canvas_transform_inverse * p_item->final_transform; - _update_transform_2d_to_mat2x3(base_transform, push_constant.world); - - Color base_color = p_item->final_modulate; - - for (int i = 0; i < 4; i++) { - push_constant.modulation[i] = 0; - push_constant.ninepatch_margins[i] = 0; - push_constant.src_rect[i] = 0; - push_constant.dst_rect[i] = 0; - } - push_constant.flags = 0; - push_constant.color_texture_pixel_size[0] = 0; - push_constant.color_texture_pixel_size[1] = 0; - - push_constant.pad[0] = 0; - push_constant.pad[1] = 0; - - push_constant.lights[0] = 0; - push_constant.lights[1] = 0; - push_constant.lights[2] = 0; - push_constant.lights[3] = 0; - - uint32_t base_flags = 0; - - bool light_uniform_set_dirty = false; - - if (!p_item->custom_data) { - p_item->custom_data = memnew(ItemStateData); - light_uniform_set_dirty = true; - } - - ItemStateData *state_data = (ItemStateData *)p_item->custom_data; - - Light *light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; - uint16_t light_count = 0; - PipelineLightMode light_mode; - - { - - Light *light = p_lights; - - while (light) { - - if (light->render_index_cache >= 0 && p_item->light_mask & light->item_mask && p_item->z_final >= light->z_min && p_item->z_final <= light->z_max && p_item->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { - - uint32_t light_index = light->render_index_cache; - push_constant.lights[light_count >> 2] |= light_index << ((light_count & 3) * 8); - - if (!light_uniform_set_dirty && (state_data->light_cache[light_count].light != light || state_data->light_cache[light_count].light_version != light->version)) { - light_uniform_set_dirty = true; - } - - light_cache[light_count] = light; - - light_count++; - if (light->mode == VS::CANVAS_LIGHT_MODE_MASK) { - base_flags |= FLAGS_USING_LIGHT_MASK; - } - if (light_count == state.max_lights_per_item) { - break; - } - } - light = light->next_ptr; - } - - if (light_count != state_data->light_cache_count) { - light_uniform_set_dirty = true; - } - base_flags |= light_count << FLAGS_LIGHT_COUNT_SHIFT; - } - - { - - RID &canvas_item_state = light_count ? state_data->state_uniform_set_with_light : state_data->state_uniform_set; - - bool invalid_uniform = canvas_item_state.is_valid() && !RD::get_singleton()->uniform_set_is_valid(canvas_item_state); - - if (canvas_item_state.is_null() || invalid_uniform || (light_count > 0 && light_uniform_set_dirty)) { - //re create canvas state - Vector uniforms; - - if (state_data->state_uniform_set_with_light.is_valid() && !invalid_uniform) { - RD::get_singleton()->free(canvas_item_state); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(state.canvas_state_buffer); - uniforms.push_back(u); - } - - if (false && p_item->skeleton.is_valid()) { - //bind skeleton stuff - } else { - //bind default - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE_BUFFER; - u.binding = 1; - u.ids.push_back(shader.default_skeleton_texture_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 2; - u.ids.push_back(shader.default_skeleton_uniform_buffer); - uniforms.push_back(u); - } - } - - //validate and update lighs if they are being used - - if (light_count > 0) { - //recreate uniform set - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 3; - u.ids.push_back(state.lights_uniform_buffer); - uniforms.push_back(u); - } - - { - - RD::Uniform u_lights; - u_lights.type = RD::UNIFORM_TYPE_TEXTURE; - u_lights.binding = 4; - - RD::Uniform u_shadows; - u_shadows.type = RD::UNIFORM_TYPE_TEXTURE; - u_shadows.binding = 5; - - //lights - for (uint32_t i = 0; i < state.max_lights_per_item; i++) { - if (i < light_count) { - - CanvasLight *cl = canvas_light_owner.getornull(light_cache[i]->light_internal); - ERR_CONTINUE(!cl); - - RID rd_texture; - - if (cl->texture.is_valid()) { - rd_texture = storage->texture_get_rd_texture(cl->texture); - } - if (rd_texture.is_valid()) { - u_lights.ids.push_back(rd_texture); - } else { - u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - } - if (cl->shadow.texture.is_valid()) { - u_shadows.ids.push_back(cl->shadow.texture); - } else { - u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); - } - } else { - u_lights.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - u_shadows.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); - } - } - - uniforms.push_back(u_lights); - uniforms.push_back(u_shadows); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 6; - u.ids.push_back(state.shadow_sampler); - uniforms.push_back(u); - } - - canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader_light, 2); - } else { - canvas_item_state = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, 2); - } - } - - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, canvas_item_state, 2); - } - - light_mode = light_count > 0 ? PIPELINE_LIGHT_MODE_ENABLED : PIPELINE_LIGHT_MODE_DISABLED; - - PipelineVariants *pipeline_variants = p_pipeline_variants; - - bool reclip = false; - - const Item::Command *c = p_item->commands; - while (c) { - push_constant.flags = base_flags; //reset on each command for sanity - push_constant.specular_shininess = 0xFFFFFFFF; - - switch (c->type) { - case Item::Command::TYPE_RECT: { - - const Item::CommandRect *rect = static_cast(c); - - //bind pipeline - { - RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_QUAD].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - } - - //bind textures - - Size2 texpixel_size; - { - texpixel_size = _bind_texture_binding(rect->texture_binding.binding_id, p_draw_list, push_constant.flags); - texpixel_size.x = 1.0 / texpixel_size.x; - texpixel_size.y = 1.0 / texpixel_size.y; - } - - if (rect->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(rect->specular_shininess, &push_constant.specular_shininess); - - Rect2 src_rect; - Rect2 dst_rect; - - if (texpixel_size != Vector2()) { - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - - src_rect = (rect->flags & CANVAS_RECT_REGION) ? Rect2(rect->source.position * texpixel_size, rect->source.size * texpixel_size) : Rect2(0, 0, 1, 1); - dst_rect = Rect2(rect->rect.position, rect->rect.size); - - if (dst_rect.size.width < 0) { - dst_rect.position.x += dst_rect.size.width; - dst_rect.size.width *= -1; - } - if (dst_rect.size.height < 0) { - dst_rect.position.y += dst_rect.size.height; - dst_rect.size.height *= -1; - } - - if (rect->flags & CANVAS_RECT_FLIP_H) { - src_rect.size.x *= -1; - } - - if (rect->flags & CANVAS_RECT_FLIP_V) { - src_rect.size.y *= -1; - } - - if (rect->flags & CANVAS_RECT_TRANSPOSE) { - dst_rect.size.x *= -1; // Encoding in the dst_rect.z uniform - } - - if (rect->flags & CANVAS_RECT_CLIP_UV) { - push_constant.flags |= FLAGS_CLIP_RECT_UV; - } - - } else { - dst_rect = Rect2(rect->rect.position, rect->rect.size); - - if (dst_rect.size.width < 0) { - dst_rect.position.x += dst_rect.size.width; - dst_rect.size.width *= -1; - } - if (dst_rect.size.height < 0) { - dst_rect.position.y += dst_rect.size.height; - dst_rect.size.height *= -1; - } - - src_rect = Rect2(0, 0, 1, 1); - texpixel_size = Vector2(1, 1); - } - - push_constant.modulation[0] = rect->modulate.r * base_color.r; - push_constant.modulation[1] = rect->modulate.g * base_color.g; - push_constant.modulation[2] = rect->modulate.b * base_color.b; - push_constant.modulation[3] = rect->modulate.a * base_color.a; - - push_constant.src_rect[0] = src_rect.position.x; - push_constant.src_rect[1] = src_rect.position.y; - push_constant.src_rect[2] = src_rect.size.width; - push_constant.src_rect[3] = src_rect.size.height; - - push_constant.dst_rect[0] = dst_rect.position.x; - push_constant.dst_rect[1] = dst_rect.position.y; - push_constant.dst_rect[2] = dst_rect.size.width; - push_constant.dst_rect[3] = dst_rect.size.height; - - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); - RD::get_singleton()->draw_list_draw(p_draw_list, true); - - } break; - - case Item::Command::TYPE_NINEPATCH: { - - const Item::CommandNinePatch *np = static_cast(c); - - //bind pipeline - { - RID pipeline = pipeline_variants->variants[light_mode][PIPELINE_VARIANT_NINEPATCH].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - } - - //bind textures - - Size2 texpixel_size; - { - texpixel_size = _bind_texture_binding(np->texture_binding.binding_id, p_draw_list, push_constant.flags); - texpixel_size.x = 1.0 / texpixel_size.x; - texpixel_size.y = 1.0 / texpixel_size.y; - } - - if (np->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(np->specular_shininess, &push_constant.specular_shininess); - - Rect2 src_rect; - Rect2 dst_rect(np->rect.position.x, np->rect.position.y, np->rect.size.x, np->rect.size.y); - - if (texpixel_size == Size2()) { - - texpixel_size = Size2(1, 1); - src_rect = Rect2(0, 0, 1, 1); - - } else { - - if (np->source != Rect2()) { - src_rect = Rect2(np->source.position.x * texpixel_size.width, np->source.position.y * texpixel_size.height, np->source.size.x * texpixel_size.width, np->source.size.y * texpixel_size.height); - texpixel_size = Size2(1.0 / np->source.size.width, 1.0 / np->source.size.height); - } else { - src_rect = Rect2(0, 0, 1, 1); - } - } - - push_constant.modulation[0] = np->color.r * base_color.r; - push_constant.modulation[1] = np->color.g * base_color.g; - push_constant.modulation[2] = np->color.b * base_color.b; - push_constant.modulation[3] = np->color.a * base_color.a; - - push_constant.src_rect[0] = src_rect.position.x; - push_constant.src_rect[1] = src_rect.position.y; - push_constant.src_rect[2] = src_rect.size.width; - push_constant.src_rect[3] = src_rect.size.height; - - push_constant.dst_rect[0] = dst_rect.position.x; - push_constant.dst_rect[1] = dst_rect.position.y; - push_constant.dst_rect[2] = dst_rect.size.width; - push_constant.dst_rect[3] = dst_rect.size.height; - - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - - push_constant.flags |= int(np->axis_x) << FLAGS_NINEPATCH_H_MODE_SHIFT; - push_constant.flags |= int(np->axis_y) << FLAGS_NINEPATCH_V_MODE_SHIFT; - - if (np->draw_center) { - push_constant.flags |= FLAGS_NINEPACH_DRAW_CENTER; - } - - push_constant.ninepatch_margins[0] = np->margin[MARGIN_LEFT]; - push_constant.ninepatch_margins[1] = np->margin[MARGIN_TOP]; - push_constant.ninepatch_margins[2] = np->margin[MARGIN_RIGHT]; - push_constant.ninepatch_margins[3] = np->margin[MARGIN_BOTTOM]; - - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, shader.quad_index_array); - RD::get_singleton()->draw_list_draw(p_draw_list, true); - - } break; - case Item::Command::TYPE_POLYGON: { - - const Item::CommandPolygon *polygon = static_cast(c); - - PolygonBuffers *pb = polygon_buffers.polygons.getptr(polygon->polygon.polygon_id); - ERR_CONTINUE(!pb); - //bind pipeline - { - static const PipelineVariant variant[VS::PRIMITIVE_MAX] = { PIPELINE_VARIANT_ATTRIBUTE_POINTS, PIPELINE_VARIANT_ATTRIBUTE_LINES, PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP }; - ERR_CONTINUE(polygon->primitive < 0 || polygon->primitive >= VS::PRIMITIVE_MAX); - RID pipeline = pipeline_variants->variants[light_mode][variant[polygon->primitive]].get_render_pipeline(pb->vertex_format_id, p_framebuffer_format); - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - } - - if (polygon->primitive == VS::PRIMITIVE_LINES) { - //not supported in most hardware, so pointless - //RD::get_singleton()->draw_list_set_line_width(p_draw_list, polygon->line_width); - } - - //bind textures - - Size2 texpixel_size; - { - texpixel_size = _bind_texture_binding(polygon->texture_binding.binding_id, p_draw_list, push_constant.flags); - texpixel_size.x = 1.0 / texpixel_size.x; - texpixel_size.y = 1.0 / texpixel_size.y; - } - - if (polygon->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(polygon->specular_shininess, &push_constant.specular_shininess); - - push_constant.modulation[0] = base_color.r; - push_constant.modulation[1] = base_color.g; - push_constant.modulation[2] = base_color.b; - push_constant.modulation[3] = base_color.a; - - for (int j = 0; j < 4; j++) { - push_constant.src_rect[j] = 0; - push_constant.dst_rect[j] = 0; - push_constant.ninepatch_margins[j] = 0; - } - - push_constant.color_texture_pixel_size[0] = texpixel_size.x; - push_constant.color_texture_pixel_size[1] = texpixel_size.y; - - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - RD::get_singleton()->draw_list_bind_vertex_array(p_draw_list, pb->vertex_array); - if (pb->indices.is_valid()) { - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, pb->indices); - } - RD::get_singleton()->draw_list_draw(p_draw_list, pb->indices.is_valid()); - - } break; - case Item::Command::TYPE_PRIMITIVE: { - - const Item::CommandPrimitive *primitive = static_cast(c); - - //bind pipeline - { - static const PipelineVariant variant[4] = { PIPELINE_VARIANT_PRIMITIVE_POINTS, PIPELINE_VARIANT_PRIMITIVE_LINES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, PIPELINE_VARIANT_PRIMITIVE_TRIANGLES }; - ERR_CONTINUE(primitive->point_count == 0 || primitive->point_count > 4); - RID pipeline = pipeline_variants->variants[light_mode][variant[primitive->point_count - 1]].get_render_pipeline(RD::INVALID_ID, p_framebuffer_format); - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, pipeline); - } - - //bind textures - - { - _bind_texture_binding(primitive->texture_binding.binding_id, p_draw_list, push_constant.flags); - } - - if (primitive->specular_shininess.a < 0.999) { - push_constant.flags |= FLAGS_DEFAULT_SPECULAR_MAP_USED; - } - - _update_specular_shininess(primitive->specular_shininess, &push_constant.specular_shininess); - - RD::get_singleton()->draw_list_bind_index_array(p_draw_list, primitive_arrays.index_array[MIN(3, primitive->point_count) - 1]); - - for (uint32_t j = 0; j < MIN(3, primitive->point_count); j++) { - push_constant.points[j * 2 + 0] = primitive->points[j].x; - push_constant.points[j * 2 + 1] = primitive->points[j].y; - push_constant.uvs[j * 2 + 0] = primitive->uvs[j].x; - push_constant.uvs[j * 2 + 1] = primitive->uvs[j].y; - Color col = primitive->colors[j] * base_color; - push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); - push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); - } - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - RD::get_singleton()->draw_list_draw(p_draw_list, true); - - if (primitive->point_count == 4) { - for (uint32_t j = 1; j < 3; j++) { - //second half of triangle - push_constant.points[j * 2 + 0] = primitive->points[j + 1].x; - push_constant.points[j * 2 + 1] = primitive->points[j + 1].y; - push_constant.uvs[j * 2 + 0] = primitive->uvs[j + 1].x; - push_constant.uvs[j * 2 + 1] = primitive->uvs[j + 1].y; - Color col = primitive->colors[j + 1] * base_color; - push_constant.colors[j * 2 + 0] = (uint32_t(Math::make_half_float(col.g)) << 16) | Math::make_half_float(col.r); - push_constant.colors[j * 2 + 1] = (uint32_t(Math::make_half_float(col.a)) << 16) | Math::make_half_float(col.b); - } - - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(PushConstant)); - RD::get_singleton()->draw_list_draw(p_draw_list, true); - } - - } break; - case Item::Command::TYPE_MESH: - case Item::Command::TYPE_MULTIMESH: - case Item::Command::TYPE_PARTICLES: { - ERR_PRINT("FIXME: Mesh, MultiMesh and Particles render commands are unimplemented currently, they need to be ported to the 4.0 rendering architecture."); -#ifndef _MSC_VER -#warning Item::Command types for Mesh, MultiMesh and Particles need to be implemented. -#endif - // See #if 0'ed code below to port from GLES3. - } break; - -#if 0 - case Item::Command::TYPE_MESH: { - - Item::CommandMesh *mesh = static_cast(c); - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mesh->texture, mesh->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * mesh->transform); - - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(mesh->mesh); - if (mesh_data) { - - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing - glBindVertexArray(s->array_id); - - glVertexAttrib4f(VS::ARRAY_COLOR, mesh->modulate.r, mesh->modulate.g, mesh->modulate.b, mesh->modulate.a); - - if (s->index_array_len) { - glDrawElements(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0); - } else { - glDrawArrays(gl_primitive[s->primitive], 0, s->array_len); - } - - glBindVertexArray(0); - } - } - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform); - - } break; - case Item::Command::TYPE_MULTIMESH: { - - Item::CommandMultiMesh *mmesh = static_cast(c); - - RasterizerStorageGLES3::MultiMesh *multi_mesh = storage->multimesh_owner.getornull(mmesh->multimesh); - - if (!multi_mesh) - break; - - RasterizerStorageGLES3::Mesh *mesh_data = storage->mesh_owner.getornull(multi_mesh->mesh); - - if (!mesh_data) - break; - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(mmesh->texture, mmesh->normal_map); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, multi_mesh->custom_data_format != VS::MULTIMESH_CUSTOM_DATA_NONE); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } - - int amount = MIN(multi_mesh->size, multi_mesh->visible_instances); - - if (amount == -1) { - amount = multi_mesh->size; - } - - for (int j = 0; j < mesh_data->surfaces.size(); j++) { - RasterizerStorageGLES3::Surface *s = mesh_data->surfaces[j]; - // materials are ignored in 2D meshes, could be added but many things (ie, lighting mode, reading from screen, etc) would break as they are not meant be set up at this point of drawing - glBindVertexArray(s->instancing_array_id); - - glBindBuffer(GL_ARRAY_BUFFER, multi_mesh->buffer); //modify the buffer - - int stride = (multi_mesh->xform_floats + multi_mesh->color_floats + multi_mesh->custom_data_floats) * 4; - glEnableVertexAttribArray(8); - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(0)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(4 * 4)); - glVertexAttribDivisor(9, 1); - - int color_ofs; - - if (multi_mesh->transform_format == VS::MULTIMESH_TRANSFORM_3D) { - glEnableVertexAttribArray(10); - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(8 * 4)); - glVertexAttribDivisor(10, 1); - color_ofs = 12 * 4; - } else { - glDisableVertexAttribArray(10); - glVertexAttrib4f(10, 0, 0, 1, 0); - color_ofs = 8 * 4; - } - - int custom_data_ofs = color_ofs; - - switch (multi_mesh->color_format) { - - case VS::MULTIMESH_COLOR_NONE: { - glDisableVertexAttribArray(11); - glVertexAttrib4f(11, 1, 1, 1, 1); - } break; - case VS::MULTIMESH_COLOR_8BIT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4; - - } break; - case VS::MULTIMESH_COLOR_FLOAT: { - glEnableVertexAttribArray(11); - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(color_ofs)); - glVertexAttribDivisor(11, 1); - custom_data_ofs += 4 * 4; - } break; - } - - switch (multi_mesh->custom_data_format) { - - case VS::MULTIMESH_CUSTOM_DATA_NONE: { - glDisableVertexAttribArray(12); - glVertexAttrib4f(12, 1, 1, 1, 1); - } break; - case VS::MULTIMESH_CUSTOM_DATA_8BIT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - - } break; - case VS::MULTIMESH_CUSTOM_DATA_FLOAT: { - glEnableVertexAttribArray(12); - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(custom_data_ofs)); - glVertexAttribDivisor(12, 1); - } break; - } - - if (s->index_array_len) { - glDrawElementsInstanced(gl_primitive[s->primitive], s->index_array_len, (s->array_len >= (1 << 16)) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, 0, amount); - } else { - glDrawArraysInstanced(gl_primitive[s->primitive], 0, s->array_len, amount); - } - - glBindVertexArray(0); - } - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - } break; - case Item::Command::TYPE_PARTICLES: { - - Item::CommandParticles *particles_cmd = static_cast(c); - - RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(particles_cmd->particles); - if (!particles) - break; - - if (particles->inactive && !particles->emitting) - break; - - glVertexAttrib4f(VS::ARRAY_COLOR, 1, 1, 1, 1); //not used, so keep white - - VisualServerRaster::redraw_request(); - - storage->particles_request_process(particles_cmd->particles); - //enable instancing - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, true); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, true); - //reset shader and force rebind - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - RasterizerStorageGLES3::Texture *texture = _bind_canvas_texture(particles_cmd->texture, particles_cmd->normal_map); - - if (texture) { - Size2 texpixel_size(1.0 / texture->width, 1.0 / texture->height); - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, texpixel_size); - } else { - state.canvas_shader.set_uniform(CanvasShaderGLES3::COLOR_TEXPIXEL_SIZE, Vector2(1.0, 1.0)); - } - - if (!particles->use_local_coords) { - - Transform2D inv_xf; - inv_xf.set_axis(0, Vector2(particles->emission_transform.basis.get_axis(0).x, particles->emission_transform.basis.get_axis(0).y)); - inv_xf.set_axis(1, Vector2(particles->emission_transform.basis.get_axis(1).x, particles->emission_transform.basis.get_axis(1).y)); - inv_xf.set_origin(Vector2(particles->emission_transform.get_origin().x, particles->emission_transform.get_origin().y)); - inv_xf.affine_invert(); - - state.canvas_shader.set_uniform(CanvasShaderGLES3::MODELVIEW_MATRIX, state.final_transform * inv_xf); - } - - glBindVertexArray(data.particle_quad_array); //use particle quad array - glBindBuffer(GL_ARRAY_BUFFER, particles->particle_buffers[0]); //bind particle buffer - - int stride = sizeof(float) * 4 * 6; - - int amount = particles->amount; - - if (particles->draw_order != VS::PARTICLES_DRAW_ORDER_LIFETIME) { - - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount); - } else { - //split - int split = int(Math::ceil(particles->phase * particles->amount)); - - if (amount - split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + 0)); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(stride * split + sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, amount - split); - } - - if (split > 0) { - glEnableVertexAttribArray(8); //xform x - glVertexAttribPointer(8, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 3)); - glVertexAttribDivisor(8, 1); - glEnableVertexAttribArray(9); //xform y - glVertexAttribPointer(9, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 4)); - glVertexAttribDivisor(9, 1); - glEnableVertexAttribArray(10); //xform z - glVertexAttribPointer(10, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 5)); - glVertexAttribDivisor(10, 1); - glEnableVertexAttribArray(11); //color - glVertexAttribPointer(11, 4, GL_FLOAT, GL_FALSE, stride, NULL); - glVertexAttribDivisor(11, 1); - glEnableVertexAttribArray(12); //custom - glVertexAttribPointer(12, 4, GL_FLOAT, GL_FALSE, stride, CAST_INT_TO_UCHAR_PTR(sizeof(float) * 4 * 2)); - glVertexAttribDivisor(12, 1); - - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, split); - } - } - - glBindVertexArray(0); - - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCE_CUSTOM, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_PARTICLES, false); - state.canvas_shader.set_conditional(CanvasShaderGLES3::USE_INSTANCING, false); - state.using_texture_rect = true; - _set_texture_rect_mode(false); - - } break; -#endif - case Item::Command::TYPE_TRANSFORM: { - - const Item::CommandTransform *transform = static_cast(c); - _update_transform_2d_to_mat2x3(base_transform * transform->xform, push_constant.world); - - } break; - case Item::Command::TYPE_CLIP_IGNORE: { - - const Item::CommandClipIgnore *ci = static_cast(c); - if (current_clip) { - - if (ci->ignore != reclip) { - - if (ci->ignore) { - RD::get_singleton()->draw_list_disable_scissor(p_draw_list); - reclip = true; - } else { - - RD::get_singleton()->draw_list_enable_scissor(p_draw_list, current_clip->final_clip_rect); - reclip = false; - } - } - } - - } break; - } - - c = c->next; - } - - if (current_clip && reclip) { - //will make it re-enable clipping if needed afterwards - current_clip = NULL; - } -} - -void RasterizerCanvasRD::_render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set) { - - Item *current_clip = NULL; - - Transform2D canvas_transform_inverse = p_canvas_transform_inverse; - - RID framebuffer = storage->render_target_get_rd_framebuffer(p_to_render_target); - - Vector clear_colors; - bool clear = false; - if (storage->render_target_is_clear_requested(p_to_render_target)) { - clear = true; - clear_colors.push_back(storage->render_target_get_clear_request_color(p_to_render_target)); - storage->render_target_disable_clear_request(p_to_render_target); - } -#ifndef _MSC_VER -#warning TODO obtain from framebuffer format eventually when this is implemented -#endif - - RD::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(framebuffer); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(framebuffer, clear ? RD::INITIAL_ACTION_CLEAR : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); - - if (p_screen_uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_screen_uniform_set, 3); - } - RID prev_material; - - PipelineVariants *pipeline_variants = &shader.pipeline_variants; - - for (int i = 0; i < p_item_count; i++) { - - Item *ci = items[i]; - - if (current_clip != ci->final_clip_owner) { - - current_clip = ci->final_clip_owner; - - //setup clip - if (current_clip) { - - RD::get_singleton()->draw_list_enable_scissor(draw_list, current_clip->final_clip_rect); - - } else { - - RD::get_singleton()->draw_list_disable_scissor(draw_list); - } - } - - if (ci->material != prev_material) { - - MaterialData *material_data = NULL; - if (ci->material.is_valid()) { - material_data = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); - } - - if (material_data) { - - if (material_data->shader_data->version.is_valid() && material_data->shader_data->valid) { - pipeline_variants = &material_data->shader_data->pipeline_variants; - if (material_data->uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material_data->uniform_set, 1); - } - } else { - pipeline_variants = &shader.pipeline_variants; - } - } else { - pipeline_variants = &shader.pipeline_variants; - } - } - - _render_item(draw_list, ci, fb_format, canvas_transform_inverse, current_clip, p_lights, pipeline_variants); - - prev_material = ci->material; - } - - RD::get_singleton()->draw_list_end(); -} - -void RasterizerCanvasRD::canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform) { - - int item_count = 0; - - //setup canvas state uniforms if needed - - Transform2D canvas_transform_inverse = p_canvas_transform.affine_inverse(); - - { - //update canvas state uniform buffer - State::Buffer state_buffer; - - Size2i ssize = storage->render_target_get_size(p_to_render_target); - - Transform screen_transform; - screen_transform.translate(-(ssize.width / 2.0f), -(ssize.height / 2.0f), 0.0f); - screen_transform.scale(Vector3(2.0f / ssize.width, 2.0f / ssize.height, 1.0f)); - _update_transform_to_mat4(screen_transform, state_buffer.screen_transform); - _update_transform_2d_to_mat4(p_canvas_transform, state_buffer.canvas_transform); - - Transform2D normal_transform = p_canvas_transform; - normal_transform.elements[0].normalize(); - normal_transform.elements[1].normalize(); - normal_transform.elements[2] = Vector2(); - _update_transform_2d_to_mat4(normal_transform, state_buffer.canvas_normal_transform); - - state_buffer.canvas_modulate[0] = p_modulate.r; - state_buffer.canvas_modulate[1] = p_modulate.g; - state_buffer.canvas_modulate[2] = p_modulate.b; - state_buffer.canvas_modulate[3] = p_modulate.a; - - Size2 render_target_size = storage->render_target_get_size(p_to_render_target); - state_buffer.screen_pixel_size[0] = 1.0 / render_target_size.x; - state_buffer.screen_pixel_size[1] = 1.0 / render_target_size.y; - - state_buffer.time = state.time; - RD::get_singleton()->buffer_update(state.canvas_state_buffer, 0, sizeof(State::Buffer), &state_buffer, true); - } - - //setup lights if exist - - { - - Light *l = p_light_list; - uint32_t index = 0; - - while (l) { - - if (index == state.max_lights_per_render) { - l->render_index_cache = -1; - l = l->next_ptr; - continue; - } - - CanvasLight *clight = canvas_light_owner.getornull(l->light_internal); - if (!clight) { //unused or invalid texture - l->render_index_cache = -1; - l = l->next_ptr; - ERR_CONTINUE(!clight); - } - Transform2D to_light_xform = (p_canvas_transform * l->light_shader_xform).affine_inverse(); - - Vector2 canvas_light_pos = p_canvas_transform.xform(l->xform.get_origin()); //convert light position to canvas coordinates, as all computation is done in canvas coords to avoid precision loss - state.light_uniforms[index].position[0] = canvas_light_pos.x; - state.light_uniforms[index].position[1] = canvas_light_pos.y; - - _update_transform_2d_to_mat2x4(to_light_xform, state.light_uniforms[index].matrix); - _update_transform_2d_to_mat2x4(l->xform_cache.affine_inverse(), state.light_uniforms[index].shadow_matrix); - - state.light_uniforms[index].height = l->height * (p_canvas_transform.elements[0].length() + p_canvas_transform.elements[1].length()) * 0.5; //approximate height conversion to the canvas size, since all calculations are done in canvas coords to avoid precision loss - for (int i = 0; i < 4; i++) { - state.light_uniforms[index].shadow_color[i] = l->shadow_color[i]; - state.light_uniforms[index].color[i] = l->color[i]; - } - - state.light_uniforms[index].color[3] = l->energy; //use alpha for energy, so base color can go separate - - if (clight->shadow.texture.is_valid()) { - state.light_uniforms[index].shadow_pixel_size = (1.0 / clight->shadow.size) * (1.0 + l->shadow_smooth); - } else { - state.light_uniforms[index].shadow_pixel_size = 1.0; - } - - state.light_uniforms[index].flags |= l->mode << LIGHT_FLAGS_BLEND_SHIFT; - state.light_uniforms[index].flags |= l->shadow_filter << LIGHT_FLAGS_FILTER_SHIFT; - if (clight->shadow.texture.is_valid()) { - state.light_uniforms[index].flags |= LIGHT_FLAGS_HAS_SHADOW; - } - - l->render_index_cache = index; - - index++; - l = l->next_ptr; - } - - if (index > 0) { - RD::get_singleton()->buffer_update(state.lights_uniform_buffer, 0, sizeof(LightUniform) * index, &state.light_uniforms[0], true); - } - } - - //fill the list until rendering is possible. - bool material_screen_texture_found = false; - Item *ci = p_item_list; - Rect2 back_buffer_rect; - bool backbuffer_copy = false; - RID screen_uniform_set; - - while (ci) { - - if (ci->copy_back_buffer) { - backbuffer_copy = true; - - if (ci->copy_back_buffer->full) { - back_buffer_rect = Rect2(); - } else { - back_buffer_rect = ci->copy_back_buffer->rect; - } - } - - if (ci->material.is_valid()) { - MaterialData *md = (MaterialData *)storage->material_get_data(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); - if (md && md->shader_data->valid) { - - if (md->shader_data->uses_screen_texture) { - if (!material_screen_texture_found) { - backbuffer_copy = true; - back_buffer_rect = Rect2(); - } - if (screen_uniform_set.is_null()) { - RID backbuffer_shader = shader.canvas_shader.version_get_shader(md->shader_data->version, 0); //any version is fine - screen_uniform_set = storage->render_target_get_back_buffer_uniform_set(p_to_render_target, backbuffer_shader); - } - } - - if (md->last_frame != RasterizerRD::get_frame_number()) { - md->last_frame = RasterizerRD::get_frame_number(); - if (!RD::get_singleton()->uniform_set_is_valid(md->uniform_set)) { - // uniform set may be gone because a dependency was erased. In this case, it will happen - // if a texture is deleted, so just re-create it. - storage->material_force_update_textures(ci->material, RasterizerStorageRD::SHADER_TYPE_2D); - } - } - } - } - - if (backbuffer_copy) { - //render anything pending, including clearing if no items - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set); - item_count = 0; - - storage->render_target_copy_to_back_buffer(p_to_render_target, back_buffer_rect); - - backbuffer_copy = false; - material_screen_texture_found = true; //after a backbuffer copy, screen texture makes no further copies - } - - items[item_count++] = ci; - - if (!ci->next || item_count == MAX_RENDER_ITEMS - 1) { - _render_items(p_to_render_target, item_count, canvas_transform_inverse, p_light_list, screen_uniform_set); - //then reset - item_count = 0; - } - - ci = ci->next; - } -} - -RID RasterizerCanvasRD::light_create() { - - CanvasLight canvas_light; - canvas_light.shadow.size = 0; - return canvas_light_owner.make_rid(canvas_light); -} - -void RasterizerCanvasRD::light_set_texture(RID p_rid, RID p_texture) { - CanvasLight *cl = canvas_light_owner.getornull(p_rid); - ERR_FAIL_COND(!cl); - if (cl->texture == p_texture) { - return; - } - - cl->texture = p_texture; -} -void RasterizerCanvasRD::light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution) { - CanvasLight *cl = canvas_light_owner.getornull(p_rid); - ERR_FAIL_COND(!cl); - ERR_FAIL_COND(p_resolution < 64); - if (cl->shadow.texture.is_valid() == p_enable && p_resolution == cl->shadow.size) { - return; - } - - if (cl->shadow.texture.is_valid()) { - - RD::get_singleton()->free(cl->shadow.fb); - RD::get_singleton()->free(cl->shadow.depth); - RD::get_singleton()->free(cl->shadow.texture); - cl->shadow.fb = RID(); - cl->shadow.texture = RID(); - cl->shadow.depth = RID(); - } - - if (p_enable) { - - Vector fb_textures; - - { //texture - RD::TextureFormat tf; - tf.type = RD::TEXTURE_TYPE_2D; - tf.width = p_resolution; - tf.height = 1; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - - cl->shadow.texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - fb_textures.push_back(cl->shadow.texture); - } - { - RD::TextureFormat tf; - tf.type = RD::TEXTURE_TYPE_2D; - tf.width = p_resolution; - tf.height = 1; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_X8_D24_UNORM_PACK32, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_X8_D24_UNORM_PACK32 : RD::DATA_FORMAT_D32_SFLOAT; - //chunks to write - cl->shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - fb_textures.push_back(cl->shadow.depth); - } - - cl->shadow.fb = RD::get_singleton()->framebuffer_create(fb_textures); - } - - cl->shadow.size = p_resolution; -} - -void RasterizerCanvasRD::light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders) { - - CanvasLight *cl = canvas_light_owner.getornull(p_rid); - ERR_FAIL_COND(cl->shadow.texture.is_null()); - - for (int i = 0; i < 4; i++) { - - //make sure it remains orthogonal, makes easy to read angle later - - //light.basis.scale(Vector3(to_light.elements[0].length(),to_light.elements[1].length(),1)); - - Vector cc; - cc.push_back(Color(p_far, p_far, p_far, 1.0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(cl->shadow.fb, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, cc, 1.0, 0, Rect2i((cl->shadow.size / 4) * i, 0, (cl->shadow.size / 4), 1)); - - CameraMatrix projection; - { - real_t fov = 90; - real_t nearp = p_near; - real_t farp = p_far; - real_t aspect = 1.0; - - real_t ymax = nearp * Math::tan(Math::deg2rad(fov * 0.5)); - real_t ymin = -ymax; - real_t xmin = ymin * aspect; - real_t xmax = ymax * aspect; - - projection.set_frustum(xmin, xmax, ymin, ymax, nearp, farp); - } - - Vector3 cam_target = Basis(Vector3(0, 0, Math_PI * 2 * ((i + 3) / 4.0))).xform(Vector3(0, 1, 0)); - projection = projection * CameraMatrix(Transform().looking_at(cam_target, Vector3(0, 0, -1)).affine_inverse()); - - ShadowRenderPushConstant push_constant; - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - push_constant.projection[y * 4 + x] = projection.matrix[y][x]; - } - } - static const Vector2 directions[4] = { Vector2(1, 0), Vector2(0, 1), Vector2(-1, 0), Vector2(0, -1) }; - push_constant.direction[0] = directions[i].x; - push_constant.direction[1] = directions[i].y; - push_constant.pad[0] = 0; - push_constant.pad[1] = 0; - - /*if (i == 0) - *p_xform_cache = projection;*/ - - LightOccluderInstance *instance = p_occluders; - - while (instance) { - - OccluderPolygon *co = occluder_polygon_owner.getornull(instance->occluder); - - if (!co || co->index_array.is_null() || !(p_light_mask & instance->light_mask)) { - - instance = instance->next; - continue; - } - - _update_transform_2d_to_mat2x4(p_light_xform * instance->xform_cache, push_constant.modelview); - - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, shadow_render.render_pipelines[co->cull_mode]); - RD::get_singleton()->draw_list_bind_vertex_array(draw_list, co->vertex_array); - RD::get_singleton()->draw_list_bind_index_array(draw_list, co->index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(ShadowRenderPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - - instance = instance->next; - } - - RD::get_singleton()->draw_list_end(); - } -} - -RID RasterizerCanvasRD::occluder_polygon_create() { - - OccluderPolygon occluder; - occluder.point_count = 0; - occluder.cull_mode = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; - return occluder_polygon_owner.make_rid(occluder); -} - -void RasterizerCanvasRD::occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines) { - - OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); - ERR_FAIL_COND(!oc); - - if (oc->point_count != p_lines.size() && oc->vertex_array.is_valid()) { - - RD::get_singleton()->free(oc->vertex_array); - RD::get_singleton()->free(oc->vertex_buffer); - RD::get_singleton()->free(oc->index_array); - RD::get_singleton()->free(oc->index_buffer); - - oc->vertex_array = RID(); - oc->vertex_buffer = RID(); - oc->index_array = RID(); - oc->index_buffer = RID(); - } - - if (p_lines.size()) { - - Vector geometry; - Vector indices; - int lc = p_lines.size(); - - geometry.resize(lc * 6 * sizeof(float)); - indices.resize(lc * 3 * sizeof(uint16_t)); - - { - uint8_t *vw = geometry.ptrw(); - float *vwptr = (float *)vw; - uint8_t *iw = indices.ptrw(); - uint16_t *iwptr = (uint16_t *)iw; - - const Vector2 *lr = p_lines.ptr(); - - const int POLY_HEIGHT = 16384; - - for (int i = 0; i < lc / 2; i++) { - - vwptr[i * 12 + 0] = lr[i * 2 + 0].x; - vwptr[i * 12 + 1] = lr[i * 2 + 0].y; - vwptr[i * 12 + 2] = POLY_HEIGHT; - - vwptr[i * 12 + 3] = lr[i * 2 + 1].x; - vwptr[i * 12 + 4] = lr[i * 2 + 1].y; - vwptr[i * 12 + 5] = POLY_HEIGHT; - - vwptr[i * 12 + 6] = lr[i * 2 + 1].x; - vwptr[i * 12 + 7] = lr[i * 2 + 1].y; - vwptr[i * 12 + 8] = -POLY_HEIGHT; - - vwptr[i * 12 + 9] = lr[i * 2 + 0].x; - vwptr[i * 12 + 10] = lr[i * 2 + 0].y; - vwptr[i * 12 + 11] = -POLY_HEIGHT; - - iwptr[i * 6 + 0] = i * 4 + 0; - iwptr[i * 6 + 1] = i * 4 + 1; - iwptr[i * 6 + 2] = i * 4 + 2; - - iwptr[i * 6 + 3] = i * 4 + 2; - iwptr[i * 6 + 4] = i * 4 + 3; - iwptr[i * 6 + 5] = i * 4 + 0; - } - } - - //if same buffer len is being set, just use BufferSubData to avoid a pipeline flush - - if (oc->vertex_array.is_null()) { - //create from scratch - //vertices - oc->vertex_buffer = RD::get_singleton()->vertex_buffer_create(lc * 6 * sizeof(real_t), geometry); - - Vector buffer; - buffer.push_back(oc->vertex_buffer); - oc->vertex_array = RD::get_singleton()->vertex_array_create(4 * lc / 2, shadow_render.vertex_format, buffer); - //indices - - oc->index_buffer = RD::get_singleton()->index_buffer_create(3 * lc, RD::INDEX_BUFFER_FORMAT_UINT16, indices); - oc->index_array = RD::get_singleton()->index_array_create(oc->index_buffer, 0, 3 * lc); - - } else { - //update existing - const uint8_t *vr = geometry.ptr(); - RD::get_singleton()->buffer_update(oc->vertex_buffer, 0, geometry.size(), vr); - const uint8_t *ir = indices.ptr(); - RD::get_singleton()->buffer_update(oc->index_buffer, 0, indices.size(), ir); - } - } -} -void RasterizerCanvasRD::occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode) { - OccluderPolygon *oc = occluder_polygon_owner.getornull(p_occluder); - ERR_FAIL_COND(!oc); - oc->cull_mode = p_mode; -} - -void RasterizerCanvasRD::ShaderData::set_code(const String &p_code) { - //compile - - code = p_code; - valid = false; - ubo_size = 0; - uniforms.clear(); - uses_screen_texture = false; - uses_material_samplers = false; - - if (code == String()) { - return; //just invalid, but no error - } - - ShaderCompilerRD::GeneratedCode gen_code; - - int light_mode = LIGHT_MODE_NORMAL; - int blend_mode = BLEND_MODE_MIX; - uses_screen_texture = false; - - ShaderCompilerRD::IdentifierActions actions; - - actions.render_mode_values["blend_add"] = Pair(&blend_mode, BLEND_MODE_ADD); - actions.render_mode_values["blend_mix"] = Pair(&blend_mode, BLEND_MODE_MIX); - actions.render_mode_values["blend_sub"] = Pair(&blend_mode, BLEND_MODE_SUB); - actions.render_mode_values["blend_mul"] = Pair(&blend_mode, BLEND_MODE_MUL); - actions.render_mode_values["blend_premul_alpha"] = Pair(&blend_mode, BLEND_MODE_PMALPHA); - actions.render_mode_values["blend_disabled"] = Pair(&blend_mode, BLEND_MODE_DISABLED); - - actions.render_mode_values["unshaded"] = Pair(&light_mode, LIGHT_MODE_UNSHADED); - actions.render_mode_values["light_only"] = Pair(&light_mode, LIGHT_MODE_LIGHT_ONLY); - - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - - actions.uniforms = &uniforms; - - RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; - - Error err = canvas_singleton->shader.compiler.compile(VS::SHADER_CANVAS_ITEM, code, &actions, path, gen_code); - - ERR_FAIL_COND(err != OK); - - if (version.is_null()) { - version = canvas_singleton->shader.canvas_shader.version_create(); - } - - if (gen_code.texture_uniforms.size() || uses_screen_texture) { //requires the samplers - gen_code.defines.push_back("\n#define USE_MATERIAL_SAMPLERS\n"); - uses_material_samplers = true; - } -#if 0 - print_line("**compiling shader:"); - print_line("**defines:\n"); - for (int i = 0; i < gen_code.defines.size(); i++) { - print_line(gen_code.defines[i]); - } - print_line("\n**uniforms:\n" + gen_code.uniforms); - print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); -#endif - canvas_singleton->shader.canvas_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); - ERR_FAIL_COND(!canvas_singleton->shader.canvas_shader.version_is_valid(version)); - - ubo_size = gen_code.uniform_total_size; - ubo_offsets = gen_code.uniform_offsets; - texture_uniforms = gen_code.texture_uniforms; - - //update them pipelines - - RD::PipelineColorBlendState::Attachment attachment; - - switch (blend_mode) { - case BLEND_MODE_DISABLED: { - - // nothing to do here, disabled by default - - } break; - case BLEND_MODE_MIX: { - - attachment.enable_blend = true; - attachment.alpha_blend_op = RD::BLEND_OP_ADD; - attachment.color_blend_op = RD::BLEND_OP_ADD; - attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - - } break; - case BLEND_MODE_ADD: { - - attachment.enable_blend = true; - attachment.alpha_blend_op = RD::BLEND_OP_ADD; - attachment.color_blend_op = RD::BLEND_OP_ADD; - attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - - } break; - case BLEND_MODE_SUB: { - - attachment.enable_blend = true; - attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT; - attachment.color_blend_op = RD::BLEND_OP_SUBTRACT; - attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - - } break; - case BLEND_MODE_MUL: { - attachment.enable_blend = true; - attachment.alpha_blend_op = RD::BLEND_OP_ADD; - attachment.color_blend_op = RD::BLEND_OP_ADD; - attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR; - attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO; - attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA; - attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; - - } break; - case BLEND_MODE_PMALPHA: { - attachment.enable_blend = true; - attachment.alpha_blend_op = RD::BLEND_OP_ADD; - attachment.color_blend_op = RD::BLEND_OP_ADD; - attachment.src_color_blend_factor = RD::BLEND_FACTOR_ONE; - attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - - } break; - } - - RD::PipelineColorBlendState blend_state; - blend_state.attachments.push_back(attachment); - - //update pipelines - - for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { - for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { - RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_LINES, - RD::RENDER_PRIMITIVE_POINTS, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, - RD::RENDER_PRIMITIVE_LINES, - RD::RENDER_PRIMITIVE_LINESTRIPS, - RD::RENDER_PRIMITIVE_POINTS, - }; - - ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit - SHADER_VARIANT_QUAD, - SHADER_VARIANT_NINEPATCH, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE_POINTS, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit - SHADER_VARIANT_QUAD_LIGHT, - SHADER_VARIANT_NINEPATCH_LIGHT, - SHADER_VARIANT_PRIMITIVE_LIGHT, - SHADER_VARIANT_PRIMITIVE_LIGHT, - SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, - }; - - RID shader_variant = canvas_singleton->shader.canvas_shader.version_get_shader(version, shader_variants[i][j]); - pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), blend_state, 0); - } - } - - valid = true; -} - -void RasterizerCanvasRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { - if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); - } else { - default_texture_params[p_name] = p_texture; - } -} -void RasterizerCanvasRD::ShaderData::get_param_list(List *p_param_list) const { - - Map order; - - for (Map::Element *E = uniforms.front(); E; E = E->next()) { - - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); - } else { - order[E->get().order] = E->key(); - } - } - - for (Map::Element *E = order.front(); E; E = E->next()) { - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); - p_param_list->push_back(pi); - } -} - -bool RasterizerCanvasRD::ShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RasterizerCanvasRD::ShaderData::is_animated() const { - return false; -} -bool RasterizerCanvasRD::ShaderData::casts_shadows() const { - return false; -} -Variant RasterizerCanvasRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); - } - return Variant(); -} - -RasterizerCanvasRD::ShaderData::ShaderData() { - valid = false; - uses_screen_texture = false; - uses_material_samplers = false; -} - -RasterizerCanvasRD::ShaderData::~ShaderData() { - RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; - ERR_FAIL_COND(!canvas_singleton); - //pipeline variants will clear themselves if shader is gone - if (version.is_valid()) { - canvas_singleton->shader.canvas_shader.version_free(version); - } -} - -RasterizerStorageRD::ShaderData *RasterizerCanvasRD::_create_shader_func() { - ShaderData *shader_data = memnew(ShaderData); - return shader_data; -} -void RasterizerCanvasRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - - RasterizerCanvasRD *canvas_singleton = (RasterizerCanvasRD *)RasterizerCanvas::singleton; - - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), false); - } - - if (shader_data->ubo_size == 0 && !shader_data->uses_material_samplers) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - if (shader_data->uses_material_samplers) { - //needs samplers for the material (uses custom textures) create them - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 0; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); - ids_ptr[0] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = canvas_singleton->storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - uniforms.push_back(u); - } - - if (shader_data->ubo_size) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 1; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, canvas_singleton->shader.canvas_shader.version_get_shader(shader_data->version, 0), 1); -} -RasterizerCanvasRD::MaterialData::~MaterialData() { - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } -} - -RasterizerStorageRD::MaterialData *RasterizerCanvasRD::_create_material_func(ShaderData *p_shader) { - MaterialData *material_data = memnew(MaterialData); - material_data->shader_data = p_shader; - material_data->last_frame = false; - //update will happen later anyway so do nothing. - return material_data; -} - -void RasterizerCanvasRD::set_time(double p_time) { - state.time = p_time; -} - -void RasterizerCanvasRD::update() { - _dispose_bindings(); -} - -RasterizerCanvasRD::RasterizerCanvasRD(RasterizerStorageRD *p_storage) { - storage = p_storage; - - { //create default samplers - - default_samplers.default_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR; - default_samplers.default_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED; - } - - { //shader variants - - uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); - - String global_defines; - if (textures_per_stage <= 16) { - //ARM pretty much, and very old Intel GPUs under Linux - state.max_lights_per_item = 4; //sad - global_defines += "#define MAX_LIGHT_TEXTURES 4\n"; - } else if (textures_per_stage <= 32) { - //Apple (Metal) - state.max_lights_per_item = 8; //sad - global_defines += "#define MAX_LIGHT_TEXTURES 8\n"; - } else { - //Anything else (16 lights per item) - state.max_lights_per_item = DEFAULT_MAX_LIGHTS_PER_ITEM; - global_defines += "#define MAX_LIGHT_TEXTURES " + itos(DEFAULT_MAX_LIGHTS_PER_ITEM) + "\n"; - } - - uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); - if (uniform_max_size < 65536) { - //Yes, you guessed right, ARM again - state.max_lights_per_render = 64; - global_defines += "#define MAX_LIGHTS 64\n"; - } else { - state.max_lights_per_render = DEFAULT_MAX_LIGHTS_PER_RENDER; - global_defines += "#define MAX_LIGHTS " + itos(DEFAULT_MAX_LIGHTS_PER_RENDER) + "\n"; - } - - state.light_uniforms = memnew_arr(LightUniform, state.max_lights_per_render); - Vector variants; - //non light variants - variants.push_back(""); //none by default is first variant - variants.push_back("#define USE_NINEPATCH\n"); //ninepatch is the second variant - variants.push_back("#define USE_PRIMITIVE\n"); //primitive is the third - variants.push_back("#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size - variants.push_back("#define USE_ATTRIBUTES\n"); // attributes for vertex arrays - variants.push_back("#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size - //light variants - variants.push_back("#define USE_LIGHTING\n"); //none by default is first variant - variants.push_back("#define USE_LIGHTING\n#define USE_NINEPATCH\n"); //ninepatch is the second variant - variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n"); //primitive is the third - variants.push_back("#define USE_LIGHTING\n#define USE_PRIMITIVE\n#define USE_POINT_SIZE\n"); //points need point size - variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n"); // attributes for vertex arrays - variants.push_back("#define USE_LIGHTING\n#define USE_ATTRIBUTES\n#define USE_POINT_SIZE\n"); //attributes with point size - - shader.canvas_shader.initialize(variants, global_defines); - - shader.default_version = shader.canvas_shader.version_create(); - shader.default_version_rd_shader = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD); - shader.default_version_rd_shader_light = shader.canvas_shader.version_get_shader(shader.default_version, SHADER_VARIANT_QUAD_LIGHT); - - for (int i = 0; i < PIPELINE_LIGHT_MODE_MAX; i++) { - for (int j = 0; j < PIPELINE_VARIANT_MAX; j++) { - RD::RenderPrimitive primitive[PIPELINE_VARIANT_MAX] = { - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_LINES, - RD::RENDER_PRIMITIVE_POINTS, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, - RD::RENDER_PRIMITIVE_LINES, - RD::RENDER_PRIMITIVE_LINESTRIPS, - RD::RENDER_PRIMITIVE_POINTS, - }; - - ShaderVariant shader_variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX] = { - { //non lit - SHADER_VARIANT_QUAD, - SHADER_VARIANT_NINEPATCH, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE_POINTS, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS }, - { //lit - SHADER_VARIANT_QUAD_LIGHT, - SHADER_VARIANT_NINEPATCH_LIGHT, - SHADER_VARIANT_PRIMITIVE_LIGHT, - SHADER_VARIANT_PRIMITIVE_LIGHT, - SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT }, - }; - - RID shader_variant = shader.canvas_shader.version_get_shader(shader.default_version, shader_variants[i][j]); - shader.pipeline_variants.variants[i][j].setup(shader_variant, primitive[j], RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_blend(), 0); - } - } - } - - { - //shader compiler - ShaderCompilerRD::DefaultIdentifierActions actions; - - actions.renames["VERTEX"] = "vertex"; - actions.renames["LIGHT_VERTEX"] = "light_vertex"; - actions.renames["SHADOW_VERTEX"] = "shadow_vertex"; - actions.renames["UV"] = "uv"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; - - actions.renames["WORLD_MATRIX"] = "world_matrix"; - actions.renames["CANVAS_MATRIX"] = "canvas_data.canvas_transform"; - actions.renames["SCREEN_MATRIX"] = "canvas_data.screen_transform"; - actions.renames["TIME"] = "canvas_data.time"; - actions.renames["AT_LIGHT_PASS"] = "false"; - actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; - - actions.renames["COLOR"] = "color"; - actions.renames["NORMAL"] = "normal"; - actions.renames["NORMALMAP"] = "normal_map"; - actions.renames["NORMALMAP_DEPTH"] = "normal_depth"; - actions.renames["TEXTURE"] = "color_texture"; - actions.renames["TEXTURE_PIXEL_SIZE"] = "draw_data.color_texture_pixel_size"; - actions.renames["NORMAL_TEXTURE"] = "normal_texture"; - actions.renames["SPECULAR_SHININESS_TEXTURE"] = "specular_texture"; - actions.renames["SPECULAR_SHININESS"] = "specular_shininess"; - actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "screen_texture"; - actions.renames["SCREEN_PIXEL_SIZE"] = "canvas_data.screen_pixel_size"; - actions.renames["FRAGCOORD"] = "gl_FragCoord"; - actions.renames["POINT_COORD"] = "gl_PointCoord"; - - actions.renames["LIGHT_POSITION"] = "light_pos"; - actions.renames["LIGHT_COLOR"] = "light_color"; - actions.renames["LIGHT_ENERGY"] = "light_energy"; - actions.renames["LIGHT"] = "light"; - actions.renames["SHADOW_MODULATE"] = "shadow_modulate"; - - actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - actions.usage_defines["SCREEN_PIXEL_SIZE"] = "@SCREEN_UV"; - actions.usage_defines["NORMAL"] = "#define NORMAL_USED\n"; - actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions.usage_defines["LIGHT"] = "#define LIGHT_SHADER_CODE_USED\n"; - - actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - - actions.custom_samplers["TEXTURE"] = "texture_sampler"; - actions.custom_samplers["NORMAL_TEXTURE"] = "texture_sampler"; - actions.custom_samplers["SPECULAR_SHININESS_TEXTURE"] = "texture_sampler"; - actions.custom_samplers["SCREEN_TEXTURE"] = "material_samplers[3]"; //mipmap and filter for screen texture - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 2; - actions.texture_layout_set = 1; - actions.base_uniform_string = "material."; - actions.default_filter = ShaderLanguage::FILTER_LINEAR; - actions.default_repeat = ShaderLanguage::REPEAT_DISABLE; - actions.base_varying_index = 4; - - shader.compiler.initialize(actions); - } - - { //shadow rendering - Vector versions; - versions.push_back(String()); //no versions - shadow_render.shader.initialize(versions); - - { - Vector attachments; - - RD::AttachmentFormat af_color; - af_color.format = RD::DATA_FORMAT_R32_SFLOAT; - af_color.usage_flags = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - attachments.push_back(af_color); - - RD::AttachmentFormat af_depth; - af_depth.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - af_depth.usage_flags = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - attachments.push_back(af_depth); - - shadow_render.framebuffer_format = RD::get_singleton()->framebuffer_format_create(attachments); - } - - //pipelines - Vector vf; - RD::VertexDescription vd; - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - vd.location = 0; - vd.offset = 0; - vd.stride = sizeof(float) * 3; - vf.push_back(vd); - shadow_render.vertex_format = RD::get_singleton()->vertex_format_create(vf); - - shadow_render.shader_version = shadow_render.shader.version_create(); - - for (int i = 0; i < 3; i++) { - RD::PipelineRasterizationState rs; - rs.cull_mode = i == 0 ? RD::POLYGON_CULL_DISABLED : (i == 1 ? RD::POLYGON_CULL_FRONT : RD::POLYGON_CULL_BACK); - RD::PipelineDepthStencilState ds; - ds.enable_depth_write = true; - ds.enable_depth_test = true; - ds.depth_compare_operator = RD::COMPARE_OP_LESS; - shadow_render.render_pipelines[i] = RD::get_singleton()->render_pipeline_create(shadow_render.shader.version_get_shader(shadow_render.shader_version, 0), shadow_render.framebuffer_format, shadow_render.vertex_format, RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); - } - } - - { //bindings - bindings.id_generator = 0; - //generate for 0 - bindings.default_empty = request_texture_binding(RID(), RID(), RID(), VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, RID()); - - { //state allocate - state.canvas_state_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(State::Buffer)); - state.lights_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(LightUniform) * state.max_lights_per_render); - - RD::SamplerState shadow_sampler_state; - shadow_sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - shadow_sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - shadow_sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; //shadow wrap around - shadow_sampler_state.compare_op = RD::COMPARE_OP_GREATER; - state.shadow_sampler = RD::get_singleton()->sampler_create(shadow_sampler_state); - } - } - - { - //polygon buffers - polygon_buffers.last_id = 1; - } - - { // default index buffer - - Vector pv; - pv.resize(6 * 4); - { - uint8_t *w = pv.ptrw(); - int *p32 = (int *)w; - p32[0] = 0; - p32[1] = 1; - p32[2] = 2; - p32[3] = 0; - p32[4] = 2; - p32[5] = 3; - } - shader.quad_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); - shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6); - } - - { //primitive - primitive_arrays.index_array[0] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 1); - primitive_arrays.index_array[1] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 2); - primitive_arrays.index_array[2] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 3); - primitive_arrays.index_array[3] = shader.quad_index_array = RD::get_singleton()->index_array_create(shader.quad_index_buffer, 0, 6); - } - - { //default skeleton buffer - - shader.default_skeleton_uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SkeletonUniform)); - SkeletonUniform su; - _update_transform_2d_to_mat4(Transform2D(), su.skeleton_inverse); - _update_transform_2d_to_mat4(Transform2D(), su.skeleton_transform); - RD::get_singleton()->buffer_update(shader.default_skeleton_uniform_buffer, 0, sizeof(SkeletonUniform), &su); - - shader.default_skeleton_texture_buffer = RD::get_singleton()->texture_buffer_create(32, RD::DATA_FORMAT_R32G32B32A32_SFLOAT); - } - - //create functions for shader and material - storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_shader_funcs); - storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_2D, _create_material_funcs); - - state.time = 0; - - static_assert(sizeof(PushConstant) == 128); -} - -bool RasterizerCanvasRD::free(RID p_rid) { - - if (canvas_light_owner.owns(p_rid)) { - CanvasLight *cl = canvas_light_owner.getornull(p_rid); - ERR_FAIL_COND_V(!cl, false); - light_set_use_shadow(p_rid, false, 64); - canvas_light_owner.free(p_rid); - } else if (occluder_polygon_owner.owns(p_rid)) { - occluder_polygon_set_shape_as_lines(p_rid, Vector()); - occluder_polygon_owner.free(p_rid); - } else { - return false; - } - - return true; -} - -RasterizerCanvasRD::~RasterizerCanvasRD() { - - //canvas state - - { - if (state.canvas_state_buffer.is_valid()) { - RD::get_singleton()->free(state.canvas_state_buffer); - } - - memdelete_arr(state.light_uniforms); - RD::get_singleton()->free(state.lights_uniform_buffer); - RD::get_singleton()->free(shader.default_skeleton_uniform_buffer); - RD::get_singleton()->free(shader.default_skeleton_texture_buffer); - } - - //shadow rendering - { - - shadow_render.shader.version_free(shadow_render.shader_version); - //this will also automatically clear all pipelines - RD::get_singleton()->free(state.shadow_sampler); - } - //bindings - { - - free_texture_binding(bindings.default_empty); - - //dispose pending - _dispose_bindings(); - //anything remains? - if (bindings.texture_bindings.size()) { - ERR_PRINT("Some texture bindings were not properly freed (leaked canvasitems?"); - const TextureBindingID *key = NULL; - while ((key = bindings.texture_bindings.next(key))) { - TextureBinding *tb = bindings.texture_bindings[*key]; - tb->reference_count = 1; - free_texture_binding(*key); - } - //dispose pending - _dispose_bindings(); - } - } - - //shaders - - shader.canvas_shader.version_free(shader.default_version); - - //buffers - { - RD::get_singleton()->free(shader.quad_index_array); - RD::get_singleton()->free(shader.quad_index_buffer); - //primitives are erase by dependency - } - - //pipelines don't need freeing, they are all gone after shaders are gone -} diff --git a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h b/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h deleted file mode 100644 index 894a00a436..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_canvas_rd.h +++ /dev/null @@ -1,501 +0,0 @@ -/*************************************************************************/ -/* rasterizer_canvas_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_CANVAS_RD_H -#define RASTERIZER_CANVAS_RD_H - -#include "servers/visual/rasterizer.h" -#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" -#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" -#include "servers/visual/rasterizer_rd/shader_compiler_rd.h" -#include "servers/visual/rasterizer_rd/shaders/canvas.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl.gen.h" -#include "servers/visual/rendering_device.h" - -class RasterizerCanvasRD : public RasterizerCanvas { - - RasterizerStorageRD *storage; - - enum ShaderVariant { - SHADER_VARIANT_QUAD, - SHADER_VARIANT_NINEPATCH, - SHADER_VARIANT_PRIMITIVE, - SHADER_VARIANT_PRIMITIVE_POINTS, - SHADER_VARIANT_ATTRIBUTES, - SHADER_VARIANT_ATTRIBUTES_POINTS, - SHADER_VARIANT_QUAD_LIGHT, - SHADER_VARIANT_NINEPATCH_LIGHT, - SHADER_VARIANT_PRIMITIVE_LIGHT, - SHADER_VARIANT_PRIMITIVE_POINTS_LIGHT, - SHADER_VARIANT_ATTRIBUTES_LIGHT, - SHADER_VARIANT_ATTRIBUTES_POINTS_LIGHT, - SHADER_VARIANT_MAX - }; - - enum { - FLAGS_INSTANCING_STRIDE_MASK = 0xF, - FLAGS_INSTANCING_ENABLED = (1 << 4), - FLAGS_INSTANCING_HAS_COLORS = (1 << 5), - FLAGS_INSTANCING_COLOR_8BIT = (1 << 6), - FLAGS_INSTANCING_HAS_CUSTOM_DATA = (1 << 7), - FLAGS_INSTANCING_CUSTOM_DATA_8_BIT = (1 << 8), - - FLAGS_CLIP_RECT_UV = (1 << 9), - FLAGS_TRANSPOSE_RECT = (1 << 10), - FLAGS_USING_LIGHT_MASK = (1 << 11), - - FLAGS_NINEPACH_DRAW_CENTER = (1 << 12), - FLAGS_USING_PARTICLES = (1 << 13), - FLAGS_USE_PIXEL_SNAP = (1 << 14), - - FLAGS_USE_SKELETON = (1 << 15), - FLAGS_NINEPATCH_H_MODE_SHIFT = 16, - FLAGS_NINEPATCH_V_MODE_SHIFT = 18, - FLAGS_LIGHT_COUNT_SHIFT = 20, - - FLAGS_DEFAULT_NORMAL_MAP_USED = (1 << 26), - FLAGS_DEFAULT_SPECULAR_MAP_USED = (1 << 27) - - }; - - enum { - LIGHT_FLAGS_TEXTURE_MASK = 0xFFFF, - LIGHT_FLAGS_BLEND_SHIFT = 16, - LIGHT_FLAGS_BLEND_MASK = (3 << 16), - LIGHT_FLAGS_BLEND_MODE_ADD = (0 << 16), - LIGHT_FLAGS_BLEND_MODE_SUB = (1 << 16), - LIGHT_FLAGS_BLEND_MODE_MIX = (2 << 16), - LIGHT_FLAGS_BLEND_MODE_MASK = (3 << 16), - LIGHT_FLAGS_HAS_SHADOW = (1 << 20), - LIGHT_FLAGS_FILTER_SHIFT = 22 - - }; - - enum { - MAX_RENDER_ITEMS = 256 * 1024, - MAX_LIGHT_TEXTURES = 1024, - DEFAULT_MAX_LIGHTS_PER_ITEM = 16, - DEFAULT_MAX_LIGHTS_PER_RENDER = 256 - }; - - /****************/ - /**** SHADER ****/ - /****************/ - - enum PipelineVariant { - PIPELINE_VARIANT_QUAD, - PIPELINE_VARIANT_NINEPATCH, - PIPELINE_VARIANT_PRIMITIVE_TRIANGLES, - PIPELINE_VARIANT_PRIMITIVE_LINES, - PIPELINE_VARIANT_PRIMITIVE_POINTS, - PIPELINE_VARIANT_ATTRIBUTE_TRIANGLES, - PIPELINE_VARIANT_ATTRIBUTE_TRIANGLE_STRIP, - PIPELINE_VARIANT_ATTRIBUTE_LINES, - PIPELINE_VARIANT_ATTRIBUTE_LINES_STRIP, - PIPELINE_VARIANT_ATTRIBUTE_POINTS, - PIPELINE_VARIANT_MAX - }; - enum PipelineLightMode { - PIPELINE_LIGHT_MODE_DISABLED, - PIPELINE_LIGHT_MODE_ENABLED, - PIPELINE_LIGHT_MODE_MAX - }; - - struct PipelineVariants { - RenderPipelineVertexFormatCacheRD variants[PIPELINE_LIGHT_MODE_MAX][PIPELINE_VARIANT_MAX]; - }; - - struct { - CanvasShaderRD canvas_shader; - RID default_version; - RID default_version_rd_shader; - RID default_version_rd_shader_light; - RID quad_index_buffer; - RID quad_index_array; - PipelineVariants pipeline_variants; - - // default_skeleton uniform set - RID default_skeleton_uniform_buffer; - RID default_skeleton_texture_buffer; - - ShaderCompilerRD compiler; - } shader; - - struct ShaderData : public RasterizerStorageRD::ShaderData { - - enum BlendMode { //used internally - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - BLEND_MODE_PMALPHA, - BLEND_MODE_DISABLED, - }; - - enum LightMode { - LIGHT_MODE_NORMAL, - LIGHT_MODE_UNSHADED, - LIGHT_MODE_LIGHT_ONLY - }; - - bool valid; - RID version; - PipelineVariants pipeline_variants; - String path; - - Map uniforms; - Vector texture_uniforms; - - Vector ubo_offsets; - uint32_t ubo_size; - - String code; - Map default_texture_params; - - bool uses_screen_texture; - bool uses_material_samplers; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); - virtual void get_param_list(List *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; - virtual bool is_animated() const; - virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; - ShaderData(); - virtual ~ShaderData(); - }; - - RasterizerStorageRD::ShaderData *_create_shader_func(); - static RasterizerStorageRD::ShaderData *_create_shader_funcs() { - return static_cast(singleton)->_create_shader_func(); - } - - struct MaterialData : public RasterizerStorageRD::MaterialData { - uint64_t last_frame; - ShaderData *shader_data; - RID uniform_buffer; - RID uniform_set; - Vector texture_cache; - Vector ubo_data; - - virtual void set_render_priority(int p_priority) {} - virtual void set_next_pass(RID p_pass) {} - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~MaterialData(); - }; - - RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast(singleton)->_create_material_func(static_cast(p_shader)); - } - - /**************************/ - /**** TEXTURE BINDINGS ****/ - /**************************/ - - // bindings used to render commands, - // cached for performance. - - struct TextureBindingKey { - RID texture; - RID normalmap; - RID specular; - RID multimesh; - VS::CanvasItemTextureFilter texture_filter; - VS::CanvasItemTextureRepeat texture_repeat; - bool operator==(const TextureBindingKey &p_key) const { - return texture == p_key.texture && normalmap == p_key.normalmap && specular == p_key.specular && multimesh == p_key.specular && texture_filter == p_key.texture_filter && texture_repeat == p_key.texture_repeat; - } - }; - - struct TextureBindingKeyHasher { - static _FORCE_INLINE_ uint32_t hash(const TextureBindingKey &p_key) { - uint32_t hash = hash_djb2_one_64(p_key.texture.get_id()); - hash = hash_djb2_one_64(p_key.normalmap.get_id(), hash); - hash = hash_djb2_one_64(p_key.specular.get_id(), hash); - hash = hash_djb2_one_64(p_key.multimesh.get_id(), hash); - hash = hash_djb2_one_32(uint32_t(p_key.texture_filter) << 16 | uint32_t(p_key.texture_repeat), hash); - return hash; - } - }; - - struct TextureBinding { - TextureBindingID id; - TextureBindingKey key; - SelfList to_dispose; - uint32_t reference_count; - RID uniform_set; - TextureBinding() : - to_dispose(this) { - reference_count = 0; - } - }; - - struct { - SelfList::List to_dispose_list; - - TextureBindingID id_generator; - HashMap texture_key_bindings; - HashMap texture_bindings; - - TextureBindingID default_empty; - } bindings; - - RID _create_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat, RID p_multimesh); - void _dispose_bindings(); - - struct { - VS::CanvasItemTextureFilter default_filter; - VS::CanvasItemTextureRepeat default_repeat; - } default_samplers; - - /******************/ - /**** POLYGONS ****/ - /******************/ - - struct PolygonBuffers { - RD::VertexFormatID vertex_format_id; - RID vertex_buffer; - RID vertex_array; - RID index_buffer; - RID indices; - }; - - struct { - HashMap polygons; - PolygonID last_id; - } polygon_buffers; - - /********************/ - /**** PRIMITIVES ****/ - /********************/ - - struct { - RID index_array[4]; - } primitive_arrays; - - /*******************/ - /**** MATERIALS ****/ - /*******************/ - - /******************/ - /**** LIGHTING ****/ - /******************/ - - struct CanvasLight { - - RID texture; - struct { - int size; - RID texture; - RID depth; - RID fb; - } shadow; - }; - - RID_Owner canvas_light_owner; - - struct ShadowRenderPushConstant { - float projection[16]; - float modelview[8]; - float direction[2]; - float pad[2]; - }; - - struct OccluderPolygon { - - VS::CanvasOccluderPolygonCullMode cull_mode; - int point_count; - RID vertex_buffer; - RID vertex_array; - RID index_buffer; - RID index_array; - }; - - struct LightUniform { - float matrix[8]; //light to texture coordinate matrix - float shadow_matrix[8]; //light to shadow coordinate matrix - float color[4]; - float shadow_color[4]; - float position[2]; - uint32_t flags; //index to light texture - float height; - float shadow_pixel_size; - float pad[3]; - }; - - RID_Owner occluder_polygon_owner; - - struct { - CanvasOcclusionShaderRD shader; - RID shader_version; - RID render_pipelines[3]; - RD::VertexFormatID vertex_format; - RD::FramebufferFormatID framebuffer_format; - } shadow_render; - - /***************/ - /**** STATE ****/ - /***************/ - - //state that does not vary across rendering all items - - struct ItemStateData : public Item::CustomData { - - struct LightCache { - uint64_t light_version; - Light *light; - }; - - LightCache light_cache[DEFAULT_MAX_LIGHTS_PER_ITEM]; - uint32_t light_cache_count; - RID state_uniform_set_with_light; - RID state_uniform_set; - ItemStateData() { - - for (int i = 0; i < DEFAULT_MAX_LIGHTS_PER_ITEM; i++) { - light_cache[i].light_version = 0; - light_cache[i].light = NULL; - } - light_cache_count = 0xFFFFFFFF; - } - - ~ItemStateData() { - if (state_uniform_set_with_light.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set_with_light)) { - RD::get_singleton()->free(state_uniform_set_with_light); - } - if (state_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(state_uniform_set)) { - RD::get_singleton()->free(state_uniform_set); - } - } - }; - - struct State { - - //state buffer - struct Buffer { - float canvas_transform[16]; - float screen_transform[16]; - float canvas_normal_transform[16]; - float canvas_modulate[4]; - float screen_pixel_size[2]; - float time; - float pad; - - //uint32_t light_count; - //uint32_t pad[3]; - }; - - LightUniform *light_uniforms; - - RID lights_uniform_buffer; - RID canvas_state_buffer; - RID shadow_sampler; - - uint32_t max_lights_per_render; - uint32_t max_lights_per_item; - - double time; - } state; - - struct PushConstant { - float world[6]; - uint32_t flags; - uint32_t specular_shininess; - union { - //rect - struct { - float modulation[4]; - float ninepatch_margins[4]; - float dst_rect[4]; - float src_rect[4]; - float pad[2]; - }; - //primitive - struct { - float points[6]; // vec2 points[3] - float uvs[6]; // vec2 points[3] - uint32_t colors[6]; // colors encoded as half - }; - }; - float color_texture_pixel_size[2]; - uint32_t lights[4]; - }; - - struct SkeletonUniform { - float skeleton_transform[16]; - float skeleton_inverse[16]; - }; - - Item *items[MAX_RENDER_ITEMS]; - - Size2i _bind_texture_binding(TextureBindingID p_binding, RenderingDevice::DrawListID p_draw_list, uint32_t &flags); - void _render_item(RenderingDevice::DrawListID p_draw_list, const Item *p_item, RenderingDevice::FramebufferFormatID p_framebuffer_format, const Transform2D &p_canvas_transform_inverse, Item *¤t_clip, Light *p_lights, PipelineVariants *p_pipeline_variants); - void _render_items(RID p_to_render_target, int p_item_count, const Transform2D &p_canvas_transform_inverse, Light *p_lights, RID p_screen_uniform_set); - - _FORCE_INLINE_ void _update_transform_2d_to_mat2x4(const Transform2D &p_transform, float *p_mat2x4); - _FORCE_INLINE_ void _update_transform_2d_to_mat2x3(const Transform2D &p_transform, float *p_mat2x3); - - _FORCE_INLINE_ void _update_transform_2d_to_mat4(const Transform2D &p_transform, float *p_mat4); - _FORCE_INLINE_ void _update_transform_to_mat4(const Transform &p_transform, float *p_mat4); - - _FORCE_INLINE_ void _update_specular_shininess(const Color &p_transform, uint32_t *r_ss); - -public: - TextureBindingID request_texture_binding(RID p_texture, RID p_normalmap, RID p_specular, VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat, RID p_multimesh); - void free_texture_binding(TextureBindingID p_binding); - - PolygonID request_polygon(const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector()); - void free_polygon(PolygonID p_polygon); - - RID light_create(); - void light_set_texture(RID p_rid, RID p_texture); - void light_set_use_shadow(RID p_rid, bool p_enable, int p_resolution); - void light_update_shadow(RID p_rid, const Transform2D &p_light_xform, int p_light_mask, float p_near, float p_far, LightOccluderInstance *p_occluders); - - RID occluder_polygon_create(); - void occluder_polygon_set_shape_as_lines(RID p_occluder, const Vector &p_lines); - void occluder_polygon_set_cull_mode(RID p_occluder, VS::CanvasOccluderPolygonCullMode p_mode); - - void canvas_render_items(RID p_to_render_target, Item *p_item_list, const Color &p_modulate, Light *p_light_list, const Transform2D &p_canvas_transform); - - void canvas_debug_viewport_shadows(Light *p_lights_with_shadow){}; - - void draw_window_margins(int *p_margins, RID *p_margin_textures) {} - - void set_time(double p_time); - void update(); - bool free(RID p_rid); - RasterizerCanvasRD(RasterizerStorageRD *p_storage); - ~RasterizerCanvasRD(); -}; - -#endif // RASTERIZER_CANVAS_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp deleted file mode 100644 index 355ebfa409..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.cpp +++ /dev/null @@ -1,1092 +0,0 @@ -/*************************************************************************/ -/* rasterizer_effects_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_effects_rd.h" -#include "core/os/os.h" -#include "core/project_settings.h" -#include "cubemap_coeffs.h" - -static _FORCE_INLINE_ void store_transform_3x3(const Basis &p_basis, float *p_array) { - p_array[0] = p_basis.elements[0][0]; - p_array[1] = p_basis.elements[1][0]; - p_array[2] = p_basis.elements[2][0]; - p_array[3] = 0; - p_array[4] = p_basis.elements[0][1]; - p_array[5] = p_basis.elements[1][1]; - p_array[6] = p_basis.elements[2][1]; - p_array[7] = 0; - p_array[8] = p_basis.elements[0][2]; - p_array[9] = p_basis.elements[1][2]; - p_array[10] = p_basis.elements[2][2]; - p_array[11] = 0; -} - -RID RasterizerEffectsRD::_get_uniform_set_from_image(RID p_image) { - - if (image_to_uniform_set_cache.has(p_image)) { - RID uniform_set = image_to_uniform_set_cache[p_image]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 0; - u.ids.push_back(p_image); - uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 1); - - image_to_uniform_set_cache[p_image] = uniform_set; - - return uniform_set; -} - -RID RasterizerEffectsRD::_get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { - - if (texture_to_uniform_set_cache.has(p_texture)) { - RID uniform_set = texture_to_uniform_set_cache[p_texture]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture); - uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, blur.shader.version_get_shader(blur.shader_version, 0), 0); - - texture_to_uniform_set_cache[p_texture] = uniform_set; - - return uniform_set; -} - -RID RasterizerEffectsRD::_get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps) { - - if (texture_to_compute_uniform_set_cache.has(p_texture)) { - RID uniform_set = texture_to_compute_uniform_set_cache[p_texture]; - if (RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - return uniform_set; - } - } - - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.ids.push_back(p_use_mipmaps ? default_mipmap_sampler : default_sampler); - u.ids.push_back(p_texture); - uniforms.push_back(u); - //any thing with the same configuration (one texture in binding 0 for set 0), is good - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, 0), 0); - - texture_to_compute_uniform_set_cache[p_texture] = uniform_set; - - return uniform_set; -} - -void RasterizerEffectsRD::copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y, bool p_force_luminance) { - - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - if (p_flip_y) { - blur.push_constant.flags |= BLUR_FLAG_FLIP_Y; - } - if (p_force_luminance) { - blur.push_constant.flags |= BLUR_COPY_FORCE_LUMINANCE; - } - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector(), 1.0, 0, p_rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region) { - - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - - if (p_region != Rect2()) { - blur.push_constant.flags = BLUR_FLAG_USE_BLUR_SECTION; - blur.push_constant.section[0] = p_region.position.x; - blur.push_constant.section[1] = p_region.position.y; - blur.push_constant.section[2] = p_region.size.width; - blur.push_constant.section[3] = p_region.size.height; - } - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_SIMPLY_COPY].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region) { - - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - - uint32_t base_flags = 0; - if (p_region != Rect2()) { - base_flags = BLUR_FLAG_USE_BLUR_SECTION; - blur.push_constant.section[0] = p_region.position.x; - blur.push_constant.section[1] = p_region.position.y; - blur.push_constant.section[2] = p_region.size.width; - blur.push_constant.section[3] = p_region.size.height; - } - - blur.push_constant.pixel_size[0] = p_pixel_size.x; - blur.push_constant.pixel_size[1] = p_pixel_size.y; - - //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_GAUSSIAN_BLUR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur.push_constant.flags = base_flags; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength, bool p_first_pass, float p_luminance_cap, float p_exposure, float p_bloom, float p_hdr_bleed_treshold, float p_hdr_bleed_scale, RID p_auto_exposure, float p_auto_exposure_grey) { - - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - - BlurMode blur_mode = p_first_pass && p_auto_exposure.is_valid() ? BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE : BLUR_MODE_GAUSSIAN_GLOW; - uint32_t base_flags = 0; - - blur.push_constant.pixel_size[0] = p_pixel_size.x; - blur.push_constant.pixel_size[1] = p_pixel_size.y; - - blur.push_constant.glow_strength = p_strength; - blur.push_constant.glow_bloom = p_bloom; - blur.push_constant.glow_hdr_threshold = p_hdr_bleed_treshold; - blur.push_constant.glow_hdr_scale = p_hdr_bleed_scale; - blur.push_constant.glow_exposure = p_exposure; - blur.push_constant.glow_white = 0; //actually unused - blur.push_constant.glow_luminance_cap = p_luminance_cap; - blur.push_constant.glow_auto_exposure_grey = p_auto_exposure_grey; //unused also - - //HORIZONTAL - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer_half, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer_half))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - if (p_auto_exposure.is_valid() && p_first_pass) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_auto_exposure), 1); - } - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur.push_constant.flags = base_flags | BLUR_FLAG_HORIZONTAL | (p_first_pass ? BLUR_FLAG_GLOW_FIRST_PASS : 0); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); - - blur_mode = BLUR_MODE_GAUSSIAN_GLOW; - - //VERTICAL - draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[blur_mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_rd_texture_half), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - blur.push_constant.flags = base_flags; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::make_mipmap(RID p_source_rd_texture, RID p_dest_framebuffer, const Vector2 &p_pixel_size) { - - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - - blur.push_constant.pixel_size[0] = p_pixel_size.x; - blur.push_constant.pixel_size[1] = p_pixel_size.y; - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, blur.pipelines[BLUR_MODE_MIPMAP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &blur.push_constant, sizeof(BlurPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip) { - - CopyToDPPushConstant push_constant; - push_constant.bias = p_bias; - push_constant.z_far = p_z_far; - push_constant.z_near = p_z_near; - push_constant.z_flip = p_dp_flip; - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, Vector(), 1.0, 0, p_rect); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy.pipelines[COPY_MODE_CUBE_TO_DP].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(CopyToDPPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings) { - - zeromem(&tonemap.push_constant, sizeof(TonemapPushConstant)); - - tonemap.push_constant.use_bcs = p_settings.use_bcs; - tonemap.push_constant.bcs[0] = p_settings.brightness; - tonemap.push_constant.bcs[1] = p_settings.contrast; - tonemap.push_constant.bcs[2] = p_settings.saturation; - - tonemap.push_constant.use_glow = p_settings.use_glow; - tonemap.push_constant.glow_intensity = p_settings.glow_intensity; - tonemap.push_constant.glow_level_flags = p_settings.glow_level_flags; - tonemap.push_constant.glow_texture_size[0] = p_settings.glow_texture_size.x; - tonemap.push_constant.glow_texture_size[1] = p_settings.glow_texture_size.y; - tonemap.push_constant.glow_mode = p_settings.glow_mode; - - TonemapMode mode = p_settings.glow_use_bicubic_upscale ? TONEMAP_MODE_BICUBIC_GLOW_FILTER : TONEMAP_MODE_NORMAL; - - tonemap.push_constant.tonemapper = p_settings.tonemap_mode; - tonemap.push_constant.use_auto_exposure = p_settings.use_auto_exposure; - tonemap.push_constant.exposure = p_settings.exposure; - tonemap.push_constant.white = p_settings.white; - tonemap.push_constant.auto_exposure_grey = p_settings.auto_exposure_grey; - - tonemap.push_constant.use_color_correction = p_settings.use_color_correction; - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dst_framebuffer, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, tonemap.pipelines[mode].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dst_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_source_color), 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.exposure_texture), 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.glow_texture, true), 2); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, _get_uniform_set_from_texture(p_settings.color_correction_texture), 3); - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &tonemap.push_constant, sizeof(TonemapPushConstant)); - RD::get_singleton()->draw_list_draw(draw_list, true); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerEffectsRD::luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set) { - - luminance_reduce.push_constant.source_size[0] = p_source_size.x; - luminance_reduce.push_constant.source_size[1] = p_source_size.y; - luminance_reduce.push_constant.max_luminance = p_max_luminance; - luminance_reduce.push_constant.min_luminance = p_min_luminance; - luminance_reduce.push_constant.exposure_adjust = p_adjust; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - for (int i = 0; i < p_reduce.size(); i++) { - - if (i == 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_READ]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_texture), 0); - } else { - - RD::get_singleton()->compute_list_add_barrier(compute_list); //needs barrier, wait until previous is done - - if (i == p_reduce.size() - 1 && !p_set) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE_WRITE]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_prev_luminance), 2); - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, luminance_reduce.pipelines[LUMINANCE_REDUCE]); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i - 1]), 0); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_reduce[i]), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &luminance_reduce.push_constant, sizeof(LuminanceReducePushConstant)); - - int32_t x_groups = (luminance_reduce.push_constant.source_size[0] - 1) / 8 + 1; - int32_t y_groups = (luminance_reduce.push_constant.source_size[1] - 1) / 8 + 1; - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - - luminance_reduce.push_constant.source_size[0] = MAX(luminance_reduce.push_constant.source_size[0] / 8, 1); - luminance_reduce.push_constant.source_size[1] = MAX(luminance_reduce.push_constant.source_size[1] / 8, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_halfsize_texture1, RID p_halfsize_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, VisualServer::DOFBokehShape p_bokeh_shape, VS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal) { - - bokeh.push_constant.blur_far_active = p_dof_far; - bokeh.push_constant.blur_far_begin = p_dof_far_begin; - bokeh.push_constant.blur_far_end = p_dof_far_begin + p_dof_far_size; - - bokeh.push_constant.blur_near_active = p_dof_near; - bokeh.push_constant.blur_near_begin = p_dof_near_begin; - bokeh.push_constant.blur_near_end = MAX(0, p_dof_near_begin - p_dof_near_size); - bokeh.push_constant.use_jitter = p_use_jitter; - bokeh.push_constant.jitter_seed = Math::randf() * 1000.0; - - bokeh.push_constant.z_near = p_cam_znear; - bokeh.push_constant.z_far = p_cam_zfar; - bokeh.push_constant.orthogonal = p_cam_orthogonal; - bokeh.push_constant.blur_size = p_bokeh_size; - - bokeh.push_constant.second_pass = false; - bokeh.push_constant.half_size = false; - - bokeh.push_constant.blur_scale = 0.5; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - /* FIRST PASS */ - // The alpha channel of the source color texture is filled with the expected circle size - // If used for DOF far, the size is positive, if used for near, its negative. - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BLUR_SIZE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_texture), 1); - - int32_t x_groups = (p_base_texture_size.x - 1) / 8 + 1; - int32_t y_groups = (p_base_texture_size.y - 1) / 8 + 1; - bokeh.push_constant.size[0] = p_base_texture_size.x; - bokeh.push_constant.size[1] = p_base_texture_size.y; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (p_bokeh_shape == VS::DOF_BOKEH_BOX || p_bokeh_shape == VS::DOF_BOKEH_HEXAGON) { - - //second pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[p_bokeh_shape == VS::DOF_BOKEH_BOX ? BOKEH_GEN_BOKEH_BOX : BOKEH_GEN_BOKEH_HEXAGONAL]); - - static const int quality_samples[4] = { 6, 12, 12, 24 }; - - bokeh.push_constant.steps = quality_samples[p_quality]; - - if (p_quality == VS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == VS::DOF_BLUR_QUALITY_LOW) { - //box and hexagon are more or less the same, and they can work in either half (very low and low quality) or full (medium and high quality_ sizes) - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1); - - x_groups = ((p_base_texture_size.x >> 1) - 1) / 8 + 1; - y_groups = ((p_base_texture_size.y >> 1) - 1) / 8 + 1; - bokeh.push_constant.size[0] = p_base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - bokeh.push_constant.blur_size *= 0.5; - - } else { - //medium and high quality use full size - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_secondary_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //third pass - bokeh.push_constant.second_pass = true; - - if (p_quality == VS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == VS::DOF_BLUR_QUALITY_LOW) { - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture2), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_secondary_texture), 1); - } - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (p_quality == VS::DOF_BLUR_QUALITY_VERY_LOW || p_quality == VS::DOF_BLUR_QUALITY_LOW) { - //forth pass, upscale for low quality - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture2), 1); - - x_groups = (p_base_texture_size.x - 1) / 8 + 1; - y_groups = (p_base_texture_size.y - 1) / 8 + 1; - bokeh.push_constant.size[0] = p_base_texture_size.x; - bokeh.push_constant.size[1] = p_base_texture_size.y; - bokeh.push_constant.half_size = false; - bokeh.push_constant.second_pass = false; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - } - } else { - //circle - - //second pass - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_GEN_BOKEH_CIRCULAR]); - - static const float quality_scale[4] = { 8.0, 4.0, 1.0, 0.5 }; - - bokeh.push_constant.steps = 0; - bokeh.push_constant.blur_scale = quality_scale[p_quality]; - - //circle always runs in half size, otherwise too expensive - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_halfsize_texture1), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_base_texture), 1); - - x_groups = ((p_base_texture_size.x >> 1) - 1) / 8 + 1; - y_groups = ((p_base_texture_size.y >> 1) - 1) / 8 + 1; - bokeh.push_constant.size[0] = p_base_texture_size.x >> 1; - bokeh.push_constant.size[1] = p_base_texture_size.y >> 1; - bokeh.push_constant.half_size = true; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - //circle is just one pass, then upscale - - // upscale - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, bokeh.pipelines[BOKEH_COMPOSITE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_base_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_halfsize_texture1), 1); - - x_groups = (p_base_texture_size.x - 1) / 8 + 1; - y_groups = (p_base_texture_size.y - 1) / 8 + 1; - bokeh.push_constant.size[0] = p_base_texture_size.x; - bokeh.push_constant.size[1] = p_base_texture_size.y; - bokeh.push_constant.half_size = false; - bokeh.push_constant.second_pass = false; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &bokeh.push_constant, sizeof(BokehPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness) { - - //minify first - ssao.minify_push_constant.orthogonal = p_projection.is_orthogonal(); - ssao.minify_push_constant.z_near = p_projection.get_z_near(); - ssao.minify_push_constant.z_far = p_projection.get_z_far(); - ssao.minify_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; - ssao.minify_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; - ssao.minify_push_constant.source_size[0] = p_depth_buffer_size.x; - ssao.minify_push_constant.source_size[1] = p_depth_buffer_size.y; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - /* FIRST PASS */ - // Minify the depth buffer. - - for (int i = 0; i < depth_mipmaps.size(); i++) { - - if (i == 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_FIRST]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 0); - } else { - if (i == 1) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_MINIFY_MIPMAP]); - } - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i - 1]), 0); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(depth_mipmaps[i]), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.minify_push_constant, sizeof(SSAOMinifyPushConstant)); - // shrink after set - ssao.minify_push_constant.source_size[0] = MAX(1, ssao.minify_push_constant.source_size[0] >> 1); - ssao.minify_push_constant.source_size[1] = MAX(1, ssao.minify_push_constant.source_size[1] >> 1); - - int x_groups = (ssao.minify_push_constant.source_size[0] - 1) / 8 + 1; - int y_groups = (ssao.minify_push_constant.source_size[1] - 1) / 8 + 1; - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - } - - /* SECOND PASS */ - // Gather samples - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[(SSAO_GATHER_LOW + p_quality) + (p_half_size ? 4 : 0)]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 1); - if (!p_half_size) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 2); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_normal_buffer), 3); - - ssao.gather_push_constant.screen_size[0] = p_depth_buffer_size.x; - ssao.gather_push_constant.screen_size[1] = p_depth_buffer_size.y; - if (p_half_size) { - ssao.gather_push_constant.screen_size[0] >>= 1; - ssao.gather_push_constant.screen_size[1] >>= 1; - } - ssao.gather_push_constant.z_far = p_projection.get_z_far(); - ssao.gather_push_constant.z_near = p_projection.get_z_near(); - ssao.gather_push_constant.orthogonal = p_projection.is_orthogonal(); - - ssao.gather_push_constant.proj_info[0] = -2.0f / (ssao.gather_push_constant.screen_size[0] * p_projection.matrix[0][0]); - ssao.gather_push_constant.proj_info[1] = -2.0f / (ssao.gather_push_constant.screen_size[1] * p_projection.matrix[1][1]); - ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; - ssao.gather_push_constant.proj_info[3] = (1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; - //ssao.gather_push_constant.proj_info[2] = (1.0f - p_projection.matrix[0][2]) / p_projection.matrix[0][0]; - //ssao.gather_push_constant.proj_info[3] = -(1.0f + p_projection.matrix[1][2]) / p_projection.matrix[1][1]; - - ssao.gather_push_constant.radius = p_radius; - - ssao.gather_push_constant.proj_scale = float(p_projection.get_pixels_per_meter(ssao.gather_push_constant.screen_size[0])); - ssao.gather_push_constant.bias = p_bias; - ssao.gather_push_constant.intensity_div_r6 = p_intensity / pow(p_radius, 6.0f); - - ssao.gather_push_constant.pixel_size[0] = 1.0 / p_depth_buffer_size.x; - ssao.gather_push_constant.pixel_size[1] = 1.0 / p_depth_buffer_size.y; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.gather_push_constant, sizeof(SSAOGatherPushConstant)); - - int x_groups = (ssao.gather_push_constant.screen_size[0] - 1) / 8 + 1; - int y_groups = (ssao.gather_push_constant.screen_size[1] - 1) / 8 + 1; - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - /* THIRD PASS */ - // Blur horizontal - - ssao.blur_push_constant.edge_sharpness = p_edge_sharpness; - ssao.blur_push_constant.filter_scale = p_blur; - ssao.blur_push_constant.screen_size[0] = ssao.gather_push_constant.screen_size[0]; - ssao.blur_push_constant.screen_size[1] = ssao.gather_push_constant.screen_size[1]; - ssao.blur_push_constant.z_far = p_projection.get_z_far(); - ssao.blur_push_constant.z_near = p_projection.get_z_near(); - ssao.blur_push_constant.orthogonal = p_projection.is_orthogonal(); - ssao.blur_push_constant.axis[0] = 1; - ssao.blur_push_constant.axis[1] = 0; - - if (p_blur != VS::ENV_SSAO_BLUR_DISABLED) { - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[p_half_size ? SSAO_BLUR_PASS_HALF : SSAO_BLUR_PASS]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); - if (p_half_size) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 1); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao2), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - RD::get_singleton()->compute_list_add_barrier(compute_list); - - /* THIRD PASS */ - // Blur vertical - - ssao.blur_push_constant.axis[0] = 0; - ssao.blur_push_constant.axis[1] = 1; - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao2), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_ao1), 3); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - } - if (p_half_size) { //must upscale - - /* FOURTH PASS */ - // upscale if half size - //back to full size - ssao.blur_push_constant.screen_size[0] = p_depth_buffer_size.x; - ssao.blur_push_constant.screen_size[1] = p_depth_buffer_size.y; - - RD::get_singleton()->compute_list_add_barrier(compute_list); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, ssao.pipelines[SSAO_BLUR_UPSCALE]); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_ao1), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_upscale_buffer), 3); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_buffer), 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_depth_mipmaps_texture), 2); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &ssao.blur_push_constant, sizeof(SSAOBlurPushConstant)); //not used but set anyway - - x_groups = (p_depth_buffer_size.x - 1) / 8 + 1; - y_groups = (p_depth_buffer_size.y - 1) / 8 + 1; - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - } - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve) { - - roughness_limiter.push_constant.screen_size[0] = p_size.x; - roughness_limiter.push_constant.screen_size[1] = p_size.y; - roughness_limiter.push_constant.curve = p_curve; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness_limiter.pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_normal), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_roughness), 1); - - int x_groups = (p_size.x - 1) / 8 + 1; - int y_groups = (p_size.y - 1) / 8 + 1; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness_limiter.push_constant, sizeof(RoughnessLimiterPushConstant)); //not used but set anyway - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 1); - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size) { - - zeromem(&roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); - - roughness.push_constant.face_id = p_face_id > 9 ? 0 : p_face_id; - roughness.push_constant.roughness = p_roughness; - roughness.push_constant.sample_count = p_sample_count; - roughness.push_constant.use_direct_write = p_roughness == 0.0; - roughness.push_constant.face_size = p_size; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, roughness.pipeline); - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_rd_texture), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_framebuffer), 1); - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &roughness.push_constant, sizeof(CubemapRoughnessPushConstant)); - - int x_groups = (p_size - 1) / 8 + 1; - int y_groups = (p_size - 1) / 8 + 1; - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, p_face_id > 9 ? 6 : 1); - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size) { - - cubemap_downsampler.push_constant.face_size = p_size.x; - - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, cubemap_downsampler.pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_uniform_set_from_image(p_dest_cubemap), 1); - - int x_groups = (p_size.x - 1) / 8 + 1; - int y_groups = (p_size.y - 1) / 8 + 1; - - RD::get_singleton()->compute_list_set_push_constant(compute_list, &cubemap_downsampler.push_constant, sizeof(CubemapDownsamplerPushConstant)); - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, y_groups, 6); // one z_group for each face - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::cubemap_filter(RID p_source_cubemap, Vector p_dest_cubemap, bool p_use_array) { - - Vector uniforms; - for (int i = 0; i < p_dest_cubemap.size(); i++) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = i; - u.ids.push_back(p_dest_cubemap[i]); - uniforms.push_back(u); - } - if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { - RD::get_singleton()->free(filter.image_uniform_set); - } - filter.image_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, 0), 2); - - int pipeline = p_use_array ? FILTER_MODE_HIGH_QUALITY_ARRAY : FILTER_MODE_HIGH_QUALITY; - pipeline = filter.use_high_quality ? pipeline : pipeline + 1; - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, filter.pipelines[pipeline]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, _get_compute_uniform_set_from_texture(p_source_cubemap, true), 0); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.uniform_set, 1); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, filter.image_uniform_set, 2); - - int x_groups = p_use_array ? 1792 : 342; // (128 * 128 * 7) / 64 : (128*128 + 64*64 + 32*32 + 16*16 + 8*8 + 4*4 + 2*2) / 64 - - RD::get_singleton()->compute_list_dispatch(compute_list, x_groups, 6, 1); // one y_group for each face - - RD::get_singleton()->compute_list_end(); -} - -void RasterizerEffectsRD::render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position) { - - SkyPushConstant sky_push_constant; - - zeromem(&sky_push_constant, sizeof(SkyPushConstant)); - - sky_push_constant.proj[0] = p_camera.matrix[2][0]; - sky_push_constant.proj[1] = p_camera.matrix[0][0]; - sky_push_constant.proj[2] = p_camera.matrix[2][1]; - sky_push_constant.proj[3] = p_camera.matrix[1][1]; - sky_push_constant.position[0] = p_position.x; - sky_push_constant.position[1] = p_position.y; - sky_push_constant.position[2] = p_position.z; - sky_push_constant.multiplier = p_multiplier; - sky_push_constant.time = p_time; - store_transform_3x3(p_orientation, sky_push_constant.orientation); - - RenderingDevice::FramebufferFormatID fb_format = RD::get_singleton()->framebuffer_get_format(p_fb); - - RD::DrawListID draw_list = p_list; - - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, p_pipeline->get_render_pipeline(RD::INVALID_ID, fb_format)); - - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_samplers, 0); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_uniform_set, 1); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_texture_set, 2); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_lights, 3); - - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array); - - RD::get_singleton()->draw_list_set_push_constant(draw_list, &sky_push_constant, sizeof(SkyPushConstant)); - - RD::get_singleton()->draw_list_draw(draw_list, true); -} - -RasterizerEffectsRD::RasterizerEffectsRD() { - - { - // Initialize blur - Vector blur_modes; - blur_modes.push_back("\n#define MODE_GAUSSIAN_BLUR\n"); - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n"); - blur_modes.push_back("\n#define MODE_GAUSSIAN_GLOW\n#define GLOW_USE_AUTO_EXPOSURE\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_LOW\n#define DOF_NEAR_BLUR_MERGE\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_MEDIUM\n#define DOF_NEAR_BLUR_MERGE\n"); - blur_modes.push_back("\n#define MODE_DOF_NEAR_BLUR\n#define DOF_QUALITY_HIGH\n#define DOF_NEAR_BLUR_MERGE\n"); - blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_LOW\n"); - blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_MEDIUM\n"); - blur_modes.push_back("\n#define MODE_DOF_FAR_BLUR\n#define DOF_QUALITY_HIGH\n"); - blur_modes.push_back("\n#define MODE_SSAO_MERGE\n"); - blur_modes.push_back("\n#define MODE_SIMPLE_COPY\n"); - blur_modes.push_back("\n#define MODE_MIPMAP\n"); - - blur.shader.initialize(blur_modes); - zeromem(&blur.push_constant, sizeof(BlurPushConstant)); - blur.shader_version = blur.shader.version_create(); - - for (int i = 0; i < BLUR_MODE_MAX; i++) { - blur.pipelines[i].setup(blur.shader.version_get_shader(blur.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } - } - - { - // Initialize roughness - Vector cubemap_roughness_modes; - cubemap_roughness_modes.push_back(""); - roughness.shader.initialize(cubemap_roughness_modes); - - roughness.shader_version = roughness.shader.version_create(); - - roughness.pipeline = RD::get_singleton()->compute_pipeline_create(roughness.shader.version_get_shader(roughness.shader_version, 0)); - } - - { - // Initialize tonemapper - Vector tonemap_modes; - tonemap_modes.push_back("\n"); - tonemap_modes.push_back("\n#define USE_GLOW_FILTER_BICUBIC\n"); - - tonemap.shader.initialize(tonemap_modes); - - tonemap.shader_version = tonemap.shader.version_create(); - - for (int i = 0; i < TONEMAP_MODE_MAX; i++) { - tonemap.pipelines[i].setup(tonemap.shader.version_get_shader(tonemap.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } - } - - { - // Initialize luminance_reduce - Vector luminance_reduce_modes; - luminance_reduce_modes.push_back("\n#define READ_TEXTURE\n"); - luminance_reduce_modes.push_back("\n"); - luminance_reduce_modes.push_back("\n#define WRITE_LUMINANCE\n"); - - luminance_reduce.shader.initialize(luminance_reduce_modes); - - luminance_reduce.shader_version = luminance_reduce.shader.version_create(); - - for (int i = 0; i < LUMINANCE_REDUCE_MAX; i++) { - luminance_reduce.pipelines[i] = RD::get_singleton()->compute_pipeline_create(luminance_reduce.shader.version_get_shader(luminance_reduce.shader_version, i)); - } - } - - { - // Initialize copier - Vector copy_modes; - copy_modes.push_back("\n#define MODE_CUBE_TO_DP\n"); - - copy.shader.initialize(copy_modes); - - copy.shader_version = copy.shader.version_create(); - - for (int i = 0; i < COPY_MODE_MAX; i++) { - copy.pipelines[i].setup(copy.shader.version_get_shader(copy.shader_version, i), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); - } - } - - { - // Initialize bokeh - Vector bokeh_modes; - bokeh_modes.push_back("\n#define MODE_GEN_BLUR_SIZE\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_BOX\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_HEXAGONAL\n"); - bokeh_modes.push_back("\n#define MODE_BOKEH_CIRCULAR\n"); - bokeh_modes.push_back("\n#define MODE_COMPOSITE_BOKEH\n"); - - bokeh.shader.initialize(bokeh_modes); - - bokeh.shader_version = bokeh.shader.version_create(); - - for (int i = 0; i < BOKEH_MAX; i++) { - bokeh.pipelines[i] = RD::get_singleton()->compute_pipeline_create(bokeh.shader.version_get_shader(bokeh.shader_version, i)); - } - } - - { - // Initialize ssao - uint32_t pipeline = 0; - { - Vector ssao_modes; - ssao_modes.push_back("\n#define MINIFY_START\n"); - ssao_modes.push_back("\n"); - - ssao.minify_shader.initialize(ssao_modes); - - ssao.minify_shader_version = ssao.minify_shader.version_create(); - - for (int i = 0; i <= SSAO_MINIFY_MIPMAP; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.minify_shader.version_get_shader(ssao.minify_shader_version, i)); - pipeline++; - } - } - { - Vector ssao_modes; - ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n"); - ssao_modes.push_back("\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_LOW\n#define USE_HALF_SIZE\n"); - ssao_modes.push_back("\n#define USE_HALF_SIZE\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_HIGH\n#define USE_HALF_SIZE\n"); - ssao_modes.push_back("\n#define SSAO_QUALITY_ULTRA\n#define USE_HALF_SIZE\n"); - - ssao.gather_shader.initialize(ssao_modes); - - ssao.gather_shader_version = ssao.gather_shader.version_create(); - - for (int i = SSAO_GATHER_LOW; i <= SSAO_GATHER_ULTRA_HALF; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.gather_shader.version_get_shader(ssao.gather_shader_version, i - SSAO_GATHER_LOW)); - pipeline++; - } - } - { - Vector ssao_modes; - ssao_modes.push_back("\n#define MODE_FULL_SIZE\n"); - ssao_modes.push_back("\n"); - ssao_modes.push_back("\n#define MODE_UPSCALE\n"); - - ssao.blur_shader.initialize(ssao_modes); - - ssao.blur_shader_version = ssao.blur_shader.version_create(); - - for (int i = SSAO_BLUR_PASS; i <= SSAO_BLUR_UPSCALE; i++) { - ssao.pipelines[pipeline] = RD::get_singleton()->compute_pipeline_create(ssao.blur_shader.version_get_shader(ssao.blur_shader_version, i - SSAO_BLUR_PASS)); - pipeline++; - } - } - - ERR_FAIL_COND(pipeline != SSAO_MAX); - } - - { - // Initialize roughness limiter - Vector shader_modes; - shader_modes.push_back(""); - - roughness_limiter.shader.initialize(shader_modes); - - roughness_limiter.shader_version = roughness_limiter.shader.version_create(); - - roughness_limiter.pipeline = RD::get_singleton()->compute_pipeline_create(roughness_limiter.shader.version_get_shader(roughness_limiter.shader_version, 0)); - } - - { - //Initialize cubemap downsampler - Vector cubemap_downsampler_modes; - cubemap_downsampler_modes.push_back(""); - cubemap_downsampler.shader.initialize(cubemap_downsampler_modes); - - cubemap_downsampler.shader_version = cubemap_downsampler.shader.version_create(); - - cubemap_downsampler.pipeline = RD::get_singleton()->compute_pipeline_create(cubemap_downsampler.shader.version_get_shader(cubemap_downsampler.shader_version, 0)); - } - - { - // Initialize cubemap filter - filter.use_high_quality = GLOBAL_GET("rendering/quality/reflections/fast_filter_high_quality"); - - Vector cubemap_filter_modes; - cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n"); - cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n"); - cubemap_filter_modes.push_back("\n#define USE_HIGH_QUALITY\n#define USE_TEXTURE_ARRAY\n"); - cubemap_filter_modes.push_back("\n#define USE_LOW_QUALITY\n#define USE_TEXTURE_ARRAY\n"); - filter.shader.initialize(cubemap_filter_modes); - filter.shader_version = filter.shader.version_create(); - - for (int i = 0; i < FILTER_MODE_MAX; i++) { - filter.pipelines[i] = RD::get_singleton()->compute_pipeline_create(filter.shader.version_get_shader(filter.shader_version, i)); - } - - if (filter.use_high_quality) { - filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(high_quality_coeffs)); - RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(high_quality_coeffs), &high_quality_coeffs[0], false); - } else { - filter.coefficient_buffer = RD::get_singleton()->storage_buffer_create(sizeof(low_quality_coeffs)); - RD::get_singleton()->buffer_update(filter.coefficient_buffer, 0, sizeof(low_quality_coeffs), &low_quality_coeffs[0], false); - } - - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.ids.push_back(filter.coefficient_buffer); - uniforms.push_back(u); - } - filter.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, filter.shader.version_get_shader(filter.shader_version, filter.use_high_quality ? 0 : 1), 1); - } - - RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.max_lod = 0; - - default_sampler = RD::get_singleton()->sampler_create(sampler); - - sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.mip_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.max_lod = 1e20; - - default_mipmap_sampler = RD::get_singleton()->sampler_create(sampler); - - { //create index array for copy shaders - Vector pv; - pv.resize(6 * 4); - { - uint8_t *w = pv.ptrw(); - int *p32 = (int *)w; - p32[0] = 0; - p32[1] = 1; - p32[2] = 2; - p32[3] = 0; - p32[4] = 2; - p32[5] = 3; - } - index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); - index_array = RD::get_singleton()->index_array_create(index_buffer, 0, 6); - } -} - -RasterizerEffectsRD::~RasterizerEffectsRD() { - if (RD::get_singleton()->uniform_set_is_valid(filter.image_uniform_set)) { - RD::get_singleton()->free(filter.image_uniform_set); - } - - if (RD::get_singleton()->uniform_set_is_valid(filter.uniform_set)) { - RD::get_singleton()->free(filter.uniform_set); - } - - RD::get_singleton()->free(default_sampler); - RD::get_singleton()->free(default_mipmap_sampler); - RD::get_singleton()->free(index_buffer); //array gets freed as dependency - RD::get_singleton()->free(filter.coefficient_buffer); - blur.shader.version_free(blur.shader_version); - roughness.shader.version_free(roughness.shader_version); - tonemap.shader.version_free(tonemap.shader_version); - luminance_reduce.shader.version_free(luminance_reduce.shader_version); - copy.shader.version_free(copy.shader_version); - bokeh.shader.version_free(bokeh.shader_version); - ssao.minify_shader.version_free(ssao.minify_shader_version); - ssao.gather_shader.version_free(ssao.gather_shader_version); - ssao.blur_shader.version_free(ssao.blur_shader_version); - roughness_limiter.shader.version_free(roughness_limiter.shader_version); - cubemap_downsampler.shader.version_free(cubemap_downsampler.shader_version); - filter.shader.version_free(filter.shader_version); -} diff --git a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h b/servers/visual/rasterizer_rd/rasterizer_effects_rd.h deleted file mode 100644 index 562a7b674b..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_effects_rd.h +++ /dev/null @@ -1,457 +0,0 @@ -/*************************************************************************/ -/* rasterizer_effects_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_EFFECTS_RD_H -#define RASTERIZER_EFFECTS_RD_H - -#include "core/math/camera_matrix.h" -#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" -#include "servers/visual/rasterizer_rd/shaders/blur.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/copy.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/ssao.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/ssao_blur.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/ssao_minify.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/tonemap.glsl.gen.h" - -#include "servers/visual_server.h" - -class RasterizerEffectsRD { - - enum BlurMode { - BLUR_MODE_GAUSSIAN_BLUR, - BLUR_MODE_GAUSSIAN_GLOW, - BLUR_MODE_GAUSSIAN_GLOW_AUTO_EXPOSURE, - BLUR_MODE_DOF_NEAR_LOW, - BLUR_MODE_DOF_NEAR_MEDIUM, - BLUR_MODE_DOF_NEAR_HIGH, - BLUR_MODE_DOF_NEAR_MERGE_LOW, - BLUR_MODE_DOF_NEAR_MERGE_MEDIUM, - BLUR_MODE_DOF_NEAR_MERGE_HIGH, - BLUR_MODE_DOF_FAR_LOW, - BLUR_MODE_DOF_FAR_MEDIUM, - BLUR_MODE_DOF_FAR_HIGH, - BLUR_MODE_SSAO_MERGE, - BLUR_MODE_SIMPLY_COPY, - BLUR_MODE_MIPMAP, - BLUR_MODE_MAX, - - }; - - enum { - BLUR_FLAG_HORIZONTAL = (1 << 0), - BLUR_FLAG_USE_BLUR_SECTION = (1 << 1), - BLUR_FLAG_USE_ORTHOGONAL_PROJECTION = (1 << 2), - BLUR_FLAG_DOF_NEAR_FIRST_TAP = (1 << 3), - BLUR_FLAG_GLOW_FIRST_PASS = (1 << 4), - BLUR_FLAG_FLIP_Y = (1 << 5), - BLUR_COPY_FORCE_LUMINANCE = (1 << 6) - }; - - struct BlurPushConstant { - float section[4]; - float pixel_size[2]; - uint32_t flags; - uint32_t pad; - //glow - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; - //dof - float dof_begin; - float dof_end; - float dof_radius; - float dof_pad; - - float dof_dir[2]; - float camera_z_far; - float camera_z_near; - - float ssao_color[4]; - }; - - struct Blur { - BlurPushConstant push_constant; - BlurShaderRD shader; - RID shader_version; - RenderPipelineVertexFormatCacheRD pipelines[BLUR_MODE_MAX]; - - } blur; - - struct CubemapRoughnessPushConstant { - uint32_t face_id; - uint32_t sample_count; - float roughness; - uint32_t use_direct_write; - float face_size; - float pad[3]; - }; - - struct CubemapRoughness { - - CubemapRoughnessPushConstant push_constant; - CubemapRoughnessShaderRD shader; - RID shader_version; - RID pipeline; - } roughness; - - enum TonemapMode { - TONEMAP_MODE_NORMAL, - TONEMAP_MODE_BICUBIC_GLOW_FILTER, - TONEMAP_MODE_MAX - }; - - struct TonemapPushConstant { - float bcs[3]; - uint32_t use_bcs; - - uint32_t use_glow; - uint32_t use_auto_exposure; - uint32_t use_color_correction; - uint32_t tonemapper; - - uint32_t glow_texture_size[2]; - - float glow_intensity; - uint32_t glow_level_flags; - uint32_t glow_mode; - - float exposure; - float white; - float auto_exposure_grey; - }; - - struct Tonemap { - - TonemapPushConstant push_constant; - TonemapShaderRD shader; - RID shader_version; - RenderPipelineVertexFormatCacheRD pipelines[TONEMAP_MODE_MAX]; - } tonemap; - - enum LuminanceReduceMode { - LUMINANCE_REDUCE_READ, - LUMINANCE_REDUCE, - LUMINANCE_REDUCE_WRITE, - LUMINANCE_REDUCE_MAX - }; - - struct LuminanceReducePushConstant { - int32_t source_size[2]; - float max_luminance; - float min_luminance; - float exposure_adjust; - float pad[3]; - }; - - struct LuminanceReduce { - - LuminanceReducePushConstant push_constant; - LuminanceReduceShaderRD shader; - RID shader_version; - RID pipelines[LUMINANCE_REDUCE_MAX]; - } luminance_reduce; - - struct CopyToDPPushConstant { - float bias; - float z_far; - float z_near; - uint32_t z_flip; - }; - - enum CopyMode { - COPY_MODE_CUBE_TO_DP, - COPY_MODE_MAX - }; - - struct Copy { - - CopyShaderRD shader; - RID shader_version; - RenderPipelineVertexFormatCacheRD pipelines[COPY_MODE_MAX]; - } copy; - - struct BokehPushConstant { - uint32_t size[2]; - float z_far; - float z_near; - - uint32_t orthogonal; - float blur_size; - float blur_scale; - uint32_t steps; - - uint32_t blur_near_active; - float blur_near_begin; - float blur_near_end; - uint32_t blur_far_active; - - float blur_far_begin; - float blur_far_end; - uint32_t second_pass; - uint32_t half_size; - - uint32_t use_jitter; - float jitter_seed; - uint32_t pad[2]; - }; - - enum BokehMode { - BOKEH_GEN_BLUR_SIZE, - BOKEH_GEN_BOKEH_BOX, - BOKEH_GEN_BOKEH_HEXAGONAL, - BOKEH_GEN_BOKEH_CIRCULAR, - BOKEH_COMPOSITE, - BOKEH_MAX - }; - - struct Bokeh { - - BokehPushConstant push_constant; - BokehDofShaderRD shader; - RID shader_version; - RID pipelines[BOKEH_MAX]; - } bokeh; - - enum SSAOMode { - SSAO_MINIFY_FIRST, - SSAO_MINIFY_MIPMAP, - SSAO_GATHER_LOW, - SSAO_GATHER_MEDIUM, - SSAO_GATHER_HIGH, - SSAO_GATHER_ULTRA, - SSAO_GATHER_LOW_HALF, - SSAO_GATHER_MEDIUM_HALF, - SSAO_GATHER_HIGH_HALF, - SSAO_GATHER_ULTRA_HALF, - SSAO_BLUR_PASS, - SSAO_BLUR_PASS_HALF, - SSAO_BLUR_UPSCALE, - SSAO_MAX - }; - - struct SSAOMinifyPushConstant { - float pixel_size[2]; - float z_far; - float z_near; - int32_t source_size[2]; - uint32_t orthogonal; - uint32_t pad; - }; - - struct SSAOGatherPushConstant { - int32_t screen_size[2]; - float z_far; - float z_near; - - uint32_t orthogonal; - float intensity_div_r6; - float radius; - float bias; - - float proj_info[4]; - float pixel_size[2]; - float proj_scale; - uint32_t pad; - }; - - struct SSAOBlurPushConstant { - float edge_sharpness; - int32_t filter_scale; - float z_far; - float z_near; - uint32_t orthogonal; - uint32_t pad[3]; - int32_t axis[2]; - int32_t screen_size[2]; - }; - - struct SSAO { - - SSAOMinifyPushConstant minify_push_constant; - SsaoMinifyShaderRD minify_shader; - RID minify_shader_version; - - SSAOGatherPushConstant gather_push_constant; - SsaoShaderRD gather_shader; - RID gather_shader_version; - - SSAOBlurPushConstant blur_push_constant; - SsaoBlurShaderRD blur_shader; - RID blur_shader_version; - - RID pipelines[SSAO_MAX]; - } ssao; - - struct RoughnessLimiterPushConstant { - int32_t screen_size[2]; - float curve; - uint32_t pad; - }; - - struct RoughnessLimiter { - - RoughnessLimiterPushConstant push_constant; - RoughnessLimiterShaderRD shader; - RID shader_version; - RID pipeline; - - } roughness_limiter; - - struct CubemapDownsamplerPushConstant { - uint32_t face_size; - float pad[3]; - }; - - struct CubemapDownsampler { - - CubemapDownsamplerPushConstant push_constant; - CubemapDownsamplerShaderRD shader; - RID shader_version; - RID pipeline; - - } cubemap_downsampler; - - enum CubemapFilterMode { - FILTER_MODE_HIGH_QUALITY, - FILTER_MODE_LOW_QUALITY, - FILTER_MODE_HIGH_QUALITY_ARRAY, - FILTER_MODE_LOW_QUALITY_ARRAY, - FILTER_MODE_MAX, - }; - - struct CubemapFilter { - - CubemapFilterShaderRD shader; - RID shader_version; - RID pipelines[FILTER_MODE_MAX]; - RID uniform_set; - RID image_uniform_set; - RID coefficient_buffer; - bool use_high_quality; - - } filter; - - struct SkyPushConstant { - float orientation[12]; - float proj[4]; - float position[3]; - float multiplier; - float time; - float pad[3]; - }; - - RID default_sampler; - RID default_mipmap_sampler; - RID index_buffer; - RID index_array; - - Map texture_to_uniform_set_cache; - - Map image_to_uniform_set_cache; - Map texture_to_compute_uniform_set_cache; - - RID _get_uniform_set_from_image(RID p_texture); - RID _get_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); - RID _get_compute_uniform_set_from_texture(RID p_texture, bool p_use_mipmaps = false); - -public: - //TODO must re-do most of the shaders in compute - - void region_copy(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_region); - void copy_to_rect(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, bool p_flip_y = false, bool p_force_luminance = false); - void gaussian_blur(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, const Rect2 &p_region); - void gaussian_glow(RID p_source_rd_texture, RID p_framebuffer_half, RID p_rd_texture_half, RID p_dest_framebuffer, const Vector2 &p_pixel_size, float p_strength = 1.0, bool p_first_pass = false, float p_luminance_cap = 16.0, float p_exposure = 1.0, float p_bloom = 0.0, float p_hdr_bleed_treshold = 1.0, float p_hdr_bleed_scale = 1.0, RID p_auto_exposure = RID(), float p_auto_exposure_grey = 1.0); - - void cubemap_roughness(RID p_source_rd_texture, RID p_dest_framebuffer, uint32_t p_face_id, uint32_t p_sample_count, float p_roughness, float p_size); - void make_mipmap(RID p_source_rd_texture, RID p_framebuffer_half, const Vector2 &p_pixel_size); - void copy_cubemap_to_dp(RID p_source_rd_texture, RID p_dest_framebuffer, const Rect2 &p_rect, float p_z_near, float p_z_far, float p_bias, bool p_dp_flip); - void luminance_reduction(RID p_source_texture, const Size2i p_source_size, const Vector p_reduce, RID p_prev_luminance, float p_min_luminance, float p_max_luminance, float p_adjust, bool p_set = false); - void bokeh_dof(RID p_base_texture, RID p_depth_texture, const Size2i &p_base_texture_size, RID p_secondary_texture, RID p_bokeh_texture1, RID p_bokeh_texture2, bool p_dof_far, float p_dof_far_begin, float p_dof_far_size, bool p_dof_near, float p_dof_near_begin, float p_dof_near_size, float p_bokeh_size, VS::DOFBokehShape p_bokeh_shape, VS::DOFBlurQuality p_quality, bool p_use_jitter, float p_cam_znear, float p_cam_zfar, bool p_cam_orthogonal); - - struct TonemapSettings { - - bool use_glow = false; - enum GlowMode { - GLOW_MODE_ADD, - GLOW_MODE_SCREEN, - GLOW_MODE_SOFTLIGHT, - GLOW_MODE_REPLACE, - GLOW_MODE_MIX - }; - - GlowMode glow_mode = GLOW_MODE_ADD; - float glow_intensity = 1.0; - uint32_t glow_level_flags = 0; - Vector2i glow_texture_size; - bool glow_use_bicubic_upscale = false; - RID glow_texture; - - VS::EnvironmentToneMapper tonemap_mode = VS::ENV_TONE_MAPPER_LINEAR; - float exposure = 1.0; - float white = 1.0; - - bool use_auto_exposure = false; - float auto_exposure_grey = 0.5; - RID exposure_texture; - - bool use_bcs = false; - float brightness = 1.0; - float contrast = 1.0; - float saturation = 1.0; - - bool use_color_correction = false; - RID color_correction_texture; - }; - - void tonemapper(RID p_source_color, RID p_dst_framebuffer, const TonemapSettings &p_settings); - - void generate_ssao(RID p_depth_buffer, RID p_normal_buffer, const Size2i &p_depth_buffer_size, RID p_depth_mipmaps_texture, const Vector &depth_mipmaps, RID p_ao1, bool p_half_size, RID p_ao2, RID p_upscale_buffer, float p_intensity, float p_radius, float p_bias, const CameraMatrix &p_projection, VS::EnvironmentSSAOQuality p_quality, VS::EnvironmentSSAOBlur p_blur, float p_edge_sharpness); - - void roughness_limit(RID p_source_normal, RID p_roughness, const Size2i &p_size, float p_curve); - void cubemap_downsample(RID p_source_cubemap, RID p_dest_cubemap, const Size2i &p_size); - void cubemap_filter(RID p_source_cubemap, Vector p_dest_cubemap, bool p_use_array); - void render_sky(RD::DrawListID p_list, float p_time, RID p_fb, RID p_samplers, RID p_lights, RenderPipelineVertexFormatCacheRD *p_pipeline, RID p_uniform_set, RID p_texture_set, const CameraMatrix &p_camera, const Basis &p_orientation, float p_multiplier, const Vector3 &p_position); - - RasterizerEffectsRD(); - ~RasterizerEffectsRD(); -}; - -#endif // !RASTERIZER_EFFECTS_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_rd.cpp deleted file mode 100644 index 9c54f0caae..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_rd.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/*************************************************************************/ -/* rasterizer_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_rd.h" - -void RasterizerRD::prepare_for_blitting_render_targets() { - RD::get_singleton()->prepare_screen_for_drawing(); -} - -void RasterizerRD::blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount) { - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin_for_screen(p_screen); - - for (int i = 0; i < p_amount; i++) { - RID texture = storage->render_target_get_texture(p_render_targets[i].render_target); - ERR_CONTINUE(texture.is_null()); - RID rd_texture = storage->texture_get_rd_texture(texture); - ERR_CONTINUE(rd_texture.is_null()); - if (!render_target_descriptors.has(rd_texture) || !RD::get_singleton()->uniform_set_is_valid(render_target_descriptors[rd_texture])) { - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE; - u.binding = 0; - u.ids.push_back(copy_viewports_sampler); - u.ids.push_back(rd_texture); - uniforms.push_back(u); - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, copy_viewports_rd_shader, 0); - - render_target_descriptors[rd_texture] = uniform_set; - } - - Size2 screen_size(RD::get_singleton()->screen_get_width(p_screen), RD::get_singleton()->screen_get_height(p_screen)); - - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, copy_viewports_rd_pipeline); - RD::get_singleton()->draw_list_bind_index_array(draw_list, copy_viewports_rd_array); - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_target_descriptors[rd_texture], 0); - - float push_constant[4] = { - p_render_targets[i].rect.position.x / screen_size.width, - p_render_targets[i].rect.position.y / screen_size.height, - p_render_targets[i].rect.size.width / screen_size.width, - p_render_targets[i].rect.size.height / screen_size.height, - }; - RD::get_singleton()->draw_list_set_push_constant(draw_list, push_constant, 4 * sizeof(float)); - RD::get_singleton()->draw_list_draw(draw_list, true); - } - - RD::get_singleton()->draw_list_end(); -} - -void RasterizerRD::begin_frame(double frame_step) { - frame++; - time += frame_step; - canvas->set_time(time); - scene->set_time(time, frame_step); -} - -void RasterizerRD::end_frame(bool p_swap_buffers) { - -#ifndef _MSC_VER -#warning TODO: likely passa bool to swap buffers to avoid display? -#endif - RD::get_singleton()->swap_buffers(); //probably should pass some bool to avoid display? -} - -void RasterizerRD::initialize() { - - { //create framebuffer copy shader - RenderingDevice::ShaderStageData vert; - vert.shader_stage = RenderingDevice::SHADER_STAGE_VERTEX; - vert.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_VERTEX, - "#version 450\n" - "layout(push_constant, binding = 0, std140) uniform Pos { vec4 dst_rect; } pos;\n" - "layout(location =0) out vec2 uv;\n" - "void main() { \n" - " vec2 base_arr[4] = vec2[](vec2(0.0,0.0),vec2(0.0,1.0),vec2(1.0,1.0),vec2(1.0,0.0));\n" - " uv = base_arr[gl_VertexIndex];\n" - " vec2 vtx = pos.dst_rect.xy+uv*pos.dst_rect.zw;\n" - " gl_Position = vec4(vtx * 2.0 - 1.0,0.0,1.0);\n" - "}\n"); - - RenderingDevice::ShaderStageData frag; - frag.shader_stage = RenderingDevice::SHADER_STAGE_FRAGMENT; - frag.spir_v = RenderingDevice::get_singleton()->shader_compile_from_source(RenderingDevice::SHADER_STAGE_FRAGMENT, - "#version 450\n" - "layout (location = 0) in vec2 uv;\n" - "layout (location = 0) out vec4 color;\n" - "layout (binding = 0) uniform sampler2D src_rt;\n" - "void main() { color=texture(src_rt,uv); }\n"); - - Vector source; - source.push_back(vert); - source.push_back(frag); - String error; - copy_viewports_rd_shader = RD::get_singleton()->shader_create(source); - if (!copy_viewports_rd_shader.is_valid()) { - print_line("Failed compilation: " + error); - } - } - - { //create index array for copy shader - Vector pv; - pv.resize(6 * 4); - { - uint8_t *w = pv.ptrw(); - int *p32 = (int *)w; - p32[0] = 0; - p32[1] = 1; - p32[2] = 2; - p32[3] = 0; - p32[4] = 2; - p32[5] = 3; - } - copy_viewports_rd_index_buffer = RD::get_singleton()->index_buffer_create(6, RenderingDevice::INDEX_BUFFER_FORMAT_UINT32, pv); - copy_viewports_rd_array = RD::get_singleton()->index_array_create(copy_viewports_rd_index_buffer, 0, 6); - } - - { //pipeline - copy_viewports_rd_pipeline = RD::get_singleton()->render_pipeline_create(copy_viewports_rd_shader, RD::get_singleton()->screen_get_framebuffer_format(), RD::INVALID_ID, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RenderingDevice::PipelineColorBlendState::create_disabled(), 0); - } - { // sampler - copy_viewports_sampler = RD::get_singleton()->sampler_create(RD::SamplerState()); - } -} - -ThreadWorkPool RasterizerRD::thread_work_pool; -uint32_t RasterizerRD::frame = 1; - -void RasterizerRD::finalize() { - - thread_work_pool.finish(); - - memdelete(scene); - memdelete(canvas); - memdelete(storage); - - //only need to erase these, the rest are erased by cascade - RD::get_singleton()->free(copy_viewports_rd_index_buffer); - RD::get_singleton()->free(copy_viewports_rd_shader); - RD::get_singleton()->free(copy_viewports_sampler); -} - -RasterizerRD::RasterizerRD() { - thread_work_pool.init(); - time = 0; - - storage = memnew(RasterizerStorageRD); - canvas = memnew(RasterizerCanvasRD(storage)); - scene = memnew(RasterizerSceneHighEndRD(storage)); -} diff --git a/servers/visual/rasterizer_rd/rasterizer_rd.h b/servers/visual/rasterizer_rd/rasterizer_rd.h deleted file mode 100644 index bbcf9bfefe..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_rd.h +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************/ -/* rasterizer_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_RD_H -#define RASTERIZER_RD_H - -#include "core/os/os.h" -#include "core/thread_work_pool.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/rasterizer_rd/rasterizer_canvas_rd.h" -#include "servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h" -#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" - -class RasterizerRD : public Rasterizer { -protected: - RasterizerCanvasRD *canvas; - RasterizerStorageRD *storage; - RasterizerSceneHighEndRD *scene; - - RID copy_viewports_rd_shader; - RID copy_viewports_rd_pipeline; - RID copy_viewports_rd_index_buffer; - RID copy_viewports_rd_array; - RID copy_viewports_sampler; - - Map render_target_descriptors; - - double time; - - static uint32_t frame; - -public: - RasterizerStorage *get_storage() { return storage; } - RasterizerCanvas *get_canvas() { return canvas; } - RasterizerScene *get_scene() { return scene; } - - void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter) {} - - void initialize(); - void begin_frame(double frame_step); - void prepare_for_blitting_render_targets(); - void blit_render_targets_to_screen(DisplayServer::WindowID p_screen, const BlitToScreen *p_render_targets, int p_amount); - - void end_frame(bool p_swap_buffers); - void finalize(); - - static _ALWAYS_INLINE_ uint64_t get_frame_number() { return frame; } - - static Error is_viable() { - return OK; - } - - static Rasterizer *_create_current() { - return memnew(RasterizerRD); - } - - static void make_current() { - _create_func = _create_current; - } - - virtual bool is_low_end() const { return false; } - - static ThreadWorkPool thread_work_pool; - - RasterizerRD(); - ~RasterizerRD() {} -}; -#endif // RASTERIZER_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp deleted file mode 100644 index 70219a3981..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.cpp +++ /dev/null @@ -1,2729 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_high_end_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_scene_high_end_rd.h" -#include "core/project_settings.h" -#include "servers/visual/rendering_device.h" -#include "servers/visual/visual_server_raster.h" - -static _FORCE_INLINE_ void store_transform(const Transform &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.elements[0][0]; - p_array[1] = p_mtx.basis.elements[1][0]; - p_array[2] = p_mtx.basis.elements[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.basis.elements[0][1]; - p_array[5] = p_mtx.basis.elements[1][1]; - p_array[6] = p_mtx.basis.elements[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.basis.elements[0][2]; - p_array[9] = p_mtx.basis.elements[1][2]; - p_array[10] = p_mtx.basis.elements[2][2]; - p_array[11] = 0; - p_array[12] = p_mtx.origin.x; - p_array[13] = p_mtx.origin.y; - p_array[14] = p_mtx.origin.z; - p_array[15] = 1; -} - -static _FORCE_INLINE_ void store_transform_3x3(const Transform &p_mtx, float *p_array) { - p_array[0] = p_mtx.basis.elements[0][0]; - p_array[1] = p_mtx.basis.elements[1][0]; - p_array[2] = p_mtx.basis.elements[2][0]; - p_array[3] = 0; - p_array[4] = p_mtx.basis.elements[0][1]; - p_array[5] = p_mtx.basis.elements[1][1]; - p_array[6] = p_mtx.basis.elements[2][1]; - p_array[7] = 0; - p_array[8] = p_mtx.basis.elements[0][2]; - p_array[9] = p_mtx.basis.elements[1][2]; - p_array[10] = p_mtx.basis.elements[2][2]; - p_array[11] = 0; -} - -static _FORCE_INLINE_ void store_camera(const CameraMatrix &p_mtx, float *p_array) { - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - - p_array[i * 4 + j] = p_mtx.matrix[i][j]; - } - } -} - -/* SCENE SHADER */ -void RasterizerSceneHighEndRD::ShaderData::set_code(const String &p_code) { - //compile - - code = p_code; - valid = false; - ubo_size = 0; - uniforms.clear(); - uses_screen_texture = false; - - if (code == String()) { - return; //just invalid, but no error - } - - ShaderCompilerRD::GeneratedCode gen_code; - - int blend_mode = BLEND_MODE_MIX; - int depth_testi = DEPTH_TEST_ENABLED; - int cull = CULL_BACK; - - uses_point_size = false; - uses_alpha = false; - uses_blend_alpha = false; - uses_depth_pre_pass = false; - uses_discard = false; - uses_roughness = false; - uses_normal = false; - bool wireframe = false; - - unshaded = false; - uses_vertex = false; - uses_sss = false; - uses_screen_texture = false; - uses_depth_texture = false; - uses_normal_texture = false; - uses_time = false; - writes_modelview_or_projection = false; - uses_world_coordinates = false; - - int depth_drawi = DEPTH_DRAW_OPAQUE; - - ShaderCompilerRD::IdentifierActions actions; - - actions.render_mode_values["blend_add"] = Pair(&blend_mode, BLEND_MODE_ADD); - actions.render_mode_values["blend_mix"] = Pair(&blend_mode, BLEND_MODE_MIX); - actions.render_mode_values["blend_sub"] = Pair(&blend_mode, BLEND_MODE_SUB); - actions.render_mode_values["blend_mul"] = Pair(&blend_mode, BLEND_MODE_MUL); - - actions.render_mode_values["depth_draw_never"] = Pair(&depth_drawi, DEPTH_DRAW_DISABLED); - actions.render_mode_values["depth_draw_opaque"] = Pair(&depth_drawi, DEPTH_DRAW_OPAQUE); - actions.render_mode_values["depth_draw_always"] = Pair(&depth_drawi, DEPTH_DRAW_ALWAYS); - - actions.render_mode_values["depth_test_disabled"] = Pair(&depth_testi, DEPTH_TEST_DISABLED); - - actions.render_mode_values["cull_disabled"] = Pair(&cull, CULL_DISABLED); - actions.render_mode_values["cull_front"] = Pair(&cull, CULL_FRONT); - actions.render_mode_values["cull_back"] = Pair(&cull, CULL_BACK); - - actions.render_mode_flags["unshaded"] = &unshaded; - actions.render_mode_flags["wireframe"] = &wireframe; - - actions.usage_flag_pointers["ALPHA"] = &uses_alpha; - actions.render_mode_flags["depth_prepass_alpha"] = &uses_depth_pre_pass; - - actions.usage_flag_pointers["SSS_STRENGTH"] = &uses_sss; - - actions.usage_flag_pointers["SCREEN_TEXTURE"] = &uses_screen_texture; - actions.usage_flag_pointers["DEPTH_TEXTURE"] = &uses_depth_texture; - actions.usage_flag_pointers["NORMAL_TEXTURE"] = &uses_normal_texture; - actions.usage_flag_pointers["DISCARD"] = &uses_discard; - actions.usage_flag_pointers["TIME"] = &uses_time; - actions.usage_flag_pointers["ROUGHNESS"] = &uses_roughness; - actions.usage_flag_pointers["NORMAL"] = &uses_normal; - actions.usage_flag_pointers["NORMALMAP"] = &uses_normal; - - actions.usage_flag_pointers["POINT_SIZE"] = &uses_point_size; - actions.usage_flag_pointers["POINT_COORD"] = &uses_point_size; - - actions.write_flag_pointers["MODELVIEW_MATRIX"] = &writes_modelview_or_projection; - actions.write_flag_pointers["PROJECTION_MATRIX"] = &writes_modelview_or_projection; - actions.write_flag_pointers["VERTEX"] = &uses_vertex; - - actions.uniforms = &uniforms; - - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; - - Error err = scene_singleton->shader.compiler.compile(VS::SHADER_SPATIAL, code, &actions, path, gen_code); - - ERR_FAIL_COND(err != OK); - - if (version.is_null()) { - version = scene_singleton->shader.scene_shader.version_create(); - } - - depth_draw = DepthDraw(depth_drawi); - depth_test = DepthTest(depth_testi); - -#if 0 - print_line("**compiling shader:"); - print_line("**defines:\n"); - for (int i = 0; i < gen_code.defines.size(); i++) { - print_line(gen_code.defines[i]); - } - print_line("\n**uniforms:\n" + gen_code.uniforms); - print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); -#endif - scene_singleton->shader.scene_shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); - ERR_FAIL_COND(!scene_singleton->shader.scene_shader.version_is_valid(version)); - - ubo_size = gen_code.uniform_total_size; - ubo_offsets = gen_code.uniform_offsets; - texture_uniforms = gen_code.texture_uniforms; - - //blend modes - - RD::PipelineColorBlendState::Attachment blend_attachment; - - switch (blend_mode) { - case BLEND_MODE_MIX: { - - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - - } break; - case BLEND_MODE_ADD: { - - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - uses_blend_alpha = true; //force alpha used because of blend - - } break; - case BLEND_MODE_SUB: { - - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_SUBTRACT; - blend_attachment.color_blend_op = RD::BLEND_OP_SUBTRACT; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ONE; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_SRC_ALPHA; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ONE; - uses_blend_alpha = true; //force alpha used because of blend - - } break; - case BLEND_MODE_MUL: { - blend_attachment.enable_blend = true; - blend_attachment.alpha_blend_op = RD::BLEND_OP_ADD; - blend_attachment.color_blend_op = RD::BLEND_OP_ADD; - blend_attachment.src_color_blend_factor = RD::BLEND_FACTOR_DST_COLOR; - blend_attachment.dst_color_blend_factor = RD::BLEND_FACTOR_ZERO; - blend_attachment.src_alpha_blend_factor = RD::BLEND_FACTOR_DST_ALPHA; - blend_attachment.dst_alpha_blend_factor = RD::BLEND_FACTOR_ZERO; - uses_blend_alpha = true; //force alpha used because of blend - } break; - } - - RD::PipelineColorBlendState blend_state_blend; - blend_state_blend.attachments.push_back(blend_attachment); - RD::PipelineColorBlendState blend_state_opaque = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_opaque_specular = RD::PipelineColorBlendState::create_disabled(2); - RD::PipelineColorBlendState blend_state_depth_normal = RD::PipelineColorBlendState::create_disabled(1); - RD::PipelineColorBlendState blend_state_depth_normal_roughness = RD::PipelineColorBlendState::create_disabled(2); - - //update pipelines - - RD::PipelineDepthStencilState depth_stencil_state; - - if (depth_test != DEPTH_TEST_DISABLED) { - depth_stencil_state.enable_depth_test = true; - depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - depth_stencil_state.enable_depth_write = depth_draw != DEPTH_DRAW_DISABLED ? true : false; - } - - for (int i = 0; i < CULL_VARIANT_MAX; i++) { - - RD::PolygonCullMode cull_mode_rd_table[CULL_VARIANT_MAX][3] = { - { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_FRONT, RD::POLYGON_CULL_BACK }, - { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_BACK, RD::POLYGON_CULL_FRONT }, - { RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED, RD::POLYGON_CULL_DISABLED } - }; - - RD::PolygonCullMode cull_mode_rd = cull_mode_rd_table[i][cull]; - - for (int j = 0; j < VS::PRIMITIVE_MAX; j++) { - - RD::RenderPrimitive primitive_rd_table[VS::PRIMITIVE_MAX] = { - RD::RENDER_PRIMITIVE_POINTS, - RD::RENDER_PRIMITIVE_LINES, - RD::RENDER_PRIMITIVE_LINESTRIPS, - RD::RENDER_PRIMITIVE_TRIANGLES, - RD::RENDER_PRIMITIVE_TRIANGLE_STRIPS, - }; - - RD::RenderPrimitive primitive_rd = uses_point_size ? RD::RENDER_PRIMITIVE_POINTS : primitive_rd_table[j]; - - for (int k = 0; k < SHADER_VERSION_MAX; k++) { - - RD::PipelineRasterizationState raster_state; - raster_state.cull_mode = cull_mode_rd; - raster_state.wireframe = wireframe; - - RD::PipelineColorBlendState blend_state; - RD::PipelineDepthStencilState depth_stencil = depth_stencil_state; - - if (uses_alpha || uses_blend_alpha) { - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { - blend_state = blend_state_blend; - if (depth_draw == DEPTH_DRAW_OPAQUE) { - depth_stencil.enable_depth_write = false; //alpha does not draw depth - } - } else if (uses_depth_pre_pass && (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL || k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS || k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL)) { - if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { - //none, blend state contains nothing - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - } else { - blend_state = blend_state_opaque; //writes to normal and roughness in opaque way - } - } else { - pipelines[i][j][k].clear(); - continue; // do not use this version (will error if using it is attempted) - } - } else { - - if (k == SHADER_VERSION_COLOR_PASS || k == SHADER_VERSION_VCT_COLOR_PASS || k == SHADER_VERSION_LIGHTMAP_COLOR_PASS) { - blend_state = blend_state_opaque; - } else if (k == SHADER_VERSION_DEPTH_PASS || k == SHADER_VERSION_DEPTH_PASS_DP) { - //none, leave empty - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL) { - blend_state = blend_state_depth_normal; - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS) { - blend_state = blend_state_depth_normal; - } else if (k == SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL) { - blend_state = RD::PipelineColorBlendState::create_disabled(5); //writes to normal and roughness in opaque way - - } else { - //specular write - blend_state = blend_state_opaque_specular; - } - } - - RID shader_variant = scene_singleton->shader.scene_shader.version_get_shader(version, k); - pipelines[i][j][k].setup(shader_variant, primitive_rd, raster_state, RD::PipelineMultisampleState(), depth_stencil, blend_state, 0); - } - } - } - - valid = true; -} - -void RasterizerSceneHighEndRD::ShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { - if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); - } else { - default_texture_params[p_name] = p_texture; - } -} - -void RasterizerSceneHighEndRD::ShaderData::get_param_list(List *p_param_list) const { - - Map order; - - for (Map::Element *E = uniforms.front(); E; E = E->next()) { - - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); - } else { - order[E->get().order] = E->key(); - } - } - - for (Map::Element *E = order.front(); E; E = E->next()) { - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); - p_param_list->push_back(pi); - } -} - -bool RasterizerSceneHighEndRD::ShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RasterizerSceneHighEndRD::ShaderData::is_animated() const { - return false; -} - -bool RasterizerSceneHighEndRD::ShaderData::casts_shadows() const { - return false; -} -Variant RasterizerSceneHighEndRD::ShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); - } - return Variant(); -} - -RasterizerSceneHighEndRD::ShaderData::ShaderData() { - valid = false; - uses_screen_texture = false; -} - -RasterizerSceneHighEndRD::ShaderData::~ShaderData() { - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; - ERR_FAIL_COND(!scene_singleton); - //pipeline variants will clear themselves if shader is gone - if (version.is_valid()) { - scene_singleton->shader.scene_shader.version_free(version); - } -} - -RasterizerStorageRD::ShaderData *RasterizerSceneHighEndRD::_create_shader_func() { - ShaderData *shader_data = memnew(ShaderData); - return shader_data; -} - -void RasterizerSceneHighEndRD::MaterialData::set_render_priority(int p_priority) { - priority = p_priority - VS::MATERIAL_RENDER_PRIORITY_MIN; //8 bits -} - -void RasterizerSceneHighEndRD::MaterialData::set_next_pass(RID p_pass) { - next_pass = p_pass; -} - -void RasterizerSceneHighEndRD::MaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - - RasterizerSceneHighEndRD *scene_singleton = (RasterizerSceneHighEndRD *)RasterizerSceneHighEndRD::singleton; - - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - - if (shader_data->ubo_size) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->shader.scene_shader.version_get_shader(shader_data->version, 0), MATERIAL_UNIFORM_SET); -} - -RasterizerSceneHighEndRD::MaterialData::~MaterialData() { - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } -} - -RasterizerStorageRD::MaterialData *RasterizerSceneHighEndRD::_create_material_func(ShaderData *p_shader) { - MaterialData *material_data = memnew(MaterialData); - material_data->shader_data = p_shader; - material_data->last_frame = false; - //update will happen later anyway so do nothing. - return material_data; -} - -RasterizerSceneHighEndRD::RenderBufferDataHighEnd::~RenderBufferDataHighEnd() { - clear(); -} - -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::ensure_specular() { - - if (!specular.is_valid()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = width; - tf.height = height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - specular = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - Vector fb; - fb.push_back(color); - fb.push_back(specular); - fb.push_back(depth); - - color_specular_fb = RD::get_singleton()->framebuffer_create(fb); - } -} - -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::clear() { - - if (specular.is_valid()) { - RD::get_singleton()->free(specular); - specular = RID(); - } - - color_specular_fb = RID(); - color_fb = RID(); - - if (normal_buffer.is_valid()) { - RD::get_singleton()->free(normal_buffer); - normal_buffer = RID(); - depth_normal_fb = RID(); - } - - if (roughness_buffer.is_valid()) { - RD::get_singleton()->free(roughness_buffer); - roughness_buffer = RID(); - depth_normal_roughness_fb = RID(); - } -} - -void RasterizerSceneHighEndRD::RenderBufferDataHighEnd::configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) { - clear(); - - width = p_width; - height = p_height; - - color = p_color_buffer; - depth = p_depth_buffer; - - { - Vector fb; - fb.push_back(p_color_buffer); - fb.push_back(depth); - - color_fb = RD::get_singleton()->framebuffer_create(fb); - } - { - Vector fb; - fb.push_back(depth); - - depth_fb = RD::get_singleton()->framebuffer_create(fb); - } -} - -void RasterizerSceneHighEndRD::_allocate_normal_texture(RenderBufferDataHighEnd *rb) { - if (rb->normal_buffer.is_valid()) { - return; - } - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_A2B10G10R10_UNORM_PACK32; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - rb->normal_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector fb; - fb.push_back(rb->depth); - fb.push_back(rb->normal_buffer); - rb->depth_normal_fb = RD::get_singleton()->framebuffer_create(fb); - - _render_buffers_clear_uniform_set(rb); -} - -void RasterizerSceneHighEndRD::_allocate_roughness_texture(RenderBufferDataHighEnd *rb) { - - if (rb->roughness_buffer.is_valid()) { - return; - } - - ERR_FAIL_COND(rb->normal_buffer.is_null()); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - rb->roughness_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector fb; - fb.push_back(rb->depth); - fb.push_back(rb->normal_buffer); - fb.push_back(rb->roughness_buffer); - rb->depth_normal_roughness_fb = RD::get_singleton()->framebuffer_create(fb); - - _render_buffers_clear_uniform_set(rb); -} - -RasterizerSceneRD::RenderBufferData *RasterizerSceneHighEndRD::_create_render_buffer_data() { - return memnew(RenderBufferDataHighEnd); -} - -bool RasterizerSceneHighEndRD::free(RID p_rid) { - if (RasterizerSceneRD::free(p_rid)) { - return true; - } - return false; -} - -void RasterizerSceneHighEndRD::_fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth) { - - for (int i = 0; i < p_element_count; i++) { - - const RenderList::Element *e = p_elements[i]; - InstanceData &id = scene_state.instances[i]; - store_transform(e->instance->transform, id.transform); - store_transform(Transform(e->instance->transform.basis.inverse().transposed()), id.normal_transform); - id.flags = 0; - id.mask = e->instance->layer_mask; - - if (e->instance->base_type == VS::INSTANCE_MULTIMESH) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH; - uint32_t stride; - if (storage->multimesh_get_transform_format(e->instance->base) == VS::MULTIMESH_TRANSFORM_2D) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D; - stride = 2; - } else { - stride = 3; - } - if (storage->multimesh_uses_colors(e->instance->base)) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR; - stride += 1; - } - if (storage->multimesh_uses_custom_data(e->instance->base)) { - id.flags |= INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA; - stride += 1; - } - - id.flags |= (stride << INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT); - } else if (e->instance->base_type == VS::INSTANCE_MESH) { - if (e->instance->skeleton.is_valid()) { - id.flags |= INSTANCE_DATA_FLAG_SKELETON; - } - } - - if (p_for_depth) { - id.gi_offset = 0xFFFFFFFF; - continue; - } - - if (!e->instance->gi_probe_instances.empty()) { - uint32_t written = 0; - for (int j = 0; j < e->instance->gi_probe_instances.size(); j++) { - RID probe = e->instance->gi_probe_instances[j]; - int slot = gi_probe_instance_get_slot(probe); - if (slot < 0) { - continue; //unallocated, dont render - } - - if (render_pass != gi_probe_instance_get_render_pass(probe)) { - continue; //not rendered in this frame - } - - uint32_t index = gi_probe_instance_get_render_index(probe); - - if (written == 0) { - id.gi_offset = index; - written = 1; - } else { - id.gi_offset = index << 16; - written = 2; - break; - } - } - if (written == 0) { - id.gi_offset = 0xFFFFFFFF; - } else if (written == 1) { - id.gi_offset |= 0xFFFF0000; - } - } else { - id.gi_offset = 0xFFFFFFFF; - } - } - - RD::get_singleton()->buffer_update(scene_state.instance_buffer, 0, sizeof(InstanceData) * p_element_count, scene_state.instances, true); -} - -/// RENDERING /// - -void RasterizerSceneHighEndRD::_render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set) { - - RD::DrawListID draw_list = p_draw_list; - RD::FramebufferFormatID framebuffer_format = p_framebuffer_Format; - - //global scope bindings - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, render_base_uniform_set, SCENE_UNIFORM_SET); - if (p_radiance_uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_radiance_uniform_set, RADIANCE_UNIFORM_SET); - } else { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_radiance_uniform_set, RADIANCE_UNIFORM_SET); - } - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, view_dependant_uniform_set, VIEW_DEPENDANT_UNIFORM_SET); - if (p_render_buffers_uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, p_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); - } else { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_render_buffers_uniform_set, RENDER_BUFFERS_UNIFORM_SET); - } - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, default_vec4_xform_uniform_set, TRANSFORMS_UNIFORM_SET); - - MaterialData *prev_material = nullptr; - - RID prev_vertex_array_rd; - RID prev_index_array_rd; - RID prev_pipeline_rd; - RID prev_xforms_uniform_set; - - PushConstant push_constant; - zeromem(&push_constant, sizeof(PushConstant)); - - for (int i = 0; i < p_element_count; i++) { - - const RenderList::Element *e = p_elements[i]; - - MaterialData *material = e->material; - ShaderData *shader = material->shader_data; - RID xforms_uniform_set; - - //find cull variant - ShaderData::CullVariant cull_variant; - - if ((p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_SHADOW_DP) && e->instance->cast_shadows == VS::SHADOW_CASTING_SETTING_DOUBLE_SIDED) { - cull_variant = ShaderData::CULL_VARIANT_DOUBLE_SIDED; - } else { - bool mirror = e->instance->mirror; - if (p_reverse_cull) { - mirror = !mirror; - } - cull_variant = mirror ? ShaderData::CULL_VARIANT_REVERSED : ShaderData::CULL_VARIANT_NORMAL; - } - - //find primitive and vertex format - VS::PrimitiveType primitive; - - switch (e->instance->base_type) { - case VS::INSTANCE_MESH: { - primitive = storage->mesh_surface_get_primitive(e->instance->base, e->surface_index); - if (e->instance->skeleton.is_valid()) { - xforms_uniform_set = storage->skeleton_get_3d_uniform_set(e->instance->skeleton, default_shader_rd, TRANSFORMS_UNIFORM_SET); - } - } break; - case VS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(e->instance->base); - ERR_CONTINUE(!mesh.is_valid()); //should be a bug - primitive = storage->mesh_surface_get_primitive(mesh, e->surface_index); - - xforms_uniform_set = storage->multimesh_get_3d_uniform_set(e->instance->base, default_shader_rd, TRANSFORMS_UNIFORM_SET); - - } break; - case VS::INSTANCE_IMMEDIATE: { - ERR_CONTINUE(true); //should be a bug - } break; - case VS::INSTANCE_PARTICLES: { - ERR_CONTINUE(true); //should be a bug - } break; - default: { - ERR_CONTINUE(true); //should be a bug - } - } - - ShaderVersion shader_version = SHADER_VERSION_MAX; // Assigned to silence wrong -Wmaybe-initialized. - - switch (p_pass_mode) { - case PASS_MODE_COLOR: - case PASS_MODE_COLOR_TRANSPARENT: { - if (e->uses_lightmap) { - shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS; - } else if (e->uses_vct) { - shader_version = SHADER_VERSION_VCT_COLOR_PASS; - } else { - shader_version = SHADER_VERSION_COLOR_PASS; - } - } break; - case PASS_MODE_COLOR_SPECULAR: { - if (e->uses_lightmap) { - shader_version = SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR; - } else if (e->uses_vct) { - shader_version = SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR; - } else { - shader_version = SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR; - } - } break; - case PASS_MODE_SHADOW: - case PASS_MODE_DEPTH: { - shader_version = SHADER_VERSION_DEPTH_PASS; - } break; - case PASS_MODE_SHADOW_DP: { - shader_version = SHADER_VERSION_DEPTH_PASS_DP; - } break; - case PASS_MODE_DEPTH_NORMAL: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL; - } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS; - } break; - case PASS_MODE_DEPTH_MATERIAL: { - shader_version = SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL; - } break; - } - - RenderPipelineVertexFormatCacheRD *pipeline = nullptr; - - pipeline = &shader->pipelines[cull_variant][primitive][shader_version]; - - RD::VertexFormatID vertex_format = -1; - RID vertex_array_rd; - RID index_array_rd; - - switch (e->instance->base_type) { - case VS::INSTANCE_MESH: { - storage->mesh_surface_get_arrays_and_format(e->instance->base, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); - } break; - case VS::INSTANCE_MULTIMESH: { - RID mesh = storage->multimesh_get_mesh(e->instance->base); - ERR_CONTINUE(!mesh.is_valid()); //should be a bug - storage->mesh_surface_get_arrays_and_format(mesh, e->surface_index, pipeline->get_vertex_input_mask(), vertex_array_rd, index_array_rd, vertex_format); - } break; - case VS::INSTANCE_IMMEDIATE: { - ERR_CONTINUE(true); //should be a bug - } break; - case VS::INSTANCE_PARTICLES: { - ERR_CONTINUE(true); //should be a bug - } break; - default: { - ERR_CONTINUE(true); //should be a bug - } - } - - if (prev_vertex_array_rd != vertex_array_rd) { - RD::get_singleton()->draw_list_bind_vertex_array(draw_list, vertex_array_rd); - prev_vertex_array_rd = vertex_array_rd; - } - - if (prev_index_array_rd != index_array_rd) { - if (index_array_rd.is_valid()) { - RD::get_singleton()->draw_list_bind_index_array(draw_list, index_array_rd); - } - prev_index_array_rd = index_array_rd; - } - - RID pipeline_rd = pipeline->get_render_pipeline(vertex_format, framebuffer_format); - - if (pipeline_rd != prev_pipeline_rd) { - // checking with prev shader does not make so much sense, as - // the pipeline may still be different. - RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, pipeline_rd); - prev_pipeline_rd = pipeline_rd; - } - - if (xforms_uniform_set.is_valid() && prev_xforms_uniform_set != xforms_uniform_set) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, xforms_uniform_set, TRANSFORMS_UNIFORM_SET); - prev_xforms_uniform_set = xforms_uniform_set; - } - - if (material != prev_material) { - //update uniform set - if (material->uniform_set.is_valid()) { - RD::get_singleton()->draw_list_bind_uniform_set(draw_list, material->uniform_set, MATERIAL_UNIFORM_SET); - } - - prev_material = material; - } - - push_constant.index = i; - RD::get_singleton()->draw_list_set_push_constant(draw_list, &push_constant, sizeof(PushConstant)); - - switch (e->instance->base_type) { - case VS::INSTANCE_MESH: { - RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid()); - } break; - case VS::INSTANCE_MULTIMESH: { - uint32_t instances = storage->multimesh_get_instances_to_draw(e->instance->base); - RD::get_singleton()->draw_list_draw(draw_list, index_array_rd.is_valid(), instances); - } break; - case VS::INSTANCE_IMMEDIATE: { - - } break; - case VS::INSTANCE_PARTICLES: { - - } break; - default: { - ERR_CONTINUE(true); //should be a bug - } - } - } -} - -void RasterizerSceneHighEndRD::_setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers) { - - //CameraMatrix projection = p_cam_projection; - //projection.flip_y(); // Vulkan and modern APIs use Y-Down - CameraMatrix correction; - correction.set_depth_correction(p_flip_y); - CameraMatrix projection = correction * p_cam_projection; - - //store camera into ubo - store_camera(projection, scene_state.ubo.projection_matrix); - store_camera(projection.inverse(), scene_state.ubo.inv_projection_matrix); - store_transform(p_cam_transform, scene_state.ubo.camera_matrix); - store_transform(p_cam_transform.affine_inverse(), scene_state.ubo.inv_camera_matrix); - - scene_state.ubo.z_far = p_zfar; - scene_state.ubo.z_near = p_znear; - - scene_state.ubo.screen_pixel_size[0] = p_screen_pixel_size.x; - scene_state.ubo.screen_pixel_size[1] = p_screen_pixel_size.y; - - if (p_shadow_atlas.is_valid()) { - Vector2 sas = shadow_atlas_get_size(p_shadow_atlas); - scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / sas.x; - scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / sas.y; - } - { - Vector2 dss = directional_shadow_get_size(); - scene_state.ubo.directional_shadow_pixel_size[0] = 1.0 / dss.x; - scene_state.ubo.directional_shadow_pixel_size[1] = 1.0 / dss.y; - } - //time global variables - scene_state.ubo.time = time; - - if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - - scene_state.ubo.use_ambient_light = true; - scene_state.ubo.ambient_light_color_energy[0] = 1; - scene_state.ubo.ambient_light_color_energy[1] = 1; - scene_state.ubo.ambient_light_color_energy[2] = 1; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - scene_state.ubo.use_ambient_cubemap = false; - scene_state.ubo.use_reflection_cubemap = false; - scene_state.ubo.ssao_enabled = false; - - } else if (is_environment(p_environment)) { - - VS::EnvironmentBG env_bg = environment_get_background(p_environment); - VS::EnvironmentAmbientSource ambient_src = environment_get_ambient_light_ambient_source(p_environment); - - float bg_energy = environment_get_bg_energy(p_environment); - scene_state.ubo.ambient_light_color_energy[3] = bg_energy; - - scene_state.ubo.ambient_color_sky_mix = environment_get_ambient_sky_contribution(p_environment); - - //ambient - if (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && (env_bg == VS::ENV_BG_CLEAR_COLOR || env_bg == VS::ENV_BG_COLOR)) { - - Color color = env_bg == VS::ENV_BG_CLEAR_COLOR ? p_default_bg_color : environment_get_bg_color(p_environment); - color = color.to_linear(); - - scene_state.ubo.ambient_light_color_energy[0] = color.r * bg_energy; - scene_state.ubo.ambient_light_color_energy[1] = color.g * bg_energy; - scene_state.ubo.ambient_light_color_energy[2] = color.b * bg_energy; - scene_state.ubo.use_ambient_light = true; - scene_state.ubo.use_ambient_cubemap = false; - } else { - - float energy = environment_get_ambient_light_ambient_energy(p_environment); - Color color = environment_get_ambient_light_color(p_environment); - color = color.to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = color.r * energy; - scene_state.ubo.ambient_light_color_energy[1] = color.g * energy; - scene_state.ubo.ambient_light_color_energy[2] = color.b * energy; - - Basis sky_transform = environment_get_sky_orientation(p_environment); - sky_transform = sky_transform.inverse() * p_cam_transform.basis; - store_transform_3x3(sky_transform, scene_state.ubo.radiance_inverse_xform); - - scene_state.ubo.use_ambient_cubemap = (ambient_src == VS::ENV_AMBIENT_SOURCE_BG && env_bg == VS::ENV_BG_SKY) || ambient_src == VS::ENV_AMBIENT_SOURCE_SKY; - scene_state.ubo.use_ambient_light = scene_state.ubo.use_ambient_cubemap || ambient_src == VS::ENV_AMBIENT_SOURCE_COLOR; - } - - //specular - VS::EnvironmentReflectionSource ref_src = environment_get_reflection_source(p_environment); - if ((ref_src == VS::ENV_REFLECTION_SOURCE_BG && env_bg == VS::ENV_BG_SKY) || ref_src == VS::ENV_REFLECTION_SOURCE_SKY) { - scene_state.ubo.use_reflection_cubemap = true; - } else { - scene_state.ubo.use_reflection_cubemap = false; - } - - scene_state.ubo.ssao_enabled = p_opaque_render_buffers && environment_is_ssao_enabled(p_environment); - scene_state.ubo.ssao_ao_affect = environment_get_ssao_ao_affect(p_environment); - scene_state.ubo.ssao_light_affect = environment_get_ssao_light_affect(p_environment); - - Color ao_color = environment_get_ao_color(p_environment); - scene_state.ubo.ao_color[0] = ao_color.r; - scene_state.ubo.ao_color[1] = ao_color.g; - scene_state.ubo.ao_color[2] = ao_color.b; - scene_state.ubo.ao_color[3] = ao_color.a; - - } else { - - if (p_reflection_probe.is_valid() && storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { - scene_state.ubo.use_ambient_light = false; - } else { - scene_state.ubo.use_ambient_light = true; - Color clear_color = p_default_bg_color; - clear_color = clear_color.to_linear(); - scene_state.ubo.ambient_light_color_energy[0] = clear_color.r; - scene_state.ubo.ambient_light_color_energy[1] = clear_color.g; - scene_state.ubo.ambient_light_color_energy[2] = clear_color.b; - scene_state.ubo.ambient_light_color_energy[3] = 1.0; - } - - scene_state.ubo.use_ambient_cubemap = false; - scene_state.ubo.use_reflection_cubemap = false; - } - - scene_state.ubo.roughness_limiter_enabled = p_opaque_render_buffers && screen_space_roughness_limiter_is_active(); - - RD::get_singleton()->buffer_update(scene_state.uniform_buffer, 0, sizeof(SceneState::UBO), &scene_state.ubo, true); -} - -void RasterizerSceneHighEndRD::_add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index) { - - RID m_src; - - m_src = p_instance->material_override.is_valid() ? p_instance->material_override : p_material; - - if (unlikely(get_debug_draw_mode() != VS::VIEWPORT_DEBUG_DRAW_DISABLED)) { - if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { - m_src = overdraw_material; - } else if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_WIREFRAME) { - m_src = wireframe_material; - } else if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_LIGHTING) { - m_src = default_material; - } - } - - MaterialData *material = NULL; - - if (m_src.is_valid()) { - material = (MaterialData *)storage->material_get_data(m_src, RasterizerStorageRD::SHADER_TYPE_3D); - if (!material || !material->shader_data->valid) { - material = NULL; - } - } - - if (!material) { - material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - m_src = default_material; - } - - ERR_FAIL_COND(!material); - - _add_geometry_with_material(p_instance, p_surface, material, m_src, p_pass_mode, p_geometry_index); - - while (material->next_pass.is_valid()) { - - material = (MaterialData *)storage->material_get_data(material->next_pass, RasterizerStorageRD::SHADER_TYPE_3D); - if (!material || !material->shader_data->valid) - break; - _add_geometry_with_material(p_instance, p_surface, material, material->next_pass, p_pass_mode, p_geometry_index); - } -} - -void RasterizerSceneHighEndRD::_add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index) { - - bool has_read_screen_alpha = p_material->shader_data->uses_screen_texture || p_material->shader_data->uses_depth_texture || p_material->shader_data->uses_normal_texture; - bool has_base_alpha = (p_material->shader_data->uses_alpha || has_read_screen_alpha); - bool has_blend_alpha = p_material->shader_data->uses_blend_alpha; - bool has_alpha = has_base_alpha || has_blend_alpha; - - if (p_material->shader_data->uses_sss) { - scene_state.used_sss = true; - } - - if (p_material->shader_data->uses_screen_texture) { - scene_state.used_screen_texture = true; - } - - if (p_material->shader_data->uses_depth_texture) { - scene_state.used_depth_texture = true; - } - - if (p_material->shader_data->uses_normal_texture) { - scene_state.used_normal_texture = true; - } - - if (p_pass_mode != PASS_MODE_COLOR && p_pass_mode != PASS_MODE_COLOR_SPECULAR) { - - if (has_blend_alpha || has_read_screen_alpha || (has_base_alpha && !p_material->shader_data->uses_depth_pre_pass) || p_material->shader_data->depth_draw == ShaderData::DEPTH_DRAW_DISABLED || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED || p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) { - //conditions in which no depth pass should be processed - return; - } - - if (p_pass_mode != PASS_MODE_DEPTH_MATERIAL && !p_material->shader_data->writes_modelview_or_projection && !p_material->shader_data->uses_vertex && !p_material->shader_data->uses_discard && !p_material->shader_data->uses_depth_pre_pass) { - //shader does not use discard and does not write a vertex position, use generic material - if (p_pass_mode == PASS_MODE_SHADOW || p_pass_mode == PASS_MODE_DEPTH) { - p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL && !p_material->shader_data->uses_normal) { - p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } else if (p_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS && !p_material->shader_data->uses_normal && !p_material->shader_data->uses_roughness) { - p_material = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - } - } - - has_alpha = false; - } - - RenderList::Element *e = (has_alpha || p_material->shader_data->depth_test == ShaderData::DEPTH_TEST_DISABLED) ? render_list.add_alpha_element() : render_list.add_element(); - - if (!e) - return; - - e->instance = p_instance; - e->material = p_material; - e->surface_index = p_surface; - e->sort_key = 0; - - if (e->material->last_pass != render_pass) { - if (!RD::get_singleton()->uniform_set_is_valid(e->material->uniform_set)) { - //uniform set no longer valid, probably a texture changed - storage->material_force_update_textures(p_material_rid, RasterizerStorageRD::SHADER_TYPE_3D); - } - e->material->last_pass = render_pass; - e->material->index = scene_state.current_material_index++; - if (e->material->shader_data->last_pass != render_pass) { - e->material->shader_data->last_pass = scene_state.current_material_index++; - e->material->shader_data->index = scene_state.current_shader_index++; - } - } - e->geometry_index = p_geometry_index; - e->material_index = e->material->index; - e->uses_instancing = e->instance->base_type == VS::INSTANCE_MULTIMESH; - e->uses_lightmap = e->instance->lightmap.is_valid(); - e->uses_vct = e->instance->gi_probe_instances.size(); - e->shader_index = e->shader_index; - e->depth_layer = e->instance->depth_layer; - e->priority = p_material->priority; - - if (p_material->shader_data->uses_time) { - VisualServerRaster::redraw_request(); - } -} - -void RasterizerSceneHighEndRD::_fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi) { - - scene_state.current_shader_index = 0; - scene_state.current_material_index = 0; - scene_state.used_sss = false; - scene_state.used_screen_texture = false; - scene_state.used_normal_texture = false; - scene_state.used_depth_texture = false; - - uint32_t geometry_index = 0; - - //fill list - - for (int i = 0; i < p_cull_count; i++) { - - InstanceBase *inst = p_cull_result[i]; - - //add geometry for drawing - switch (inst->base_type) { - - case VS::INSTANCE_MESH: { - - const RID *materials = NULL; - uint32_t surface_count; - - materials = storage->mesh_get_surface_count_and_materials(inst->base, surface_count); - if (!materials) { - continue; //nothing to do - } - - const RID *inst_materials = inst->materials.ptr(); - - for (uint32_t j = 0; j < surface_count; j++) { - - RID material = inst_materials[j].is_valid() ? inst_materials[j] : materials[j]; - - uint32_t surface_index = storage->mesh_surface_get_render_pass_index(inst->base, j, render_pass, &geometry_index); - _add_geometry(inst, j, material, p_pass_mode, surface_index); - } - - //mesh->last_pass=frame; - - } break; - - case VS::INSTANCE_MULTIMESH: { - - if (storage->multimesh_get_instances_to_draw(inst->base) == 0) { - //not visible, 0 instances - continue; - } - - RID mesh = storage->multimesh_get_mesh(inst->base); - if (!mesh.is_valid()) { - continue; - } - - const RID *materials = NULL; - uint32_t surface_count; - - materials = storage->mesh_get_surface_count_and_materials(mesh, surface_count); - if (!materials) { - continue; //nothing to do - } - - for (uint32_t j = 0; j < surface_count; j++) { - - uint32_t surface_index = storage->mesh_surface_get_multimesh_render_pass_index(mesh, j, render_pass, &geometry_index); - _add_geometry(inst, j, materials[j], p_pass_mode, surface_index); - } - - } break; -#if 0 - case VS::INSTANCE_IMMEDIATE: { - - RasterizerStorageGLES3::Immediate *immediate = storage->immediate_owner.getornull(inst->base); - ERR_CONTINUE(!immediate); - - _add_geometry(immediate, inst, NULL, -1, p_depth_pass, p_shadow_pass); - - } break; - case VS::INSTANCE_PARTICLES: { - - RasterizerStorageGLES3::Particles *particles = storage->particles_owner.getornull(inst->base); - ERR_CONTINUE(!particles); - - for (int j = 0; j < particles->draw_passes.size(); j++) { - - RID pmesh = particles->draw_passes[j]; - if (!pmesh.is_valid()) - continue; - RasterizerStorageGLES3::Mesh *mesh = storage->mesh_owner.getornull(pmesh); - if (!mesh) - continue; //mesh not assigned - - int ssize = mesh->surfaces.size(); - - for (int k = 0; k < ssize; k++) { - - RasterizerStorageGLES3::Surface *s = mesh->surfaces[k]; - _add_geometry(s, inst, particles, -1, p_depth_pass, p_shadow_pass); - } - } - - } break; -#endif - default: { - } - } - } -} - -void RasterizerSceneHighEndRD::_setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment) { - - for (int i = 0; i < p_reflection_probe_cull_count; i++) { - - RID rpi = p_reflection_probe_cull_result[i]; - - if (i >= (int)scene_state.max_reflections) { - reflection_probe_instance_set_render_index(rpi, 0); //invalid, but something needs to be set - continue; - } - - reflection_probe_instance_set_render_index(rpi, i); - - RID base_probe = reflection_probe_instance_get_probe(rpi); - - ReflectionData &reflection_ubo = scene_state.reflections[i]; - - Vector3 extents = storage->reflection_probe_get_extents(base_probe); - - reflection_ubo.box_extents[0] = extents.x; - reflection_ubo.box_extents[1] = extents.y; - reflection_ubo.box_extents[2] = extents.z; - reflection_ubo.index = reflection_probe_instance_get_atlas_index(rpi); - - Vector3 origin_offset = storage->reflection_probe_get_origin_offset(base_probe); - - reflection_ubo.box_offset[0] = origin_offset.x; - reflection_ubo.box_offset[1] = origin_offset.y; - reflection_ubo.box_offset[2] = origin_offset.z; - reflection_ubo.mask = storage->reflection_probe_get_cull_mask(base_probe); - - float intensity = storage->reflection_probe_get_intensity(base_probe); - bool interior = storage->reflection_probe_is_interior(base_probe); - bool box_projection = storage->reflection_probe_is_box_projection(base_probe); - - reflection_ubo.params[0] = intensity; - reflection_ubo.params[1] = 0; - reflection_ubo.params[2] = interior ? 1.0 : 0.0; - reflection_ubo.params[3] = box_projection ? 1.0 : 0.0; - - if (interior) { - Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear(); - float interior_ambient_energy = storage->reflection_probe_get_interior_ambient_energy(base_probe); - float interior_ambient_probe_contrib = storage->reflection_probe_get_interior_ambient_probe_contribution(base_probe); - reflection_ubo.ambient[0] = ambient_linear.r * interior_ambient_energy; - reflection_ubo.ambient[1] = ambient_linear.g * interior_ambient_energy; - reflection_ubo.ambient[2] = ambient_linear.b * interior_ambient_energy; - reflection_ubo.ambient[3] = interior_ambient_probe_contrib; - } else { - Color ambient_linear = storage->reflection_probe_get_interior_ambient(base_probe).to_linear(); - if (is_environment(p_environment)) { - Color env_ambient_color = environment_get_ambient_light_color(p_environment).to_linear(); - float env_ambient_energy = environment_get_ambient_light_ambient_energy(p_environment); - ambient_linear = env_ambient_color; - ambient_linear.r *= env_ambient_energy; - ambient_linear.g *= env_ambient_energy; - ambient_linear.b *= env_ambient_energy; - } - - reflection_ubo.ambient[0] = ambient_linear.r; - reflection_ubo.ambient[1] = ambient_linear.g; - reflection_ubo.ambient[2] = ambient_linear.b; - reflection_ubo.ambient[3] = 0; //not used in exterior mode, since it just blends with regular ambient light - } - - Transform transform = reflection_probe_instance_get_transform(rpi); - Transform proj = (p_camera_inverse_transform * transform).inverse(); - store_transform(proj, reflection_ubo.local_matrix); - - cluster_builder.add_reflection_probe(transform, extents); - - reflection_probe_instance_set_render_pass(rpi, render_pass); - } - - if (p_reflection_probe_cull_count) { - RD::get_singleton()->buffer_update(scene_state.reflection_buffer, 0, MIN(scene_state.max_reflections, (unsigned int)p_reflection_probe_cull_count) * sizeof(ReflectionData), scene_state.reflections, true); - } -} - -void RasterizerSceneHighEndRD::_setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform) { - - int index = 0; - - for (int i = 0; i < p_gi_probe_probe_cull_count; i++) { - - RID rpi = p_gi_probe_probe_cull_result[i]; - - if (index >= (int)scene_state.max_gi_probes) { - continue; - } - - int slot = gi_probe_instance_get_slot(rpi); - if (slot < 0) { - continue; //not usable - } - - RID base_probe = gi_probe_instance_get_base_probe(rpi); - - GIProbeData &gi_probe_ubo = scene_state.gi_probes[index]; - - Transform to_cell = gi_probe_instance_get_transform_to_cell(rpi) * p_camera_transform; - - store_transform(to_cell, gi_probe_ubo.xform); - - Vector3 bounds = storage->gi_probe_get_octree_size(base_probe); - - gi_probe_ubo.bounds[0] = bounds.x; - gi_probe_ubo.bounds[1] = bounds.y; - gi_probe_ubo.bounds[2] = bounds.z; - - gi_probe_ubo.dynamic_range = storage->gi_probe_get_dynamic_range(base_probe) * storage->gi_probe_get_energy(base_probe); - gi_probe_ubo.bias = storage->gi_probe_get_bias(base_probe); - gi_probe_ubo.normal_bias = storage->gi_probe_get_normal_bias(base_probe); - gi_probe_ubo.blend_ambient = !storage->gi_probe_is_interior(base_probe); - gi_probe_ubo.texture_slot = gi_probe_instance_get_slot(rpi); - gi_probe_ubo.anisotropy_strength = storage->gi_probe_get_anisotropy_strength(base_probe); - gi_probe_ubo.ao = storage->gi_probe_get_ao(base_probe); - gi_probe_ubo.ao_size = Math::pow(storage->gi_probe_get_ao_size(base_probe), 4.0f); - - if (gi_probe_is_anisotropic()) { - gi_probe_ubo.texture_slot *= 3; - } - - gi_probe_instance_set_render_index(rpi, index); - gi_probe_instance_set_render_pass(rpi, render_pass); - - index++; - } - - if (index) { - RD::get_singleton()->buffer_update(scene_state.gi_probe_buffer, 0, index * sizeof(GIProbeData), scene_state.gi_probes, true); - } -} - -void RasterizerSceneHighEndRD::_setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows) { - - uint32_t light_count = 0; - scene_state.ubo.directional_light_count = 0; - sky_scene_state.directional_light_count = 0; - - for (int i = 0; i < p_light_cull_count; i++) { - - RID li = p_light_cull_result[i]; - RID base = light_instance_get_base_light(li); - - ERR_CONTINUE(base.is_null()); - - VS::LightType type = storage->light_get_type(base); - switch (type) { - - case VS::LIGHT_DIRECTIONAL: { - - if (scene_state.ubo.directional_light_count >= scene_state.max_directional_lights) { - continue; - } - - DirectionalLightData &light_data = scene_state.directional_lights[scene_state.ubo.directional_light_count]; - - Transform light_transform = light_instance_get_base_transform(li); - - Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, 1))).normalized(); - - light_data.direction[0] = direction.x; - light_data.direction[1] = direction.y; - light_data.direction[2] = direction.z; - - float sign = storage->light_is_negative(base) ? -1 : 1; - - light_data.energy = sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI; - - Color linear_col = storage->light_get_color(base).to_linear(); - light_data.color[0] = linear_col.r; - light_data.color[1] = linear_col.g; - light_data.color[2] = linear_col.b; - - light_data.specular = storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR); - light_data.mask = storage->light_get_cull_mask(base); - - Color shadow_col = storage->light_get_shadow_color(base).to_linear(); - - light_data.shadow_color[0] = shadow_col.r; - light_data.shadow_color[1] = shadow_col.g; - light_data.shadow_color[2] = shadow_col.b; - - light_data.shadow_enabled = p_using_shadows && storage->light_has_shadow(base); - - if (light_data.shadow_enabled) { - - VS::LightDirectionalShadowMode smode = storage->light_directional_get_shadow_mode(base); - - int limit = smode == VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL ? 0 : (smode == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS ? 1 : 3); - light_data.blend_splits = storage->light_directional_get_blend_splits(base); - for (int j = 0; j < 4; j++) { - Rect2 atlas_rect = light_instance_get_directional_shadow_atlas_rect(li, j); - CameraMatrix matrix = light_instance_get_shadow_camera(li, j); - float split = light_instance_get_directional_shadow_split(li, MIN(limit, j)); - - CameraMatrix bias; - bias.set_light_bias(); - CameraMatrix rectm; - rectm.set_light_atlas_rect(atlas_rect); - - Transform modelview = (p_camera_inverse_transform * light_instance_get_shadow_transform(li, j)).inverse(); - - CameraMatrix shadow_mtx = rectm * bias * matrix * modelview; - light_data.shadow_split_offsets[j] = split; - store_camera(shadow_mtx, light_data.shadow_matrices[j]); - } - - float fade_start = storage->light_get_param(base, VS::LIGHT_PARAM_SHADOW_FADE_START); - light_data.fade_from = -light_data.shadow_split_offsets[3] * MIN(fade_start, 0.999); //using 1.0 would break smoothstep - light_data.fade_to = -light_data.shadow_split_offsets[3]; - } - - // Copy to SkyDirectionalLightData - if (sky_scene_state.directional_light_count < sky_scene_state.max_directional_lights) { - - SkyDirectionalLightData &sky_light_data = sky_scene_state.directional_lights[sky_scene_state.directional_light_count]; - - Vector3 world_direction = light_transform.basis.xform(Vector3(0, 0, 1)).normalized(); - - sky_light_data.direction[0] = world_direction.x; - sky_light_data.direction[1] = world_direction.y; - sky_light_data.direction[2] = -world_direction.z; - - sky_light_data.energy = light_data.energy / Math_PI; - - sky_light_data.color[0] = light_data.color[0]; - sky_light_data.color[1] = light_data.color[1]; - sky_light_data.color[2] = light_data.color[2]; - - sky_light_data.enabled = true; - sky_scene_state.directional_light_count++; - } - - scene_state.ubo.directional_light_count++; - } break; - case VS::LIGHT_SPOT: - case VS::LIGHT_OMNI: { - - if (light_count >= scene_state.max_lights) { - continue; - } - - Transform light_transform = light_instance_get_base_transform(li); - - LightData &light_data = scene_state.lights[light_count]; - - float sign = storage->light_is_negative(base) ? -1 : 1; - Color linear_col = storage->light_get_color(base).to_linear(); - - light_data.attenuation_energy[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_ATTENUATION)); - light_data.attenuation_energy[1] = Math::make_half_float(sign * storage->light_get_param(base, VS::LIGHT_PARAM_ENERGY) * Math_PI); - - light_data.color_specular[0] = MIN(uint32_t(linear_col.r * 255), 255); - light_data.color_specular[1] = MIN(uint32_t(linear_col.g * 255), 255); - light_data.color_specular[2] = MIN(uint32_t(linear_col.b * 255), 255); - light_data.color_specular[3] = MIN(uint32_t(storage->light_get_param(base, VS::LIGHT_PARAM_SPECULAR) * 255), 255); - - float radius = MAX(0.001, storage->light_get_param(base, VS::LIGHT_PARAM_RANGE)); - light_data.inv_radius = 1.0 / radius; - - Vector3 pos = p_camera_inverse_transform.xform(light_transform.origin); - - light_data.position[0] = pos.x; - light_data.position[1] = pos.y; - light_data.position[2] = pos.z; - - Vector3 direction = p_camera_inverse_transform.basis.xform(light_transform.basis.xform(Vector3(0, 0, -1))).normalized(); - - light_data.direction[0] = direction.x; - light_data.direction[1] = direction.y; - light_data.direction[2] = direction.z; - - light_data.cone_attenuation_angle[0] = Math::make_half_float(storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ATTENUATION)); - float spot_angle = storage->light_get_param(base, VS::LIGHT_PARAM_SPOT_ANGLE); - light_data.cone_attenuation_angle[1] = Math::make_half_float(Math::cos(Math::deg2rad(spot_angle))); - - light_data.mask = storage->light_get_cull_mask(base); - - Color shadow_color = storage->light_get_shadow_color(base); - - bool has_shadow = p_using_shadows && storage->light_has_shadow(base); - light_data.shadow_color_enabled[0] = MIN(uint32_t(shadow_color.r * 255), 255); - light_data.shadow_color_enabled[1] = MIN(uint32_t(shadow_color.g * 255), 255); - light_data.shadow_color_enabled[2] = MIN(uint32_t(shadow_color.b * 255), 255); - light_data.shadow_color_enabled[3] = has_shadow ? 255 : 0; - - light_data.atlas_rect[0] = 0; - light_data.atlas_rect[1] = 0; - light_data.atlas_rect[2] = 0; - light_data.atlas_rect[3] = 0; - - if (p_using_shadows && p_shadow_atlas.is_valid() && shadow_atlas_owns_light_instance(p_shadow_atlas, li)) { - // fill in the shadow information - - Rect2 rect = light_instance_get_shadow_atlas_rect(li, p_shadow_atlas); - - if (type == VS::LIGHT_OMNI) { - - light_data.atlas_rect[0] = rect.position.x; - light_data.atlas_rect[1] = rect.position.y; - light_data.atlas_rect[2] = rect.size.width; - light_data.atlas_rect[3] = rect.size.height * 0.5; - - Transform proj = (p_camera_inverse_transform * light_transform).inverse(); - - store_transform(proj, light_data.shadow_matrix); - } else if (type == VS::LIGHT_SPOT) { - - Transform modelview = (p_camera_inverse_transform * light_transform).inverse(); - CameraMatrix bias; - bias.set_light_bias(); - CameraMatrix rectm; - rectm.set_light_atlas_rect(rect); - - CameraMatrix shadow_mtx = rectm * bias * light_instance_get_shadow_camera(li, 0) * modelview; - store_camera(shadow_mtx, light_data.shadow_matrix); - } - } - - light_instance_set_index(li, light_count); - - cluster_builder.add_light(type == VS::LIGHT_SPOT ? LightClusterBuilder::LIGHT_TYPE_SPOT : LightClusterBuilder::LIGHT_TYPE_OMNI, light_transform, radius, spot_angle); - - light_count++; - } break; - } - - light_instance_set_render_pass(li, render_pass); - - //update UBO for forward rendering, blit to texture for clustered - } - - if (light_count) { - RD::get_singleton()->buffer_update(scene_state.light_buffer, 0, sizeof(LightData) * light_count, scene_state.lights, true); - } - - if (scene_state.ubo.directional_light_count) { - RD::get_singleton()->buffer_update(scene_state.directional_light_buffer, 0, sizeof(DirectionalLightData) * scene_state.ubo.directional_light_count, scene_state.directional_lights, true); - } -} - -void RasterizerSceneHighEndRD::_render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color) { - - RenderBufferDataHighEnd *render_buffer = NULL; - if (p_render_buffer.is_valid()) { - render_buffer = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffer); - } - - //first of all, make a new render pass - render_pass++; - - //fill up ubo -#if 0 - storage->info.render.object_count += p_cull_count; - - Environment *env = environment_owner.getornull(p_environment); - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - ReflectionAtlas *reflection_atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - - if (shadow_atlas && shadow_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 5); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_LESS); - scene_state.ubo.shadow_atlas_pixel_size[0] = 1.0 / shadow_atlas->size; - scene_state.ubo.shadow_atlas_pixel_size[1] = 1.0 / shadow_atlas->size; - } - - if (reflection_atlas && reflection_atlas->size) { - glActiveTexture(GL_TEXTURE0 + storage->config.max_texture_image_units - 3); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - } -#endif - - RENDER_TIMESTAMP("Setup 3D Scene"); - - if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_UNSHADED) { - p_light_cull_count = 0; - p_reflection_probe_cull_count = 0; - p_gi_probe_cull_count = 0; - } - - bool using_shadows = true; - - if (p_reflection_probe.is_valid()) { - scene_state.ubo.reflection_multiplier = 0.0; - if (!storage->reflection_probe_renders_shadows(reflection_probe_instance_get_probe(p_reflection_probe))) { - using_shadows = false; - } - } else { - scene_state.ubo.reflection_multiplier = 1.0; - } - - //scene_state.ubo.subsurface_scatter_width = subsurface_scatter_size; - - scene_state.ubo.shadow_z_offset = 0; - scene_state.ubo.shadow_z_slope_scale = 0; - - Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); - scene_state.ubo.viewport_size[0] = vp_he.x; - scene_state.ubo.viewport_size[1] = vp_he.y; - - Size2 screen_pixel_size; - Size2i screen_size; - RID opaque_framebuffer; - RID depth_framebuffer; - RID alpha_framebuffer; - - PassMode depth_pass_mode = PASS_MODE_DEPTH; - Vector depth_pass_clear; - - if (render_buffer) { - screen_pixel_size.width = 1.0 / render_buffer->width; - screen_pixel_size.height = 1.0 / render_buffer->height; - screen_size.x = render_buffer->width; - screen_size.y = render_buffer->height; - - opaque_framebuffer = render_buffer->color_fb; - - if (p_environment.is_valid() && environment_is_ssr_enabled(p_environment)) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL_ROUGHNESS; - } else if (screen_space_roughness_limiter_is_active()) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL; - //we need to allocate both these, if not allocated - _allocate_normal_texture(render_buffer); - _allocate_roughness_texture(render_buffer); - } else if (p_environment.is_valid() && (environment_is_ssao_enabled(p_environment) || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER)) { - depth_pass_mode = PASS_MODE_DEPTH_NORMAL; - } - - switch (depth_pass_mode) { - case PASS_MODE_DEPTH: { - depth_framebuffer = render_buffer->depth_fb; - } break; - case PASS_MODE_DEPTH_NORMAL: { - _allocate_normal_texture(render_buffer); - depth_framebuffer = render_buffer->depth_normal_fb; - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); - } break; - case PASS_MODE_DEPTH_NORMAL_ROUGHNESS: { - _allocate_normal_texture(render_buffer); - _allocate_roughness_texture(render_buffer); - depth_framebuffer = render_buffer->depth_normal_roughness_fb; - depth_pass_clear.push_back(Color(0.5, 0.5, 0.5, 0)); - depth_pass_clear.push_back(Color()); - } break; - default: { - }; - } - - alpha_framebuffer = opaque_framebuffer; - - } else if (p_reflection_probe.is_valid()) { - uint32_t resolution = reflection_probe_instance_get_resolution(p_reflection_probe); - screen_pixel_size.width = 1.0 / resolution; - screen_pixel_size.height = 1.0 / resolution; - screen_size.x = resolution; - screen_size.y = resolution; - - opaque_framebuffer = reflection_probe_instance_get_framebuffer(p_reflection_probe, p_reflection_probe_pass); - depth_framebuffer = reflection_probe_instance_get_depth_framebuffer(p_reflection_probe, p_reflection_probe_pass); - alpha_framebuffer = opaque_framebuffer; - - if (storage->reflection_probe_is_interior(reflection_probe_instance_get_probe(p_reflection_probe))) { - p_environment = RID(); //no environment on interiors - } - - } else { - ERR_FAIL(); //bug? - } - - cluster_builder.begin(p_cam_transform.affine_inverse(), p_cam_projection); //prepare cluster - - _setup_lights(p_light_cull_result, p_light_cull_count, p_cam_transform.affine_inverse(), p_shadow_atlas, using_shadows); - _setup_reflections(p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_cam_transform.affine_inverse(), p_environment); - _setup_gi_probes(p_gi_probe_cull_result, p_gi_probe_cull_count, p_cam_transform); - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); - - cluster_builder.bake_cluster(); //bake to cluster - - _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) - - render_list.clear(); - _fill_render_list(p_cull_result, p_cull_count, PASS_MODE_COLOR, render_buffer == nullptr); - - RID radiance_uniform_set; - bool draw_sky = false; - - Color clear_color; - bool keep_color = false; - - if (get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_OVERDRAW) { - clear_color = Color(0, 0, 0, 1); //in overdraw mode, BG should always be black - } else if (is_environment(p_environment)) { - VS::EnvironmentBG bg_mode = environment_get_background(p_environment); - float bg_energy = environment_get_bg_energy(p_environment); - switch (bg_mode) { - case VS::ENV_BG_CLEAR_COLOR: { - clear_color = p_default_bg_color; - clear_color.r *= bg_energy; - clear_color.g *= bg_energy; - clear_color.b *= bg_energy; - } break; - case VS::ENV_BG_COLOR: { - clear_color = environment_get_bg_color(p_environment); - clear_color.r *= bg_energy; - clear_color.g *= bg_energy; - clear_color.b *= bg_energy; - } break; - case VS::ENV_BG_SKY: { - RID sky = environment_get_sky(p_environment); - if (sky.is_valid()) { - - RENDER_TIMESTAMP("Setup Sky"); - CameraMatrix projection = p_cam_projection; - if (p_reflection_probe.is_valid()) { - CameraMatrix correction; - correction.set_depth_correction(true); - projection = correction * p_cam_projection; - } - - _setup_sky(p_environment, p_cam_transform.origin, screen_size); - _update_sky(p_environment, projection, p_cam_transform); - radiance_uniform_set = sky_get_radiance_uniform_set_rd(sky, default_shader_rd, RADIANCE_UNIFORM_SET); - - draw_sky = true; - } - } break; - case VS::ENV_BG_CANVAS: { - keep_color = true; - } break; - case VS::ENV_BG_KEEP: { - keep_color = true; - } break; - case VS::ENV_BG_CAMERA_FEED: { - - } break; - default: { - } - } - } else { - - clear_color = p_default_bg_color; - } - - _setup_view_dependant_uniform_set(p_shadow_atlas, p_reflection_atlas); - - render_list.sort_by_key(false); - - _fill_instances(render_list.elements, render_list.element_count, false); - - bool can_continue = true; //unless the middle buffers are needed - bool debug_giprobes = get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING || get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION; - bool using_separate_specular = false; - - bool depth_pre_pass = depth_framebuffer.is_valid(); - RID render_buffers_uniform_set; - - if (depth_pre_pass) { //depth pre pass - RENDER_TIMESTAMP("Render Depth Pre-Pass"); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_CONTINUE, depth_pass_clear); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(depth_framebuffer), render_list.elements, render_list.element_count, false, depth_pass_mode, render_buffer == nullptr, radiance_uniform_set, RID()); - RD::get_singleton()->draw_list_end(); - } - - if (p_render_buffer.is_valid() && p_environment.is_valid() && environment_is_ssao_enabled(p_environment)) { - _process_ssao(p_render_buffer, p_environment, render_buffer->normal_buffer, p_cam_projection); - } - - if (p_render_buffer.is_valid() && screen_space_roughness_limiter_is_active()) { - storage->get_effects()->roughness_limit(render_buffer->normal_buffer, render_buffer->roughness_buffer, Size2(render_buffer->width, render_buffer->height), screen_space_roughness_limiter_get_curve()); - } - - if (p_render_buffer.is_valid()) { - //update the render buffers uniform set in case it changed - _update_render_buffers_uniform_set(p_render_buffer); - render_buffers_uniform_set = render_buffer->uniform_set; - } - - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), p_render_buffer.is_valid()); - - RENDER_TIMESTAMP("Render Opaque Pass"); - - { - bool will_continue = (can_continue || draw_sky || debug_giprobes); - //regular forward for now - Vector c; - c.push_back(clear_color.to_linear()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, keep_color ? RD::INITIAL_ACTION_KEEP : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, depth_pre_pass ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_CLEAR, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, c, 1.0, 0); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(opaque_framebuffer), render_list.elements, render_list.element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); - RD::get_singleton()->draw_list_end(); - } - - if (debug_giprobes) { - //debug giprobes - bool will_continue = (can_continue || draw_sky); - CameraMatrix dc; - dc.set_depth_correction(true); - CameraMatrix cm = (dc * p_cam_projection) * CameraMatrix(p_cam_transform.affine_inverse()); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(opaque_framebuffer, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, will_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - for (int i = 0; i < p_gi_probe_cull_count; i++) { - _debug_giprobe(p_gi_probe_cull_result[i], draw_list, opaque_framebuffer, cm, get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, get_debug_draw_mode() == VS::VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, 1.0); - } - RD::get_singleton()->draw_list_end(); - } - - if (draw_sky) { - RENDER_TIMESTAMP("Render Sky"); - - CameraMatrix projection = p_cam_projection; - if (p_reflection_probe.is_valid()) { - CameraMatrix correction; - correction.set_depth_correction(true); - projection = correction * p_cam_projection; - } - - _draw_sky(can_continue, opaque_framebuffer, p_environment, projection, p_cam_transform); - - if (using_separate_specular && !can_continue) { - //can't continue, so close the buffers - //RD::get_singleton()->draw_list_begin(render_buffer->color_specular_fb, RD::INITIAL_ACTION_CONTINUE, RD::FINAL_ACTION_READ_COLOR_AND_DEPTH, c); - //RD::get_singleton()->draw_list_end(); - } - } - - RENDER_TIMESTAMP("Render Transparent Pass"); - - _setup_environment(p_environment, p_cam_projection, p_cam_transform, p_reflection_probe, p_reflection_probe.is_valid(), screen_pixel_size, p_shadow_atlas, !p_reflection_probe.is_valid(), p_default_bg_color, p_cam_projection.get_z_near(), p_cam_projection.get_z_far(), false); - - render_list.sort_by_reverse_depth_and_priority(true); - - _fill_instances(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false); - - { - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(alpha_framebuffer, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, can_continue ? RD::INITIAL_ACTION_CONTINUE : RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(alpha_framebuffer), &render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, false, PASS_MODE_COLOR, render_buffer == nullptr, radiance_uniform_set, render_buffers_uniform_set); - RD::get_singleton()->draw_list_end(); - } - - //_render_list -#if 0 - if (state.directional_light_count == 0) { - directional_light = NULL; - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, false, shadow_atlas != NULL); - } else { - for (int i = 0; i < state.directional_light_count; i++) { - directional_light = directional_lights[i]; - _setup_directional_light(i, p_cam_transform.affine_inverse(), shadow_atlas != NULL && shadow_atlas->size > 0); - _render_list(&render_list.elements[render_list.max_elements - render_list.alpha_element_count], render_list.alpha_element_count, p_cam_transform, p_cam_projection, env_radiance_tex, false, true, false, i > 0, shadow_atlas != NULL); - } - } -#endif - -#if 0 - _post_process(env, p_cam_projection); - // Needed only for debugging - /* if (shadow_atlas && storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, shadow_atlas->depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if (storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, exposure_shrink[4].color); - //glBindTexture(GL_TEXTURE_2D,storage->frame.current_rt->exposure.color); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 16, storage->frame.current_rt->height / 16), Rect2(0, 0, 1, 1)); - } - - if (reflection_atlas && storage->frame.current_rt) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, reflection_atlas->color); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if (directional_shadow.fbo) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, directional_shadow.depth); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - } - - if ( env_radiance_tex) { - - //_copy_texture_to_front_buffer(shadow_atlas->depth); - storage->canvas->canvas_begin(); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, env_radiance_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - storage->canvas->draw_generic_textured_rect(Rect2(0, 0, storage->frame.current_rt->width / 2, storage->frame.current_rt->height / 2), Rect2(0, 0, 1, 1)); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - }*/ - //disable all stuff -#endif -} -void RasterizerSceneHighEndRD::_render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip) { - - RENDER_TIMESTAMP("Setup Rendering Shadow"); - - _update_render_base_uniform_set(); - - render_pass++; - - scene_state.ubo.shadow_z_offset = p_bias; - scene_state.ubo.shadow_z_slope_scale = p_normal_bias; - scene_state.ubo.dual_paraboloid_side = p_use_dp_flip ? -1 : 1; - - _setup_environment(RID(), p_projection, p_transform, RID(), true, Vector2(1, 1), RID(), true, Color(), 0, p_zfar); - - render_list.clear(); - - PassMode pass_mode = p_use_dp ? PASS_MODE_SHADOW_DP : PASS_MODE_SHADOW; - - _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); - - _setup_view_dependant_uniform_set(RID(), RID()); - - RENDER_TIMESTAMP("Render Shadow"); - - render_list.sort_by_key(false); - - _fill_instances(render_list.elements, render_list.element_count, true); - - { - //regular forward for now - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, p_use_dp_flip, pass_mode, true, RID(), RID()); - RD::get_singleton()->draw_list_end(); - } -} - -void RasterizerSceneHighEndRD::_render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { - RENDER_TIMESTAMP("Setup Rendering Shadow"); - - _update_render_base_uniform_set(); - - render_pass++; - - scene_state.ubo.shadow_z_offset = 0; - scene_state.ubo.shadow_z_slope_scale = 0; - scene_state.ubo.dual_paraboloid_side = 0; - - _setup_environment(RID(), p_cam_projection, p_cam_transform, RID(), true, Vector2(1, 1), RID(), false, Color(), 0, 0); - - render_list.clear(); - - PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; - _fill_render_list(p_cull_result, p_cull_count, pass_mode, true); - - _setup_view_dependant_uniform_set(RID(), RID()); - - RENDER_TIMESTAMP("Render Material"); - - render_list.sort_by_key(false); - - _fill_instances(render_list.elements, render_list.element_count, true); - - { - //regular forward for now - Vector clear; - clear.push_back(Color(0, 0, 0, 0)); - clear.push_back(Color(0, 0, 0, 0)); - clear.push_back(Color(0, 0, 0, 0)); - clear.push_back(Color(0, 0, 0, 0)); - clear.push_back(Color(0, 0, 0, 0)); - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, clear, 1.0, 0, p_region); - _render_list(draw_list, RD::get_singleton()->framebuffer_get_format(p_framebuffer), render_list.elements, render_list.element_count, true, pass_mode, true, RID(), RID()); - RD::get_singleton()->draw_list_end(); - } -} - -void RasterizerSceneHighEndRD::_base_uniforms_changed() { - - if (!render_base_uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { - RD::get_singleton()->free(render_base_uniform_set); - } - render_base_uniform_set = RID(); -} - -void RasterizerSceneHighEndRD::_update_render_base_uniform_set() { - - if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { - - if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { - RD::get_singleton()->free(render_base_uniform_set); - } - - Vector uniforms; - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 1; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); - ids_ptr[0] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 2; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.ids.push_back(shadow_sampler); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 3; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.uniform_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 4; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(scene_state.instance_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 5; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.light_buffer); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 6; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.reflection_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 7; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.directional_light_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 8; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(scene_state.gi_probe_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 9; - u.type = RD::UNIFORM_TYPE_TEXTURE; - int slot_count = gi_probe_get_slots().size(); - if (gi_probe_is_anisotropic()) { - u.ids.resize(slot_count * 3); - } else { - u.ids.resize(slot_count); - } - - for (int i = 0; i < slot_count; i++) { - - RID probe = gi_probe_get_slots()[i]; - - if (gi_probe_is_anisotropic()) { - if (probe.is_null()) { - RID empty_tex = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - u.ids.write[i * 3 + 0] = empty_tex; - u.ids.write[i * 3 + 1] = empty_tex; - u.ids.write[i * 3 + 2] = empty_tex; - } else { - u.ids.write[i * 3 + 0] = gi_probe_instance_get_texture(probe); - u.ids.write[i * 3 + 1] = gi_probe_instance_get_aniso_texture(probe, 0); - u.ids.write[i * 3 + 2] = gi_probe_instance_get_aniso_texture(probe, 1); - } - } else { - if (probe.is_null()) { - u.ids.write[i] = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - } else { - u.ids.write[i] = gi_probe_instance_get_texture(probe); - } - } - } - - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 10; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.ids.push_back(cluster_builder.get_cluster_texture()); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 11; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(cluster_builder.get_cluster_indices_buffer()); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 12; - u.type = RD::UNIFORM_TYPE_TEXTURE; - if (directional_shadow_get_texture().is_valid()) { - u.ids.push_back(directional_shadow_get_texture()); - } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - } - uniforms.push_back(u); - } - - render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, SCENE_UNIFORM_SET); - } -} - -void RasterizerSceneHighEndRD::_setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas) { - - if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { - RD::get_singleton()->free(view_dependant_uniform_set); - } - - //default render buffer and scene state uniform set - - Vector uniforms; - - { - - RID ref_texture = p_reflection_atlas.is_valid() ? reflection_atlas_get_texture(p_reflection_atlas) : RID(); - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - if (ref_texture.is_valid()) { - u.ids.push_back(ref_texture); - } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK)); - } - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture; - if (p_shadow_atlas.is_valid()) { - texture = shadow_atlas_get_texture(p_shadow_atlas); - } - if (!texture.is_valid()) { - texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - } - u.ids.push_back(texture); - uniforms.push_back(u); - } - - view_dependant_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, VIEW_DEPENDANT_UNIFORM_SET); -} - -void RasterizerSceneHighEndRD::_render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb) { - - if (!rb->uniform_set.is_null() && RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { - RD::get_singleton()->free(rb->uniform_set); - } - rb->uniform_set = RID(); -} - -void RasterizerSceneHighEndRD::_render_buffers_uniform_set_changed(RID p_render_buffers) { - - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - _render_buffers_clear_uniform_set(rb); -} - -RID RasterizerSceneHighEndRD::_render_buffers_get_roughness_texture(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - return rb->roughness_buffer; -} - -RID RasterizerSceneHighEndRD::_render_buffers_get_normal_texture(RID p_render_buffers) { - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - return rb->normal_buffer; -} - -void RasterizerSceneHighEndRD::_update_render_buffers_uniform_set(RID p_render_buffers) { - - RenderBufferDataHighEnd *rb = (RenderBufferDataHighEnd *)render_buffers_get_data(p_render_buffers); - - if (rb->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(rb->uniform_set)) { - - Vector uniforms; - { - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = false && rb->depth.is_valid() ? rb->depth : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 1; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID bbt = render_buffers_get_back_buffer_texture(p_render_buffers); - RID texture = bbt.is_valid() ? bbt : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.binding = 2; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->normal_buffer.is_valid() ? rb->normal_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL); - u.ids.push_back(texture); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 3; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = rb->roughness_buffer.is_valid() ? rb->roughness_buffer : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.binding = 4; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID aot = render_buffers_get_ao_texture(p_render_buffers); - RID texture = aot.is_valid() ? aot : storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - } - - rb->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); - } -} - -RasterizerSceneHighEndRD *RasterizerSceneHighEndRD::singleton = NULL; - -void RasterizerSceneHighEndRD::set_time(double p_time, double p_step) { - time = p_time; - RasterizerSceneRD::set_time(p_time, p_step); -} - -RasterizerSceneHighEndRD::RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage) : - RasterizerSceneRD(p_storage) { - singleton = this; - storage = p_storage; - - /* SCENE SHADER */ - - { - String defines; - defines += "\n#define MAX_ROUGHNESS_LOD " + itos(get_roughness_layers() - 1) + ".0\n"; - if (is_using_radiance_cubemap_array()) { - defines += "\n#define USE_RADIANCE_CUBEMAP_ARRAY \n"; - } - - uint32_t uniform_max_size = RD::get_singleton()->limit_get(RD::LIMIT_MAX_UNIFORM_BUFFER_SIZE); - - { //reflections - uint32_t reflection_buffer_size; - if (uniform_max_size < 65536) { - //Yes, you guessed right, ARM again - reflection_buffer_size = uniform_max_size; - } else { - reflection_buffer_size = 65536; - } - - scene_state.max_reflections = reflection_buffer_size / sizeof(ReflectionData); - scene_state.reflections = memnew_arr(ReflectionData, scene_state.max_reflections); - scene_state.reflection_buffer = RD::get_singleton()->uniform_buffer_create(reflection_buffer_size); - defines += "\n#define MAX_REFLECTION_DATA_STRUCTS " + itos(scene_state.max_reflections) + "\n"; - } - - { //lights - scene_state.max_lights = MIN(65536, uniform_max_size) / sizeof(LightData); - uint32_t light_buffer_size = scene_state.max_lights * sizeof(LightData); - scene_state.lights = memnew_arr(LightData, scene_state.max_lights); - scene_state.light_buffer = RD::get_singleton()->uniform_buffer_create(light_buffer_size); - defines += "\n#define MAX_LIGHT_DATA_STRUCTS " + itos(scene_state.max_lights) + "\n"; - - scene_state.max_directional_lights = 8; - uint32_t directional_light_buffer_size = scene_state.max_directional_lights * sizeof(DirectionalLightData); - scene_state.directional_lights = memnew_arr(DirectionalLightData, scene_state.max_directional_lights); - scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); - defines += "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(scene_state.max_directional_lights) + "\n"; - } - - { //giprobes - int slot_count = gi_probe_get_slots().size(); - if (gi_probe_is_anisotropic()) { - slot_count *= 3; - defines += "\n#define GI_PROBE_USE_ANISOTROPY\n"; - } - - if (gi_probe_get_quality() == GIPROBE_QUALITY_ULTRA_LOW) { - defines += "\n#define GI_PROBE_LOW_QUALITY\n"; - } else if (gi_probe_get_quality() == GIPROBE_QUALITY_HIGH) { - defines += "\n#define GI_PROBE_HIGH_QUALITY\n"; - } - - defines += "\n#define MAX_GI_PROBE_TEXTURES " + itos(slot_count) + "\n"; - - uint32_t giprobe_buffer_size; - if (uniform_max_size < 65536) { - //Yes, you guessed right, ARM again - giprobe_buffer_size = uniform_max_size; - } else { - giprobe_buffer_size = 65536; - } - - giprobe_buffer_size = MIN(sizeof(GIProbeData) * gi_probe_get_slots().size(), giprobe_buffer_size); - scene_state.max_gi_probes = giprobe_buffer_size / sizeof(GIProbeData); - scene_state.gi_probes = memnew_arr(GIProbeData, scene_state.max_gi_probes); - scene_state.gi_probe_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(GIProbeData) * scene_state.max_gi_probes); - defines += "\n#define MAX_GI_PROBES " + itos(scene_state.max_gi_probes) + "\n"; - } - - Vector shader_versions; - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_DUAL_PARABOLOID\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_NORMAL\n#define MODE_RENDER_ROUGHNESS\n"); - shader_versions.push_back("\n#define MODE_RENDER_DEPTH\n#define MODE_RENDER_MATERIAL\n"); - shader_versions.push_back(""); - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n"); - shader_versions.push_back("\n#define USE_VOXEL_CONE_TRACING\n"); - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_VOXEL_CONE_TRACING\n"); - shader_versions.push_back("\n#define USE_LIGHTMAP\n"); - shader_versions.push_back("\n#define MODE_MULTIPLE_RENDER_TARGETS\n#define USE_LIGHTMAP\n"); - shader.scene_shader.initialize(shader_versions, defines); - } - - storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_shader_funcs); - storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_3D, _create_material_funcs); - - { - //shader compiler - ShaderCompilerRD::DefaultIdentifierActions actions; - - actions.renames["WORLD_MATRIX"] = "world_matrix"; - actions.renames["WORLD_NORMAL_MATRIX"] = "world_normal_matrix"; - actions.renames["INV_CAMERA_MATRIX"] = "scene_data.inv_camera_matrix"; - actions.renames["CAMERA_MATRIX"] = "scene_data.camera_matrix"; - actions.renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions.renames["INV_PROJECTION_MATRIX"] = "scene_data.inv_projection_matrix"; - actions.renames["MODELVIEW_MATRIX"] = "modelview"; - actions.renames["MODELVIEW_NORMAL_MATRIX"] = "modelview_normal"; - - actions.renames["VERTEX"] = "vertex"; - actions.renames["NORMAL"] = "normal"; - actions.renames["TANGENT"] = "tangent"; - actions.renames["BINORMAL"] = "binormal"; - actions.renames["POSITION"] = "position"; - actions.renames["UV"] = "uv_interp"; - actions.renames["UV2"] = "uv2_interp"; - actions.renames["COLOR"] = "color_interp"; - actions.renames["POINT_SIZE"] = "gl_PointSize"; - actions.renames["INSTANCE_ID"] = "gl_InstanceIndex"; - - //builtins - - actions.renames["TIME"] = "scene_data.time"; - actions.renames["VIEWPORT_SIZE"] = "scene_data.viewport_size"; - - actions.renames["FRAGCOORD"] = "gl_FragCoord"; - actions.renames["FRONT_FACING"] = "gl_FrontFacing"; - actions.renames["NORMALMAP"] = "normalmap"; - actions.renames["NORMALMAP_DEPTH"] = "normaldepth"; - actions.renames["ALBEDO"] = "albedo"; - actions.renames["ALPHA"] = "alpha"; - actions.renames["METALLIC"] = "metallic"; - actions.renames["SPECULAR"] = "specular"; - actions.renames["ROUGHNESS"] = "roughness"; - actions.renames["RIM"] = "rim"; - actions.renames["RIM_TINT"] = "rim_tint"; - actions.renames["CLEARCOAT"] = "clearcoat"; - actions.renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions.renames["ANISOTROPY"] = "anisotropy"; - actions.renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions.renames["SSS_STRENGTH"] = "sss_strength"; - actions.renames["TRANSMISSION"] = "transmission"; - actions.renames["AO"] = "ao"; - actions.renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions.renames["EMISSION"] = "emission"; - actions.renames["POINT_COORD"] = "gl_PointCoord"; - actions.renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions.renames["SCREEN_UV"] = "screen_uv"; - actions.renames["SCREEN_TEXTURE"] = "color_buffer"; - actions.renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions.renames["NORMAL_TEXTURE"] = "normal_buffer"; - actions.renames["DEPTH"] = "gl_FragDepth"; - actions.renames["OUTPUT_IS_SRGB"] = "true"; - - //for light - actions.renames["VIEW"] = "view"; - actions.renames["LIGHT_COLOR"] = "light_color"; - actions.renames["LIGHT"] = "light"; - actions.renames["ATTENUATION"] = "attenuation"; - actions.renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions.renames["SPECULAR_LIGHT"] = "specular_light"; - - actions.usage_defines["TANGENT"] = "#define TANGENT_USED\n"; - actions.usage_defines["BINORMAL"] = "@TANGENT"; - actions.usage_defines["RIM"] = "#define LIGHT_RIM_USED\n"; - actions.usage_defines["RIM_TINT"] = "@RIM"; - actions.usage_defines["CLEARCOAT"] = "#define LIGHT_CLEARCOAT_USED\n"; - actions.usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions.usage_defines["ANISOTROPY"] = "#define LIGHT_ANISOTROPY_USED\n"; - actions.usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions.usage_defines["AO"] = "#define AO_USED\n"; - actions.usage_defines["AO_LIGHT_AFFECT"] = "#define AO_USED\n"; - actions.usage_defines["UV"] = "#define UV_USED\n"; - actions.usage_defines["UV2"] = "#define UV2_USED\n"; - actions.usage_defines["NORMALMAP"] = "#define NORMALMAP_USED\n"; - actions.usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; - actions.usage_defines["COLOR"] = "#define COLOR_USED\n"; - actions.usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions.usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions.usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions.usage_defines["TRANSMISSION"] = "#define LIGHT_TRANSMISSION_USED\n"; - actions.usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions.usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions.usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions.usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - - actions.render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions.render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; - actions.render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; - actions.render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - actions.render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; - - bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); - - if (!force_lambert) { - actions.render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; - } - - actions.render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; - actions.render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions.render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; - - bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx"); - - if (!force_blinn) { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions.render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } - - actions.render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions.render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions.render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions.render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions.render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions.render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions.render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; - actions.render_mode_defines["unshaded"] = "#define MODE_UNSHADED\n"; - - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = MATERIAL_UNIFORM_SET; - actions.base_uniform_string = "material."; - actions.base_varying_index = 10; - - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; - actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - - shader.compiler.initialize(actions); - } - - //render list - render_list.max_elements = GLOBAL_DEF_RST("rendering/limits/rendering/max_renderable_elements", (int)128000); - render_list.init(); - render_pass = 0; - - { - - scene_state.max_instances = render_list.max_elements; - scene_state.instances = memnew_arr(InstanceData, scene_state.max_instances); - scene_state.instance_buffer = RD::get_singleton()->storage_buffer_create(sizeof(InstanceData) * scene_state.max_instances); - } - - scene_state.uniform_buffer = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); - - { - //default material and shader - default_shader = storage->shader_create(); - storage->shader_set_code(default_shader, "shader_type spatial; void vertex() { ROUGHNESS = 0.8; } void fragment() { ALBEDO=vec3(0.6); ROUGHNESS=0.8; METALLIC=0.2; } \n"); - default_material = storage->material_create(); - storage->material_set_shader(default_material, default_shader); - - MaterialData *md = (MaterialData *)storage->material_get_data(default_material, RasterizerStorageRD::SHADER_TYPE_3D); - default_shader_rd = shader.scene_shader.version_get_shader(md->shader_data->version, SHADER_VERSION_COLOR_PASS); - } - - { - - overdraw_material_shader = storage->shader_create(); - storage->shader_set_code(overdraw_material_shader, "shader_type spatial;\nrender_mode blend_add,unshaded;\n void fragment() { ALBEDO=vec3(0.4,0.8,0.8); ALPHA=0.2; }"); - overdraw_material = storage->material_create(); - storage->material_set_shader(overdraw_material, overdraw_material_shader); - - wireframe_material_shader = storage->shader_create(); - storage->shader_set_code(wireframe_material_shader, "shader_type spatial;\nrender_mode wireframe,unshaded;\n void fragment() { ALBEDO=vec3(0.0,0.0,0.0); }"); - wireframe_material = storage->material_create(); - storage->material_set_shader(wireframe_material, wireframe_material_shader); - } - - { - default_vec4_xform_buffer = RD::get_singleton()->storage_buffer_create(256); - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.ids.push_back(default_vec4_xform_buffer); - u.binding = 0; - uniforms.push_back(u); - - default_vec4_xform_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, TRANSFORMS_UNIFORM_SET); - } - { - - RD::SamplerState sampler; - sampler.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler.enable_compare = true; - sampler.compare_op = RD::COMPARE_OP_LESS; - shadow_sampler = RD::get_singleton()->sampler_create(sampler); - } - - { - Vector uniforms; - - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(is_using_radiance_cubemap_array() ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK : RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK); - u.ids.push_back(texture); - uniforms.push_back(u); - - default_radiance_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RADIANCE_UNIFORM_SET); - } - - { //render buffers - Vector uniforms; - for (int i = 0; i < 5; i++) { - RD::Uniform u; - u.binding = i; - u.type = RD::UNIFORM_TYPE_TEXTURE; - RID texture = storage->texture_rd_get_default(i == 0 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE : (i == 2 ? RasterizerStorageRD::DEFAULT_RD_TEXTURE_NORMAL : RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK)); - u.ids.push_back(texture); - uniforms.push_back(u); - } - - default_render_buffers_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, default_shader_rd, RENDER_BUFFERS_UNIFORM_SET); - } - - cluster_builder.setup(16, 8, 24); -} - -RasterizerSceneHighEndRD::~RasterizerSceneHighEndRD() { - directional_shadow_atlas_set_size(0); - - //clear base uniform set if still valid - if (view_dependant_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(view_dependant_uniform_set)) { - RD::get_singleton()->free(view_dependant_uniform_set); - } - - RD::get_singleton()->free(default_render_buffers_uniform_set); - RD::get_singleton()->free(default_radiance_uniform_set); - RD::get_singleton()->free(default_vec4_xform_buffer); - RD::get_singleton()->free(shadow_sampler); - - storage->free(wireframe_material_shader); - storage->free(overdraw_material_shader); - storage->free(default_shader); - - storage->free(wireframe_material); - storage->free(overdraw_material); - storage->free(default_material); - - { - RD::get_singleton()->free(scene_state.uniform_buffer); - RD::get_singleton()->free(scene_state.instance_buffer); - RD::get_singleton()->free(scene_state.gi_probe_buffer); - RD::get_singleton()->free(scene_state.directional_light_buffer); - RD::get_singleton()->free(scene_state.light_buffer); - RD::get_singleton()->free(scene_state.reflection_buffer); - memdelete_arr(scene_state.instances); - memdelete_arr(scene_state.gi_probes); - memdelete_arr(scene_state.directional_lights); - memdelete_arr(scene_state.lights); - memdelete_arr(scene_state.reflections); - } -} diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h deleted file mode 100644 index 960b95ee86..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_scene_high_end_rd.h +++ /dev/null @@ -1,585 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_high_end_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_SCENE_HIGHEND_RD_H -#define RASTERIZER_SCENE_HIGHEND_RD_H - -#include "servers/visual/rasterizer_rd/light_cluster_builder.h" -#include "servers/visual/rasterizer_rd/rasterizer_scene_rd.h" -#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" -#include "servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h" -#include "servers/visual/rasterizer_rd/shaders/scene_high_end.glsl.gen.h" - -class RasterizerSceneHighEndRD : public RasterizerSceneRD { - - enum { - SCENE_UNIFORM_SET = 0, - RADIANCE_UNIFORM_SET = 1, - VIEW_DEPENDANT_UNIFORM_SET = 2, - RENDER_BUFFERS_UNIFORM_SET = 3, - TRANSFORMS_UNIFORM_SET = 4, - MATERIAL_UNIFORM_SET = 5 - }; - - /* Scene Shader */ - - enum ShaderVersion { - SHADER_VERSION_DEPTH_PASS, - SHADER_VERSION_DEPTH_PASS_DP, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL, - SHADER_VERSION_DEPTH_PASS_WITH_NORMAL_AND_ROUGHNESS, - SHADER_VERSION_DEPTH_PASS_WITH_MATERIAL, - SHADER_VERSION_COLOR_PASS, - SHADER_VERSION_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_VCT_COLOR_PASS, - SHADER_VERSION_VCT_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_LIGHTMAP_COLOR_PASS, - SHADER_VERSION_LIGHTMAP_COLOR_PASS_WITH_SEPARATE_SPECULAR, - SHADER_VERSION_MAX - }; - - struct { - SceneHighEndShaderRD scene_shader; - ShaderCompilerRD compiler; - } shader; - - RasterizerStorageRD *storage; - - /* Material */ - - struct ShaderData : public RasterizerStorageRD::ShaderData { - - enum BlendMode { //used internally - BLEND_MODE_MIX, - BLEND_MODE_ADD, - BLEND_MODE_SUB, - BLEND_MODE_MUL, - }; - - enum DepthDraw { - DEPTH_DRAW_DISABLED, - DEPTH_DRAW_OPAQUE, - DEPTH_DRAW_ALWAYS - }; - - enum DepthTest { - DEPTH_TEST_DISABLED, - DEPTH_TEST_ENABLED - }; - - enum Cull { - CULL_DISABLED, - CULL_FRONT, - CULL_BACK - }; - - enum CullVariant { - CULL_VARIANT_NORMAL, - CULL_VARIANT_REVERSED, - CULL_VARIANT_DOUBLE_SIDED, - CULL_VARIANT_MAX - - }; - - bool valid; - RID version; - uint32_t vertex_input_mask; - RenderPipelineVertexFormatCacheRD pipelines[CULL_VARIANT_MAX][VS::PRIMITIVE_MAX][SHADER_VERSION_MAX]; - - String path; - - Map uniforms; - Vector texture_uniforms; - - Vector ubo_offsets; - uint32_t ubo_size; - - String code; - Map default_texture_params; - - DepthDraw depth_draw; - DepthTest depth_test; - - bool uses_point_size; - bool uses_alpha; - bool uses_blend_alpha; - bool uses_depth_pre_pass; - bool uses_discard; - bool uses_roughness; - bool uses_normal; - - bool unshaded; - bool uses_vertex; - bool uses_sss; - bool uses_screen_texture; - bool uses_depth_texture; - bool uses_normal_texture; - bool uses_time; - bool writes_modelview_or_projection; - bool uses_world_coordinates; - - uint64_t last_pass = 0; - uint32_t index = 0; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); - virtual void get_param_list(List *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; - virtual bool is_animated() const; - virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; - ShaderData(); - virtual ~ShaderData(); - }; - - RasterizerStorageRD::ShaderData *_create_shader_func(); - static RasterizerStorageRD::ShaderData *_create_shader_funcs() { - return static_cast(singleton)->_create_shader_func(); - } - - struct MaterialData : public RasterizerStorageRD::MaterialData { - uint64_t last_frame; - ShaderData *shader_data; - RID uniform_buffer; - RID uniform_set; - Vector texture_cache; - Vector ubo_data; - uint64_t last_pass = 0; - uint32_t index = 0; - RID next_pass; - uint8_t priority; - virtual void set_render_priority(int p_priority); - virtual void set_next_pass(RID p_pass); - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~MaterialData(); - }; - - RasterizerStorageRD::MaterialData *_create_material_func(ShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast(singleton)->_create_material_func(static_cast(p_shader)); - } - - /* Push Constant */ - - struct PushConstant { - uint32_t index; - uint32_t pad[3]; - }; - - /* Framebuffer */ - - struct RenderBufferDataHighEnd : public RenderBufferData { - //for rendering, may be MSAAd - RID color; - RID depth; - RID specular; - RID normal_buffer; - RID roughness_buffer; - RID depth_fb; - RID depth_normal_fb; - RID depth_normal_roughness_fb; - RID color_fb; - RID color_specular_fb; - int width, height; - - void ensure_specular(); - void clear(); - virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa); - - RID uniform_set; - - ~RenderBufferDataHighEnd(); - }; - - virtual RenderBufferData *_create_render_buffer_data(); - void _allocate_normal_texture(RenderBufferDataHighEnd *rb); - void _allocate_roughness_texture(RenderBufferDataHighEnd *rb); - - RID shadow_sampler; - RID render_base_uniform_set; - RID view_dependant_uniform_set; - - virtual void _base_uniforms_changed(); - void _render_buffers_clear_uniform_set(RenderBufferDataHighEnd *rb); - virtual void _render_buffers_uniform_set_changed(RID p_render_buffers); - virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers); - virtual RID _render_buffers_get_normal_texture(RID p_render_buffers); - - void _update_render_base_uniform_set(); - void _setup_view_dependant_uniform_set(RID p_shadow_atlas, RID p_reflection_atlas); - void _update_render_buffers_uniform_set(RID p_render_buffers); - - /* Scene State UBO */ - - struct ReflectionData { //should always be 128 bytes - float box_extents[3]; - float index; - float box_offset[3]; - uint32_t mask; - float params[4]; // intensity, 0, interior , boxproject - float ambient[4]; // ambient color, energy - float local_matrix[16]; // up to here for spot and omni, rest is for directional - }; - - struct LightData { - float position[3]; - float inv_radius; - float direction[3]; - uint16_t attenuation_energy[2]; //16 bits attenuation, then energy - uint8_t color_specular[4]; //rgb color, a specular (8 bit unorm) - uint16_t cone_attenuation_angle[2]; // attenuation and angle, (16bit float) - uint32_t mask; - uint8_t shadow_color_enabled[4]; //shadow rgb color, a>0.5 enabled (8bit unorm) - float atlas_rect[4]; // in omni, used for atlas uv, in spot, used for projector uv - float shadow_matrix[16]; - }; - - struct DirectionalLightData { - - float direction[3]; - float energy; - float color[3]; - float specular; - float shadow_color[3]; - uint32_t mask; - uint32_t blend_splits; - uint32_t shadow_enabled; - float fade_from; - float fade_to; - float shadow_split_offsets[4]; - float shadow_matrices[4][16]; - }; - - struct GIProbeData { - float xform[16]; - float bounds[3]; - float dynamic_range; - - float bias; - float normal_bias; - uint32_t blend_ambient; - uint32_t texture_slot; - - float anisotropy_strength; - float ao; - float ao_size; - uint32_t pad[1]; - }; - - enum { - INSTANCE_DATA_FLAG_MULTIMESH = 1 << 12, - INSTANCE_DATA_FLAG_MULTIMESH_FORMAT_2D = 1 << 13, - INSTANCE_DATA_FLAG_MULTIMESH_HAS_COLOR = 1 << 14, - INSTANCE_DATA_FLAG_MULTIMESH_HAS_CUSTOM_DATA = 1 << 15, - INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_SHIFT = 16, - INSTANCE_DATA_FLAGS_MULTIMESH_STRIDE_MASK = 0x7, - INSTANCE_DATA_FLAG_SKELETON = 1 << 19, - }; - - struct InstanceData { - float transform[16]; - float normal_transform[16]; - uint32_t flags; - uint32_t instance_ofs; //instance_offset in instancing/skeleton buffer - uint32_t gi_offset; //GI information when using lightmapping (VCT or lightmap) - uint32_t mask; - }; - - struct SceneState { - struct UBO { - float projection_matrix[16]; - float inv_projection_matrix[16]; - - float camera_matrix[16]; - float inv_camera_matrix[16]; - - float viewport_size[2]; - float screen_pixel_size[2]; - - float shadow_z_offset; - float shadow_z_slope_scale; - - float time; - float reflection_multiplier; - - float ambient_light_color_energy[4]; - - float ambient_color_sky_mix; - uint32_t use_ambient_light; - uint32_t use_ambient_cubemap; - uint32_t use_reflection_cubemap; - - float radiance_inverse_xform[12]; - - float shadow_atlas_pixel_size[2]; - float directional_shadow_pixel_size[2]; - - uint32_t directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; - - uint32_t ssao_enabled; - float ssao_light_affect; - float ssao_ao_affect; - uint32_t roughness_limiter_enabled; - - float ao_color[4]; - }; - - UBO ubo; - - RID uniform_buffer; - - ReflectionData *reflections; - uint32_t max_reflections; - RID reflection_buffer; - uint32_t max_reflection_probes_per_instance; - - GIProbeData *gi_probes; - uint32_t max_gi_probes; - RID gi_probe_buffer; - uint32_t max_gi_probe_probes_per_instance; - - LightData *lights; - uint32_t max_lights; - RID light_buffer; - - DirectionalLightData *directional_lights; - uint32_t max_directional_lights; - RID directional_light_buffer; - - RID instance_buffer; - InstanceData *instances; - uint32_t max_instances; - - bool used_screen_texture = false; - bool used_normal_texture = false; - bool used_depth_texture = false; - bool used_sss = false; - uint32_t current_shader_index = 0; - uint32_t current_material_index = 0; - } scene_state; - - /* Render List */ - - struct RenderList { - - int max_elements; - - struct Element { - RasterizerScene::InstanceBase *instance; - MaterialData *material; - union { - struct { - //from least significant to most significant in sort, TODO: should be endian swapped on big endian - uint64_t geometry_index : 20; - uint64_t material_index : 15; - uint64_t shader_index : 12; - uint64_t uses_instancing : 1; - uint64_t uses_vct : 1; - uint64_t uses_lightmap : 1; - uint64_t depth_layer : 4; - uint64_t priority : 8; - }; - - uint64_t sort_key; - }; - uint32_t surface_index; - }; - - Element *base_elements; - Element **elements; - - int element_count; - int alpha_element_count; - - void clear() { - - element_count = 0; - alpha_element_count = 0; - } - - //should eventually be replaced by radix - - struct SortByKey { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - return A->sort_key < B->sort_key; - } - }; - - void sort_by_key(bool p_alpha) { - - SortArray sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - struct SortByDepth { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - return A->instance->depth < B->instance->depth; - } - }; - - void sort_by_depth(bool p_alpha) { //used for shadows - - SortArray sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - struct SortByReverseDepthAndPriority { - - _FORCE_INLINE_ bool operator()(const Element *A, const Element *B) const { - uint32_t layer_A = uint32_t(A->priority); - uint32_t layer_B = uint32_t(B->priority); - if (layer_A == layer_B) { - return A->instance->depth > B->instance->depth; - } else { - return layer_A < layer_B; - } - } - }; - - void sort_by_reverse_depth_and_priority(bool p_alpha) { //used for alpha - - SortArray sorter; - if (p_alpha) { - sorter.sort(&elements[max_elements - alpha_element_count], alpha_element_count); - } else { - sorter.sort(elements, element_count); - } - } - - _FORCE_INLINE_ Element *add_element() { - - if (element_count + alpha_element_count >= max_elements) - return NULL; - elements[element_count] = &base_elements[element_count]; - return elements[element_count++]; - } - - _FORCE_INLINE_ Element *add_alpha_element() { - - if (element_count + alpha_element_count >= max_elements) - return NULL; - int idx = max_elements - alpha_element_count - 1; - elements[idx] = &base_elements[idx]; - alpha_element_count++; - return elements[idx]; - } - - void init() { - - element_count = 0; - alpha_element_count = 0; - elements = memnew_arr(Element *, max_elements); - base_elements = memnew_arr(Element, max_elements); - for (int i = 0; i < max_elements; i++) - elements[i] = &base_elements[i]; // assign elements - } - - RenderList() { - - max_elements = 0; - } - - ~RenderList() { - memdelete_arr(elements); - memdelete_arr(base_elements); - } - }; - - RenderList render_list; - - static RasterizerSceneHighEndRD *singleton; - uint64_t render_pass; - double time; - RID default_shader; - RID default_material; - RID overdraw_material_shader; - RID overdraw_material; - RID wireframe_material_shader; - RID wireframe_material; - RID default_shader_rd; - RID default_radiance_uniform_set; - RID default_render_buffers_uniform_set; - - RID default_vec4_xform_buffer; - RID default_vec4_xform_uniform_set; - - LightClusterBuilder cluster_builder; - - enum PassMode { - PASS_MODE_COLOR, - PASS_MODE_COLOR_SPECULAR, - PASS_MODE_COLOR_TRANSPARENT, - PASS_MODE_SHADOW, - PASS_MODE_SHADOW_DP, - PASS_MODE_DEPTH, - PASS_MODE_DEPTH_NORMAL, - PASS_MODE_DEPTH_NORMAL_ROUGHNESS, - PASS_MODE_DEPTH_MATERIAL, - }; - - void _setup_environment(RID p_environment, const CameraMatrix &p_cam_projection, const Transform &p_cam_transform, RID p_reflection_probe, bool p_no_fog, const Size2 &p_screen_pixel_size, RID p_shadow_atlas, bool p_flip_y, const Color &p_default_bg_color, float p_znear, float p_zfar, bool p_opaque_render_buffers = false); - void _setup_lights(RID *p_light_cull_result, int p_light_cull_count, const Transform &p_camera_inverse_transform, RID p_shadow_atlas, bool p_using_shadows); - void _setup_reflections(RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, const Transform &p_camera_inverse_transform, RID p_environment); - void _setup_gi_probes(RID *p_gi_probe_probe_cull_result, int p_gi_probe_probe_cull_count, const Transform &p_camera_transform); - - void _fill_instances(RenderList::Element **p_elements, int p_element_count, bool p_for_depth); - void _render_list(RenderingDevice::DrawListID p_draw_list, RenderingDevice::FramebufferFormatID p_framebuffer_Format, RenderList::Element **p_elements, int p_element_count, bool p_reverse_cull, PassMode p_pass_mode, bool p_no_gi, RID p_radiance_uniform_set, RID p_render_buffers_uniform_set); - _FORCE_INLINE_ void _add_geometry(InstanceBase *p_instance, uint32_t p_surface, RID p_material, PassMode p_pass_mode, uint32_t p_geometry_index); - _FORCE_INLINE_ void _add_geometry_with_material(InstanceBase *p_instance, uint32_t p_surface, MaterialData *p_material, RID p_material_rid, PassMode p_pass_mode, uint32_t p_geometry_index); - - void _fill_render_list(InstanceBase **p_cull_result, int p_cull_count, PassMode p_pass_mode, bool p_no_gi); - -protected: - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_bg_color); - virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool p_use_dp_flip); - virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); - -public: - virtual void set_time(double p_time, double p_step); - - virtual bool free(RID p_rid); - - RasterizerSceneHighEndRD(RasterizerStorageRD *p_storage); - ~RasterizerSceneHighEndRD(); -}; -#endif // RASTERIZER_SCENE_HIGHEND_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp deleted file mode 100644 index 395b73ca9b..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.cpp +++ /dev/null @@ -1,4039 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_scene_rd.h" - -#include "core/os/os.h" -#include "core/project_settings.h" -#include "servers/visual/visual_server_raster.h" - -uint64_t RasterizerSceneRD::auto_exposure_counter = 2; - -void RasterizerSceneRD::_clear_reflection_data(ReflectionData &rd) { - - rd.layers.clear(); - rd.radiance_base_cubemap = RID(); - if (rd.downsampled_radiance_cubemap.is_valid()) { - RD::get_singleton()->free(rd.downsampled_radiance_cubemap); - } - rd.downsampled_radiance_cubemap = RID(); - rd.downsampled_layer.mipmaps.clear(); - rd.coefficient_buffer = RID(); -} - -void RasterizerSceneRD::_update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality) { - //recreate radiance and all data - - int mipmaps = p_mipmaps; - uint32_t w = p_size, h = p_size; - - if (p_use_array) { - int layers = p_low_quality ? 8 : roughness_layers; - - for (int i = 0; i < layers; i++) { - ReflectionData::Layer layer; - uint32_t mmw = w; - uint32_t mmh = h; - layer.mipmaps.resize(mipmaps); - layer.views.resize(mipmaps); - for (int j = 0; j < mipmaps; j++) { - ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j]; - mm.size.width = mmw; - mm.size.height = mmh; - for (int k = 0; k < 6; k++) { - mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6 + k, j); - Vector fbtex; - fbtex.push_back(mm.views[k]); - mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex); - } - - layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + i * 6, j, RD::TEXTURE_SLICE_CUBEMAP); - - mmw = MAX(1, mmw >> 1); - mmh = MAX(1, mmh >> 1); - } - - rd.layers.push_back(layer); - } - - } else { - mipmaps = p_low_quality ? 8 : mipmaps; - //regular cubemap, lower quality (aliasing, less memory) - ReflectionData::Layer layer; - uint32_t mmw = w; - uint32_t mmh = h; - layer.mipmaps.resize(mipmaps); - layer.views.resize(mipmaps); - for (int j = 0; j < mipmaps; j++) { - ReflectionData::Layer::Mipmap &mm = layer.mipmaps.write[j]; - mm.size.width = mmw; - mm.size.height = mmh; - for (int k = 0; k < 6; k++) { - mm.views[k] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer + k, j); - Vector fbtex; - fbtex.push_back(mm.views[k]); - mm.framebuffers[k] = RD::get_singleton()->framebuffer_create(fbtex); - } - - layer.views.write[j] = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, j, RD::TEXTURE_SLICE_CUBEMAP); - - mmw = MAX(1, mmw >> 1); - mmh = MAX(1, mmh >> 1); - } - - rd.layers.push_back(layer); - } - - rd.radiance_base_cubemap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), p_base_cube, p_base_layer, 0, RD::TEXTURE_SLICE_CUBEMAP); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = 64; // Always 64x64 - tf.height = 64; - tf.type = RD::TEXTURE_TYPE_CUBE; - tf.array_layers = 6; - tf.mipmaps = 7; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - rd.downsampled_radiance_cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); - { - uint32_t mmw = 64; - uint32_t mmh = 64; - rd.downsampled_layer.mipmaps.resize(7); - for (int j = 0; j < rd.downsampled_layer.mipmaps.size(); j++) { - ReflectionData::DownsampleLayer::Mipmap &mm = rd.downsampled_layer.mipmaps.write[j]; - mm.size.width = mmw; - mm.size.height = mmh; - mm.view = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rd.downsampled_radiance_cubemap, 0, j, RD::TEXTURE_SLICE_CUBEMAP); - - mmw = MAX(1, mmw >> 1); - mmh = MAX(1, mmh >> 1); - } - } -} - -void RasterizerSceneRD::_create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays) { - - storage->get_effects()->cubemap_downsample(rd.radiance_base_cubemap, rd.downsampled_layer.mipmaps[0].view, rd.downsampled_layer.mipmaps[0].size); - - for (int i = 1; i < rd.downsampled_layer.mipmaps.size(); i++) { - storage->get_effects()->cubemap_downsample(rd.downsampled_layer.mipmaps[i - 1].view, rd.downsampled_layer.mipmaps[i].view, rd.downsampled_layer.mipmaps[i].size); - } - - Vector views; - if (p_use_arrays) { - for (int i = 1; i < rd.layers.size(); i++) { - views.push_back(rd.layers[i].views[0]); - } - } else { - for (int i = 1; i < rd.layers[0].views.size(); i++) { - views.push_back(rd.layers[0].views[i]); - } - } - - storage->get_effects()->cubemap_filter(rd.downsampled_radiance_cubemap, views, p_use_arrays); -} - -void RasterizerSceneRD::_create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer) { - - if (p_use_arrays) { - - //render directly to the layers - storage->get_effects()->cubemap_roughness(rd.radiance_base_cubemap, rd.layers[p_base_layer].views[0], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers.size() - 1.0), rd.layers[p_base_layer].mipmaps[0].size.x); - } else { - - storage->get_effects()->cubemap_roughness(rd.layers[0].views[p_base_layer - 1], rd.layers[0].views[p_base_layer], p_cube_side, sky_ggx_samples_quality, float(p_base_layer) / (rd.layers[0].mipmaps.size() - 1.0), rd.layers[0].mipmaps[p_base_layer].size.x); - } -} - -void RasterizerSceneRD::_update_reflection_mipmaps(ReflectionData &rd) { - - if (sky_use_cubemap_array) { - - for (int i = 0; i < rd.layers.size(); i++) { - for (int j = 0; j < rd.layers[i].mipmaps.size() - 1; j++) { - for (int k = 0; k < 6; k++) { - RID view = rd.layers[i].mipmaps[j].views[k]; - RID fb = rd.layers[i].mipmaps[j + 1].framebuffers[k]; - Vector2 size = rd.layers[i].mipmaps[j].size; - size = Vector2(1.0 / size.x, 1.0 / size.y); - storage->get_effects()->make_mipmap(view, fb, size); - } - } - } - } -} - -RID RasterizerSceneRD::sky_create() { - return sky_owner.make_rid(Sky()); -} - -void RasterizerSceneRD::_sky_invalidate(Sky *p_sky) { - if (!p_sky->dirty) { - p_sky->dirty = true; - p_sky->dirty_list = dirty_sky_list; - dirty_sky_list = p_sky; - } -} - -void RasterizerSceneRD::sky_set_radiance_size(RID p_sky, int p_radiance_size) { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND(!sky); - ERR_FAIL_COND(p_radiance_size < 32 || p_radiance_size > 2048); - if (sky->radiance_size == p_radiance_size) { - return; - } - sky->radiance_size = p_radiance_size; - - if (sky->mode == VS::SKY_MODE_REALTIME && sky->radiance_size != 256) { - WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally."); - sky->radiance_size = 256; - } - - _sky_invalidate(sky); - if (sky->radiance.is_valid()) { - RD::get_singleton()->free(sky->radiance); - sky->radiance = RID(); - } - _clear_reflection_data(sky->reflection); -} - -void RasterizerSceneRD::sky_set_mode(RID p_sky, VS::SkyMode p_mode) { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND(!sky); - - if (sky->mode == p_mode) { - return; - } - - sky->mode = p_mode; - - if (sky->mode == VS::SKY_MODE_REALTIME && sky->radiance_size != 256) { - WARN_PRINT("Realtime Skies can only use a radiance size of 256. Radiance size will be set to 256 internally."); - sky_set_radiance_size(p_sky, 256); - } - - _sky_invalidate(sky); - if (sky->radiance.is_valid()) { - RD::get_singleton()->free(sky->radiance); - sky->radiance = RID(); - } - _clear_reflection_data(sky->reflection); -} - -void RasterizerSceneRD::sky_set_material(RID p_sky, RID p_material) { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND(!sky); - sky->material = p_material; -} -void RasterizerSceneRD::_update_dirty_skys() { - - Sky *sky = dirty_sky_list; - - while (sky) { - - bool texture_set_dirty = false; - //update sky configuration if texture is missing - - if (sky->radiance.is_null()) { - int mipmaps = Image::get_image_required_mipmaps(sky->radiance_size, sky->radiance_size, Image::FORMAT_RGBAH) + 1; - - uint32_t w = sky->radiance_size, h = sky->radiance_size; - int layers = roughness_layers; - if (sky->mode == VS::SKY_MODE_REALTIME) { - layers = 8; - if (roughness_layers != 8) { - WARN_PRINT("When using REALTIME skies, roughness_layers should be set to 8 in the project settings for best quality reflections"); - } - } - - if (sky_use_cubemap_array) { - //array (higher quality, 6 times more memory) - RD::TextureFormat tf; - tf.array_layers = layers * 6; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; - tf.mipmaps = mipmaps; - tf.width = w; - tf.height = h; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - - sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - _update_reflection_data(sky->reflection, sky->radiance_size, mipmaps, true, sky->radiance, 0, sky->mode == VS::SKY_MODE_REALTIME); - - } else { - //regular cubemap, lower quality (aliasing, less memory) - RD::TextureFormat tf; - tf.array_layers = 6; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.type = RD::TEXTURE_TYPE_CUBE; - tf.mipmaps = MIN(mipmaps, layers); - tf.width = w; - tf.height = h; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - - sky->radiance = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - _update_reflection_data(sky->reflection, sky->radiance_size, MIN(mipmaps, layers), false, sky->radiance, 0, sky->mode == VS::SKY_MODE_REALTIME); - } - texture_set_dirty = true; - } - - // Create subpass buffers if they havent been created already - if (sky->half_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->half_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tformat.width = sky->screen_size.x / 2; - tformat.height = sky->screen_size.y / 2; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; - - sky->half_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - Vector texs; - texs.push_back(sky->half_res_pass); - sky->half_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); - texture_set_dirty = true; - } - - if (sky->quarter_res_pass.is_null() && !RD::get_singleton()->texture_is_valid(sky->quarter_res_pass) && sky->screen_size.x >= 4 && sky->screen_size.y >= 4) { - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tformat.width = sky->screen_size.x / 4; - tformat.height = sky->screen_size.y / 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; - - sky->quarter_res_pass = RD::get_singleton()->texture_create(tformat, RD::TextureView()); - Vector texs; - texs.push_back(sky->quarter_res_pass); - sky->quarter_res_framebuffer = RD::get_singleton()->framebuffer_create(texs); - texture_set_dirty = true; - } - - if (texture_set_dirty) { - for (int i = 0; i < SKY_TEXTURE_SET_MAX; i++) { - if (sky->texture_uniform_sets[i].is_valid() && RD::get_singleton()->uniform_set_is_valid(sky->texture_uniform_sets[i])) { - RD::get_singleton()->free(sky->texture_uniform_sets[i]); - sky->texture_uniform_sets[i] = RID(); - } - } - } - - sky->reflection.dirty = true; - - Sky *next = sky->dirty_list; - sky->dirty_list = nullptr; - sky->dirty = false; - sky = next; - } - - dirty_sky_list = nullptr; -} - -RID RasterizerSceneRD::sky_get_radiance_texture_rd(RID p_sky) const { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND_V(!sky, RID()); - - return sky->radiance; -} - -RID RasterizerSceneRD::sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND_V(!sky, RID()); - - if (sky->uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(sky->uniform_set)) { - - sky->uniform_set = RID(); - if (sky->radiance.is_valid()) { - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - u.ids.push_back(sky->radiance); - uniforms.push_back(u); - } - - sky->uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - } - - return sky->uniform_set; -} - -RID RasterizerSceneRD::_get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version) { - - if (p_sky->texture_uniform_sets[p_version].is_valid() && RD::get_singleton()->uniform_set_is_valid(p_sky->texture_uniform_sets[p_version])) { - return p_sky->texture_uniform_sets[p_version]; - } - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - if (p_sky->radiance.is_valid() && p_version <= SKY_TEXTURE_SET_QUARTER_RES) { - u.ids.push_back(p_sky->radiance); - } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); - } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1; // half res - if (p_sky->half_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_HALF_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_HALF_RES) { - if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(p_sky->reflection.layers[0].views[1]); - } else { - u.ids.push_back(p_sky->half_res_pass); - } - } else { - if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); - } - } - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; // quarter res - if (p_sky->quarter_res_pass.is_valid() && p_version != SKY_TEXTURE_SET_QUARTER_RES && p_version != SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES) { - if (p_version >= SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(p_sky->reflection.layers[0].views[2]); - } else { - u.ids.push_back(p_sky->quarter_res_pass); - } - } else { - if (p_version < SKY_TEXTURE_SET_CUBEMAP) { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE)); - } else { - u.ids.push_back(storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_CUBEMAP_BLACK)); - } - } - uniforms.push_back(u); - } - - p_sky->texture_uniform_sets[p_version] = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_TEXTURES); - return p_sky->texture_uniform_sets[p_version]; -} - -RID RasterizerSceneRD::sky_get_material(RID p_sky) const { - Sky *sky = sky_owner.getornull(p_sky); - ERR_FAIL_COND_V(!sky, RID()); - - return sky->material; -} - -void RasterizerSceneRD::_draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { - - ERR_FAIL_COND(!is_environment(p_environment)); - - Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); - ERR_FAIL_COND(!sky); - - RID sky_material = sky_get_material(environment_get_sky(p_environment)); - - SkyMaterialData *material = NULL; - - if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); - if (!material || !material->shader_data->valid) { - material = NULL; - } - } - - if (!material) { - sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); - } - - ERR_FAIL_COND(!material); - - SkyShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); - - Basis sky_transform = environment_get_sky_orientation(p_environment); - sky_transform.invert(); - - float multiplier = environment_get_bg_energy(p_environment); - float custom_fov = environment_get_sky_custom_fov(p_environment); - // Camera - CameraMatrix camera; - - if (custom_fov) { - - float near_plane = p_projection.get_z_near(); - float far_plane = p_projection.get_z_far(); - float aspect = p_projection.get_aspect(); - - camera.set_perspective(custom_fov, aspect, near_plane, far_plane); - - } else { - camera = p_projection; - } - - sky_transform = p_transform.basis * sky_transform; - - if (shader_data->uses_quarter_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_QUARTER_RES]; - - RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_QUARTER_RES); - - Vector clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->quarter_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - storage->get_effects()->render_sky(draw_list, time, sky->quarter_res_framebuffer, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin); - RD::get_singleton()->draw_list_end(); - } - - if (shader_data->uses_half_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_HALF_RES]; - - RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_HALF_RES); - - Vector clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(sky->half_res_framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_DISCARD, clear_colors); - storage->get_effects()->render_sky(draw_list, time, sky->half_res_framebuffer, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin); - RD::get_singleton()->draw_list_end(); - } - - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_BACKGROUND]; - - RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_BACKGROUND); - - RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_fb, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_CONTINUE, p_can_continue ? RD::FINAL_ACTION_CONTINUE : RD::FINAL_ACTION_READ); - storage->get_effects()->render_sky(draw_list, time, p_fb, sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, camera, sky_transform, multiplier, p_transform.origin); - RD::get_singleton()->draw_list_end(); -} - -void RasterizerSceneRD::_setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size) { - - ERR_FAIL_COND(!is_environment(p_environment)); - - Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); - ERR_FAIL_COND(!sky); - - RID sky_material = sky_get_material(environment_get_sky(p_environment)); - - SkyMaterialData *material = NULL; - - if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); - if (!material || !material->shader_data->valid) { - material = NULL; - } - } - - if (!material) { - sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); - } - - ERR_FAIL_COND(!material); - - SkyShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); - - // Invalidate supbass buffers if screen size changes - if (sky->screen_size != p_screen_size) { - sky->screen_size = p_screen_size; - sky->screen_size.x = sky->screen_size.x < 4 ? 4 : sky->screen_size.x; - sky->screen_size.y = sky->screen_size.y < 4 ? 4 : sky->screen_size.y; - if (shader_data->uses_half_res) { - if (sky->half_res_pass.is_valid()) { - RD::get_singleton()->free(sky->half_res_pass); - sky->half_res_pass = RID(); - } - _sky_invalidate(sky); - } - if (shader_data->uses_quarter_res) { - if (sky->quarter_res_pass.is_valid()) { - RD::get_singleton()->free(sky->quarter_res_pass); - sky->quarter_res_pass = RID(); - } - _sky_invalidate(sky); - } - } - - // Create new subpass buffers if necessary - if ((shader_data->uses_half_res && sky->half_res_pass.is_null()) || - (shader_data->uses_quarter_res && sky->quarter_res_pass.is_null()) || - sky->radiance.is_null()) { - _sky_invalidate(sky); - _update_dirty_skys(); - } - - if (shader_data->uses_time && time - sky->prev_time > 0.00001) { - - sky->prev_time = time; - sky->reflection.dirty = true; - VisualServerRaster::redraw_request(); - } - - if (material != sky->prev_material) { - - sky->prev_material = material; - sky->reflection.dirty = true; - } - - if (material->uniform_set_updated) { - - material->uniform_set_updated = false; - sky->reflection.dirty = true; - } - - if (!p_position.is_equal_approx(sky->prev_position) && shader_data->uses_position) { - - sky->prev_position = p_position; - sky->reflection.dirty = true; - } - - if (shader_data->uses_light || sky_scene_state.light_uniform_set.is_null()) { - // Check whether the directional_light_buffer changes - bool light_data_dirty = false; - - if (sky_scene_state.directional_light_count != sky_scene_state.last_frame_directional_light_count) { - light_data_dirty = true; - for (uint32_t i = sky_scene_state.directional_light_count; i < sky_scene_state.max_directional_lights; i++) { - sky_scene_state.directional_lights[i].enabled = false; - } - } - if (!light_data_dirty) { - for (uint32_t i = 0; i < sky_scene_state.directional_light_count; i++) { - if (sky_scene_state.directional_lights[i].direction[0] != sky_scene_state.last_frame_directional_lights[i].direction[0] || - sky_scene_state.directional_lights[i].direction[1] != sky_scene_state.last_frame_directional_lights[i].direction[1] || - sky_scene_state.directional_lights[i].direction[2] != sky_scene_state.last_frame_directional_lights[i].direction[2] || - sky_scene_state.directional_lights[i].energy != sky_scene_state.last_frame_directional_lights[i].energy || - sky_scene_state.directional_lights[i].color[0] != sky_scene_state.last_frame_directional_lights[i].color[0] || - sky_scene_state.directional_lights[i].color[1] != sky_scene_state.last_frame_directional_lights[i].color[1] || - sky_scene_state.directional_lights[i].color[2] != sky_scene_state.last_frame_directional_lights[i].color[2] || - sky_scene_state.directional_lights[i].enabled != sky_scene_state.last_frame_directional_lights[i].enabled) { - light_data_dirty = true; - break; - } - } - } - - if (light_data_dirty || sky_scene_state.light_uniform_set.is_null()) { - - RD::get_singleton()->buffer_update(sky_scene_state.directional_light_buffer, 0, sizeof(SkyDirectionalLightData) * sky_scene_state.max_directional_lights, sky_scene_state.directional_lights, true); - - if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) { - RD::get_singleton()->free(sky_scene_state.light_uniform_set); - } - - Vector uniforms; - { - RD::Uniform u; - u.binding = 0; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.ids.push_back(sky_scene_state.directional_light_buffer); - uniforms.push_back(u); - } - - sky_scene_state.light_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_LIGHTS); - - RasterizerSceneRD::SkyDirectionalLightData *temp = sky_scene_state.last_frame_directional_lights; - sky_scene_state.last_frame_directional_lights = sky_scene_state.directional_lights; - sky_scene_state.directional_lights = temp; - sky_scene_state.last_frame_directional_light_count = sky_scene_state.directional_light_count; - sky->reflection.dirty = true; - } - } -} - -void RasterizerSceneRD::_update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform) { - - ERR_FAIL_COND(!is_environment(p_environment)); - - Sky *sky = sky_owner.getornull(environment_get_sky(p_environment)); - ERR_FAIL_COND(!sky); - - RID sky_material = sky_get_material(environment_get_sky(p_environment)); - - SkyMaterialData *material = NULL; - - if (sky_material.is_valid()) { - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); - if (!material || !material->shader_data->valid) { - material = NULL; - } - } - - if (!material) { - sky_material = sky_shader.default_material; - material = (SkyMaterialData *)storage->material_get_data(sky_material, RasterizerStorageRD::SHADER_TYPE_SKY); - } - - ERR_FAIL_COND(!material); - - SkyShaderData *shader_data = material->shader_data; - - ERR_FAIL_COND(!shader_data); - - float multiplier = environment_get_bg_energy(p_environment); - - // Update radiance cubemap - if (sky->reflection.dirty) { - - static const Vector3 view_normals[6] = { - Vector3(+1, 0, 0), - Vector3(-1, 0, 0), - Vector3(0, +1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1) - }; - static const Vector3 view_up[6] = { - Vector3(0, -1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1), - Vector3(0, -1, 0), - Vector3(0, -1, 0) - }; - - CameraMatrix cm; - cm.set_perspective(90, 1, 0.01, 10.0); - CameraMatrix correction; - correction.set_depth_correction(true); - cm = correction * cm; - - if (shader_data->uses_quarter_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_QUARTER_RES]; - - Vector clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID cubemap_draw_list; - - for (int i = 0; i < 6; i++) { - Transform local_view; - local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]); - RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES); - - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[2].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[2].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin); - RD::get_singleton()->draw_list_end(); - } - } - - if (shader_data->uses_half_res) { - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP_HALF_RES]; - - Vector clear_colors; - clear_colors.push_back(Color(0.0, 0.0, 0.0)); - RD::DrawListID cubemap_draw_list; - - for (int i = 0; i < 6; i++) { - Transform local_view; - local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]); - RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP_HALF_RES); - - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[1].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[1].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin); - RD::get_singleton()->draw_list_end(); - } - } - - RD::DrawListID cubemap_draw_list; - RenderPipelineVertexFormatCacheRD *pipeline = &shader_data->pipelines[SKY_VERSION_CUBEMAP]; - - for (int i = 0; i < 6; i++) { - Transform local_view; - local_view.set_look_at(Vector3(0, 0, 0), view_normals[i], view_up[i]); - RID texture_uniform_set = _get_sky_textures(sky, SKY_TEXTURE_SET_CUBEMAP); - - cubemap_draw_list = RD::get_singleton()->draw_list_begin(sky->reflection.layers[0].mipmaps[0].framebuffers[i], RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD); - storage->get_effects()->render_sky(cubemap_draw_list, time, sky->reflection.layers[0].mipmaps[0].framebuffers[i], sky_scene_state.sampler_uniform_set, sky_scene_state.light_uniform_set, pipeline, material->uniform_set, texture_uniform_set, cm, local_view.basis, multiplier, p_transform.origin); - RD::get_singleton()->draw_list_end(); - } - if (sky_use_cubemap_array) { - if (sky->mode == VS::SKY_MODE_QUALITY) { - for (int i = 1; i < sky->reflection.layers.size(); i++) { - _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i); - } - } else { - _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array); - } - - _update_reflection_mipmaps(sky->reflection); - } else { - if (sky->mode == VS::SKY_MODE_QUALITY) { - for (int i = 1; i < sky->reflection.layers[0].mipmaps.size(); i++) { - _create_reflection_importance_sample(sky->reflection, sky_use_cubemap_array, 10, i); - } - } else { - _create_reflection_fast_filter(sky->reflection, sky_use_cubemap_array); - } - } - - sky->reflection.dirty = false; - } -} - -/* SKY SHADER */ - -void RasterizerSceneRD::SkyShaderData::set_code(const String &p_code) { - //compile - - code = p_code; - valid = false; - ubo_size = 0; - uniforms.clear(); - - if (code == String()) { - return; //just invalid, but no error - } - - ShaderCompilerRD::GeneratedCode gen_code; - ShaderCompilerRD::IdentifierActions actions; - - uses_time = false; - uses_half_res = false; - uses_quarter_res = false; - uses_position = false; - uses_light = false; - - actions.render_mode_flags["use_half_res_pass"] = &uses_half_res; - actions.render_mode_flags["use_quarter_res_pass"] = &uses_quarter_res; - - actions.usage_flag_pointers["TIME"] = &uses_time; - actions.usage_flag_pointers["POSITION"] = &uses_position; - actions.usage_flag_pointers["LIGHT0_ENABLED"] = &uses_light; - actions.usage_flag_pointers["LIGHT0_ENERGY"] = &uses_light; - actions.usage_flag_pointers["LIGHT0_DIRECTION"] = &uses_light; - actions.usage_flag_pointers["LIGHT0_COLOR"] = &uses_light; - actions.usage_flag_pointers["LIGHT1_ENABLED"] = &uses_light; - actions.usage_flag_pointers["LIGHT1_ENERGY"] = &uses_light; - actions.usage_flag_pointers["LIGHT1_DIRECTION"] = &uses_light; - actions.usage_flag_pointers["LIGHT1_COLOR"] = &uses_light; - actions.usage_flag_pointers["LIGHT2_ENABLED"] = &uses_light; - actions.usage_flag_pointers["LIGHT2_ENERGY"] = &uses_light; - actions.usage_flag_pointers["LIGHT2_DIRECTION"] = &uses_light; - actions.usage_flag_pointers["LIGHT2_COLOR"] = &uses_light; - actions.usage_flag_pointers["LIGHT3_ENABLED"] = &uses_light; - actions.usage_flag_pointers["LIGHT3_ENERGY"] = &uses_light; - actions.usage_flag_pointers["LIGHT3_DIRECTION"] = &uses_light; - actions.usage_flag_pointers["LIGHT3_COLOR"] = &uses_light; - - actions.uniforms = &uniforms; - - RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; - - Error err = scene_singleton->sky_shader.compiler.compile(VS::SHADER_SKY, code, &actions, path, gen_code); - - ERR_FAIL_COND(err != OK); - - if (version.is_null()) { - version = scene_singleton->sky_shader.shader.version_create(); - } - -#if 0 - print_line("**compiling shader:"); - print_line("**defines:\n"); - for (int i = 0; i < gen_code.defines.size(); i++) { - print_line(gen_code.defines[i]); - } - print_line("\n**uniforms:\n" + gen_code.uniforms); - // print_line("\n**vertex_globals:\n" + gen_code.vertex_global); - // print_line("\n**vertex_code:\n" + gen_code.vertex); - print_line("\n**fragment_globals:\n" + gen_code.fragment_global); - print_line("\n**fragment_code:\n" + gen_code.fragment); - print_line("\n**light_code:\n" + gen_code.light); -#endif - - scene_singleton->sky_shader.shader.version_set_code(version, gen_code.uniforms, gen_code.vertex_global, gen_code.vertex, gen_code.fragment_global, gen_code.light, gen_code.fragment, gen_code.defines); - ERR_FAIL_COND(!scene_singleton->sky_shader.shader.version_is_valid(version)); - - ubo_size = gen_code.uniform_total_size; - ubo_offsets = gen_code.uniform_offsets; - texture_uniforms = gen_code.texture_uniforms; - - //update pipelines - - for (int i = 0; i < SKY_VERSION_MAX; i++) { - - RD::PipelineDepthStencilState depth_stencil_state; - depth_stencil_state.enable_depth_test = true; - depth_stencil_state.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - - RID shader_variant = scene_singleton->sky_shader.shader.version_get_shader(version, i); - pipelines[i].setup(shader_variant, RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), depth_stencil_state, RD::PipelineColorBlendState::create_disabled(), 0); - } - - valid = true; -} - -void RasterizerSceneRD::SkyShaderData::set_default_texture_param(const StringName &p_name, RID p_texture) { - if (!p_texture.is_valid()) { - default_texture_params.erase(p_name); - } else { - default_texture_params[p_name] = p_texture; - } -} - -void RasterizerSceneRD::SkyShaderData::get_param_list(List *p_param_list) const { - - Map order; - - for (Map::Element *E = uniforms.front(); E; E = E->next()) { - - if (E->get().texture_order >= 0) { - order[E->get().texture_order + 100000] = E->key(); - } else { - order[E->get().order] = E->key(); - } - } - - for (Map::Element *E = order.front(); E; E = E->next()) { - - PropertyInfo pi = ShaderLanguage::uniform_to_property_info(uniforms[E->get()]); - pi.name = E->get(); - p_param_list->push_back(pi); - } -} - -bool RasterizerSceneRD::SkyShaderData::is_param_texture(const StringName &p_param) const { - if (!uniforms.has(p_param)) { - return false; - } - - return uniforms[p_param].texture_order >= 0; -} - -bool RasterizerSceneRD::SkyShaderData::is_animated() const { - return false; -} - -bool RasterizerSceneRD::SkyShaderData::casts_shadows() const { - return false; -} - -Variant RasterizerSceneRD::SkyShaderData::get_default_parameter(const StringName &p_parameter) const { - if (uniforms.has(p_parameter)) { - ShaderLanguage::ShaderNode::Uniform uniform = uniforms[p_parameter]; - Vector default_value = uniform.default_value; - return ShaderLanguage::constant_value_to_variant(default_value, uniform.type, uniform.hint); - } - return Variant(); -} - -RasterizerSceneRD::SkyShaderData::SkyShaderData() { - valid = false; -} - -RasterizerSceneRD::SkyShaderData::~SkyShaderData() { - RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; - ERR_FAIL_COND(!scene_singleton); - //pipeline variants will clear themselves if shader is gone - if (version.is_valid()) { - scene_singleton->sky_shader.shader.version_free(version); - } -} - -RasterizerStorageRD::ShaderData *RasterizerSceneRD::_create_sky_shader_func() { - SkyShaderData *shader_data = memnew(SkyShaderData); - return shader_data; -} - -void RasterizerSceneRD::SkyMaterialData::update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) { - - RasterizerSceneRD *scene_singleton = (RasterizerSceneRD *)RasterizerSceneRD::singleton; - - uniform_set_updated = true; - - if ((uint32_t)ubo_data.size() != shader_data->ubo_size) { - p_uniform_dirty = true; - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - uniform_buffer = RID(); - } - - ubo_data.resize(shader_data->ubo_size); - if (ubo_data.size()) { - uniform_buffer = RD::get_singleton()->uniform_buffer_create(ubo_data.size()); - memset(ubo_data.ptrw(), 0, ubo_data.size()); //clear - } - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - //check whether buffer changed - if (p_uniform_dirty && ubo_data.size()) { - - update_uniform_buffer(shader_data->uniforms, shader_data->ubo_offsets.ptr(), p_parameters, ubo_data.ptrw(), ubo_data.size(), false); - RD::get_singleton()->buffer_update(uniform_buffer, 0, ubo_data.size(), ubo_data.ptrw()); - } - - uint32_t tex_uniform_count = shader_data->texture_uniforms.size(); - - if ((uint32_t)texture_cache.size() != tex_uniform_count) { - texture_cache.resize(tex_uniform_count); - p_textures_dirty = true; - - //clear previous uniform set - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - uniform_set = RID(); - } - } - - if (p_textures_dirty && tex_uniform_count) { - - update_textures(p_parameters, shader_data->default_texture_params, shader_data->texture_uniforms, texture_cache.ptrw(), true); - } - - if (shader_data->ubo_size == 0 && shader_data->texture_uniforms.size() == 0) { - // This material does not require an uniform set, so don't create it. - return; - } - - if (!p_textures_dirty && uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - //no reason to update uniform set, only UBO (or nothing) was needed to update - return; - } - - Vector uniforms; - - { - - if (shader_data->ubo_size) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 0; - u.ids.push_back(uniform_buffer); - uniforms.push_back(u); - } - - const RID *textures = texture_cache.ptrw(); - for (uint32_t i = 0; i < tex_uniform_count; i++) { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 1 + i; - u.ids.push_back(textures[i]); - uniforms.push_back(u); - } - } - - uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_singleton->sky_shader.shader.version_get_shader(shader_data->version, 0), SKY_SET_MATERIAL); -} - -RasterizerSceneRD::SkyMaterialData::~SkyMaterialData() { - if (uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(uniform_set)) { - RD::get_singleton()->free(uniform_set); - } - - if (uniform_buffer.is_valid()) { - RD::get_singleton()->free(uniform_buffer); - } -} - -RasterizerStorageRD::MaterialData *RasterizerSceneRD::_create_sky_material_func(SkyShaderData *p_shader) { - SkyMaterialData *material_data = memnew(SkyMaterialData); - material_data->shader_data = p_shader; - material_data->last_frame = false; - //update will happen later anyway so do nothing. - return material_data; -} - -RID RasterizerSceneRD::environment_create() { - - return environment_owner.make_rid(Environent()); -} - -void RasterizerSceneRD::environment_set_background(RID p_env, VS::EnvironmentBG p_bg) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->background = p_bg; -} -void RasterizerSceneRD::environment_set_sky(RID p_env, RID p_sky) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->sky = p_sky; -} -void RasterizerSceneRD::environment_set_sky_custom_fov(RID p_env, float p_scale) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->sky_custom_fov = p_scale; -} -void RasterizerSceneRD::environment_set_sky_orientation(RID p_env, const Basis &p_orientation) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->sky_orientation = p_orientation; -} -void RasterizerSceneRD::environment_set_bg_color(RID p_env, const Color &p_color) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->bg_color = p_color; -} -void RasterizerSceneRD::environment_set_bg_energy(RID p_env, float p_energy) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->bg_energy = p_energy; -} -void RasterizerSceneRD::environment_set_canvas_max_layer(RID p_env, int p_max_layer) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->canvas_max_layer = p_max_layer; -} -void RasterizerSceneRD::environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient, float p_energy, float p_sky_contribution, VS::EnvironmentReflectionSource p_reflection_source, const Color &p_ao_color) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->ambient_light = p_color; - env->ambient_source = p_ambient; - env->ambient_light_energy = p_energy; - env->ambient_sky_contribution = p_sky_contribution; - env->reflection_source = p_reflection_source; - env->ao_color = p_ao_color; -} - -VS::EnvironmentBG RasterizerSceneRD::environment_get_background(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_BG_MAX); - return env->background; -} -RID RasterizerSceneRD::environment_get_sky(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, RID()); - return env->sky; -} -float RasterizerSceneRD::environment_get_sky_custom_fov(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->sky_custom_fov; -} -Basis RasterizerSceneRD::environment_get_sky_orientation(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, Basis()); - return env->sky_orientation; -} -Color RasterizerSceneRD::environment_get_bg_color(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, Color()); - return env->bg_color; -} -float RasterizerSceneRD::environment_get_bg_energy(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->bg_energy; -} -int RasterizerSceneRD::environment_get_canvas_max_layer(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->canvas_max_layer; -} -Color RasterizerSceneRD::environment_get_ambient_light_color(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, Color()); - return env->ambient_light; -} -VS::EnvironmentAmbientSource RasterizerSceneRD::environment_get_ambient_light_ambient_source(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_AMBIENT_SOURCE_BG); - return env->ambient_source; -} -float RasterizerSceneRD::environment_get_ambient_light_ambient_energy(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->ambient_light_energy; -} -float RasterizerSceneRD::environment_get_ambient_sky_contribution(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, 0); - return env->ambient_sky_contribution; -} -VS::EnvironmentReflectionSource RasterizerSceneRD::environment_get_reflection_source(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, VS::ENV_REFLECTION_SOURCE_DISABLED); - return env->reflection_source; -} - -Color RasterizerSceneRD::environment_get_ao_color(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, Color()); - return env->ao_color; -} - -void RasterizerSceneRD::environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale) { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->exposure = p_exposure; - env->tone_mapper = p_tone_mapper; - if (!env->auto_exposure && p_auto_exposure) { - env->auto_exposure_version = ++auto_exposure_counter; - } - env->auto_exposure = p_auto_exposure; - env->white = p_white; - env->min_luminance = p_min_luminance; - env->max_luminance = p_max_luminance; - env->auto_exp_speed = p_auto_exp_speed; - env->auto_exp_scale = p_auto_exp_scale; -} - -void RasterizerSceneRD::environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) { - - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - env->glow_enabled = p_enable; - env->glow_levels = p_level_flags; - env->glow_intensity = p_intensity; - env->glow_strength = p_strength; - env->glow_mix = p_mix; - env->glow_bloom = p_bloom_threshold; - env->glow_blend_mode = p_blend_mode; - env->glow_hdr_bleed_threshold = p_hdr_bleed_threshold; - env->glow_hdr_bleed_scale = p_hdr_bleed_scale; - env->glow_hdr_luminance_cap = p_hdr_luminance_cap; - env->glow_bicubic_upscale = p_bicubic_upscale; -} - -void RasterizerSceneRD::environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) { - - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND(!env); - - env->ssao_enabled = p_enable; - env->ssao_radius = p_radius; - env->ssao_intensity = p_intensity; - env->ssao_bias = p_bias; - env->ssao_direct_light_affect = p_light_affect; - env->ssao_ao_channel_affect = p_ao_channel_affect; - env->ssao_blur = p_blur; -} - -void RasterizerSceneRD::environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size) { - ssao_quality = p_quality; - ssao_half_size = p_half_size; -} - -bool RasterizerSceneRD::environment_is_ssao_enabled(RID p_env) const { - - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); - return env->ssao_enabled; -} - -float RasterizerSceneRD::environment_get_ssao_ao_affect(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); - return env->ssao_ao_channel_affect; -} -float RasterizerSceneRD::environment_get_ssao_light_affect(RID p_env) const { - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); - return env->ssao_direct_light_affect; -} - -bool RasterizerSceneRD::environment_is_ssr_enabled(RID p_env) const { - - Environent *env = environment_owner.getornull(p_env); - ERR_FAIL_COND_V(!env, false); - return false; -} - -bool RasterizerSceneRD::is_environment(RID p_env) const { - return environment_owner.owns(p_env); -} - -//////////////////////////////////////////////////////////// - -RID RasterizerSceneRD::reflection_atlas_create() { - - ReflectionAtlas ra; - ra.count = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_count"); - ra.size = GLOBAL_GET("rendering/quality/reflection_atlas/reflection_size"); - - return reflection_atlas_owner.make_rid(ra); -} - -void RasterizerSceneRD::reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count) { - - ReflectionAtlas *ra = reflection_atlas_owner.getornull(p_ref_atlas); - ERR_FAIL_COND(!ra); - - if (ra->size == p_reflection_size && ra->count == p_reflection_count) { - return; //no changes - } - - ra->size = p_reflection_size; - ra->count = p_reflection_count; - - if (ra->reflection.is_valid()) { - //clear and invalidate everything - RD::get_singleton()->free(ra->reflection); - ra->reflection = RID(); - RD::get_singleton()->free(ra->depth_buffer); - ra->depth_buffer = RID(); - - for (int i = 0; i < ra->reflections.size(); i++) { - _clear_reflection_data(ra->reflections.write[i].data); - if (ra->reflections[i].owner.is_null()) { - continue; - } - reflection_probe_release_atlas_index(ra->reflections[i].owner); - //rp->atlasindex clear - } - - ra->reflections.clear(); - } -} - -//////////////////////// -RID RasterizerSceneRD::reflection_probe_instance_create(RID p_probe) { - ReflectionProbeInstance rpi; - rpi.probe = p_probe; - return reflection_probe_instance_owner.make_rid(rpi); -} - -void RasterizerSceneRD::reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - - rpi->transform = p_transform; - rpi->dirty = true; -} - -void RasterizerSceneRD::reflection_probe_release_atlas_index(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - - if (rpi->atlas.is_null()) { - return; //nothing to release - } - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); - ERR_FAIL_COND(!atlas); - ERR_FAIL_INDEX(rpi->atlas_index, atlas->reflections.size()); - atlas->reflections.write[rpi->atlas_index].owner = RID(); - rpi->atlas_index = -1; - rpi->atlas = RID(); -} - -bool RasterizerSceneRD::reflection_probe_instance_needs_redraw(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - if (rpi->rendering) { - return false; - } - - if (rpi->dirty) { - return true; - } - - if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS) { - return true; - } - - return rpi->atlas_index == -1; -} - -bool RasterizerSceneRD::reflection_probe_instance_has_reflection(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - return rpi->atlas.is_valid(); -} - -bool RasterizerSceneRD::reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas) { - - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_reflection_atlas); - - ERR_FAIL_COND_V(!atlas, false); - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - - if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->size != 256) { - WARN_PRINT("ReflectionProbes set to UPDATE_ALWAYS must have an atlas size of 256. Please update the atlas size in the ProjectSettings."); - reflection_atlas_set_size(p_reflection_atlas, 256, atlas->count); - } - - if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS && atlas->reflection.is_valid() && atlas->reflections[0].data.layers[0].mipmaps.size() != 8) { - // Invalidate reflection atlas, need to regenerate - RD::get_singleton()->free(atlas->reflection); - atlas->reflection = RID(); - - for (int i = 0; i < atlas->reflections.size(); i++) { - if (atlas->reflections[i].owner.is_null()) { - continue; - } - reflection_probe_release_atlas_index(atlas->reflections[i].owner); - } - - atlas->reflections.clear(); - } - - if (atlas->reflection.is_null()) { - int mipmaps = MIN(roughness_layers, Image::get_image_required_mipmaps(atlas->size, atlas->size, Image::FORMAT_RGBAH) + 1); - mipmaps = storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS ? 8 : mipmaps; // always use 8 mipmaps with real time filtering - { - //reflection atlas was unused, create: - RD::TextureFormat tf; - tf.array_layers = 6 * atlas->count; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.type = RD::TEXTURE_TYPE_CUBE_ARRAY; - tf.mipmaps = mipmaps; - tf.width = atlas->size; - tf.height = atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - - atlas->reflection = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - { - - RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - tf.width = atlas->size; - tf.height = atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - atlas->depth_buffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - atlas->reflections.resize(atlas->count); - for (int i = 0; i < atlas->count; i++) { - _update_reflection_data(atlas->reflections.write[i].data, atlas->size, mipmaps, false, atlas->reflection, i * 6, storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS); - for (int j = 0; j < 6; j++) { - Vector fb; - fb.push_back(atlas->reflections.write[i].data.layers[0].mipmaps[0].views[j]); - fb.push_back(atlas->depth_buffer); - atlas->reflections.write[i].fbs[j] = RD::get_singleton()->framebuffer_create(fb); - } - } - - Vector fb; - fb.push_back(atlas->depth_buffer); - atlas->depth_fb = RD::get_singleton()->framebuffer_create(fb); - } - - if (rpi->atlas_index == -1) { - for (int i = 0; i < atlas->reflections.size(); i++) { - if (atlas->reflections[i].owner.is_null()) { - rpi->atlas_index = i; - break; - } - } - //find the one used last - if (rpi->atlas_index == -1) { - //everything is in use, find the one least used via LRU - uint64_t pass_min = 0; - - for (int i = 0; i < atlas->reflections.size(); i++) { - ReflectionProbeInstance *rpi2 = reflection_probe_instance_owner.getornull(atlas->reflections[i].owner); - if (rpi2->last_pass < pass_min) { - pass_min = rpi2->last_pass; - rpi->atlas_index = i; - } - } - } - } - - rpi->atlas = p_reflection_atlas; - rpi->rendering = true; - rpi->dirty = false; - rpi->processing_layer = 1; - rpi->processing_side = 0; - - return true; -} - -bool RasterizerSceneRD::reflection_probe_instance_postprocess_step(RID p_instance) { - - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, false); - ERR_FAIL_COND_V(!rpi->rendering, false); - ERR_FAIL_COND_V(rpi->atlas.is_null(), false); - - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); - if (!atlas || rpi->atlas_index == -1) { - //does not belong to an atlas anymore, cancel (was removed from atlas or atlas changed while rendering) - rpi->rendering = false; - return false; - } - - if (storage->reflection_probe_get_update_mode(rpi->probe) == VS::REFLECTION_PROBE_UPDATE_ALWAYS) { - // Using real time reflections, all roughness is done in one step - _create_reflection_fast_filter(atlas->reflections.write[rpi->atlas_index].data, false); - rpi->rendering = false; - rpi->processing_side = 0; - rpi->processing_layer = 1; - return true; - } - - if (rpi->processing_layer > 1) { - _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, 10, rpi->processing_layer); - rpi->processing_layer++; - if (rpi->processing_layer == atlas->reflections[rpi->atlas_index].data.layers[0].mipmaps.size()) { - rpi->rendering = false; - rpi->processing_side = 0; - rpi->processing_layer = 1; - return true; - } - return false; - - } else { - _create_reflection_importance_sample(atlas->reflections.write[rpi->atlas_index].data, false, rpi->processing_side, rpi->processing_layer); - } - - rpi->processing_side++; - if (rpi->processing_side == 6) { - rpi->processing_side = 0; - rpi->processing_layer++; - } - - return false; -} - -uint32_t RasterizerSceneRD::reflection_probe_instance_get_resolution(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, 0); - - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); - ERR_FAIL_COND_V(!atlas, 0); - return atlas->size; -} - -RID RasterizerSceneRD::reflection_probe_instance_get_framebuffer(RID p_instance, int p_index) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); - ERR_FAIL_INDEX_V(p_index, 6, RID()); - - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->reflections[rpi->atlas_index].fbs[p_index]; -} - -RID RasterizerSceneRD::reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); - ERR_FAIL_INDEX_V(p_index, 6, RID()); - - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(rpi->atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->depth_fb; -} - -/////////////////////////////////////////////////////////// - -RID RasterizerSceneRD::shadow_atlas_create() { - - return shadow_atlas_owner.make_rid(ShadowAtlas()); -} - -void RasterizerSceneRD::shadow_atlas_set_size(RID p_atlas, int p_size) { - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_COND(p_size < 0); - p_size = next_power_of_2(p_size); - - if (p_size == shadow_atlas->size) - return; - - // erasing atlas - if (shadow_atlas->depth.is_valid()) { - RD::get_singleton()->free(shadow_atlas->depth); - shadow_atlas->depth = RID(); - shadow_atlas->fb = RID(); - } - for (int i = 0; i < 4; i++) { - //clear subdivisions - shadow_atlas->quadrants[i].shadows.resize(0); - shadow_atlas->quadrants[i].shadows.resize(1 << shadow_atlas->quadrants[i].subdivision); - } - - //erase shadow atlas reference from lights - for (Map::Element *E = shadow_atlas->shadow_owners.front(); E; E = E->next()) { - LightInstance *li = light_instance_owner.getornull(E->key()); - ERR_CONTINUE(!li); - li->shadow_atlases.erase(p_atlas); - } - - //clear owners - shadow_atlas->shadow_owners.clear(); - - shadow_atlas->size = p_size; - - if (shadow_atlas->size) { - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = shadow_atlas->size; - tf.height = shadow_atlas->size; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - shadow_atlas->depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - Vector fb; - fb.push_back(shadow_atlas->depth); - shadow_atlas->fb = RD::get_singleton()->framebuffer_create(fb); - } -} - -void RasterizerSceneRD::shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision) { - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_INDEX(p_quadrant, 4); - ERR_FAIL_INDEX(p_subdivision, 16384); - - uint32_t subdiv = next_power_of_2(p_subdivision); - if (subdiv & 0xaaaaaaaa) { //sqrt(subdiv) must be integer - subdiv <<= 1; - } - - subdiv = int(Math::sqrt((float)subdiv)); - - //obtain the number that will be x*x - - if (shadow_atlas->quadrants[p_quadrant].subdivision == subdiv) - return; - - //erase all data from quadrant - for (int i = 0; i < shadow_atlas->quadrants[p_quadrant].shadows.size(); i++) { - - if (shadow_atlas->quadrants[p_quadrant].shadows[i].owner.is_valid()) { - shadow_atlas->shadow_owners.erase(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); - LightInstance *li = light_instance_owner.getornull(shadow_atlas->quadrants[p_quadrant].shadows[i].owner); - ERR_CONTINUE(!li); - li->shadow_atlases.erase(p_atlas); - } - } - - shadow_atlas->quadrants[p_quadrant].shadows.resize(0); - shadow_atlas->quadrants[p_quadrant].shadows.resize(subdiv * subdiv); - shadow_atlas->quadrants[p_quadrant].subdivision = subdiv; - - //cache the smallest subdiv (for faster allocation in light update) - - shadow_atlas->smallest_subdiv = 1 << 30; - - for (int i = 0; i < 4; i++) { - if (shadow_atlas->quadrants[i].subdivision) { - shadow_atlas->smallest_subdiv = MIN(shadow_atlas->smallest_subdiv, shadow_atlas->quadrants[i].subdivision); - } - } - - if (shadow_atlas->smallest_subdiv == 1 << 30) { - shadow_atlas->smallest_subdiv = 0; - } - - //resort the size orders, simple bublesort for 4 elements.. - - int swaps = 0; - do { - swaps = 0; - - for (int i = 0; i < 3; i++) { - if (shadow_atlas->quadrants[shadow_atlas->size_order[i]].subdivision < shadow_atlas->quadrants[shadow_atlas->size_order[i + 1]].subdivision) { - SWAP(shadow_atlas->size_order[i], shadow_atlas->size_order[i + 1]); - swaps++; - } - } - } while (swaps > 0); -} - -bool RasterizerSceneRD::_shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow) { - - for (int i = p_quadrant_count - 1; i >= 0; i--) { - - int qidx = p_in_quadrants[i]; - - if (shadow_atlas->quadrants[qidx].subdivision == (uint32_t)p_current_subdiv) { - return false; - } - - //look for an empty space - int sc = shadow_atlas->quadrants[qidx].shadows.size(); - ShadowAtlas::Quadrant::Shadow *sarr = shadow_atlas->quadrants[qidx].shadows.ptrw(); - - int found_free_idx = -1; //found a free one - int found_used_idx = -1; //found existing one, must steal it - uint64_t min_pass = 0; // pass of the existing one, try to use the least recently used one (LRU fashion) - - for (int j = 0; j < sc; j++) { - if (!sarr[j].owner.is_valid()) { - found_free_idx = j; - break; - } - - LightInstance *sli = light_instance_owner.getornull(sarr[j].owner); - ERR_CONTINUE(!sli); - - if (sli->last_scene_pass != scene_pass) { - - //was just allocated, don't kill it so soon, wait a bit.. - if (p_tick - sarr[j].alloc_tick < shadow_atlas_realloc_tolerance_msec) - continue; - - if (found_used_idx == -1 || sli->last_scene_pass < min_pass) { - found_used_idx = j; - min_pass = sli->last_scene_pass; - } - } - } - - if (found_free_idx == -1 && found_used_idx == -1) - continue; //nothing found - - if (found_free_idx == -1 && found_used_idx != -1) { - found_free_idx = found_used_idx; - } - - r_quadrant = qidx; - r_shadow = found_free_idx; - - return true; - } - - return false; -} - -bool RasterizerSceneRD::shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version) { - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND_V(!shadow_atlas, false); - - LightInstance *li = light_instance_owner.getornull(p_light_intance); - ERR_FAIL_COND_V(!li, false); - - if (shadow_atlas->size == 0 || shadow_atlas->smallest_subdiv == 0) { - return false; - } - - uint32_t quad_size = shadow_atlas->size >> 1; - int desired_fit = MIN(quad_size / shadow_atlas->smallest_subdiv, next_power_of_2(quad_size * p_coverage)); - - int valid_quadrants[4]; - int valid_quadrant_count = 0; - int best_size = -1; //best size found - int best_subdiv = -1; //subdiv for the best size - - //find the quadrants this fits into, and the best possible size it can fit into - for (int i = 0; i < 4; i++) { - int q = shadow_atlas->size_order[i]; - int sd = shadow_atlas->quadrants[q].subdivision; - if (sd == 0) - continue; //unused - - int max_fit = quad_size / sd; - - if (best_size != -1 && max_fit > best_size) - break; //too large - - valid_quadrants[valid_quadrant_count++] = q; - best_subdiv = sd; - - if (max_fit >= desired_fit) { - best_size = max_fit; - } - } - - ERR_FAIL_COND_V(valid_quadrant_count == 0, false); - - uint64_t tick = OS::get_singleton()->get_ticks_msec(); - - //see if it already exists - - if (shadow_atlas->shadow_owners.has(p_light_intance)) { - //it does! - uint32_t key = shadow_atlas->shadow_owners[p_light_intance]; - uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; - - bool should_realloc = shadow_atlas->quadrants[q].subdivision != (uint32_t)best_subdiv && (shadow_atlas->quadrants[q].shadows[s].alloc_tick - tick > shadow_atlas_realloc_tolerance_msec); - bool should_redraw = shadow_atlas->quadrants[q].shadows[s].version != p_light_version; - - if (!should_realloc) { - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; - //already existing, see if it should redraw or it's just OK - return should_redraw; - } - - int new_quadrant, new_shadow; - - //find a better place - if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, shadow_atlas->quadrants[q].subdivision, tick, new_quadrant, new_shadow)) { - //found a better place! - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - if (sh->owner.is_valid()) { - //is taken, but is invalid, erasing it - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.getornull(sh->owner); - sli->shadow_atlases.erase(p_atlas); - } - - //erase previous - shadow_atlas->quadrants[q].shadows.write[s].version = 0; - shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); - - sh->owner = p_light_intance; - sh->alloc_tick = tick; - sh->version = p_light_version; - li->shadow_atlases.insert(p_atlas); - - //make new key - key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - //update it in map - shadow_atlas->shadow_owners[p_light_intance] = key; - //make it dirty, as it should redraw anyway - return true; - } - - //no better place for this shadow found, keep current - - //already existing, see if it should redraw or it's just OK - - shadow_atlas->quadrants[q].shadows.write[s].version = p_light_version; - - return should_redraw; - } - - int new_quadrant, new_shadow; - - //find a better place - if (_shadow_atlas_find_shadow(shadow_atlas, valid_quadrants, valid_quadrant_count, -1, tick, new_quadrant, new_shadow)) { - //found a better place! - ShadowAtlas::Quadrant::Shadow *sh = &shadow_atlas->quadrants[new_quadrant].shadows.write[new_shadow]; - if (sh->owner.is_valid()) { - //is taken, but is invalid, erasing it - shadow_atlas->shadow_owners.erase(sh->owner); - LightInstance *sli = light_instance_owner.getornull(sh->owner); - sli->shadow_atlases.erase(p_atlas); - } - - sh->owner = p_light_intance; - sh->alloc_tick = tick; - sh->version = p_light_version; - li->shadow_atlases.insert(p_atlas); - - //make new key - uint32_t key = new_quadrant << ShadowAtlas::QUADRANT_SHIFT; - key |= new_shadow; - //update it in map - shadow_atlas->shadow_owners[p_light_intance] = key; - //make it dirty, as it should redraw anyway - - return true; - } - - //no place to allocate this light, apologies - - return false; -} - -void RasterizerSceneRD::directional_shadow_atlas_set_size(int p_size) { - - p_size = nearest_power_of_2_templated(p_size); - - if (directional_shadow.size == p_size) { - return; - } - - directional_shadow.size = p_size; - - if (directional_shadow.depth.is_valid()) { - RD::get_singleton()->free(directional_shadow.depth); - directional_shadow.depth = RID(); - directional_shadow.fb = RID(); - } - - if (p_size > 0) { - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = p_size; - tf.height = p_size; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - directional_shadow.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - Vector fb; - fb.push_back(directional_shadow.depth); - directional_shadow.fb = RD::get_singleton()->framebuffer_create(fb); - } - - _base_uniforms_changed(); -} - -void RasterizerSceneRD::set_directional_shadow_count(int p_count) { - - directional_shadow.light_count = p_count; - directional_shadow.current_light = 0; -} - -static Rect2i _get_directional_shadow_rect(int p_size, int p_shadow_count, int p_shadow_index) { - - int split_h = 1; - int split_v = 1; - - while (split_h * split_v < p_shadow_count) { - if (split_h == split_v) { - split_h <<= 1; - } else { - split_v <<= 1; - } - } - - Rect2i rect(0, 0, p_size, p_size); - rect.size.width /= split_h; - rect.size.height /= split_v; - - rect.position.x = rect.size.width * (p_shadow_index % split_h); - rect.position.y = rect.size.height * (p_shadow_index / split_h); - - return rect; -} - -int RasterizerSceneRD::get_directional_light_shadow_size(RID p_light_intance) { - - ERR_FAIL_COND_V(directional_shadow.light_count == 0, 0); - - Rect2i r = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, 0); - - LightInstance *light_instance = light_instance_owner.getornull(p_light_intance); - ERR_FAIL_COND_V(!light_instance, 0); - - switch (storage->light_directional_get_shadow_mode(light_instance->light)) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: - break; //none - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: r.size.height /= 2; break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: r.size /= 2; break; - } - - return MAX(r.size.width, r.size.height); -} - -////////////////////////////////////////////////// - -RID RasterizerSceneRD::camera_effects_create() { - - return camera_effects_owner.make_rid(CameraEffects()); -} - -void RasterizerSceneRD::camera_effects_set_dof_blur_quality(VS::DOFBlurQuality p_quality, bool p_use_jitter) { - - dof_blur_quality = p_quality; - dof_blur_use_jitter = p_use_jitter; -} - -void RasterizerSceneRD::camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape p_shape) { - - dof_blur_bokeh_shape = p_shape; -} - -void RasterizerSceneRD::camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) { - CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); - ERR_FAIL_COND(!camfx); - - camfx->dof_blur_far_enabled = p_far_enable; - camfx->dof_blur_far_distance = p_far_distance; - camfx->dof_blur_far_transition = p_far_transition; - - camfx->dof_blur_near_enabled = p_near_enable; - camfx->dof_blur_near_distance = p_near_distance; - camfx->dof_blur_near_transition = p_near_transition; - - camfx->dof_blur_amount = p_amount; -} - -void RasterizerSceneRD::camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) { - - CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); - ERR_FAIL_COND(!camfx); - - camfx->override_exposure_enabled = p_enable; - camfx->override_exposure = p_exposure; -} - -RID RasterizerSceneRD::light_instance_create(RID p_light) { - - RID li = light_instance_owner.make_rid(LightInstance()); - - LightInstance *light_instance = light_instance_owner.getornull(li); - - light_instance->self = li; - light_instance->light = p_light; - light_instance->light_type = storage->light_get_type(p_light); - - return li; -} - -void RasterizerSceneRD::light_instance_set_transform(RID p_light_instance, const Transform &p_transform) { - - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->transform = p_transform; -} - -void RasterizerSceneRD::light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale) { - - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - if (storage->light_get_type(light_instance->light) != VS::LIGHT_DIRECTIONAL) { - p_pass = 0; - } - - ERR_FAIL_INDEX(p_pass, 4); - - light_instance->shadow_transform[p_pass].camera = p_projection; - light_instance->shadow_transform[p_pass].transform = p_transform; - light_instance->shadow_transform[p_pass].farplane = p_far; - light_instance->shadow_transform[p_pass].split = p_split; - light_instance->shadow_transform[p_pass].bias_scale = p_bias_scale; -} - -void RasterizerSceneRD::light_instance_mark_visible(RID p_light_instance) { - - LightInstance *light_instance = light_instance_owner.getornull(p_light_instance); - ERR_FAIL_COND(!light_instance); - - light_instance->last_scene_pass = scene_pass; -} - -RasterizerSceneRD::ShadowCubemap *RasterizerSceneRD::_get_shadow_cubemap(int p_size) { - - if (!shadow_cubemaps.has(p_size)) { - - ShadowCubemap sc; - { - RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - tf.width = p_size; - tf.height = p_size; - tf.type = RD::TEXTURE_TYPE_CUBE; - tf.array_layers = 6; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - sc.cubemap = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - for (int i = 0; i < 6; i++) { - RID side_texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), sc.cubemap, i, 0); - Vector fbtex; - fbtex.push_back(side_texture); - sc.side_fb[i] = RD::get_singleton()->framebuffer_create(fbtex); - } - - shadow_cubemaps[p_size] = sc; - } - - return &shadow_cubemaps[p_size]; -} - -RasterizerSceneRD::ShadowMap *RasterizerSceneRD::_get_shadow_map(const Size2i &p_size) { - - if (!shadow_maps.has(p_size)) { - - ShadowMap sm; - { - RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - tf.width = p_size.width; - tf.height = p_size.height; - tf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT; - - sm.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - Vector fbtex; - fbtex.push_back(sm.depth); - sm.fb = RD::get_singleton()->framebuffer_create(fbtex); - - shadow_maps[p_size] = sm; - } - - return &shadow_maps[p_size]; -} -///////////////////////////////// - -RID RasterizerSceneRD::gi_probe_instance_create(RID p_base) { - //find a free slot - int index = -1; - for (int i = 0; i < gi_probe_slots.size(); i++) { - if (gi_probe_slots[i] == RID()) { - index = i; - break; - } - } - - ERR_FAIL_COND_V(index == -1, RID()); - - GIProbeInstance gi_probe; - gi_probe.slot = index; - gi_probe.probe = p_base; - RID rid = gi_probe_instance_owner.make_rid(gi_probe); - gi_probe_slots.write[index] = rid; - - return rid; -} - -void RasterizerSceneRD::gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform) { - - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->transform = p_xform; -} - -bool RasterizerSceneRD::gi_probe_needs_update(RID p_probe) const { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - ERR_FAIL_COND_V(!gi_probe, false); - - //return true; - return gi_probe->last_probe_version != storage->gi_probe_get_version(gi_probe->probe); -} - -void RasterizerSceneRD::gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects) { - - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - ERR_FAIL_COND(!gi_probe); - - uint32_t data_version = storage->gi_probe_get_data_version(gi_probe->probe); - - // (RE)CREATE IF NEEDED - - if (gi_probe->last_probe_data_version != data_version) { - //need to re-create everything - if (gi_probe->texture.is_valid()) { - RD::get_singleton()->free(gi_probe->texture); - if (gi_probe_use_anisotropy) { - RD::get_singleton()->free(gi_probe->anisotropy_r16[0]); - RD::get_singleton()->free(gi_probe->anisotropy_r16[1]); - } - RD::get_singleton()->free(gi_probe->write_buffer); - gi_probe->mipmaps.clear(); - } - - for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) { - RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture); - RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth); - } - - gi_probe->dynamic_maps.clear(); - - Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); - - if (octree_size != Vector3i()) { - //can create a 3D texture - Vector levels = storage->gi_probe_get_level_counts(gi_probe->probe); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tf.width = octree_size.x; - tf.height = octree_size.y; - tf.depth = octree_size.z; - tf.type = RD::TEXTURE_TYPE_3D; - tf.mipmaps = levels.size(); - - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - - gi_probe->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); - - if (gi_probe_use_anisotropy) { - tf.format = RD::DATA_FORMAT_R16_UINT; - tf.shareable_formats.push_back(RD::DATA_FORMAT_R16_UINT); - tf.shareable_formats.push_back(RD::DATA_FORMAT_R5G6B5_UNORM_PACK16); - - //need to create R16 first, else driver does not like the storage bit for compute.. - gi_probe->anisotropy_r16[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - gi_probe->anisotropy_r16[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - RD::TextureView tv; - tv.format_override = RD::DATA_FORMAT_R5G6B5_UNORM_PACK16; - gi_probe->anisotropy[0] = RD::get_singleton()->texture_create_shared(tv, gi_probe->anisotropy_r16[0]); - gi_probe->anisotropy[1] = RD::get_singleton()->texture_create_shared(tv, gi_probe->anisotropy_r16[1]); - - RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); - RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, levels.size(), 0, 1, false); - } - - { - int total_elements = 0; - for (int i = 0; i < levels.size(); i++) { - total_elements += levels[i]; - } - - if (gi_probe_use_anisotropy) { - total_elements *= 6; - } - - gi_probe->write_buffer = RD::get_singleton()->storage_buffer_create(total_elements * 16); - } - - for (int i = 0; i < levels.size(); i++) { - GIProbeInstance::Mipmap mipmap; - mipmap.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), gi_probe->texture, 0, i, RD::TEXTURE_SLICE_3D); - if (gi_probe_use_anisotropy) { - RD::TextureView tv; - tv.format_override = RD::DATA_FORMAT_R16_UINT; - mipmap.anisotropy[0] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[0], 0, i, RD::TEXTURE_SLICE_3D); - mipmap.anisotropy[1] = RD::get_singleton()->texture_create_shared_from_slice(tv, gi_probe->anisotropy[1], 0, i, RD::TEXTURE_SLICE_3D); - } - - mipmap.level = levels.size() - i - 1; - mipmap.cell_offset = 0; - for (uint32_t j = 0; j < mipmap.level; j++) { - mipmap.cell_offset += levels[j]; - } - mipmap.cell_count = levels[mipmap.level]; - - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 1; - u.ids.push_back(storage->gi_probe_get_octree_buffer(gi_probe->probe)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe)); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 4; - u.ids.push_back(gi_probe->write_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 9; - u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 10; - u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - - { - Vector copy_uniforms = uniforms; - if (i == 0) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 3; - u.ids.push_back(gi_probe_lights_uniform); - copy_uniforms.push_back(u); - } - - mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT], 0); - - copy_uniforms = uniforms; //restore - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 5; - u.ids.push_back(gi_probe->texture); - copy_uniforms.push_back(u); - } - - if (gi_probe_use_anisotropy) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 7; - u.ids.push_back(gi_probe->anisotropy[0]); - copy_uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 8; - u.ids.push_back(gi_probe->anisotropy[1]); - copy_uniforms.push_back(u); - } - } - - mipmap.second_bounce_uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE], 0); - } else { - mipmap.uniform_set = RD::get_singleton()->uniform_set_create(copy_uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP], 0); - } - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 5; - u.ids.push_back(mipmap.texture); - uniforms.push_back(u); - } - - if (gi_probe_use_anisotropy) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 6; - u.ids.push_back(mipmap.anisotropy[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 7; - u.ids.push_back(mipmap.anisotropy[1]); - uniforms.push_back(u); - } - } - - mipmap.write_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE], 0); - - gi_probe->mipmaps.push_back(mipmap); - } - - { - uint32_t dynamic_map_size = MAX(MAX(octree_size.x, octree_size.y), octree_size.z); - uint32_t oversample = nearest_power_of_2_templated(4); - int mipmap_index = 0; - - while (mipmap_index < gi_probe->mipmaps.size()) { - GIProbeInstance::DynamicMap dmap; - - if (oversample > 0) { - dmap.size = dynamic_map_size * (1 << oversample); - dmap.mipmap = -1; - oversample--; - } else { - dmap.size = dynamic_map_size >> mipmap_index; - dmap.mipmap = mipmap_index; - mipmap_index++; - } - - RD::TextureFormat dtf; - dtf.width = dmap.size; - dtf.height = dmap.size; - dtf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; - - if (gi_probe->dynamic_maps.size() == 0) { - dtf.usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - } - dmap.texture = RD::get_singleton()->texture_create(dtf, RD::TextureView()); - - if (gi_probe->dynamic_maps.size() == 0) { - //render depth for first one - dtf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D32_SFLOAT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D32_SFLOAT : RD::DATA_FORMAT_X8_D24_UNORM_PACK32; - dtf.usage_bits = RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - dmap.fb_depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); - } - - //just use depth as-is - dtf.format = RD::DATA_FORMAT_R32_SFLOAT; - dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - dmap.depth = RD::get_singleton()->texture_create(dtf, RD::TextureView()); - - if (gi_probe->dynamic_maps.size() == 0) { - - dtf.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - dtf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - dmap.albedo = RD::get_singleton()->texture_create(dtf, RD::TextureView()); - dmap.normal = RD::get_singleton()->texture_create(dtf, RD::TextureView()); - dmap.orm = RD::get_singleton()->texture_create(dtf, RD::TextureView()); - - Vector fb; - fb.push_back(dmap.albedo); - fb.push_back(dmap.normal); - fb.push_back(dmap.orm); - fb.push_back(dmap.texture); //emission - fb.push_back(dmap.depth); - fb.push_back(dmap.fb_depth); - - dmap.fb = RD::get_singleton()->framebuffer_create(fb); - - { - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.binding = 3; - u.ids.push_back(gi_probe_lights_uniform); - uniforms.push_back(u); - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 5; - u.ids.push_back(dmap.albedo); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 6; - u.ids.push_back(dmap.normal); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 7; - u.ids.push_back(dmap.orm); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 8; - u.ids.push_back(dmap.fb_depth); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 9; - u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 10; - u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 11; - u.ids.push_back(dmap.texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 12; - u.ids.push_back(dmap.depth); - uniforms.push_back(u); - } - - dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING], 0); - } - } else { - bool plot = dmap.mipmap >= 0; - bool write = dmap.mipmap < (gi_probe->mipmaps.size() - 1); - - Vector uniforms; - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 5; - u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 6; - u.ids.push_back(gi_probe->dynamic_maps[gi_probe->dynamic_maps.size() - 1].depth); - uniforms.push_back(u); - } - - if (write) { - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 7; - u.ids.push_back(dmap.texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 8; - u.ids.push_back(dmap.depth); - uniforms.push_back(u); - } - } - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 9; - u.ids.push_back(storage->gi_probe_get_sdf_texture(gi_probe->probe)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 10; - u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - - if (plot) { - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 11; - u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].texture); - uniforms.push_back(u); - } - if (gi_probe_is_anisotropic()) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 12; - u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].anisotropy[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 13; - u.ids.push_back(gi_probe->mipmaps[dmap.mipmap].anisotropy[1]); - uniforms.push_back(u); - } - } - } - - dmap.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_lighting_shader_version_shaders[(write && plot) ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT : write ? GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE : GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT], 0); - } - - gi_probe->dynamic_maps.push_back(dmap); - } - } - } - - gi_probe->last_probe_data_version = data_version; - p_update_light_instances = true; //just in case - - _base_uniforms_changed(); - } - - // UDPDATE TIME - - if (gi_probe->has_dynamic_object_data) { - //if it has dynamic object data, it needs to be cleared - RD::get_singleton()->texture_clear(gi_probe->texture, Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); - if (gi_probe_is_anisotropic()) { - RD::get_singleton()->texture_clear(gi_probe->anisotropy[0], Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); - RD::get_singleton()->texture_clear(gi_probe->anisotropy[1], Color(0, 0, 0, 0), 0, gi_probe->mipmaps.size(), 0, 1, true); - } - } - - uint32_t light_count = 0; - - if (p_update_light_instances || p_dynamic_object_count > 0) { - - light_count = MIN(gi_probe_max_lights, (uint32_t)p_light_instances.size()); - - { - Transform to_cell = storage->gi_probe_get_to_cell_xform(gi_probe->probe); - Transform to_probe_xform = (gi_probe->transform * to_cell.affine_inverse()).affine_inverse(); - //update lights - - for (uint32_t i = 0; i < light_count; i++) { - GIProbeLight &l = gi_probe_lights[i]; - RID light_instance = p_light_instances[i]; - RID light = light_instance_get_base_light(light_instance); - - l.type = storage->light_get_type(light); - l.attenuation = storage->light_get_param(light, VS::LIGHT_PARAM_ATTENUATION); - l.energy = storage->light_get_param(light, VS::LIGHT_PARAM_ENERGY) * storage->light_get_param(light, VS::LIGHT_PARAM_INDIRECT_ENERGY); - l.radius = to_cell.basis.xform(Vector3(storage->light_get_param(light, VS::LIGHT_PARAM_RANGE), 0, 0)).length(); - Color color = storage->light_get_color(light).to_linear(); - l.color[0] = color.r; - l.color[1] = color.g; - l.color[2] = color.b; - - l.spot_angle_radians = Math::deg2rad(storage->light_get_param(light, VS::LIGHT_PARAM_SPOT_ANGLE)); - l.spot_attenuation = storage->light_get_param(light, VS::LIGHT_PARAM_SPOT_ATTENUATION); - - Transform xform = light_instance_get_base_transform(light_instance); - - Vector3 pos = to_probe_xform.xform(xform.origin); - Vector3 dir = to_probe_xform.basis.xform(-xform.basis.get_axis(2)).normalized(); - - l.position[0] = pos.x; - l.position[1] = pos.y; - l.position[2] = pos.z; - - l.direction[0] = dir.x; - l.direction[1] = dir.y; - l.direction[2] = dir.z; - - l.has_shadow = storage->light_has_shadow(light); - } - - RD::get_singleton()->buffer_update(gi_probe_lights_uniform, 0, sizeof(GIProbeLight) * light_count, gi_probe_lights, true); - } - } - - if (gi_probe->has_dynamic_object_data || p_update_light_instances || p_dynamic_object_count) { - // PROCESS MIPMAPS - if (gi_probe->mipmaps.size()) { - //can update mipmaps - - Vector3i probe_size = storage->gi_probe_get_octree_size(gi_probe->probe); - - GIProbePushConstant push_constant; - - push_constant.limits[0] = probe_size.x; - push_constant.limits[1] = probe_size.y; - push_constant.limits[2] = probe_size.z; - push_constant.stack_size = gi_probe->mipmaps.size(); - push_constant.emission_scale = 1.0; - push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe); - push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); - push_constant.light_count = light_count; - push_constant.aniso_strength = storage->gi_probe_get_anisotropy_strength(gi_probe->probe); - - /* print_line("probe update to version " + itos(gi_probe->last_probe_version)); - print_line("propagation " + rtos(push_constant.propagation)); - print_line("dynrange " + rtos(push_constant.dynamic_range)); - */ - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - - int passes; - if (p_update_light_instances) { - passes = storage->gi_probe_is_using_two_bounces(gi_probe->probe) ? 2 : 1; - } else { - passes = 1; //only re-blitting is necessary - } - int wg_size = 64; - int wg_limit_x = RD::get_singleton()->limit_get(RD::LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X); - - for (int pass = 0; pass < passes; pass++) { - - if (p_update_light_instances) { - - for (int i = 0; i < gi_probe->mipmaps.size(); i++) { - if (i == 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[pass == 0 ? GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT : GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE]); - } else if (i == 1) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP]); - } - - if (pass == 1 || i > 0) { - RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done - } - if (pass == 0 || i > 0) { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].uniform_set, 0); - } else { - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].second_bounce_uniform_set, 0); - } - - push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset; - push_constant.cell_count = gi_probe->mipmaps[i].cell_count; - - int wg_todo = (gi_probe->mipmaps[i].cell_count - 1) / wg_size + 1; - while (wg_todo) { - int wg_count = MIN(wg_todo, wg_limit_x); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant)); - RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); - wg_todo -= wg_count; - push_constant.cell_offset += wg_count * wg_size; - } - } - - RD::get_singleton()->compute_list_add_barrier(compute_list); //wait til previous step is done - } - - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_WRITE_TEXTURE]); - - for (int i = 0; i < gi_probe->mipmaps.size(); i++) { - - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->mipmaps[i].write_uniform_set, 0); - - push_constant.cell_offset = gi_probe->mipmaps[i].cell_offset; - push_constant.cell_count = gi_probe->mipmaps[i].cell_count; - - int wg_todo = (gi_probe->mipmaps[i].cell_count - 1) / wg_size + 1; - while (wg_todo) { - int wg_count = MIN(wg_todo, wg_limit_x); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbePushConstant)); - RD::get_singleton()->compute_list_dispatch(compute_list, wg_count, 1, 1); - wg_todo -= wg_count; - push_constant.cell_offset += wg_count * wg_size; - } - } - } - - RD::get_singleton()->compute_list_end(); - } - } - - gi_probe->has_dynamic_object_data = false; //clear until dynamic object data is used again - - if (p_dynamic_object_count && gi_probe->dynamic_maps.size()) { - - Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); - int multiplier = gi_probe->dynamic_maps[0].size / MAX(MAX(octree_size.x, octree_size.y), octree_size.z); - - Transform oversample_scale; - oversample_scale.basis.scale(Vector3(multiplier, multiplier, multiplier)); - - Transform to_cell = oversample_scale * storage->gi_probe_get_to_cell_xform(gi_probe->probe); - Transform to_world_xform = gi_probe->transform * to_cell.affine_inverse(); - Transform to_probe_xform = to_world_xform.affine_inverse(); - - AABB probe_aabb(Vector3(), octree_size); - - //this could probably be better parallelized in compute.. - for (int i = 0; i < p_dynamic_object_count; i++) { - - InstanceBase *instance = p_dynamic_objects[i]; - //not used, so clear - instance->depth_layer = 0; - instance->depth = 0; - - //transform aabb to giprobe - AABB aabb = (to_probe_xform * instance->transform).xform(instance->aabb); - - //this needs to wrap to grid resolution to avoid jitter - //also extend margin a bit just in case - Vector3i begin = aabb.position - Vector3i(1, 1, 1); - Vector3i end = aabb.position + aabb.size + Vector3i(1, 1, 1); - - for (int j = 0; j < 3; j++) { - if ((end[j] - begin[j]) & 1) { - end[j]++; //for half extents split, it needs to be even - } - begin[j] = MAX(begin[j], 0); - end[j] = MIN(end[j], octree_size[j] * multiplier); - } - - //aabb = aabb.intersection(probe_aabb); //intersect - aabb.position = begin; - aabb.size = end - begin; - - //print_line("aabb: " + aabb); - - for (int j = 0; j < 6; j++) { - - //if (j != 0 && j != 3) { - // continue; - //} - static const Vector3 render_z[6] = { - Vector3(1, 0, 0), - Vector3(0, 1, 0), - Vector3(0, 0, 1), - Vector3(-1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, 0, -1), - }; - static const Vector3 render_up[6] = { - Vector3(0, 1, 0), - Vector3(0, 0, 1), - Vector3(0, 1, 0), - Vector3(0, 1, 0), - Vector3(0, 0, 1), - Vector3(0, 1, 0), - }; - - Vector3 render_dir = render_z[j]; - Vector3 up_dir = render_up[j]; - - Vector3 center = aabb.position + aabb.size * 0.5; - Transform xform; - xform.set_look_at(center - aabb.size * 0.5 * render_dir, center, up_dir); - - Vector3 x_dir = xform.basis.get_axis(0).abs(); - int x_axis = int(Vector3(0, 1, 2).dot(x_dir)); - Vector3 y_dir = xform.basis.get_axis(1).abs(); - int y_axis = int(Vector3(0, 1, 2).dot(y_dir)); - Vector3 z_dir = -xform.basis.get_axis(2); - int z_axis = int(Vector3(0, 1, 2).dot(z_dir.abs())); - - Rect2i rect(aabb.position[x_axis], aabb.position[y_axis], aabb.size[x_axis], aabb.size[y_axis]); - bool x_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(0)) < 0); - bool y_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(1)) < 0); - bool z_flip = bool(Vector3(1, 1, 1).dot(xform.basis.get_axis(2)) > 0); - - CameraMatrix cm; - cm.set_orthogonal(-rect.size.width / 2, rect.size.width / 2, -rect.size.height / 2, rect.size.height / 2, 0.0001, aabb.size[z_axis]); - - _render_material(to_world_xform * xform, cm, true, &instance, 1, gi_probe->dynamic_maps[0].fb, Rect2i(Vector2i(), rect.size)); - - GIProbeDynamicPushConstant push_constant; - zeromem(&push_constant, sizeof(GIProbeDynamicPushConstant)); - push_constant.limits[0] = octree_size.x; - push_constant.limits[1] = octree_size.y; - push_constant.limits[2] = octree_size.z; - push_constant.light_count = p_light_instances.size(); - push_constant.x_dir[0] = x_dir[0]; - push_constant.x_dir[1] = x_dir[1]; - push_constant.x_dir[2] = x_dir[2]; - push_constant.y_dir[0] = y_dir[0]; - push_constant.y_dir[1] = y_dir[1]; - push_constant.y_dir[2] = y_dir[2]; - push_constant.z_dir[0] = z_dir[0]; - push_constant.z_dir[1] = z_dir[1]; - push_constant.z_dir[2] = z_dir[2]; - push_constant.z_base = xform.origin[z_axis]; - push_constant.z_sign = (z_flip ? -1.0 : 1.0); - push_constant.pos_multiplier = float(1.0) / multiplier; - push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); - push_constant.flip_x = x_flip; - push_constant.flip_y = y_flip; - push_constant.rect_pos[0] = rect.position[0]; - push_constant.rect_pos[1] = rect.position[1]; - push_constant.rect_size[0] = rect.size[0]; - push_constant.rect_size[1] = rect.size[1]; - push_constant.prev_rect_ofs[0] = 0; - push_constant.prev_rect_ofs[1] = 0; - push_constant.prev_rect_size[0] = 0; - push_constant.prev_rect_size[1] = 0; - push_constant.on_mipmap = false; - push_constant.propagation = storage->gi_probe_get_propagation(gi_probe->probe); - push_constant.pad[0] = 0; - push_constant.pad[1] = 0; - push_constant.pad[2] = 0; - - //process lighting - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING]); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->dynamic_maps[0].uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant)); - RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); - //print_line("rect: " + itos(i) + ": " + rect); - - for (int k = 1; k < gi_probe->dynamic_maps.size(); k++) { - - // enlarge the rect if needed so all pixels fit when downscaled, - // this ensures downsampling is smooth and optimal because no pixels are left behind - - //x - if (rect.position.x & 1) { - rect.size.x++; - push_constant.prev_rect_ofs[0] = 1; //this is used to ensure reading is also optimal - } else { - push_constant.prev_rect_ofs[0] = 0; - } - if (rect.size.x & 1) { - rect.size.x++; - } - - rect.position.x >>= 1; - rect.size.x = MAX(1, rect.size.x >> 1); - - //y - if (rect.position.y & 1) { - rect.size.y++; - push_constant.prev_rect_ofs[1] = 1; - } else { - push_constant.prev_rect_ofs[1] = 0; - } - if (rect.size.y & 1) { - rect.size.y++; - } - - rect.position.y >>= 1; - rect.size.y = MAX(1, rect.size.y >> 1); - - //shrink limits to ensure plot does not go outside map - if (gi_probe->dynamic_maps[k].mipmap > 0) { - for (int l = 0; l < 3; l++) { - push_constant.limits[l] = MAX(1, push_constant.limits[l] >> 1); - } - } - - //print_line("rect: " + itos(i) + ": " + rect); - push_constant.rect_pos[0] = rect.position[0]; - push_constant.rect_pos[1] = rect.position[1]; - push_constant.prev_rect_size[0] = push_constant.rect_size[0]; - push_constant.prev_rect_size[1] = push_constant.rect_size[1]; - push_constant.rect_size[0] = rect.size[0]; - push_constant.rect_size[1] = rect.size[1]; - push_constant.on_mipmap = gi_probe->dynamic_maps[k].mipmap > 0; - - RD::get_singleton()->compute_list_add_barrier(compute_list); - - if (gi_probe->dynamic_maps[k].mipmap < 0) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE]); - } else if (k < gi_probe->dynamic_maps.size() - 1) { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT]); - } else { - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT]); - } - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, gi_probe->dynamic_maps[k].uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, &push_constant, sizeof(GIProbeDynamicPushConstant)); - RD::get_singleton()->compute_list_dispatch(compute_list, (rect.size.x - 1) / 8 + 1, (rect.size.y - 1) / 8 + 1, 1); - } - - RD::get_singleton()->compute_list_end(); - } - } - - gi_probe->has_dynamic_object_data = true; //clear until dynamic object data is used again - } - - gi_probe->last_probe_version = storage->gi_probe_get_version(gi_probe->probe); -} - -void RasterizerSceneRD::_debug_giprobe(RID p_gi_probe, RD::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - if (gi_probe->mipmaps.size() == 0) { - return; - } - - CameraMatrix transform = (p_camera_with_transform * CameraMatrix(gi_probe->transform)) * CameraMatrix(storage->gi_probe_get_to_cell_xform(gi_probe->probe).affine_inverse()); - - int level = 0; - Vector3i octree_size = storage->gi_probe_get_octree_size(gi_probe->probe); - - GIProbeDebugPushConstant push_constant; - push_constant.alpha = p_alpha; - push_constant.dynamic_range = storage->gi_probe_get_dynamic_range(gi_probe->probe); - push_constant.cell_offset = gi_probe->mipmaps[level].cell_offset; - push_constant.level = level; - - push_constant.bounds[0] = octree_size.x >> level; - push_constant.bounds[1] = octree_size.y >> level; - push_constant.bounds[2] = octree_size.z >> level; - push_constant.pad = 0; - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - - push_constant.projection[i * 4 + j] = transform.matrix[i][j]; - } - } - - if (giprobe_debug_uniform_set.is_valid()) { - RD::get_singleton()->free(giprobe_debug_uniform_set); - } - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 1; - u.ids.push_back(storage->gi_probe_get_data_buffer(gi_probe->probe)); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 2; - u.ids.push_back(gi_probe->texture); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 3; - u.ids.push_back(storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED)); - uniforms.push_back(u); - } - - if (gi_probe_use_anisotropy) { - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 4; - u.ids.push_back(gi_probe->anisotropy[0]); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 5; - u.ids.push_back(gi_probe->anisotropy[1]); - uniforms.push_back(u); - } - } - - int cell_count; - if (!p_emission && p_lighting && gi_probe->has_dynamic_object_data) { - cell_count = push_constant.bounds[0] * push_constant.bounds[1] * push_constant.bounds[2]; - } else { - cell_count = gi_probe->mipmaps[level].cell_count; - } - - giprobe_debug_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_debug_shader_version_shaders[0], 0); - RD::get_singleton()->draw_list_bind_render_pipeline(p_draw_list, giprobe_debug_shader_version_pipelines[p_emission ? GI_PROBE_DEBUG_EMISSION : p_lighting ? (gi_probe->has_dynamic_object_data ? GI_PROBE_DEBUG_LIGHT_FULL : GI_PROBE_DEBUG_LIGHT) : GI_PROBE_DEBUG_COLOR].get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_framebuffer))); - RD::get_singleton()->draw_list_bind_uniform_set(p_draw_list, giprobe_debug_uniform_set, 0); - RD::get_singleton()->draw_list_set_push_constant(p_draw_list, &push_constant, sizeof(GIProbeDebugPushConstant)); - RD::get_singleton()->draw_list_draw(p_draw_list, false, cell_count, 36); -} - -const Vector &RasterizerSceneRD::gi_probe_get_slots() const { - - return gi_probe_slots; -} - -RasterizerSceneRD::GIProbeQuality RasterizerSceneRD::gi_probe_get_quality() const { - return gi_probe_quality; -} - -//////////////////////////////// -RID RasterizerSceneRD::render_buffers_create() { - RenderBuffers rb; - rb.data = _create_render_buffer_data(); - return render_buffers_owner.make_rid(rb); -} - -void RasterizerSceneRD::_allocate_blur_textures(RenderBuffers *rb) { - ERR_FAIL_COND(!rb->blur[0].texture.is_null()); - - uint32_t mipmaps_required = Image::get_image_required_mipmaps(rb->width, rb->height, Image::FORMAT_RGBAH); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->width; - tf.height = rb->height; - tf.type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - tf.mipmaps = mipmaps_required; - - rb->blur[0].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - //the second one is smaller (only used for separatable part of blur) - tf.width >>= 1; - tf.height >>= 1; - tf.mipmaps--; - rb->blur[1].texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - int base_width = rb->width; - int base_height = rb->height; - - for (uint32_t i = 0; i < mipmaps_required; i++) { - - RenderBuffers::Blur::Mipmap mm; - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[0].texture, 0, i); - { - Vector fbs; - fbs.push_back(mm.texture); - mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs); - } - - mm.width = base_width; - mm.height = base_height; - - rb->blur[0].mipmaps.push_back(mm); - - if (i > 0) { - - mm.texture = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->blur[1].texture, 0, i - 1); - { - Vector fbs; - fbs.push_back(mm.texture); - mm.framebuffer = RD::get_singleton()->framebuffer_create(fbs); - } - - rb->blur[1].mipmaps.push_back(mm); - } - - base_width = MAX(1, base_width >> 1); - base_height = MAX(1, base_height >> 1); - } -} - -void RasterizerSceneRD::_allocate_luminance_textures(RenderBuffers *rb) { - ERR_FAIL_COND(!rb->luminance.current.is_null()); - - int w = rb->width; - int h = rb->height; - - while (true) { - w = MAX(w / 8, 1); - h = MAX(h / 8, 1); - - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = w; - tf.height = h; - tf.usage_bits = RD::TEXTURE_USAGE_STORAGE_BIT; - - bool final = w == 1 && h == 1; - - if (final) { - tf.usage_bits |= RD::TEXTURE_USAGE_SAMPLING_BIT; - } - - RID texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - rb->luminance.reduce.push_back(texture); - - if (final) { - rb->luminance.current = RD::get_singleton()->texture_create(tf, RD::TextureView()); - break; - } - } -} - -void RasterizerSceneRD::_free_render_buffer_data(RenderBuffers *rb) { - - if (rb->texture.is_valid()) { - RD::get_singleton()->free(rb->texture); - rb->texture = RID(); - } - - if (rb->depth_texture.is_valid()) { - RD::get_singleton()->free(rb->depth_texture); - rb->depth_texture = RID(); - } - - for (int i = 0; i < 2; i++) { - if (rb->blur[i].texture.is_valid()) { - RD::get_singleton()->free(rb->blur[i].texture); - rb->blur[i].texture = RID(); - rb->blur[i].mipmaps.clear(); - } - } - - for (int i = 0; i < rb->luminance.reduce.size(); i++) { - RD::get_singleton()->free(rb->luminance.reduce[i]); - } - - for (int i = 0; i < rb->luminance.reduce.size(); i++) { - RD::get_singleton()->free(rb->luminance.reduce[i]); - } - rb->luminance.reduce.clear(); - - if (rb->luminance.current.is_valid()) { - RD::get_singleton()->free(rb->luminance.current); - rb->luminance.current = RID(); - } - - if (rb->ssao.ao[0].is_valid()) { - RD::get_singleton()->free(rb->ssao.depth); - RD::get_singleton()->free(rb->ssao.ao[0]); - if (rb->ssao.ao[1].is_valid()) { - RD::get_singleton()->free(rb->ssao.ao[1]); - } - if (rb->ssao.ao_full.is_valid()) { - RD::get_singleton()->free(rb->ssao.ao_full); - } - - rb->ssao.depth = RID(); - rb->ssao.ao[0] = RID(); - rb->ssao.ao[1] = RID(); - rb->ssao.ao_full = RID(); - rb->ssao.depth_slices.clear(); - } -} - -void RasterizerSceneRD::_process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection) { - - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND(!rb); - - Environent *env = environment_owner.getornull(p_environment); - ERR_FAIL_COND(!env); - - if (rb->ssao.ao[0].is_valid() && rb->ssao.ao_full.is_valid() != ssao_half_size) { - RD::get_singleton()->free(rb->ssao.depth); - RD::get_singleton()->free(rb->ssao.ao[0]); - if (rb->ssao.ao[1].is_valid()) { - RD::get_singleton()->free(rb->ssao.ao[1]); - } - if (rb->ssao.ao_full.is_valid()) { - RD::get_singleton()->free(rb->ssao.ao_full); - } - - rb->ssao.depth = RID(); - rb->ssao.ao[0] = RID(); - rb->ssao.ao[1] = RID(); - rb->ssao.ao_full = RID(); - rb->ssao.depth_slices.clear(); - } - - if (!rb->ssao.ao[0].is_valid()) { - //allocate depth slices - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R32_SFLOAT; - tf.width = rb->width / 2; - tf.height = rb->height / 2; - tf.mipmaps = Image::get_image_required_mipmaps(tf.width, tf.height, Image::FORMAT_RF) + 1; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ssao.depth = RD::get_singleton()->texture_create(tf, RD::TextureView()); - for (uint32_t i = 0; i < tf.mipmaps; i++) { - RID slice = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rb->ssao.depth, 0, i); - rb->ssao.depth_slices.push_back(slice); - } - } - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = ssao_half_size ? rb->width / 2 : rb->width; - tf.height = ssao_half_size ? rb->height / 2 : rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ssao.ao[0] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - rb->ssao.ao[1] = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - if (ssao_half_size) { - //upsample texture - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT; - rb->ssao.ao_full = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - _render_buffers_uniform_set_changed(p_render_buffers); - } - - storage->get_effects()->generate_ssao(rb->depth_texture, p_normal_buffer, Size2i(rb->width, rb->height), rb->ssao.depth, rb->ssao.depth_slices, rb->ssao.ao[0], rb->ssao.ao_full.is_valid(), rb->ssao.ao[1], rb->ssao.ao_full, env->ssao_intensity, env->ssao_radius, env->ssao_bias, p_projection, ssao_quality, env->ssao_blur, env->ssao_blur_edge_sharpness); -} - -void RasterizerSceneRD::_render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection) { - - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND(!rb); - - Environent *env = environment_owner.getornull(p_environment); - //glow (if enabled) - CameraEffects *camfx = camera_effects_owner.getornull(p_camera_effects); - - bool can_use_effects = rb->width >= 8 && rb->height >= 8; - - if (can_use_effects && camfx && (camfx->dof_blur_near_enabled || camfx->dof_blur_far_enabled) && camfx->dof_blur_amount > 0.0) { - - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); - _render_buffers_uniform_set_changed(p_render_buffers); - } - - float bokeh_size = camfx->dof_blur_amount * 64.0; - storage->get_effects()->bokeh_dof(rb->texture, rb->depth_texture, Size2i(rb->width, rb->height), rb->blur[0].mipmaps[0].texture, rb->blur[1].mipmaps[0].texture, rb->blur[0].mipmaps[1].texture, camfx->dof_blur_far_enabled, camfx->dof_blur_far_distance, camfx->dof_blur_far_transition, camfx->dof_blur_near_enabled, camfx->dof_blur_near_distance, camfx->dof_blur_near_transition, bokeh_size, dof_blur_bokeh_shape, dof_blur_quality, dof_blur_use_jitter, p_projection.get_z_near(), p_projection.get_z_far(), p_projection.is_orthogonal()); - } - - if (can_use_effects && env && env->auto_exposure) { - - if (rb->luminance.current.is_null()) { - _allocate_luminance_textures(rb); - _render_buffers_uniform_set_changed(p_render_buffers); - } - - bool set_immediate = env->auto_exposure_version != rb->auto_exposure_version; - rb->auto_exposure_version = env->auto_exposure_version; - - double step = env->auto_exp_speed * time_step; - storage->get_effects()->luminance_reduction(rb->texture, Size2i(rb->width, rb->height), rb->luminance.reduce, rb->luminance.current, env->min_luminance, env->max_luminance, step, set_immediate); - - //swap final reduce with prev luminance - SWAP(rb->luminance.current, rb->luminance.reduce.write[rb->luminance.reduce.size() - 1]); - VisualServerRaster::redraw_request(); //redraw all the time if auto exposure rendering is on - } - - int max_glow_level = -1; - int glow_mask = 0; - - if (can_use_effects && env && env->glow_enabled) { - - /* see that blur textures are allocated */ - - if (rb->blur[0].texture.is_null()) { - _allocate_blur_textures(rb); - _render_buffers_uniform_set_changed(p_render_buffers); - } - - for (int i = 0; i < VS::MAX_GLOW_LEVELS; i++) { - if (env->glow_levels & (1 << i)) { - - if (i >= rb->blur[1].mipmaps.size()) { - max_glow_level = rb->blur[1].mipmaps.size() - 1; - glow_mask |= 1 << max_glow_level; - - } else { - max_glow_level = i; - glow_mask |= (1 << i); - } - } - } - - for (int i = 0; i < (max_glow_level + 1); i++) { - - int vp_w = rb->blur[1].mipmaps[i].width; - int vp_h = rb->blur[1].mipmaps[i].height; - - if (i == 0) { - RID luminance_texture; - if (env->auto_exposure && rb->luminance.current.is_valid()) { - luminance_texture = rb->luminance.current; - } - storage->get_effects()->gaussian_glow(rb->texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength, true, env->glow_hdr_luminance_cap, env->exposure, env->glow_bloom, env->glow_hdr_bleed_threshold, env->glow_hdr_bleed_scale, luminance_texture, env->auto_exp_scale); - } else { - storage->get_effects()->gaussian_glow(rb->blur[1].mipmaps[i - 1].texture, rb->blur[0].mipmaps[i + 1].framebuffer, rb->blur[0].mipmaps[i + 1].texture, rb->blur[1].mipmaps[i].framebuffer, Vector2(1.0 / vp_w, 1.0 / vp_h), env->glow_strength); - } - } - } - - { - //tonemap - RasterizerEffectsRD::TonemapSettings tonemap; - - tonemap.color_correction_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_3D_WHITE); - - if (can_use_effects && env && env->auto_exposure && rb->luminance.current.is_valid()) { - tonemap.use_auto_exposure = true; - tonemap.exposure_texture = rb->luminance.current; - tonemap.auto_exposure_grey = env->auto_exp_scale; - } else { - - tonemap.exposure_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_WHITE); - } - - if (can_use_effects && env && env->glow_enabled) { - tonemap.use_glow = true; - tonemap.glow_mode = RasterizerEffectsRD::TonemapSettings::GlowMode(env->glow_blend_mode); - tonemap.glow_intensity = env->glow_blend_mode == VS::ENV_GLOW_BLEND_MODE_MIX ? env->glow_mix : env->glow_intensity; - tonemap.glow_level_flags = glow_mask; - tonemap.glow_texture_size.x = rb->blur[1].mipmaps[0].width; - tonemap.glow_texture_size.y = rb->blur[1].mipmaps[0].height; - tonemap.glow_use_bicubic_upscale = env->glow_bicubic_upscale; - tonemap.glow_texture = rb->blur[1].texture; - } else { - tonemap.glow_texture = storage->texture_rd_get_default(RasterizerStorageRD::DEFAULT_RD_TEXTURE_BLACK); - } - - if (env) { - tonemap.tonemap_mode = env->tone_mapper; - tonemap.white = env->white; - tonemap.exposure = env->exposure; - } - - storage->get_effects()->tonemapper(rb->texture, storage->render_target_get_rd_framebuffer(rb->render_target), tonemap); - } - - storage->render_target_disable_clear_request(rb->render_target); -} - -void RasterizerSceneRD::_render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas) { - RasterizerEffectsRD *effects = storage->get_effects(); - - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND(!rb); - - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS) { - if (p_shadow_atlas.is_valid()) { - RID shadow_atlas_texture = shadow_atlas_get_texture(p_shadow_atlas); - Size2 rtsize = storage->render_target_get_size(rb->render_target); - - effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true); - } - } - - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS) { - if (directional_shadow_get_texture().is_valid()) { - RID shadow_atlas_texture = directional_shadow_get_texture(); - Size2 rtsize = storage->render_target_get_size(rb->render_target); - - effects->copy_to_rect(shadow_atlas_texture, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 2), false, true); - } - } - - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE) { - if (rb->luminance.current.is_valid()) { - Size2 rtsize = storage->render_target_get_size(rb->render_target); - - effects->copy_to_rect(rb->luminance.current, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize / 8), false, true); - } - } - - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_SSAO && rb->ssao.ao[0].is_valid()) { - Size2 rtsize = storage->render_target_get_size(rb->render_target); - RID ao_buf = rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; - effects->copy_to_rect(ao_buf, storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); - } - - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER && _render_buffers_get_roughness_texture(p_render_buffers).is_valid()) { - Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_rect(_render_buffers_get_roughness_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize), false, true); - } - - if (debug_draw == VS::VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER && _render_buffers_get_normal_texture(p_render_buffers).is_valid()) { - Size2 rtsize = storage->render_target_get_size(rb->render_target); - effects->copy_to_rect(_render_buffers_get_normal_texture(p_render_buffers), storage->render_target_get_rd_framebuffer(rb->render_target), Rect2(Vector2(), rtsize)); - } -} - -RID RasterizerSceneRD::render_buffers_get_back_buffer_texture(RID p_render_buffers) { - - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - if (!rb->blur[0].texture.is_valid()) { - return RID(); //not valid at the moment - } - return rb->blur[0].texture; -} - -RID RasterizerSceneRD::render_buffers_get_ao_texture(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND_V(!rb, RID()); - - return rb->ssao.ao_full.is_valid() ? rb->ssao.ao_full : rb->ssao.ao[0]; -} - -void RasterizerSceneRD::render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa) { - - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - rb->width = p_width; - rb->height = p_height; - rb->render_target = p_render_target; - rb->msaa = p_msaa; - _free_render_buffer_data(rb); - - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - tf.width = rb->width; - tf.height = rb->height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; - - rb->texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - { - RD::TextureFormat tf; - tf.format = RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_D24_UNORM_S8_UINT, RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) ? RD::DATA_FORMAT_D24_UNORM_S8_UINT : RD::DATA_FORMAT_D32_SFLOAT_S8_UINT; - tf.width = p_width; - tf.height = p_height; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - rb->depth_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - - rb->data->configure(rb->texture, rb->depth_texture, p_width, p_height, p_msaa); - _render_buffers_uniform_set_changed(p_render_buffers); -} - -int RasterizerSceneRD::get_roughness_layers() const { - return roughness_layers; -} - -bool RasterizerSceneRD::is_using_radiance_cubemap_array() const { - return sky_use_cubemap_array; -} - -RasterizerSceneRD::RenderBufferData *RasterizerSceneRD::render_buffers_get_data(RID p_render_buffers) { - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND_V(!rb, NULL); - return rb->data; -} - -void RasterizerSceneRD::render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass) { - - Color clear_color; - if (p_render_buffers.is_valid()) { - RenderBuffers *rb = render_buffers_owner.getornull(p_render_buffers); - ERR_FAIL_COND(!rb); - clear_color = storage->render_target_get_clear_request_color(rb->render_target); - } else { - clear_color = storage->get_default_clear_color(); - } - - _render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_light_cull_result, p_light_cull_count, p_reflection_probe_cull_result, p_reflection_probe_cull_count, p_gi_probe_cull_result, p_gi_probe_cull_count, p_environment, p_camera_effects, p_shadow_atlas, p_reflection_atlas, p_reflection_probe, p_reflection_probe_pass, clear_color); - - if (p_render_buffers.is_valid()) { - RENDER_TIMESTAMP("Tonemap"); - - _render_buffers_post_process_and_tonemap(p_render_buffers, p_environment, p_camera_effects, p_cam_projection); - _render_buffers_debug_draw(p_render_buffers, p_shadow_atlas); - } -} - -void RasterizerSceneRD::render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count) { - - LightInstance *light_instance = light_instance_owner.getornull(p_light); - ERR_FAIL_COND(!light_instance); - - Rect2i atlas_rect; - RID atlas_fb; - - bool using_dual_paraboloid = false; - bool using_dual_paraboloid_flip = false; - float zfar = 0; - RID render_fb; - RID render_texture; - float bias = 0; - float normal_bias = 0; - - bool render_cubemap = false; - bool finalize_cubemap = false; - - CameraMatrix light_projection; - Transform light_transform; - - if (storage->light_get_type(light_instance->light) == VS::LIGHT_DIRECTIONAL) { - //set pssm stuff - if (light_instance->last_scene_shadow_pass != scene_pass) { - light_instance->directional_rect = _get_directional_shadow_rect(directional_shadow.size, directional_shadow.light_count, directional_shadow.current_light); - directional_shadow.current_light++; - light_instance->last_scene_shadow_pass = scene_pass; - } - - light_projection = light_instance->shadow_transform[p_pass].camera; - light_transform = light_instance->shadow_transform[p_pass].transform; - - atlas_rect.position.x = light_instance->directional_rect.position.x; - atlas_rect.position.y = light_instance->directional_rect.position.y; - atlas_rect.size.width = light_instance->directional_rect.size.x; - atlas_rect.size.height = light_instance->directional_rect.size.y; - - if (storage->light_directional_get_shadow_mode(light_instance->light) == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS) { - - atlas_rect.size.width /= 2; - atlas_rect.size.height /= 2; - - if (p_pass == 1) { - atlas_rect.position.x += atlas_rect.size.width; - } else if (p_pass == 2) { - atlas_rect.position.y += atlas_rect.size.height; - } else if (p_pass == 3) { - atlas_rect.position.x += atlas_rect.size.width; - atlas_rect.position.y += atlas_rect.size.height; - } - - } else if (storage->light_directional_get_shadow_mode(light_instance->light) == VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS) { - - atlas_rect.size.height /= 2; - - if (p_pass == 0) { - - } else { - atlas_rect.position.y += atlas_rect.size.height; - } - } - - light_instance->shadow_transform[p_pass].atlas_rect = atlas_rect; - - light_instance->shadow_transform[p_pass].atlas_rect.position /= directional_shadow.size; - light_instance->shadow_transform[p_pass].atlas_rect.size /= directional_shadow.size; - - float bias_mult = Math::lerp(1.0f, light_instance->shadow_transform[p_pass].bias_scale, storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE)); - zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE); - bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS) * bias_mult; - normal_bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS) * bias_mult; - - ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size); - render_fb = shadow_map->fb; - render_texture = shadow_map->depth; - atlas_fb = directional_shadow.fb; - - } else { - //set from shadow atlas - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - ERR_FAIL_COND(!shadow_atlas); - ERR_FAIL_COND(!shadow_atlas->shadow_owners.has(p_light)); - - uint32_t key = shadow_atlas->shadow_owners[p_light]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_FAIL_INDEX((int)shadow, shadow_atlas->quadrants[quadrant].shadows.size()); - - uint32_t quadrant_size = shadow_atlas->size >> 1; - - atlas_rect.position.x = (quadrant & 1) * quadrant_size; - atlas_rect.position.y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - atlas_rect.position.x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - atlas_rect.position.y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - atlas_rect.size.width = shadow_size; - atlas_rect.size.height = shadow_size; - atlas_fb = shadow_atlas->fb; - - zfar = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_RANGE); - bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_BIAS); - normal_bias = storage->light_get_param(light_instance->light, VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS); - - if (storage->light_get_type(light_instance->light) == VS::LIGHT_OMNI) { - - if (storage->light_omni_get_shadow_mode(light_instance->light) == VS::LIGHT_OMNI_SHADOW_CUBE) { - - ShadowCubemap *cubemap = _get_shadow_cubemap(shadow_size / 2); - - render_fb = cubemap->side_fb[p_pass]; - render_texture = cubemap->cubemap; - - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - render_cubemap = true; - finalize_cubemap = p_pass == 5; - - } else { - - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - atlas_rect.size.height /= 2; - atlas_rect.position.y += p_pass * atlas_rect.size.height; - - using_dual_paraboloid = true; - using_dual_paraboloid_flip = p_pass == 1; - - ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size); - render_fb = shadow_map->fb; - render_texture = shadow_map->depth; - } - - } else if (storage->light_get_type(light_instance->light) == VS::LIGHT_SPOT) { - - light_projection = light_instance->shadow_transform[0].camera; - light_transform = light_instance->shadow_transform[0].transform; - - ShadowMap *shadow_map = _get_shadow_map(atlas_rect.size); - render_fb = shadow_map->fb; - render_texture = shadow_map->depth; - } - } - - if (render_cubemap) { - //rendering to cubemap - _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, 0, 0, false, false); - if (finalize_cubemap) { - //reblit - atlas_rect.size.height /= 2; - storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, false); - atlas_rect.position.y += atlas_rect.size.height; - storage->get_effects()->copy_cubemap_to_dp(render_texture, atlas_fb, atlas_rect, light_projection.get_z_near(), light_projection.get_z_far(), bias, true); - } - } else { - //render shadow - - _render_shadow(render_fb, p_cull_result, p_cull_count, light_projection, light_transform, zfar, bias, normal_bias, using_dual_paraboloid, using_dual_paraboloid_flip); - - //copy to atlas - storage->get_effects()->copy_to_rect(render_texture, atlas_fb, atlas_rect, true); - - //does not work from depth to color - //RD::get_singleton()->texture_copy(render_texture, atlas_texture, Vector3(0, 0, 0), Vector3(atlas_rect.position.x, atlas_rect.position.y, 0), Vector3(atlas_rect.size.x, atlas_rect.size.y, 1), 0, 0, 0, 0, true); - } -} - -void RasterizerSceneRD::render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) { - - _render_material(p_cam_transform, p_cam_projection, p_cam_ortogonal, p_cull_result, p_cull_count, p_framebuffer, p_region); -} - -bool RasterizerSceneRD::free(RID p_rid) { - - if (render_buffers_owner.owns(p_rid)) { - RenderBuffers *rb = render_buffers_owner.getornull(p_rid); - _free_render_buffer_data(rb); - memdelete(rb->data); - render_buffers_owner.free(p_rid); - } else if (environment_owner.owns(p_rid)) { - //not much to delete, just free it - environment_owner.free(p_rid); - } else if (camera_effects_owner.owns(p_rid)) { - //not much to delete, just free it - camera_effects_owner.free(p_rid); - } else if (reflection_atlas_owner.owns(p_rid)) { - reflection_atlas_set_size(p_rid, 0, 0); - reflection_atlas_owner.free(p_rid); - } else if (reflection_probe_instance_owner.owns(p_rid)) { - //not much to delete, just free it - //ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_rid); - reflection_probe_release_atlas_index(p_rid); - reflection_probe_instance_owner.free(p_rid); - } else if (gi_probe_instance_owner.owns(p_rid)) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_rid); - if (gi_probe->texture.is_valid()) { - RD::get_singleton()->free(gi_probe->texture); - RD::get_singleton()->free(gi_probe->write_buffer); - } - if (gi_probe->anisotropy[0].is_valid()) { - RD::get_singleton()->free(gi_probe->anisotropy[0]); - RD::get_singleton()->free(gi_probe->anisotropy[1]); - } - - for (int i = 0; i < gi_probe->dynamic_maps.size(); i++) { - RD::get_singleton()->free(gi_probe->dynamic_maps[i].texture); - RD::get_singleton()->free(gi_probe->dynamic_maps[i].depth); - } - - gi_probe_slots.write[gi_probe->slot] = RID(); - - gi_probe_instance_owner.free(p_rid); - } else if (sky_owner.owns(p_rid)) { - _update_dirty_skys(); - Sky *sky = sky_owner.getornull(p_rid); - - if (sky->radiance.is_valid()) { - RD::get_singleton()->free(sky->radiance); - sky->radiance = RID(); - } - _clear_reflection_data(sky->reflection); - - if (sky->uniform_buffer.is_valid()) { - RD::get_singleton()->free(sky->uniform_buffer); - sky->uniform_buffer = RID(); - } - - if (sky->half_res_pass.is_valid()) { - RD::get_singleton()->free(sky->half_res_pass); - sky->half_res_pass = RID(); - } - - if (sky->quarter_res_pass.is_valid()) { - RD::get_singleton()->free(sky->quarter_res_pass); - sky->quarter_res_pass = RID(); - } - - if (sky->material.is_valid()) { - storage->free(sky->material); - } - - sky_owner.free(p_rid); - } else if (light_instance_owner.owns(p_rid)) { - - LightInstance *light_instance = light_instance_owner.getornull(p_rid); - - //remove from shadow atlases.. - for (Set::Element *E = light_instance->shadow_atlases.front(); E; E = E->next()) { - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(E->get()); - ERR_CONTINUE(!shadow_atlas->shadow_owners.has(p_rid)); - uint32_t key = shadow_atlas->shadow_owners[p_rid]; - uint32_t q = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t s = key & ShadowAtlas::SHADOW_INDEX_MASK; - - shadow_atlas->quadrants[q].shadows.write[s].owner = RID(); - shadow_atlas->shadow_owners.erase(p_rid); - } - - light_instance_owner.free(p_rid); - - } else if (shadow_atlas_owner.owns(p_rid)) { - - shadow_atlas_set_size(p_rid, 0); - shadow_atlas_owner.free(p_rid); - - } else { - return false; - } - - return true; -} - -void RasterizerSceneRD::set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw) { - debug_draw = p_debug_draw; -} - -void RasterizerSceneRD::update() { - _update_dirty_skys(); -} - -void RasterizerSceneRD::set_time(double p_time, double p_step) { - time = p_time; - time_step = p_step; -} - -void RasterizerSceneRD::screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) { - screen_space_roughness_limiter = p_enable; - screen_space_roughness_limiter_curve = p_curve; -} - -bool RasterizerSceneRD::screen_space_roughness_limiter_is_active() const { - return screen_space_roughness_limiter; -} - -float RasterizerSceneRD::screen_space_roughness_limiter_get_curve() const { - return screen_space_roughness_limiter_curve; -} - -RasterizerSceneRD *RasterizerSceneRD::singleton = NULL; - -RasterizerSceneRD::RasterizerSceneRD(RasterizerStorageRD *p_storage) { - storage = p_storage; - singleton = this; - - roughness_layers = GLOBAL_GET("rendering/quality/reflections/roughness_layers"); - sky_ggx_samples_quality = GLOBAL_GET("rendering/quality/reflections/ggx_samples"); - sky_use_cubemap_array = GLOBAL_GET("rendering/quality/reflections/texture_array_reflections"); - // sky_use_cubemap_array = false; - - uint32_t textures_per_stage = RD::get_singleton()->limit_get(RD::LIMIT_MAX_TEXTURES_PER_SHADER_STAGE); - - { - - //kinda complicated to compute the amount of slots, we try to use as many as we can - - gi_probe_max_lights = 32; - - gi_probe_lights = memnew_arr(GIProbeLight, gi_probe_max_lights); - gi_probe_lights_uniform = RD::get_singleton()->uniform_buffer_create(gi_probe_max_lights * sizeof(GIProbeLight)); - - gi_probe_use_anisotropy = GLOBAL_GET("rendering/quality/gi_probes/anisotropic"); - gi_probe_quality = GIProbeQuality(CLAMP(int(GLOBAL_GET("rendering/quality/gi_probes/quality")), 0, 2)); - - if (textures_per_stage <= 16) { - gi_probe_slots.resize(2); //thats all you can get - gi_probe_use_anisotropy = false; - } else if (textures_per_stage <= 31) { - gi_probe_slots.resize(4); //thats all you can get, iOS - gi_probe_use_anisotropy = false; - } else if (textures_per_stage <= 128) { - gi_probe_slots.resize(32); //old intel - gi_probe_use_anisotropy = false; - } else if (textures_per_stage <= 256) { - gi_probe_slots.resize(64); //old intel too - gi_probe_use_anisotropy = false; - } else { - if (gi_probe_use_anisotropy) { - gi_probe_slots.resize(1024 / 3); //needs 3 textures - } else { - gi_probe_slots.resize(1024); //modern intel, nvidia, 8192 or greater - } - } - - String defines = "\n#define MAX_LIGHTS " + itos(gi_probe_max_lights) + "\n"; - if (gi_probe_use_anisotropy) { - defines += "\n#define MODE_ANISOTROPIC\n"; - } - - Vector versions; - versions.push_back("\n#define MODE_COMPUTE_LIGHT\n"); - versions.push_back("\n#define MODE_SECOND_BOUNCE\n"); - versions.push_back("\n#define MODE_UPDATE_MIPMAPS\n"); - versions.push_back("\n#define MODE_WRITE_TEXTURE\n"); - versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_LIGHTING\n"); - versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_WRITE\n"); - versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n"); - versions.push_back("\n#define MODE_DYNAMIC\n#define MODE_DYNAMIC_SHRINK\n#define MODE_DYNAMIC_SHRINK_PLOT\n#define MODE_DYNAMIC_SHRINK_WRITE\n"); - - giprobe_shader.initialize(versions, defines); - giprobe_lighting_shader_version = giprobe_shader.version_create(); - for (int i = 0; i < GI_PROBE_SHADER_VERSION_MAX; i++) { - giprobe_lighting_shader_version_shaders[i] = giprobe_shader.version_get_shader(giprobe_lighting_shader_version, i); - giprobe_lighting_shader_version_pipelines[i] = RD::get_singleton()->compute_pipeline_create(giprobe_lighting_shader_version_shaders[i]); - } - } - - { - - String defines; - if (gi_probe_use_anisotropy) { - defines += "\n#define USE_ANISOTROPY\n"; - } - Vector versions; - versions.push_back("\n#define MODE_DEBUG_COLOR\n"); - versions.push_back("\n#define MODE_DEBUG_LIGHT\n"); - versions.push_back("\n#define MODE_DEBUG_EMISSION\n"); - versions.push_back("\n#define MODE_DEBUG_LIGHT\n#define MODE_DEBUG_LIGHT_FULL\n"); - - giprobe_debug_shader.initialize(versions, defines); - giprobe_debug_shader_version = giprobe_debug_shader.version_create(); - for (int i = 0; i < GI_PROBE_DEBUG_MAX; i++) { - giprobe_debug_shader_version_shaders[i] = giprobe_debug_shader.version_get_shader(giprobe_debug_shader_version, i); - - RD::PipelineRasterizationState rs; - rs.cull_mode = RD::POLYGON_CULL_FRONT; - RD::PipelineDepthStencilState ds; - ds.enable_depth_test = true; - ds.enable_depth_write = true; - ds.depth_compare_operator = RD::COMPARE_OP_LESS_OR_EQUAL; - - giprobe_debug_shader_version_pipelines[i].setup(giprobe_debug_shader_version_shaders[i], RD::RENDER_PRIMITIVE_TRIANGLES, rs, RD::PipelineMultisampleState(), ds, RD::PipelineColorBlendState::create_disabled(), 0); - } - } - - /* SKY SHADER */ - - { - // Start with the directional lights for the sky - sky_scene_state.max_directional_lights = 4; - uint32_t directional_light_buffer_size = sky_scene_state.max_directional_lights * sizeof(SkyDirectionalLightData); - sky_scene_state.directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights); - sky_scene_state.last_frame_directional_lights = memnew_arr(SkyDirectionalLightData, sky_scene_state.max_directional_lights); - sky_scene_state.last_frame_directional_light_count = sky_scene_state.max_directional_lights + 1; - sky_scene_state.directional_light_buffer = RD::get_singleton()->uniform_buffer_create(directional_light_buffer_size); - - String defines = "\n#define MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS " + itos(sky_scene_state.max_directional_lights) + "\n"; - - // Initialize sky - Vector sky_modes; - sky_modes.push_back(""); // Full size - sky_modes.push_back("\n#define USE_HALF_RES_PASS\n"); // Half Res - sky_modes.push_back("\n#define USE_QUARTER_RES_PASS\n"); // Quarter res - sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n"); // Cubemap - sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_HALF_RES_PASS\n"); // Half Res Cubemap - sky_modes.push_back("\n#define USE_CUBEMAP_PASS\n#define USE_QUARTER_RES_PASS\n"); // Quarter res Cubemap - sky_shader.shader.initialize(sky_modes, defines); - } - - // register our shader funds - storage->shader_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_shader_funcs); - storage->material_set_data_request_function(RasterizerStorageRD::SHADER_TYPE_SKY, _create_sky_material_funcs); - - { - ShaderCompilerRD::DefaultIdentifierActions actions; - - actions.renames["COLOR"] = "color"; - actions.renames["ALPHA"] = "alpha"; - actions.renames["EYEDIR"] = "cube_normal"; - actions.renames["POSITION"] = "params.position_multiplier.xyz"; - actions.renames["SKY_COORDS"] = "panorama_coords"; - actions.renames["SCREEN_UV"] = "uv"; - actions.renames["TIME"] = "params.time"; - actions.renames["HALF_RES_COLOR"] = "half_res_color"; - actions.renames["QUARTER_RES_COLOR"] = "quarter_res_color"; - actions.renames["RADIANCE"] = "radiance"; - actions.renames["LIGHT0_ENABLED"] = "directional_lights.data[0].enabled"; - actions.renames["LIGHT0_DIRECTION"] = "directional_lights.data[0].direction"; - actions.renames["LIGHT0_ENERGY"] = "directional_lights.data[0].energy"; - actions.renames["LIGHT0_COLOR"] = "directional_lights.data[0].color"; - actions.renames["LIGHT1_ENABLED"] = "directional_lights.data[1].enabled"; - actions.renames["LIGHT1_DIRECTION"] = "directional_lights.data[1].direction"; - actions.renames["LIGHT1_ENERGY"] = "directional_lights.data[1].energy"; - actions.renames["LIGHT1_COLOR"] = "directional_lights.data[1].color"; - actions.renames["LIGHT2_ENABLED"] = "directional_lights.data[2].enabled"; - actions.renames["LIGHT2_DIRECTION"] = "directional_lights.data[2].direction"; - actions.renames["LIGHT2_ENERGY"] = "directional_lights.data[2].energy"; - actions.renames["LIGHT2_COLOR"] = "directional_lights.data[2].color"; - actions.renames["LIGHT3_ENABLED"] = "directional_lights.data[3].enabled"; - actions.renames["LIGHT3_DIRECTION"] = "directional_lights.data[3].direction"; - actions.renames["LIGHT3_ENERGY"] = "directional_lights.data[3].energy"; - actions.renames["LIGHT3_COLOR"] = "directional_lights.data[3].color"; - actions.renames["AT_CUBEMAP_PASS"] = "AT_CUBEMAP_PASS"; - actions.renames["AT_HALF_RES_PASS"] = "AT_HALF_RES_PASS"; - actions.renames["AT_QUARTER_RES_PASS"] = "AT_QUARTER_RES_PASS"; - actions.custom_samplers["RADIANCE"] = "material_samplers[3]"; - actions.usage_defines["HALF_RES_COLOR"] = "\n#define USES_HALF_RES_COLOR\n"; - actions.usage_defines["QUARTER_RES_COLOR"] = "\n#define USES_QUARTER_RES_COLOR\n"; - - actions.sampler_array_name = "material_samplers"; - actions.base_texture_binding_index = 1; - actions.texture_layout_set = 1; - actions.base_uniform_string = "material."; - actions.base_varying_index = 10; - - actions.default_filter = ShaderLanguage::FILTER_LINEAR_MIPMAP; - actions.default_repeat = ShaderLanguage::REPEAT_ENABLE; - - sky_shader.compiler.initialize(actions); - } - - { - // default material and shader for sky shader - sky_shader.default_shader = storage->shader_create(); - storage->shader_set_code(sky_shader.default_shader, "shader_type sky; void fragment() { COLOR = mix(vec3(0.3), vec3(0.2, 0.4, 0.9), smoothstep(0.0, 0.05, EYEDIR.y)); } \n"); - sky_shader.default_material = storage->material_create(); - storage->material_set_shader(sky_shader.default_material, sky_shader.default_shader); - - SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); - sky_shader.default_shader_rd = sky_shader.shader.version_get_shader(md->shader_data->version, SKY_VERSION_BACKGROUND); - - Vector uniforms; - - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_SAMPLER; - u.binding = 0; - u.ids.resize(12); - RID *ids_ptr = u.ids.ptrw(); - ids_ptr[0] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[1] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[2] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[3] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[4] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[5] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - ids_ptr[6] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[7] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[8] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[9] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[10] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - ids_ptr[11] = storage->sampler_rd_get_default(VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - uniforms.push_back(u); - } - - sky_scene_state.sampler_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_SAMPLERS); - } - - camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_shape")))); - camera_effects_set_dof_blur_quality(VS::DOFBlurQuality(int(GLOBAL_GET("rendering/quality/filters/depth_of_field_bokeh_quality"))), GLOBAL_GET("rendering/quality/filters/depth_of_field_use_jitter")); - environment_set_ssao_quality(VS::EnvironmentSSAOQuality(int(GLOBAL_GET("rendering/quality/ssao/quality"))), GLOBAL_GET("rendering/quality/ssao/half_size")); - screen_space_roughness_limiter = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter"); - screen_space_roughness_limiter_curve = GLOBAL_GET("rendering/quality/filters/screen_space_roughness_limiter_curve"); -} - -RasterizerSceneRD::~RasterizerSceneRD() { - for (Map::Element *E = shadow_maps.front(); E; E = E->next()) { - RD::get_singleton()->free(E->get().depth); - } - for (Map::Element *E = shadow_cubemaps.front(); E; E = E->next()) { - RD::get_singleton()->free(E->get().cubemap); - } - - if (sky_scene_state.sampler_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.sampler_uniform_set)) { - RD::get_singleton()->free(sky_scene_state.sampler_uniform_set); - } - if (sky_scene_state.light_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky_scene_state.light_uniform_set)) { - RD::get_singleton()->free(sky_scene_state.light_uniform_set); - } - - RD::get_singleton()->free(gi_probe_lights_uniform); - giprobe_debug_shader.version_free(giprobe_debug_shader_version); - giprobe_shader.version_free(giprobe_lighting_shader_version); - memdelete_arr(gi_probe_lights); - SkyMaterialData *md = (SkyMaterialData *)storage->material_get_data(sky_shader.default_material, RasterizerStorageRD::SHADER_TYPE_SKY); - sky_shader.shader.version_free(md->shader_data->version); - RD::get_singleton()->free(sky_scene_state.directional_light_buffer); - memdelete_arr(sky_scene_state.directional_lights); - memdelete_arr(sky_scene_state.last_frame_directional_lights); - storage->free(sky_shader.default_shader); - storage->free(sky_shader.default_material); -} diff --git a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h b/servers/visual/rasterizer_rd/rasterizer_scene_rd.h deleted file mode 100644 index 7332f93dc5..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_scene_rd.h +++ /dev/null @@ -1,1109 +0,0 @@ -/*************************************************************************/ -/* rasterizer_scene_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_SCENE_RD_H -#define RASTERIZER_SCENE_RD_H - -#include "core/rid_owner.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/rasterizer_rd/rasterizer_storage_rd.h" -#include "servers/visual/rasterizer_rd/shaders/giprobe.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl.gen.h" -#include "servers/visual/rasterizer_rd/shaders/sky.glsl.gen.h" -#include "servers/visual/rendering_device.h" - -class RasterizerSceneRD : public RasterizerScene { -public: - enum GIProbeQuality { - GIPROBE_QUALITY_ULTRA_LOW, - GIPROBE_QUALITY_MEDIUM, - GIPROBE_QUALITY_HIGH, - }; - -protected: - double time; - - // Skys need less info from Directional Lights than the normal shaders - struct SkyDirectionalLightData { - - float direction[3]; - float energy; - float color[3]; - uint32_t enabled; - }; - - struct SkySceneState { - - SkyDirectionalLightData *directional_lights; - SkyDirectionalLightData *last_frame_directional_lights; - uint32_t max_directional_lights; - uint32_t directional_light_count; - uint32_t last_frame_directional_light_count; - RID directional_light_buffer; - RID sampler_uniform_set; - RID light_uniform_set; - } sky_scene_state; - - struct RenderBufferData { - - virtual void configure(RID p_color_buffer, RID p_depth_buffer, int p_width, int p_height, VS::ViewportMSAA p_msaa) = 0; - virtual ~RenderBufferData() {} - }; - virtual RenderBufferData *_create_render_buffer_data() = 0; - - virtual void _render_scene(RID p_render_buffer, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_camera_effects, RID p_shadow_atlas, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, const Color &p_default_color) = 0; - virtual void _render_shadow(RID p_framebuffer, InstanceBase **p_cull_result, int p_cull_count, const CameraMatrix &p_projection, const Transform &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_use_dp, bool use_dp_flip) = 0; - virtual void _render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region) = 0; - - virtual void _debug_giprobe(RID p_gi_probe, RenderingDevice::DrawListID p_draw_list, RID p_framebuffer, const CameraMatrix &p_camera_with_transform, bool p_lighting, bool p_emission, float p_alpha); - - RenderBufferData *render_buffers_get_data(RID p_render_buffers); - - virtual void _base_uniforms_changed() = 0; - virtual void _render_buffers_uniform_set_changed(RID p_render_buffers) = 0; - virtual RID _render_buffers_get_roughness_texture(RID p_render_buffers) = 0; - virtual RID _render_buffers_get_normal_texture(RID p_render_buffers) = 0; - - void _process_ssao(RID p_render_buffers, RID p_environment, RID p_normal_buffer, const CameraMatrix &p_projection); - - void _setup_sky(RID p_environment, const Vector3 &p_position, const Size2i p_screen_size); - void _update_sky(RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); - void _draw_sky(bool p_can_continue, RID p_fb, RID p_environment, const CameraMatrix &p_projection, const Transform &p_transform); - -private: - VS::ViewportDebugDraw debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; - double time_step = 0; - static RasterizerSceneRD *singleton; - - int roughness_layers; - - RasterizerStorageRD *storage; - - struct ReflectionData { - - struct Layer { - struct Mipmap { - RID framebuffers[6]; - RID views[6]; - Size2i size; - }; - Vector mipmaps; //per-face view - Vector views; // per-cubemap view - }; - - struct DownsampleLayer { - struct Mipmap { - RID view; - Size2i size; - }; - Vector mipmaps; - }; - - RID radiance_base_cubemap; //cubemap for first layer, first cubemap - RID downsampled_radiance_cubemap; - DownsampleLayer downsampled_layer; - RID coefficient_buffer; - - bool dirty = true; - - Vector layers; - }; - - void _clear_reflection_data(ReflectionData &rd); - void _update_reflection_data(ReflectionData &rd, int p_size, int p_mipmaps, bool p_use_array, RID p_base_cube, int p_base_layer, bool p_low_quality); - void _create_reflection_fast_filter(ReflectionData &rd, bool p_use_arrays); - void _create_reflection_importance_sample(ReflectionData &rd, bool p_use_arrays, int p_cube_side, int p_base_layer); - void _update_reflection_mipmaps(ReflectionData &rd); - - /* Sky shader */ - - enum SkyVersion { - SKY_VERSION_BACKGROUND, - SKY_VERSION_HALF_RES, - SKY_VERSION_QUARTER_RES, - SKY_VERSION_CUBEMAP, - SKY_VERSION_CUBEMAP_HALF_RES, - SKY_VERSION_CUBEMAP_QUARTER_RES, - SKY_VERSION_MAX - }; - - struct SkyShader { - SkyShaderRD shader; - ShaderCompilerRD compiler; - - RID default_shader; - RID default_material; - RID default_shader_rd; - } sky_shader; - - struct SkyShaderData : public RasterizerStorageRD::ShaderData { - bool valid; - RID version; - - RenderPipelineVertexFormatCacheRD pipelines[SKY_VERSION_MAX]; - Map uniforms; - Vector texture_uniforms; - - Vector ubo_offsets; - uint32_t ubo_size; - - String path; - String code; - Map default_texture_params; - - bool uses_time; - bool uses_position; - bool uses_half_res; - bool uses_quarter_res; - bool uses_light; - - virtual void set_code(const String &p_Code); - virtual void set_default_texture_param(const StringName &p_name, RID p_texture); - virtual void get_param_list(List *p_param_list) const; - virtual bool is_param_texture(const StringName &p_param) const; - virtual bool is_animated() const; - virtual bool casts_shadows() const; - virtual Variant get_default_parameter(const StringName &p_parameter) const; - SkyShaderData(); - virtual ~SkyShaderData(); - }; - - RasterizerStorageRD::ShaderData *_create_sky_shader_func(); - static RasterizerStorageRD::ShaderData *_create_sky_shader_funcs() { - return static_cast(singleton)->_create_sky_shader_func(); - }; - - struct SkyMaterialData : public RasterizerStorageRD::MaterialData { - uint64_t last_frame; - SkyShaderData *shader_data; - RID uniform_buffer; - RID uniform_set; - Vector texture_cache; - Vector ubo_data; - bool uniform_set_updated; - - virtual void set_render_priority(int p_priority) {} - virtual void set_next_pass(RID p_pass) {} - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty); - virtual ~SkyMaterialData(); - }; - - RasterizerStorageRD::MaterialData *_create_sky_material_func(SkyShaderData *p_shader); - static RasterizerStorageRD::MaterialData *_create_sky_material_funcs(RasterizerStorageRD::ShaderData *p_shader) { - return static_cast(singleton)->_create_sky_material_func(static_cast(p_shader)); - }; - - enum SkyTextureSetVersion { - SKY_TEXTURE_SET_BACKGROUND, - SKY_TEXTURE_SET_HALF_RES, - SKY_TEXTURE_SET_QUARTER_RES, - SKY_TEXTURE_SET_CUBEMAP, - SKY_TEXTURE_SET_CUBEMAP_HALF_RES, - SKY_TEXTURE_SET_CUBEMAP_QUARTER_RES, - SKY_TEXTURE_SET_MAX - }; - - enum SkySet { - SKY_SET_SAMPLERS, - SKY_SET_MATERIAL, - SKY_SET_TEXTURES, - SKY_SET_LIGHTS, - SKY_SET_MAX - }; - - /* SKY */ - struct Sky { - RID radiance; - RID half_res_pass; - RID half_res_framebuffer; - RID quarter_res_pass; - RID quarter_res_framebuffer; - Size2i screen_size; - - RID texture_uniform_sets[SKY_TEXTURE_SET_MAX]; - RID uniform_set; - - RID material; - RID uniform_buffer; - - int radiance_size = 256; - - VS::SkyMode mode = VS::SKY_MODE_QUALITY; - - ReflectionData reflection; - bool dirty = false; - Sky *dirty_list = nullptr; - - //State to track when radiance cubemap needs updating - SkyMaterialData *prev_material; - Vector3 prev_position; - float prev_time; - }; - - Sky *dirty_sky_list = nullptr; - - void _sky_invalidate(Sky *p_sky); - void _update_dirty_skys(); - RID _get_sky_textures(Sky *p_sky, SkyTextureSetVersion p_version); - - uint32_t sky_ggx_samples_quality; - bool sky_use_cubemap_array; - - mutable RID_Owner sky_owner; - - /* REFLECTION ATLAS */ - - struct ReflectionAtlas { - - int count = 0; - int size = 0; - - RID reflection; - RID depth_buffer; - RID depth_fb; - - struct Reflection { - RID owner; - ReflectionData data; - RID fbs[6]; - }; - - Vector reflections; - }; - - RID_Owner reflection_atlas_owner; - - /* REFLECTION PROBE INSTANCE */ - - struct ReflectionProbeInstance { - - RID probe; - int atlas_index = -1; - RID atlas; - - bool dirty = true; - bool rendering = false; - int processing_layer = 1; - int processing_side = 0; - - uint32_t render_step = 0; - uint64_t last_pass = 0; - uint32_t render_index = 0; - - Transform transform; - }; - - mutable RID_Owner reflection_probe_instance_owner; - - /* GIPROBE INSTANCE */ - - struct GIProbeLight { - - uint32_t type; - float energy; - float radius; - float attenuation; - - float color[3]; - float spot_angle_radians; - - float position[3]; - float spot_attenuation; - - float direction[3]; - uint32_t has_shadow; - }; - - struct GIProbePushConstant { - - int32_t limits[3]; - uint32_t stack_size; - - float emission_scale; - float propagation; - float dynamic_range; - uint32_t light_count; - - uint32_t cell_offset; - uint32_t cell_count; - float aniso_strength; - uint32_t pad; - }; - - struct GIProbeDynamicPushConstant { - - int32_t limits[3]; - uint32_t light_count; - int32_t x_dir[3]; - float z_base; - int32_t y_dir[3]; - float z_sign; - int32_t z_dir[3]; - float pos_multiplier; - uint32_t rect_pos[2]; - uint32_t rect_size[2]; - uint32_t prev_rect_ofs[2]; - uint32_t prev_rect_size[2]; - uint32_t flip_x; - uint32_t flip_y; - float dynamic_range; - uint32_t on_mipmap; - float propagation; - float pad[3]; - }; - - struct GIProbeInstance { - - RID probe; - RID texture; - RID anisotropy[2]; //only if anisotropy is used - RID anisotropy_r16[2]; //only if anisotropy is used - RID write_buffer; - - struct Mipmap { - RID texture; - RID anisotropy[2]; //only if anisotropy is used - RID uniform_set; - RID second_bounce_uniform_set; - RID write_uniform_set; - uint32_t level; - uint32_t cell_offset; - uint32_t cell_count; - }; - Vector mipmaps; - - struct DynamicMap { - RID texture; //color normally, or emission on first pass - RID fb_depth; //actual depth buffer for the first pass, float depth for later passes - RID depth; //actual depth buffer for the first pass, float depth for later passes - RID normal; //normal buffer for the first pass - RID albedo; //emission buffer for the first pass - RID orm; //orm buffer for the first pass - RID fb; //used for rendering, only valid on first map - RID uniform_set; - uint32_t size; - int mipmap; // mipmap to write to, -1 if no mipmap assigned - }; - - Vector dynamic_maps; - - int slot = -1; - uint32_t last_probe_version = 0; - uint32_t last_probe_data_version = 0; - - uint64_t last_pass = 0; - uint32_t render_index = 0; - - bool has_dynamic_object_data = false; - - Transform transform; - }; - - GIProbeLight *gi_probe_lights; - uint32_t gi_probe_max_lights; - RID gi_probe_lights_uniform; - - bool gi_probe_use_anisotropy = false; - GIProbeQuality gi_probe_quality = GIPROBE_QUALITY_MEDIUM; - - Vector gi_probe_slots; - - enum { - GI_PROBE_SHADER_VERSION_COMPUTE_LIGHT, - GI_PROBE_SHADER_VERSION_COMPUTE_SECOND_BOUNCE, - GI_PROBE_SHADER_VERSION_COMPUTE_MIPMAP, - GI_PROBE_SHADER_VERSION_WRITE_TEXTURE, - GI_PROBE_SHADER_VERSION_DYNAMIC_OBJECT_LIGHTING, - GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE, - GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_PLOT, - GI_PROBE_SHADER_VERSION_DYNAMIC_SHRINK_WRITE_PLOT, - GI_PROBE_SHADER_VERSION_MAX - }; - GiprobeShaderRD giprobe_shader; - RID giprobe_lighting_shader_version; - RID giprobe_lighting_shader_version_shaders[GI_PROBE_SHADER_VERSION_MAX]; - RID giprobe_lighting_shader_version_pipelines[GI_PROBE_SHADER_VERSION_MAX]; - - mutable RID_Owner gi_probe_instance_owner; - - enum { - GI_PROBE_DEBUG_COLOR, - GI_PROBE_DEBUG_LIGHT, - GI_PROBE_DEBUG_EMISSION, - GI_PROBE_DEBUG_LIGHT_FULL, - GI_PROBE_DEBUG_MAX - }; - - struct GIProbeDebugPushConstant { - float projection[16]; - uint32_t cell_offset; - float dynamic_range; - float alpha; - uint32_t level; - int32_t bounds[3]; - uint32_t pad; - }; - - GiprobeDebugShaderRD giprobe_debug_shader; - RID giprobe_debug_shader_version; - RID giprobe_debug_shader_version_shaders[GI_PROBE_DEBUG_MAX]; - RenderPipelineVertexFormatCacheRD giprobe_debug_shader_version_pipelines[GI_PROBE_DEBUG_MAX]; - RID giprobe_debug_uniform_set; - - /* SHADOW ATLAS */ - - struct ShadowAtlas { - - enum { - QUADRANT_SHIFT = 27, - SHADOW_INDEX_MASK = (1 << QUADRANT_SHIFT) - 1, - SHADOW_INVALID = 0xFFFFFFFF - }; - - struct Quadrant { - - uint32_t subdivision; - - struct Shadow { - RID owner; - uint64_t version; - uint64_t alloc_tick; - - Shadow() { - version = 0; - alloc_tick = 0; - } - }; - - Vector shadows; - - Quadrant() { - subdivision = 0; //not in use - } - - } quadrants[4]; - - int size_order[4] = { 0, 1, 2, 3 }; - uint32_t smallest_subdiv = 0; - - int size = 0; - - RID depth; - RID fb; //for copying - - Map shadow_owners; - }; - - RID_Owner shadow_atlas_owner; - - bool _shadow_atlas_find_shadow(ShadowAtlas *shadow_atlas, int *p_in_quadrants, int p_quadrant_count, int p_current_subdiv, uint64_t p_tick, int &r_quadrant, int &r_shadow); - - /* DIRECTIONAL SHADOW */ - - struct DirectionalShadow { - RID depth; - RID fb; //for copying - - int light_count = 0; - int size = 0; - int current_light = 0; - } directional_shadow; - - /* SHADOW CUBEMAPS */ - - struct ShadowCubemap { - - RID cubemap; - RID side_fb[6]; - }; - - Map shadow_cubemaps; - ShadowCubemap *_get_shadow_cubemap(int p_size); - - struct ShadowMap { - RID depth; - RID fb; - }; - - Map shadow_maps; - ShadowMap *_get_shadow_map(const Size2i &p_size); - - void _create_shadow_cubemaps(); - - /* LIGHT INSTANCE */ - - struct LightInstance { - - struct ShadowTransform { - - CameraMatrix camera; - Transform transform; - float farplane; - float split; - float bias_scale; - Rect2 atlas_rect; - }; - - VS::LightType light_type; - - ShadowTransform shadow_transform[4]; - - RID self; - RID light; - Transform transform; - - Vector3 light_vector; - Vector3 spot_vector; - float linear_att; - - uint64_t shadow_pass = 0; - uint64_t last_scene_pass = 0; - uint64_t last_scene_shadow_pass = 0; - uint64_t last_pass = 0; - uint32_t light_index = 0; - uint32_t light_directional_index = 0; - - uint32_t current_shadow_atlas_key; - - Vector2 dp; - - Rect2 directional_rect; - - Set shadow_atlases; //shadow atlases where this light is registered - - LightInstance() {} - }; - - mutable RID_Owner light_instance_owner; - - /* ENVIRONMENT */ - - struct Environent { - - // BG - VS::EnvironmentBG background = VS::ENV_BG_CLEAR_COLOR; - RID sky; - float sky_custom_fov = 0.0; - Basis sky_orientation; - Color bg_color; - float bg_energy = 1.0; - int canvas_max_layer = 0; - VS::EnvironmentAmbientSource ambient_source = VS::ENV_AMBIENT_SOURCE_BG; - Color ambient_light; - float ambient_light_energy = 1.0; - float ambient_sky_contribution = 1.0; - VS::EnvironmentReflectionSource reflection_source = VS::ENV_REFLECTION_SOURCE_BG; - Color ao_color; - - /// Tonemap - - VS::EnvironmentToneMapper tone_mapper; - float exposure = 1.0; - float white = 1.0; - bool auto_exposure = false; - float min_luminance = 0.2; - float max_luminance = 8.0; - float auto_exp_speed = 0.2; - float auto_exp_scale = 0.5; - uint64_t auto_exposure_version = 0; - - /// Glow - - bool glow_enabled = false; - int glow_levels = (1 << 2) | (1 << 4); - float glow_intensity = 0.8; - float glow_strength = 1.0; - float glow_bloom = 0.0; - float glow_mix = 0.01; - VS::EnvironmentGlowBlendMode glow_blend_mode = VS::ENV_GLOW_BLEND_MODE_SOFTLIGHT; - float glow_hdr_bleed_threshold = 1.0; - float glow_hdr_luminance_cap = 12.0; - float glow_hdr_bleed_scale = 2.0; - bool glow_bicubic_upscale = false; - - /// SSAO - - bool ssao_enabled = false; - float ssao_radius = 1; - float ssao_intensity = 1; - float ssao_bias = 0.01; - float ssao_direct_light_affect = 0.0; - float ssao_ao_channel_affect = 0.0; - float ssao_blur_edge_sharpness = 4.0; - VS::EnvironmentSSAOBlur ssao_blur = VS::ENV_SSAO_BLUR_3x3; - }; - - VS::EnvironmentSSAOQuality ssao_quality = VS::ENV_SSAO_QUALITY_MEDIUM; - bool ssao_half_size = false; - - static uint64_t auto_exposure_counter; - - mutable RID_Owner environment_owner; - - /* CAMERA EFFECTS */ - - struct CameraEffects { - - bool dof_blur_far_enabled = false; - float dof_blur_far_distance = 10; - float dof_blur_far_transition = 5; - - bool dof_blur_near_enabled = false; - float dof_blur_near_distance = 2; - float dof_blur_near_transition = 1; - - float dof_blur_amount = 0.1; - - bool override_exposure_enabled = false; - float override_exposure = 1; - }; - - VS::DOFBlurQuality dof_blur_quality = VS::DOF_BLUR_QUALITY_MEDIUM; - VS::DOFBokehShape dof_blur_bokeh_shape = VS::DOF_BOKEH_HEXAGON; - bool dof_blur_use_jitter = false; - - mutable RID_Owner camera_effects_owner; - - /* RENDER BUFFERS */ - - struct RenderBuffers { - - RenderBufferData *data = nullptr; - int width = 0, height = 0; - VS::ViewportMSAA msaa = VS::VIEWPORT_MSAA_DISABLED; - RID render_target; - - uint64_t auto_exposure_version = 1; - - RID texture; //main texture for rendering to, must be filled after done rendering - RID depth_texture; //main depth texture - - //built-in textures used for ping pong image processing and blurring - struct Blur { - RID texture; - - struct Mipmap { - RID texture; - RID framebuffer; - int width; - int height; - }; - - Vector mipmaps; - }; - - Blur blur[2]; //the second one starts from the first mipmap - - struct Luminance { - - Vector reduce; - RID current; - } luminance; - - struct SSAO { - RID depth; - Vector depth_slices; - RID ao[2]; - RID ao_full; //when using half-size - } ssao; - }; - - bool screen_space_roughness_limiter = false; - float screen_space_roughness_limiter_curve = 1.0; - - mutable RID_Owner render_buffers_owner; - - void _free_render_buffer_data(RenderBuffers *rb); - void _allocate_blur_textures(RenderBuffers *rb); - void _allocate_luminance_textures(RenderBuffers *rb); - - void _render_buffers_debug_draw(RID p_render_buffers, RID p_shadow_atlas); - void _render_buffers_post_process_and_tonemap(RID p_render_buffers, RID p_environment, RID p_camera_effects, const CameraMatrix &p_projection); - - uint64_t scene_pass = 0; - uint64_t shadow_atlas_realloc_tolerance_msec = 500; - -public: - /* SHADOW ATLAS API */ - - RID shadow_atlas_create(); - void shadow_atlas_set_size(RID p_atlas, int p_size); - void shadow_atlas_set_quadrant_subdivision(RID p_atlas, int p_quadrant, int p_subdivision); - bool shadow_atlas_update_light(RID p_atlas, RID p_light_intance, float p_coverage, uint64_t p_light_version); - _FORCE_INLINE_ bool shadow_atlas_owns_light_instance(RID p_atlas, RID p_light_intance) { - ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND_V(!atlas, false); - return atlas->shadow_owners.has(p_light_intance); - } - - _FORCE_INLINE_ RID shadow_atlas_get_texture(RID p_atlas) { - ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->depth; - } - - _FORCE_INLINE_ Size2i shadow_atlas_get_size(RID p_atlas) { - ShadowAtlas *atlas = shadow_atlas_owner.getornull(p_atlas); - ERR_FAIL_COND_V(!atlas, Size2i()); - return Size2(atlas->size, atlas->size); - } - - void directional_shadow_atlas_set_size(int p_size); - int get_directional_light_shadow_size(RID p_light_intance); - void set_directional_shadow_count(int p_count); - - _FORCE_INLINE_ RID directional_shadow_get_texture() { - return directional_shadow.depth; - } - - _FORCE_INLINE_ Size2i directional_shadow_get_size() { - return Size2i(directional_shadow.size, directional_shadow.size); - } - - /* SKY API */ - - RID sky_create(); - void sky_set_radiance_size(RID p_sky, int p_radiance_size); - void sky_set_mode(RID p_sky, VS::SkyMode p_mode); - void sky_set_material(RID p_sky, RID p_material); - - RID sky_get_radiance_texture_rd(RID p_sky) const; - RID sky_get_radiance_uniform_set_rd(RID p_sky, RID p_shader, int p_set) const; - RID sky_get_material(RID p_sky) const; - - /* ENVIRONMENT API */ - - RID environment_create(); - - void environment_set_background(RID p_env, VS::EnvironmentBG p_bg); - void environment_set_sky(RID p_env, RID p_sky); - void environment_set_sky_custom_fov(RID p_env, float p_scale); - void environment_set_sky_orientation(RID p_env, const Basis &p_orientation); - void environment_set_bg_color(RID p_env, const Color &p_color); - void environment_set_bg_energy(RID p_env, float p_energy); - void environment_set_canvas_max_layer(RID p_env, int p_max_layer); - void environment_set_ambient_light(RID p_env, const Color &p_color, VS::EnvironmentAmbientSource p_ambient = VS::ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, VS::EnvironmentReflectionSource p_reflection_source = VS::ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()); - - VS::EnvironmentBG environment_get_background(RID p_env) const; - RID environment_get_sky(RID p_env) const; - float environment_get_sky_custom_fov(RID p_env) const; - Basis environment_get_sky_orientation(RID p_env) const; - Color environment_get_bg_color(RID p_env) const; - float environment_get_bg_energy(RID p_env) const; - int environment_get_canvas_max_layer(RID p_env) const; - Color environment_get_ambient_light_color(RID p_env) const; - VS::EnvironmentAmbientSource environment_get_ambient_light_ambient_source(RID p_env) const; - float environment_get_ambient_light_ambient_energy(RID p_env) const; - float environment_get_ambient_sky_contribution(RID p_env) const; - VS::EnvironmentReflectionSource environment_get_reflection_source(RID p_env) const; - Color environment_get_ao_color(RID p_env) const; - - bool is_environment(RID p_env) const; - - void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, VS::EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale); - - void environment_set_fog(RID p_env, bool p_enable, float p_begin, float p_end, RID p_gradient_texture) {} - - void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_int, float p_fade_out, float p_depth_tolerance, bool p_roughness) {} - void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, VS::EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness); - void environment_set_ssao_quality(VS::EnvironmentSSAOQuality p_quality, bool p_half_size); - bool environment_is_ssao_enabled(RID p_env) const; - float environment_get_ssao_ao_affect(RID p_env) const; - float environment_get_ssao_light_affect(RID p_env) const; - bool environment_is_ssr_enabled(RID p_env) const; - - void environment_set_tonemap(RID p_env, VS::EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_scale); - void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) {} - - void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) {} - void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) {} - void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) {} - - virtual RID camera_effects_create(); - - virtual void camera_effects_set_dof_blur_quality(VS::DOFBlurQuality p_quality, bool p_use_jitter); - virtual void camera_effects_set_dof_blur_bokeh_shape(VS::DOFBokehShape p_shape); - - virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount); - virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure); - - RID light_instance_create(RID p_light); - void light_instance_set_transform(RID p_light_instance, const Transform &p_transform); - void light_instance_set_shadow_transform(RID p_light_instance, const CameraMatrix &p_projection, const Transform &p_transform, float p_far, float p_split, int p_pass, float p_bias_scale = 1.0); - void light_instance_mark_visible(RID p_light_instance); - - _FORCE_INLINE_ RID light_instance_get_base_light(RID p_light_instance) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->light; - } - - _FORCE_INLINE_ Transform light_instance_get_base_transform(RID p_light_instance) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->transform; - } - - _FORCE_INLINE_ Rect2 light_instance_get_shadow_atlas_rect(RID p_light_instance, RID p_shadow_atlas) { - - ShadowAtlas *shadow_atlas = shadow_atlas_owner.getornull(p_shadow_atlas); - LightInstance *li = light_instance_owner.getornull(p_light_instance); - uint32_t key = shadow_atlas->shadow_owners[li->self]; - - uint32_t quadrant = (key >> ShadowAtlas::QUADRANT_SHIFT) & 0x3; - uint32_t shadow = key & ShadowAtlas::SHADOW_INDEX_MASK; - - ERR_FAIL_COND_V(shadow >= (uint32_t)shadow_atlas->quadrants[quadrant].shadows.size(), Rect2()); - - uint32_t atlas_size = shadow_atlas->size; - uint32_t quadrant_size = atlas_size >> 1; - - uint32_t x = (quadrant & 1) * quadrant_size; - uint32_t y = (quadrant >> 1) * quadrant_size; - - uint32_t shadow_size = (quadrant_size / shadow_atlas->quadrants[quadrant].subdivision); - x += (shadow % shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - y += (shadow / shadow_atlas->quadrants[quadrant].subdivision) * shadow_size; - - uint32_t width = shadow_size; - uint32_t height = shadow_size; - - return Rect2(x / float(shadow_atlas->size), y / float(shadow_atlas->size), width / float(shadow_atlas->size), height / float(shadow_atlas->size)); - } - - _FORCE_INLINE_ CameraMatrix light_instance_get_shadow_camera(RID p_light_instance, int p_index) { - - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->shadow_transform[p_index].camera; - } - - _FORCE_INLINE_ Transform light_instance_get_shadow_transform(RID p_light_instance, int p_index) { - - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->shadow_transform[p_index].transform; - } - - _FORCE_INLINE_ Rect2 light_instance_get_directional_shadow_atlas_rect(RID p_light_instance, int p_index) { - - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->shadow_transform[p_index].atlas_rect; - } - - _FORCE_INLINE_ float light_instance_get_directional_shadow_split(RID p_light_instance, int p_index) { - - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->shadow_transform[p_index].split; - } - - _FORCE_INLINE_ void light_instance_set_render_pass(RID p_light_instance, uint64_t p_pass) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - li->last_pass = p_pass; - } - - _FORCE_INLINE_ uint64_t light_instance_get_render_pass(RID p_light_instance) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->last_pass; - } - - _FORCE_INLINE_ void light_instance_set_index(RID p_light_instance, uint32_t p_index) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - li->light_index = p_index; - } - - _FORCE_INLINE_ uint32_t light_instance_get_index(RID p_light_instance) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->light_index; - } - - _FORCE_INLINE_ VS::LightType light_instance_get_type(RID p_light_instance) { - LightInstance *li = light_instance_owner.getornull(p_light_instance); - return li->light_type; - } - - virtual RID reflection_atlas_create(); - virtual void reflection_atlas_set_size(RID p_ref_atlas, int p_reflection_size, int p_reflection_count); - _FORCE_INLINE_ RID reflection_atlas_get_texture(RID p_ref_atlas) { - ReflectionAtlas *atlas = reflection_atlas_owner.getornull(p_ref_atlas); - ERR_FAIL_COND_V(!atlas, RID()); - return atlas->reflection; - } - - virtual RID reflection_probe_instance_create(RID p_probe); - virtual void reflection_probe_instance_set_transform(RID p_instance, const Transform &p_transform); - virtual void reflection_probe_release_atlas_index(RID p_instance); - virtual bool reflection_probe_instance_needs_redraw(RID p_instance); - virtual bool reflection_probe_instance_has_reflection(RID p_instance); - virtual bool reflection_probe_instance_begin_render(RID p_instance, RID p_reflection_atlas); - virtual bool reflection_probe_instance_postprocess_step(RID p_instance); - - uint32_t reflection_probe_instance_get_resolution(RID p_instance); - RID reflection_probe_instance_get_framebuffer(RID p_instance, int p_index); - RID reflection_probe_instance_get_depth_framebuffer(RID p_instance, int p_index); - - _FORCE_INLINE_ RID reflection_probe_instance_get_probe(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, RID()); - - return rpi->probe; - } - - _FORCE_INLINE_ void reflection_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - rpi->render_index = p_render_index; - } - - _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_index(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, 0); - - return rpi->render_index; - } - - _FORCE_INLINE_ void reflection_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!rpi); - rpi->last_pass = p_render_pass; - } - - _FORCE_INLINE_ uint32_t reflection_probe_instance_get_render_pass(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, 0); - - return rpi->last_pass; - } - - _FORCE_INLINE_ Transform reflection_probe_instance_get_transform(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, Transform()); - - return rpi->transform; - } - - _FORCE_INLINE_ int reflection_probe_instance_get_atlas_index(RID p_instance) { - ReflectionProbeInstance *rpi = reflection_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!rpi, -1); - - return rpi->atlas_index; - } - - RID gi_probe_instance_create(RID p_base); - void gi_probe_instance_set_transform_to_data(RID p_probe, const Transform &p_xform); - bool gi_probe_needs_update(RID p_probe) const; - void gi_probe_update(RID p_probe, bool p_update_light_instances, const Vector &p_light_instances, int p_dynamic_object_count, InstanceBase **p_dynamic_objects); - - _FORCE_INLINE_ uint32_t gi_probe_instance_get_slot(RID p_probe) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - return gi_probe->slot; - } - _FORCE_INLINE_ RID gi_probe_instance_get_base_probe(RID p_probe) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - return gi_probe->probe; - } - _FORCE_INLINE_ Transform gi_probe_instance_get_transform_to_cell(RID p_probe) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - return storage->gi_probe_get_to_cell_xform(gi_probe->probe) * gi_probe->transform.affine_inverse(); - } - - _FORCE_INLINE_ RID gi_probe_instance_get_texture(RID p_probe) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - return gi_probe->texture; - } - _FORCE_INLINE_ RID gi_probe_instance_get_aniso_texture(RID p_probe, int p_index) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_probe); - return gi_probe->anisotropy[p_index]; - } - - _FORCE_INLINE_ void gi_probe_instance_set_render_index(RID p_instance, uint32_t p_render_index) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!gi_probe); - gi_probe->render_index = p_render_index; - } - - _FORCE_INLINE_ uint32_t gi_probe_instance_get_render_index(RID p_instance) { - GIProbeInstance *gi_probe = gi_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!gi_probe, 0); - - return gi_probe->render_index; - } - - _FORCE_INLINE_ void gi_probe_instance_set_render_pass(RID p_instance, uint32_t p_render_pass) { - GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND(!g_probe); - g_probe->last_pass = p_render_pass; - } - - _FORCE_INLINE_ uint32_t gi_probe_instance_get_render_pass(RID p_instance) { - GIProbeInstance *g_probe = gi_probe_instance_owner.getornull(p_instance); - ERR_FAIL_COND_V(!g_probe, 0); - - return g_probe->last_pass; - } - - const Vector &gi_probe_get_slots() const; - _FORCE_INLINE_ bool gi_probe_is_anisotropic() const { - return gi_probe_use_anisotropy; - } - GIProbeQuality gi_probe_get_quality() const; - - RID render_buffers_create(); - void render_buffers_configure(RID p_render_buffers, RID p_render_target, int p_width, int p_height, VS::ViewportMSAA p_msaa); - - RID render_buffers_get_ao_texture(RID p_render_buffers); - RID render_buffers_get_back_buffer_texture(RID p_render_buffers); - - void render_scene(RID p_render_buffers, const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID *p_light_cull_result, int p_light_cull_count, RID *p_reflection_probe_cull_result, int p_reflection_probe_cull_count, RID *p_gi_probe_cull_result, int p_gi_probe_cull_count, RID p_environment, RID p_shadow_atlas, RID p_camera_effects, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass); - - void render_shadow(RID p_light, RID p_shadow_atlas, int p_pass, InstanceBase **p_cull_result, int p_cull_count); - - void render_material(const Transform &p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_ortogonal, InstanceBase **p_cull_result, int p_cull_count, RID p_framebuffer, const Rect2i &p_region); - - virtual void set_scene_pass(uint64_t p_pass) { scene_pass = p_pass; } - _FORCE_INLINE_ uint64_t get_scene_pass() { return scene_pass; } - - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve); - virtual bool screen_space_roughness_limiter_is_active() const; - virtual float screen_space_roughness_limiter_get_curve() const; - - int get_roughness_layers() const; - bool is_using_radiance_cubemap_array() const; - - virtual bool free(RID p_rid); - - virtual void update(); - - virtual void set_debug_draw_mode(VS::ViewportDebugDraw p_debug_draw); - _FORCE_INLINE_ VS::ViewportDebugDraw get_debug_draw_mode() const { return debug_draw; } - - virtual void set_time(double p_time, double p_step); - - RasterizerSceneRD(RasterizerStorageRD *p_storage); - ~RasterizerSceneRD(); -}; - -#endif // RASTERIZER_SCENE_RD_H diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp b/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp deleted file mode 100644 index 6e7f0aac07..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.cpp +++ /dev/null @@ -1,4822 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rasterizer_storage_rd.h" -#include "core/engine.h" -#include "core/project_settings.h" -#include "servers/visual/shader_language.h" - -Ref RasterizerStorageRD::_validate_texture_format(const Ref &p_image, TextureToRDFormat &r_format) { - - Ref image = p_image->duplicate(); - - switch (p_image->get_format()) { - case Image::FORMAT_L8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //luminance - case Image::FORMAT_LA8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_G; - } break; //luminance-alpha - case Image::FORMAT_R8: { - r_format.format = RD::DATA_FORMAT_R8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RG8: { - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGB8: { - //this format is not mandatory for specification, check if supported first - if (false && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_UNORM, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT) && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R8G8B8_SRGB, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R8G8B8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8_SRGB; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBA8: { - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGBA4444: { - r_format.format = RD::DATA_FORMAT_B4G4R4A4_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; //needs swizzle - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RGB565: { - r_format.format = RD::DATA_FORMAT_B5G6R5_UNORM_PACK16; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_RF: { - r_format.format = RD::DATA_FORMAT_R32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float - case Image::FORMAT_RGF: { - r_format.format = RD::DATA_FORMAT_R32G32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBF: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R32G32B32_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - image->convert(Image::FORMAT_RGBAF); - } - - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAF: { - r_format.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RH: { - r_format.format = RD::DATA_FORMAT_R16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //half float - case Image::FORMAT_RGH: { - r_format.format = RD::DATA_FORMAT_R16G16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGBH: { - //this format is not mandatory for specification, check if supported first - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_R16G16B16_SFLOAT, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_R16G16B16_SFLOAT; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->convert(Image::FORMAT_RGBAH); - } - - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_RGBAH: { - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; - case Image::FORMAT_RGBE9995: { - r_format.format = RD::DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32; -#ifndef _MSC_VER -#warning TODO need to make a function in Image to swap bits for this -#endif - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_IDENTITY; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_IDENTITY; - } break; - case Image::FORMAT_DXT1: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC1_RGB_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //s3tc bc1 - case Image::FORMAT_DXT3: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC2_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC2_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC2_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //bc2 - case Image::FORMAT_DXT5: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; //bc3 - case Image::FORMAT_RGTC_R: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC4_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC4_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_RGTC_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC5_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_BPTC_RGBA: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC7_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC7_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - - } break; //btpc bc7 - case Image::FORMAT_BPTC_RGBF: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_SFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //float bc6h - case Image::FORMAT_BPTC_RGBFU: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC6H_UFLOAT_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R16G16B16A16_SFLOAT; - image->decompress(); - image->convert(Image::FORMAT_RGBAH); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //unsigned float bc6hu - case Image::FORMAT_PVRTC2: { - //this is not properly supported by MoltekVK it seems, so best to use ETC2 - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; - r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //pvrtc - case Image::FORMAT_PVRTC2A: { - //this is not properly supported by MoltekVK it seems, so best to use ETC2 - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG; - r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_PVRTC4: { - //this is not properly supported by MoltekVK it seems, so best to use ETC2 - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; - r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_PVRTC4A: { - //this is not properly supported by MoltekVK it seems, so best to use ETC2 - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG; - r_format.format_srgb = RD::DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_R11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; //etc2 - case Image::FORMAT_ETC2_R11S: { - - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_R8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; //signed: {} break; NOT srgb. - case Image::FORMAT_ETC2_RG11: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_UNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_UNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC2_RG11S: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_EAC_R11G11_SNORM_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8_SNORM; - image->decompress(); - image->convert(Image::FORMAT_RG8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_ETC: - case Image::FORMAT_ETC2_RGB8: { - //ETC2 is backwards compatible with ETC1, and all modern platforms support it - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - - } break; - case Image::FORMAT_ETC2_RGBA8: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RGB8A1: { - - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_G; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_B; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_A; - } break; - case Image::FORMAT_ETC2_RA_AS_RG: { - - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - case Image::FORMAT_DXT5_RA_AS_RG: { - if (RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC3_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT)) { - r_format.format = RD::DATA_FORMAT_BC3_UNORM_BLOCK; - r_format.format_srgb = RD::DATA_FORMAT_BC3_SRGB_BLOCK; - } else { - //not supported, reconvert - r_format.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - r_format.format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - image->decompress(); - image->convert(Image::FORMAT_RGBA8); - } - r_format.swizzle_r = RD::TEXTURE_SWIZZLE_R; - r_format.swizzle_g = RD::TEXTURE_SWIZZLE_A; - r_format.swizzle_b = RD::TEXTURE_SWIZZLE_ZERO; - r_format.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } break; - - default: { - } - } - - return image; -} - -RID RasterizerStorageRD::texture_2d_create(const Ref &p_image) { - ERR_FAIL_COND_V(p_image.is_null(), RID()); - ERR_FAIL_COND_V(p_image->empty(), RID()); - - TextureToRDFormat ret_format; - Ref image = _validate_texture_format(p_image, ret_format); - - Texture texture; - - texture.type = Texture::TYPE_2D; - - texture.width = p_image->get_width(); - texture.height = p_image->get_height(); - texture.layers = 1; - texture.mipmaps = p_image->get_mipmap_count() + 1; - texture.depth = 1; - texture.format = p_image->get_format(); - texture.validated_format = image->get_format(); - - texture.rd_type = RD::TEXTURE_TYPE_2D; - texture.rd_format = ret_format.format; - texture.rd_format_srgb = ret_format.format_srgb; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = texture.rd_format; - rd_format.width = texture.width; - rd_format.height = texture.height; - rd_format.depth = 1; - rd_format.array_layers = 1; - rd_format.mipmaps = texture.mipmaps; - rd_format.type = texture.rd_type; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_format.shareable_formats.push_back(texture.rd_format); - rd_format.shareable_formats.push_back(texture.rd_format_srgb); - } - } - { - rd_view.swizzle_r = ret_format.swizzle_r; - rd_view.swizzle_g = ret_format.swizzle_g; - rd_view.swizzle_b = ret_format.swizzle_b; - rd_view.swizzle_a = ret_format.swizzle_a; - } - Vector data = image->get_data(); //use image data - Vector> data_slices; - data_slices.push_back(data); - texture.rd_texture = RD::get_singleton()->texture_create(rd_format, rd_view, data_slices); - ERR_FAIL_COND_V(texture.rd_texture.is_null(), RID()); - if (texture.rd_format_srgb != RD::DATA_FORMAT_MAX) { - rd_view.format_override = texture.rd_format_srgb; - texture.rd_texture_srgb = RD::get_singleton()->texture_create_shared(rd_view, texture.rd_texture); - if (texture.rd_texture_srgb.is_null()) { - RD::get_singleton()->free(texture.rd_texture); - ERR_FAIL_COND_V(texture.rd_texture_srgb.is_null(), RID()); - } - } - - //used for 2D, overridable - texture.width_2d = texture.width; - texture.height_2d = texture.height; - texture.is_render_target = false; - texture.rd_view = rd_view; - texture.is_proxy = false; - - return texture_owner.make_rid(texture); -} - -RID RasterizerStorageRD::texture_2d_layered_create(const Vector> &p_layers, VS::TextureLayeredType p_layered_type) { - - return RID(); -} -RID RasterizerStorageRD::texture_3d_create(const Vector> &p_slices) { - - return RID(); -} - -RID RasterizerStorageRD::texture_proxy_create(RID p_base) { - Texture *tex = texture_owner.getornull(p_base); - ERR_FAIL_COND_V(!tex, RID()); - Texture proxy_tex = *tex; - - proxy_tex.rd_view.format_override = tex->rd_format; - proxy_tex.rd_texture = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - if (proxy_tex.rd_texture_srgb.is_valid()) { - proxy_tex.rd_view.format_override = tex->rd_format_srgb; - proxy_tex.rd_texture_srgb = RD::get_singleton()->texture_create_shared(proxy_tex.rd_view, tex->rd_texture); - } - proxy_tex.proxy_to = p_base; - proxy_tex.is_render_target = false; - proxy_tex.is_proxy = true; - proxy_tex.proxies.clear(); - - RID rid = texture_owner.make_rid(proxy_tex); - - tex->proxies.push_back(rid); - - return rid; -} - -void RasterizerStorageRD::_texture_2d_update(RID p_texture, const Ref &p_image, int p_layer, bool p_immediate) { - - ERR_FAIL_COND(p_image.is_null() || p_image->empty()); - - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->is_render_target); - ERR_FAIL_COND(p_image->get_width() != tex->width || p_image->get_height() != tex->height); - ERR_FAIL_COND(p_image->get_format() != tex->format); - - if (tex->type == Texture::TYPE_LAYERED) { - ERR_FAIL_INDEX(p_layer, tex->layers); - } - -#ifdef TOOLS_ENABLED - tex->image_cache_2d.unref(); -#endif - TextureToRDFormat f; - Ref validated = _validate_texture_format(p_image, f); - - RD::get_singleton()->texture_update(tex->rd_texture, p_layer, validated->get_data(), !p_immediate); -} - -void RasterizerStorageRD::texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer) { - _texture_2d_update(p_texture, p_image, p_layer, true); -} -void RasterizerStorageRD::texture_2d_update(RID p_texture, const Ref &p_image, int p_layer) { - _texture_2d_update(p_texture, p_image, p_layer, false); -} -void RasterizerStorageRD::texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap) { -} - -void RasterizerStorageRD::texture_proxy_update(RID p_texture, RID p_proxy_to) { - - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(!tex->is_proxy); - Texture *proxy_to = texture_owner.getornull(p_proxy_to); - ERR_FAIL_COND(!proxy_to); - ERR_FAIL_COND(proxy_to->is_proxy); - - if (tex->proxy_to.is_valid()) { - //unlink proxy - if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { - RD::get_singleton()->free(tex->rd_texture); - tex->rd_texture = RID(); - } - if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { - RD::get_singleton()->free(tex->rd_texture_srgb); - tex->rd_texture_srgb = RID(); - } - Texture *prev_tex = texture_owner.getornull(tex->proxy_to); - ERR_FAIL_COND(!prev_tex); - prev_tex->proxies.erase(p_texture); - } - - *tex = *proxy_to; - - tex->proxy_to = p_proxy_to; - tex->is_render_target = false; - tex->is_proxy = true; - tex->proxies.clear(); - proxy_to->proxies.push_back(p_texture); - - tex->rd_view.format_override = tex->rd_format; - tex->rd_texture = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - if (tex->rd_texture_srgb.is_valid()) { - tex->rd_view.format_override = tex->rd_format_srgb; - tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(tex->rd_view, proxy_to->rd_texture); - } -} - -//these two APIs can be used together or in combination with the others. -RID RasterizerStorageRD::texture_2d_placeholder_create() { - - //this could be better optimized to reuse an existing image , done this way - //for now to get it working - Ref image; - image.instance(); - image->create(4, 4, false, Image::FORMAT_RGBA8); - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - image->set_pixel(i, j, Color(1, 0, 1, 1)); - } - } - - return texture_2d_create(image); -} -RID RasterizerStorageRD::texture_2d_layered_placeholder_create() { - - return RID(); -} -RID RasterizerStorageRD::texture_3d_placeholder_create() { - - return RID(); -} - -Ref RasterizerStorageRD::texture_2d_get(RID p_texture) const { - - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND_V(!tex, Ref()); - -#ifdef TOOLS_ENABLED - if (tex->image_cache_2d.is_valid()) { - return tex->image_cache_2d; - } -#endif - Vector data = RD::get_singleton()->texture_get_data(tex->rd_texture, 0); - ERR_FAIL_COND_V(data.size() == 0, Ref()); - Ref image; - image.instance(); - image->create(tex->width, tex->height, tex->mipmaps > 1, tex->validated_format, data); - ERR_FAIL_COND_V(image->empty(), Ref()); - if (tex->format != tex->validated_format) { - image->convert(tex->format); - } - -#ifdef TOOLS_ENABLED - if (Engine::get_singleton()->is_editor_hint()) { - tex->image_cache_2d = image; - } -#endif - - return image; -} -Ref RasterizerStorageRD::texture_2d_layer_get(RID p_texture, int p_layer) const { - - return Ref(); -} -Ref RasterizerStorageRD::texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const { - - return Ref(); -} - -void RasterizerStorageRD::texture_replace(RID p_texture, RID p_by_texture) { - - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->proxy_to.is_valid()); //cant replace proxy - Texture *by_tex = texture_owner.getornull(p_by_texture); - ERR_FAIL_COND(!by_tex); - ERR_FAIL_COND(by_tex->proxy_to.is_valid()); //cant replace proxy - - if (tex == by_tex) { - return; - } - - if (tex->rd_texture_srgb.is_valid()) { - RD::get_singleton()->free(tex->rd_texture_srgb); - } - RD::get_singleton()->free(tex->rd_texture); - - Vector proxies_to_update = tex->proxies; - Vector proxies_to_redirect = by_tex->proxies; - - *tex = *by_tex; - - tex->proxies = proxies_to_update; //restore proxies, so they can be updated - - for (int i = 0; i < proxies_to_update.size(); i++) { - texture_proxy_update(proxies_to_update[i], p_texture); - } - for (int i = 0; i < proxies_to_redirect.size(); i++) { - texture_proxy_update(proxies_to_redirect[i], p_texture); - } - //delete last, so proxies can be updated - texture_owner.free(p_by_texture); -} -void RasterizerStorageRD::texture_set_size_override(RID p_texture, int p_width, int p_height) { - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - ERR_FAIL_COND(tex->type != Texture::TYPE_2D); - tex->width_2d = p_width; - tex->height_2d = p_height; -} - -void RasterizerStorageRD::texture_set_path(RID p_texture, const String &p_path) { - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - tex->path = p_path; -} -String RasterizerStorageRD::texture_get_path(RID p_texture) const { - return String(); -} - -void RasterizerStorageRD::texture_set_detect_3d_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_3d_callback_ud = p_userdata; - tex->detect_3d_callback = p_callback; -} -void RasterizerStorageRD::texture_set_detect_normal_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_normal_callback_ud = p_userdata; - tex->detect_normal_callback = p_callback; -} -void RasterizerStorageRD::texture_set_detect_roughness_callback(RID p_texture, VS::TextureDetectRoughnessCallback p_callback, void *p_userdata) { - Texture *tex = texture_owner.getornull(p_texture); - ERR_FAIL_COND(!tex); - tex->detect_roughness_callback_ud = p_userdata; - tex->detect_roughness_callback = p_callback; -} -void RasterizerStorageRD::texture_debug_usage(List *r_info) { -} - -void RasterizerStorageRD::texture_set_proxy(RID p_proxy, RID p_base) { -} -void RasterizerStorageRD::texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) { -} - -Size2 RasterizerStorageRD::texture_size_with_proxy(RID p_proxy) { - return texture_2d_get_size(p_proxy); -} - -/* SHADER API */ - -RID RasterizerStorageRD::shader_create() { - - Shader shader; - shader.data = NULL; - shader.type = SHADER_TYPE_MAX; - - return shader_owner.make_rid(shader); -} - -void RasterizerStorageRD::shader_set_code(RID p_shader, const String &p_code) { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - shader->code = p_code; - String mode_string = ShaderLanguage::get_shader_type(p_code); - - ShaderType new_type; - if (mode_string == "canvas_item") - new_type = SHADER_TYPE_2D; - else if (mode_string == "particles") - new_type = SHADER_TYPE_PARTICLES; - else if (mode_string == "spatial") - new_type = SHADER_TYPE_3D; - else if (mode_string == "sky") - new_type = SHADER_TYPE_SKY; - else - new_type = SHADER_TYPE_MAX; - - if (new_type != shader->type) { - if (shader->data) { - memdelete(shader->data); - shader->data = NULL; - } - - for (Set::Element *E = shader->owners.front(); E; E = E->next()) { - - Material *material = E->get(); - material->shader_type = new_type; - if (material->data) { - memdelete(material->data); - material->data = NULL; - } - } - - shader->type = new_type; - - if (new_type < SHADER_TYPE_MAX && shader_data_request_func[new_type]) { - shader->data = shader_data_request_func[new_type](); - } else { - shader->type = SHADER_TYPE_MAX; //invalid - } - - for (Set::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - if (shader->data) { - material->data = material_data_request_func[new_type](shader->data); - material->data->set_next_pass(material->next_pass); - material->data->set_render_priority(material->priority); - } - material->shader_type = new_type; - } - } - - if (shader->data) { - shader->data->set_code(p_code); - } - - for (Set::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - material->instance_dependency.instance_notify_changed(false, true); - _material_queue_update(material, true, true); - } -} - -String RasterizerStorageRD::shader_get_code(RID p_shader) const { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND_V(!shader, String()); - return shader->code; -} -void RasterizerStorageRD::shader_get_param_list(RID p_shader, List *p_param_list) const { - - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - if (shader->data) { - return shader->data->get_param_list(p_param_list); - } -} - -void RasterizerStorageRD::shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) { - - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - - if (p_texture.is_valid() && texture_owner.owns(p_texture)) { - shader->default_texture_parameter[p_name] = p_texture; - } else { - shader->default_texture_parameter.erase(p_name); - } - - for (Set::Element *E = shader->owners.front(); E; E = E->next()) { - Material *material = E->get(); - _material_queue_update(material, false, true); - } -} - -RID RasterizerStorageRD::shader_get_default_texture_param(RID p_shader, const StringName &p_name) const { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND_V(!shader, RID()); - if (shader->default_texture_parameter.has(p_name)) { - return shader->default_texture_parameter[p_name]; - } - - return RID(); -} -Variant RasterizerStorageRD::shader_get_param_default(RID p_shader, const StringName &p_param) const { - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND_V(!shader, Variant()); - if (shader->data) { - return shader->data->get_default_parameter(p_param); - } - return Variant(); -} -void RasterizerStorageRD::shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function) { - ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); - shader_data_request_func[p_shader_type] = p_function; -} - -/* COMMON MATERIAL API */ - -RID RasterizerStorageRD::material_create() { - - Material material; - material.data = NULL; - material.shader = NULL; - material.shader_type = SHADER_TYPE_MAX; - material.update_next = NULL; - material.update_requested = false; - material.uniform_dirty = false; - material.texture_dirty = false; - material.priority = 0; - RID id = material_owner.make_rid(material); - { - Material *material_ptr = material_owner.getornull(id); - material_ptr->self = id; - } - return id; -} - -void RasterizerStorageRD::_material_queue_update(Material *material, bool p_uniform, bool p_texture) { - if (material->update_requested) { - return; - } - - material->update_next = material_update_list; - material_update_list = material; - material->update_requested = true; - material->uniform_dirty = p_uniform; - material->texture_dirty = p_texture; -} - -void RasterizerStorageRD::material_set_shader(RID p_material, RID p_shader) { - - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - if (material->data) { - memdelete(material->data); - material->data = NULL; - } - - if (material->shader) { - material->shader->owners.erase(material); - material->shader = NULL; - material->shader_type = SHADER_TYPE_MAX; - } - - if (p_shader.is_null()) { - material->instance_dependency.instance_notify_changed(false, true); - return; - } - - Shader *shader = shader_owner.getornull(p_shader); - ERR_FAIL_COND(!shader); - material->shader = shader; - material->shader_type = shader->type; - shader->owners.insert(material); - - if (shader->type == SHADER_TYPE_MAX) { - return; - } - - ERR_FAIL_COND(shader->data == NULL); - - material->data = material_data_request_func[shader->type](shader->data); - material->data->set_next_pass(material->next_pass); - material->data->set_render_priority(material->priority); - //updating happens later - material->instance_dependency.instance_notify_changed(false, true); - _material_queue_update(material, true, true); -} - -void RasterizerStorageRD::material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) { - - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - if (p_value.get_type() == Variant::NIL) { - material->params.erase(p_param); - } else { - material->params[p_param] = p_value; - } - - if (material->shader && material->shader->data) { //shader is valid - bool is_texture = material->shader->data->is_param_texture(p_param); - _material_queue_update(material, !is_texture, is_texture); - } else { - _material_queue_update(material, true, true); - } -} - -Variant RasterizerStorageRD::material_get_param(RID p_material, const StringName &p_param) const { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, Variant()); - if (material->params.has(p_param)) { - return material->params[p_param]; - } else { - return Variant(); - } -} - -void RasterizerStorageRD::material_set_next_pass(RID p_material, RID p_next_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - - if (material->next_pass == p_next_material) { - return; - } - - material->next_pass = p_next_material; - if (material->data) { - material->data->set_next_pass(p_next_material); - } - - material->instance_dependency.instance_notify_changed(false, true); -} -void RasterizerStorageRD::material_set_render_priority(RID p_material, int priority) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - material->priority = priority; - if (material->data) { - material->data->set_render_priority(priority); - } -} - -bool RasterizerStorageRD::material_is_animated(RID p_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, false); - if (material->shader && material->shader->data) { - if (material->shader->data->is_animated()) { - return true; - } else if (material->next_pass.is_valid()) { - return material_is_animated(material->next_pass); - } - } - return false; //by default nothing is animated -} -bool RasterizerStorageRD::material_casts_shadows(RID p_material) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND_V(!material, true); - if (material->shader && material->shader->data) { - if (material->shader->data->casts_shadows()) { - return true; - } else if (material->next_pass.is_valid()) { - return material_casts_shadows(material->next_pass); - } - } - return true; //by default everything casts shadows -} - -void RasterizerStorageRD::material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance) { - Material *material = material_owner.getornull(p_material); - ERR_FAIL_COND(!material); - p_instance->update_dependency(&material->instance_dependency); - if (material->next_pass.is_valid()) { - material_update_dependency(material->next_pass, p_instance); - } -} - -void RasterizerStorageRD::material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function) { - ERR_FAIL_INDEX(p_shader_type, SHADER_TYPE_MAX); - material_data_request_func[p_shader_type] = p_function; -} - -_FORCE_INLINE_ static void _fill_std140_variant_ubo_value(ShaderLanguage::DataType type, const Variant &value, uint8_t *data, bool p_linear_color) { - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - - bool v = value; - - uint32_t *gui = (uint32_t *)data; - *gui = v ? 1 : 0; - } break; - case ShaderLanguage::TYPE_BVEC2: { - - int v = value; - uint32_t *gui = (uint32_t *)data; - gui[0] = v & 1 ? 1 : 0; - gui[1] = v & 2 ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC3: { - - int v = value; - uint32_t *gui = (uint32_t *)data; - gui[0] = (v & 1) ? 1 : 0; - gui[1] = (v & 2) ? 1 : 0; - gui[2] = (v & 4) ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC4: { - - int v = value; - uint32_t *gui = (uint32_t *)data; - gui[0] = (v & 1) ? 1 : 0; - gui[1] = (v & 2) ? 1 : 0; - gui[2] = (v & 4) ? 1 : 0; - gui[3] = (v & 8) ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_INT: { - - int v = value; - int32_t *gui = (int32_t *)data; - gui[0] = v; - - } break; - case ShaderLanguage::TYPE_IVEC2: { - - Vector iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - const int *r = iv.ptr(); - - for (int i = 0; i < 2; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - - } break; - case ShaderLanguage::TYPE_IVEC3: { - - Vector iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - const int *r = iv.ptr(); - - for (int i = 0; i < 3; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_IVEC4: { - - Vector iv = value; - int s = iv.size(); - int32_t *gui = (int32_t *)data; - - const int *r = iv.ptr(); - - for (int i = 0; i < 4; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_UINT: { - - int v = value; - uint32_t *gui = (uint32_t *)data; - gui[0] = v; - - } break; - case ShaderLanguage::TYPE_UVEC2: { - - Vector iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - const int *r = iv.ptr(); - - for (int i = 0; i < 2; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - Vector iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - const int *r = iv.ptr(); - - for (int i = 0; i < 3; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - - } break; - case ShaderLanguage::TYPE_UVEC4: { - Vector iv = value; - int s = iv.size(); - uint32_t *gui = (uint32_t *)data; - - const int *r = iv.ptr(); - - for (int i = 0; i < 4; i++) { - if (i < s) - gui[i] = r[i]; - else - gui[i] = 0; - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - float v = value; - float *gui = (float *)data; - gui[0] = v; - - } break; - case ShaderLanguage::TYPE_VEC2: { - Vector2 v = value; - float *gui = (float *)data; - gui[0] = v.x; - gui[1] = v.y; - - } break; - case ShaderLanguage::TYPE_VEC3: { - Vector3 v = value; - float *gui = (float *)data; - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - - } break; - case ShaderLanguage::TYPE_VEC4: { - - float *gui = (float *)data; - - if (value.get_type() == Variant::COLOR) { - Color v = value; - - if (p_linear_color) { - v = v.to_linear(); - } - - gui[0] = v.r; - gui[1] = v.g; - gui[2] = v.b; - gui[3] = v.a; - } else if (value.get_type() == Variant::RECT2) { - Rect2 v = value; - - gui[0] = v.position.x; - gui[1] = v.position.y; - gui[2] = v.size.x; - gui[3] = v.size.y; - } else if (value.get_type() == Variant::QUAT) { - Quat v = value; - - gui[0] = v.x; - gui[1] = v.y; - gui[2] = v.z; - gui[3] = v.w; - } else { - Plane v = value; - - gui[0] = v.normal.x; - gui[1] = v.normal.y; - gui[2] = v.normal.z; - gui[3] = v.d; - } - } break; - case ShaderLanguage::TYPE_MAT2: { - Transform2D v = value; - float *gui = (float *)data; - - //in std140 members of mat2 are treated as vec4s - gui[0] = v.elements[0][0]; - gui[1] = v.elements[0][1]; - gui[2] = 0; - gui[3] = 0; - gui[4] = v.elements[1][0]; - gui[5] = v.elements[1][1]; - gui[6] = 0; - gui[7] = 0; - } break; - case ShaderLanguage::TYPE_MAT3: { - - Basis v = value; - float *gui = (float *)data; - - gui[0] = v.elements[0][0]; - gui[1] = v.elements[1][0]; - gui[2] = v.elements[2][0]; - gui[3] = 0; - gui[4] = v.elements[0][1]; - gui[5] = v.elements[1][1]; - gui[6] = v.elements[2][1]; - gui[7] = 0; - gui[8] = v.elements[0][2]; - gui[9] = v.elements[1][2]; - gui[10] = v.elements[2][2]; - gui[11] = 0; - } break; - case ShaderLanguage::TYPE_MAT4: { - - Transform v = value; - float *gui = (float *)data; - - gui[0] = v.basis.elements[0][0]; - gui[1] = v.basis.elements[1][0]; - gui[2] = v.basis.elements[2][0]; - gui[3] = 0; - gui[4] = v.basis.elements[0][1]; - gui[5] = v.basis.elements[1][1]; - gui[6] = v.basis.elements[2][1]; - gui[7] = 0; - gui[8] = v.basis.elements[0][2]; - gui[9] = v.basis.elements[1][2]; - gui[10] = v.basis.elements[2][2]; - gui[11] = 0; - gui[12] = v.origin.x; - gui[13] = v.origin.y; - gui[14] = v.origin.z; - gui[15] = 1; - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_value(ShaderLanguage::DataType type, const Vector &value, uint8_t *data) { - - switch (type) { - case ShaderLanguage::TYPE_BOOL: { - - uint32_t *gui = (uint32_t *)data; - *gui = value[0].boolean ? 1 : 0; - } break; - case ShaderLanguage::TYPE_BVEC2: { - - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC3: { - - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - gui[2] = value[2].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_BVEC4: { - - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].boolean ? 1 : 0; - gui[1] = value[1].boolean ? 1 : 0; - gui[2] = value[2].boolean ? 1 : 0; - gui[3] = value[3].boolean ? 1 : 0; - - } break; - case ShaderLanguage::TYPE_INT: { - - int32_t *gui = (int32_t *)data; - gui[0] = value[0].sint; - - } break; - case ShaderLanguage::TYPE_IVEC2: { - - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC3: { - - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_IVEC4: { - - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].sint; - } - - } break; - case ShaderLanguage::TYPE_UINT: { - - uint32_t *gui = (uint32_t *)data; - gui[0] = value[0].uint; - - } break; - case ShaderLanguage::TYPE_UVEC2: { - - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_UVEC3: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].uint; - } - - } break; - case ShaderLanguage::TYPE_UVEC4: { - int32_t *gui = (int32_t *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].uint; - } - } break; - case ShaderLanguage::TYPE_FLOAT: { - - float *gui = (float *)data; - gui[0] = value[0].real; - - } break; - case ShaderLanguage::TYPE_VEC2: { - - float *gui = (float *)data; - - for (int i = 0; i < 2; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC3: { - - float *gui = (float *)data; - - for (int i = 0; i < 3; i++) { - gui[i] = value[i].real; - } - - } break; - case ShaderLanguage::TYPE_VEC4: { - - float *gui = (float *)data; - - for (int i = 0; i < 4; i++) { - gui[i] = value[i].real; - } - } break; - case ShaderLanguage::TYPE_MAT2: { - float *gui = (float *)data; - - //in std140 members of mat2 are treated as vec4s - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = 0; - gui[3] = 0; - gui[4] = value[2].real; - gui[5] = value[3].real; - gui[6] = 0; - gui[7] = 0; - } break; - case ShaderLanguage::TYPE_MAT3: { - - float *gui = (float *)data; - - gui[0] = value[0].real; - gui[1] = value[1].real; - gui[2] = value[2].real; - gui[3] = 0; - gui[4] = value[3].real; - gui[5] = value[4].real; - gui[6] = value[5].real; - gui[7] = 0; - gui[8] = value[6].real; - gui[9] = value[7].real; - gui[10] = value[8].real; - gui[11] = 0; - } break; - case ShaderLanguage::TYPE_MAT4: { - - float *gui = (float *)data; - - for (int i = 0; i < 16; i++) { - gui[i] = value[i].real; - } - } break; - default: { - } - } -} - -_FORCE_INLINE_ static void _fill_std140_ubo_empty(ShaderLanguage::DataType type, uint8_t *data) { - - switch (type) { - - case ShaderLanguage::TYPE_BOOL: - case ShaderLanguage::TYPE_INT: - case ShaderLanguage::TYPE_UINT: - case ShaderLanguage::TYPE_FLOAT: { - zeromem(data, 4); - } break; - case ShaderLanguage::TYPE_BVEC2: - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_VEC2: { - zeromem(data, 8); - } break; - case ShaderLanguage::TYPE_BVEC3: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_VEC3: - case ShaderLanguage::TYPE_BVEC4: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC4: - case ShaderLanguage::TYPE_VEC4: { - - zeromem(data, 16); - } break; - case ShaderLanguage::TYPE_MAT2: { - - zeromem(data, 32); - } break; - case ShaderLanguage::TYPE_MAT3: { - - zeromem(data, 48); - } break; - case ShaderLanguage::TYPE_MAT4: { - zeromem(data, 64); - } break; - - default: { - } - } -} - -void RasterizerStorageRD::MaterialData::update_uniform_buffer(const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Map &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color) { - - for (Map::Element *E = p_uniforms.front(); E; E = E->next()) { - - if (E->get().order < 0) - continue; // texture, does not go here - - //regular uniform - uint32_t offset = p_uniform_offsets[E->get().order]; -#ifdef DEBUG_ENABLED - uint32_t size = ShaderLanguage::get_type_size(E->get().type); - ERR_CONTINUE(offset + size > p_buffer_size); -#endif - uint8_t *data = &p_buffer[offset]; - const Map::Element *V = p_parameters.find(E->key()); - - if (V) { - //user provided - _fill_std140_variant_ubo_value(E->get().type, V->get(), data, p_use_linear_color); - - } else if (E->get().default_value.size()) { - //default value - _fill_std140_ubo_value(E->get().type, E->get().default_value, data); - //value=E->get().default_value; - } else { - //zero because it was not provided - if (E->get().type == ShaderLanguage::TYPE_VEC4 && E->get().hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - //colors must be set as black, with alpha as 1.0 - _fill_std140_variant_ubo_value(E->get().type, Color(0, 0, 0, 1), data, p_use_linear_color); - } else { - //else just zero it out - _fill_std140_ubo_empty(E->get().type, data); - } - } - } -} - -void RasterizerStorageRD::MaterialData::update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color) { - - RasterizerStorageRD *singleton = (RasterizerStorageRD *)RasterizerStorage::base_singleton; -#ifdef TOOLS_ENABLED - Texture *roughness_detect_texture = nullptr; - VS::TextureDetectRoughnessChannel roughness_channel; - Texture *normal_detect_texture = nullptr; -#endif - - for (int i = 0; i < p_texture_uniforms.size(); i++) { - - const StringName &uniform_name = p_texture_uniforms[i].name; - - RID texture; - - const Map::Element *V = p_parameters.find(uniform_name); - if (V) { - texture = V->get(); - } - - if (!texture.is_valid()) { - const Map::Element *W = p_default_textures.find(uniform_name); - if (W) { - - texture = W->get(); - } - } - - RID rd_texture; - - if (texture.is_null()) { - //check default usage - switch (p_texture_uniforms[i].hint) { - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK: - case ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_BLACK); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_NONE: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_NORMAL); - } break; - case ShaderLanguage::ShaderNode::Uniform::HINT_ANISO: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_ANISO); - } break; - default: { - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); - } break; - } - } else { - bool srgb = p_use_linear_color && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ALBEDO || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_BLACK_ALBEDO); - - Texture *tex = singleton->texture_owner.getornull(texture); - - if (tex) { - - rd_texture = (srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; -#ifdef TOOLS_ENABLED - if (tex->detect_3d_callback && p_use_linear_color) { - tex->detect_3d_callback(tex->detect_3d_callback_ud); - } - if (tex->detect_normal_callback && (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_NORMAL || p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL)) { - if (p_texture_uniforms[i].hint == ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL) { - normal_detect_texture = tex; - } - tex->detect_normal_callback(tex->detect_normal_callback_ud); - } - if (tex->detect_roughness_callback && (p_texture_uniforms[i].hint >= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R || p_texture_uniforms[i].hint <= ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_GRAY)) { - //find the normal texture - roughness_detect_texture = tex; - roughness_channel = VS::TextureDetectRoughnessChannel(p_texture_uniforms[i].hint - ShaderLanguage::ShaderNode::Uniform::HINT_ROUGHNESS_R); - } - -#endif - } - - if (rd_texture.is_null()) { - //wtf - rd_texture = singleton->texture_rd_get_default(DEFAULT_RD_TEXTURE_WHITE); - } - } - - p_textures[i] = rd_texture; - } -#ifdef TOOLS_ENABLED - if (roughness_detect_texture && normal_detect_texture && normal_detect_texture->path != String()) { - roughness_detect_texture->detect_roughness_callback(roughness_detect_texture->detect_roughness_callback_ud, normal_detect_texture->path, roughness_channel); - } -#endif -} - -void RasterizerStorageRD::material_force_update_textures(RID p_material, ShaderType p_shader_type) { - Material *material = material_owner.getornull(p_material); - if (material->shader_type != p_shader_type) { - return; - } - if (material->data) { - material->data->update_parameters(material->params, false, true); - } -} - -void RasterizerStorageRD::_update_queued_materials() { - Material *material = material_update_list; - while (material) { - Material *next = material->update_next; - - if (material->data) { - material->data->update_parameters(material->params, material->uniform_dirty, material->texture_dirty); - } - material->update_requested = false; - material->texture_dirty = false; - material->uniform_dirty = false; - material->update_next = NULL; - material = next; - } - material_update_list = NULL; -} -/* MESH API */ - -RID RasterizerStorageRD::mesh_create() { - - return mesh_owner.make_rid(Mesh()); -} - -/// Returns stride -void RasterizerStorageRD::mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - - //ensure blend shape consistency - ERR_FAIL_COND(mesh->blend_shape_count && p_surface.blend_shapes.size() != (int)mesh->blend_shape_count); - ERR_FAIL_COND(mesh->blend_shape_count && p_surface.bone_aabbs.size() != mesh->bone_aabbs.size()); - -#ifdef DEBUG_ENABLED - //do a validation, to catch errors first - { - - uint32_t stride = 0; - - for (int i = 0; i < VS::ARRAY_WEIGHTS; i++) { - - if ((p_surface.format & (1 << i))) { - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (p_surface.format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - stride += sizeof(float) * 2; - } else { - stride += sizeof(float) * 3; - } - - } break; - case VS::ARRAY_NORMAL: { - - if (p_surface.format & VS::ARRAY_COMPRESS_NORMAL) { - stride += sizeof(int8_t) * 4; - } else { - stride += sizeof(float) * 4; - } - - } break; - case VS::ARRAY_TANGENT: { - - if (p_surface.format & VS::ARRAY_COMPRESS_TANGENT) { - stride += sizeof(int8_t) * 4; - } else { - stride += sizeof(float) * 4; - } - - } break; - case VS::ARRAY_COLOR: { - - if (p_surface.format & VS::ARRAY_COMPRESS_COLOR) { - stride += sizeof(int8_t) * 4; - } else { - stride += sizeof(float) * 4; - } - - } break; - case VS::ARRAY_TEX_UV: { - - if (p_surface.format & VS::ARRAY_COMPRESS_TEX_UV) { - stride += sizeof(int16_t) * 2; - } else { - stride += sizeof(float) * 2; - } - - } break; - case VS::ARRAY_TEX_UV2: { - - if (p_surface.format & VS::ARRAY_COMPRESS_TEX_UV2) { - stride += sizeof(int16_t) * 2; - } else { - stride += sizeof(float) * 2; - } - - } break; - case VS::ARRAY_BONES: { - //assumed weights too - - //unique format, internally 16 bits, exposed as single array for 32 - - stride += sizeof(int32_t) * 4; - - } break; - } - } - } - - int expected_size = stride * p_surface.vertex_count; - ERR_FAIL_COND_MSG(expected_size != p_surface.vertex_data.size(), "Size of data provided (" + itos(p_surface.vertex_data.size()) + ") does not match expected (" + itos(expected_size) + ")"); - } - -#endif - - Mesh::Surface *s = memnew(Mesh::Surface); - - s->format = p_surface.format; - s->primitive = p_surface.primitive; - - s->vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.vertex_data.size(), p_surface.vertex_data); - s->vertex_count = p_surface.vertex_count; - - if (p_surface.index_count) { - bool is_index_16 = p_surface.vertex_count <= 65536; - - s->index_buffer = RD::get_singleton()->index_buffer_create(p_surface.index_count, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.index_data, false); - s->index_count = p_surface.index_count; - s->index_array = RD::get_singleton()->index_array_create(s->index_buffer, 0, s->index_count); - if (p_surface.lods.size()) { - s->lods = memnew_arr(Mesh::Surface::LOD, p_surface.lods.size()); - s->lod_count = p_surface.lods.size(); - - for (int i = 0; i < p_surface.lods.size(); i++) { - - uint32_t indices = p_surface.lods[i].index_data.size() / (is_index_16 ? 2 : 4); - s->lods[i].index_buffer = RD::get_singleton()->index_buffer_create(indices, is_index_16 ? RD::INDEX_BUFFER_FORMAT_UINT16 : RD::INDEX_BUFFER_FORMAT_UINT32, p_surface.lods[i].index_data); - s->lods[i].index_array = RD::get_singleton()->index_array_create(s->lods[i].index_buffer, 0, indices); - s->lods[i].edge_length = p_surface.lods[i].edge_length; - } - } - } - - s->aabb = p_surface.aabb; - s->bone_aabbs = p_surface.bone_aabbs; //only really useful for returning them. - - for (int i = 0; i < p_surface.blend_shapes.size(); i++) { - - if (p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()) { - memdelete(s); - ERR_FAIL_COND(p_surface.blend_shapes[i].size() != p_surface.vertex_data.size()); - } - RID vertex_buffer = RD::get_singleton()->vertex_buffer_create(p_surface.blend_shapes[i].size(), p_surface.blend_shapes[i]); - s->blend_shapes.push_back(vertex_buffer); - } - - mesh->blend_shape_count = p_surface.blend_shapes.size(); - - if (mesh->surface_count == 0) { - mesh->bone_aabbs = p_surface.bone_aabbs; - mesh->aabb = p_surface.aabb; - } else { - for (int i = 0; i < p_surface.bone_aabbs.size(); i++) { - mesh->bone_aabbs.write[i].merge_with(p_surface.bone_aabbs[i]); - } - mesh->aabb.merge_with(p_surface.aabb); - } - - s->material = p_surface.material; - - mesh->surfaces = (Mesh::Surface **)memrealloc(mesh->surfaces, sizeof(Mesh::Surface *) * (mesh->surface_count + 1)); - mesh->surfaces[mesh->surface_count] = s; - mesh->surface_count++; - - mesh->instance_dependency.instance_notify_changed(true, true); - - mesh->material_cache.clear(); -} - -int RasterizerStorageRD::mesh_get_blend_shape_count(RID p_mesh) const { - const Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, -1); - return mesh->blend_shape_count; -} - -void RasterizerStorageRD::mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_INDEX((int)p_mode, 2); - - mesh->blend_shape_mode = p_mode; -} -VS::BlendShapeMode RasterizerStorageRD::mesh_get_blend_shape_mode(RID p_mesh) const { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::BLEND_SHAPE_MODE_NORMALIZED); - return mesh->blend_shape_mode; -} - -void RasterizerStorageRD::mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - ERR_FAIL_COND(p_data.size() == 0); - uint64_t data_size = p_data.size(); - const uint8_t *r = p_data.ptr(); - - RD::get_singleton()->buffer_update(mesh->surfaces[p_surface]->vertex_buffer, p_offset, data_size, r); -} - -void RasterizerStorageRD::mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX((uint32_t)p_surface, mesh->surface_count); - mesh->surfaces[p_surface]->material = p_material; - - mesh->instance_dependency.instance_notify_changed(false, true); - mesh->material_cache.clear(); -} -RID RasterizerStorageRD::mesh_surface_get_material(RID p_mesh, int p_surface) const { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, RID()); - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, RID()); - - return mesh->surfaces[p_surface]->material; -} - -VS::SurfaceData RasterizerStorageRD::mesh_get_surface(RID p_mesh, int p_surface) const { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::SurfaceData()); - ERR_FAIL_UNSIGNED_INDEX_V((uint32_t)p_surface, mesh->surface_count, VS::SurfaceData()); - - Mesh::Surface &s = *mesh->surfaces[p_surface]; - - VS::SurfaceData sd; - sd.format = s.format; - sd.vertex_data = RD::get_singleton()->buffer_get_data(s.vertex_buffer); - sd.vertex_count = s.vertex_count; - sd.index_count = s.index_count; - sd.primitive = s.primitive; - - if (sd.index_count) { - sd.index_data = RD::get_singleton()->buffer_get_data(s.index_buffer); - } - sd.aabb = s.aabb; - for (uint32_t i = 0; i < s.lod_count; i++) { - VS::SurfaceData::LOD lod; - lod.edge_length = s.lods[i].edge_length; - lod.index_data = RD::get_singleton()->buffer_get_data(s.lods[i].index_buffer); - sd.lods.push_back(lod); - } - - sd.bone_aabbs = s.bone_aabbs; - - for (int i = 0; i < s.blend_shapes.size(); i++) { - Vector bs = RD::get_singleton()->buffer_get_data(s.blend_shapes[i]); - sd.blend_shapes.push_back(bs); - } - - return sd; -} - -int RasterizerStorageRD::mesh_get_surface_count(RID p_mesh) const { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, 0); - return mesh->surface_count; -} - -void RasterizerStorageRD::mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - mesh->custom_aabb = p_aabb; -} -AABB RasterizerStorageRD::mesh_get_custom_aabb(RID p_mesh) const { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - return mesh->custom_aabb; -} - -AABB RasterizerStorageRD::mesh_get_aabb(RID p_mesh, RID p_skeleton) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, AABB()); - - if (mesh->custom_aabb != AABB()) { - return mesh->custom_aabb; - } - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - if (!skeleton || skeleton->size == 0) { - return mesh->aabb; - } - - AABB aabb; - - for (uint32_t i = 0; i < mesh->surface_count; i++) { - - AABB laabb; - if ((mesh->surfaces[i]->format & VS::ARRAY_FORMAT_BONES) && mesh->surfaces[i]->bone_aabbs.size()) { - - int bs = mesh->surfaces[i]->bone_aabbs.size(); - const AABB *skbones = mesh->surfaces[i]->bone_aabbs.ptr(); - - int sbs = skeleton->size; - ERR_CONTINUE(bs > sbs); - const float *baseptr = skeleton->data.ptr(); - - bool first = true; - - if (skeleton->use_2d) { - for (int j = 0; j < bs; j++) { - - if (skbones[0].size == Vector3()) - continue; //bone is unused - - const float *dataptr = baseptr + j * 8; - - Transform mtx; - - mtx.basis.elements[0].x = dataptr[0]; - mtx.basis.elements[1].x = dataptr[1]; - mtx.origin.x = dataptr[3]; - - mtx.basis.elements[0].y = dataptr[4]; - mtx.basis.elements[1].y = dataptr[5]; - mtx.origin.y = dataptr[7]; - - AABB baabb = mtx.xform(skbones[j]); - - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } else { - for (int j = 0; j < bs; j++) { - - if (skbones[0].size == Vector3()) - continue; //bone is unused - - const float *dataptr = baseptr + j * 12; - - Transform mtx; - - mtx.basis.elements[0][0] = dataptr[0]; - mtx.basis.elements[0][1] = dataptr[1]; - mtx.basis.elements[0][2] = dataptr[2]; - mtx.origin.x = dataptr[3]; - mtx.basis.elements[1][0] = dataptr[4]; - mtx.basis.elements[1][1] = dataptr[5]; - mtx.basis.elements[1][2] = dataptr[6]; - mtx.origin.y = dataptr[7]; - mtx.basis.elements[2][0] = dataptr[8]; - mtx.basis.elements[2][1] = dataptr[9]; - mtx.basis.elements[2][2] = dataptr[10]; - mtx.origin.z = dataptr[11]; - - AABB baabb = mtx.xform(skbones[j]); - if (first) { - laabb = baabb; - first = false; - } else { - laabb.merge_with(baabb); - } - } - } - - if (laabb.size == Vector3()) { - laabb = mesh->surfaces[i]->aabb; - } - } else { - - laabb = mesh->surfaces[i]->aabb; - } - - if (i == 0) { - aabb = laabb; - } else { - aabb.merge_with(laabb); - } - } - - return aabb; -} - -void RasterizerStorageRD::mesh_clear(RID p_mesh) { - - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - for (uint32_t i = 0; i < mesh->surface_count; i++) { - Mesh::Surface &s = *mesh->surfaces[i]; - RD::get_singleton()->free(s.vertex_buffer); //clears arrays as dependency automatically, including all versions - if (s.versions) { - memfree(s.versions); //reallocs, so free with memfree. - } - - if (s.index_buffer.is_valid()) { - RD::get_singleton()->free(s.index_buffer); - } - - if (s.lod_count) { - for (uint32_t j = 0; j < s.lod_count; j++) { - RD::get_singleton()->free(s.lods[j].index_buffer); - } - memdelete_arr(s.lods); - } - - for (int32_t j = 0; j < s.blend_shapes.size(); j++) { - RD::get_singleton()->free(s.blend_shapes[j]); - } - - if (s.blend_shape_base_buffer.is_valid()) { - RD::get_singleton()->free(s.blend_shape_base_buffer); - } - - memdelete(mesh->surfaces[i]); - } - if (mesh->surfaces) { - memfree(mesh->surfaces); - } - - mesh->surfaces = nullptr; - mesh->surface_count = 0; - mesh->material_cache.clear(); - mesh->instance_dependency.instance_notify_changed(true, true); -} - -void RasterizerStorageRD::_mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask) { - uint32_t version = s->version_count; - s->version_count++; - s->versions = (Mesh::Surface::Version *)memrealloc(s->versions, sizeof(Mesh::Surface::Version) * s->version_count); - - Mesh::Surface::Version &v = s->versions[version]; - - Vector attributes; - Vector buffers; - - uint32_t stride = 0; - - for (int i = 0; i < VS::ARRAY_WEIGHTS; i++) { - - RD::VertexDescription vd; - RID buffer; - vd.location = i; - - if (!(s->format & (1 << i))) { - // Not supplied by surface, use default value - buffer = mesh_default_rd_buffers[i]; - switch (i) { - - case VS::ARRAY_VERTEX: { - - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - - } break; - case VS::ARRAY_NORMAL: { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - } break; - case VS::ARRAY_TANGENT: { - - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - } break; - case VS::ARRAY_COLOR: { - - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - - } break; - case VS::ARRAY_TEX_UV: { - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - - } break; - case VS::ARRAY_TEX_UV2: { - - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - } break; - case VS::ARRAY_BONES: { - - //assumed weights too - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - } break; - } - } else { - //Supplied, use it - - vd.offset = stride; - vd.stride = 1; //mark that it needs a stride set - buffer = s->vertex_buffer; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (s->format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32_SFLOAT; - stride += sizeof(float) * 3; - } - - } break; - case VS::ARRAY_NORMAL: { - - if (s->format & VS::ARRAY_COMPRESS_NORMAL) { - vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM; - stride += sizeof(int8_t) * 4; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - stride += sizeof(float) * 4; - } - - } break; - case VS::ARRAY_TANGENT: { - - if (s->format & VS::ARRAY_COMPRESS_TANGENT) { - vd.format = RD::DATA_FORMAT_R8G8B8A8_SNORM; - stride += sizeof(int8_t) * 4; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - stride += sizeof(float) * 4; - } - - } break; - case VS::ARRAY_COLOR: { - - if (s->format & VS::ARRAY_COMPRESS_COLOR) { - vd.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - stride += sizeof(int8_t) * 4; - } else { - vd.format = RD::DATA_FORMAT_R32G32B32A32_SFLOAT; - stride += sizeof(float) * 4; - } - - } break; - case VS::ARRAY_TEX_UV: { - - if (s->format & VS::ARRAY_COMPRESS_TEX_UV) { - vd.format = RD::DATA_FORMAT_R16G16_SFLOAT; - stride += sizeof(int16_t) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } - - } break; - case VS::ARRAY_TEX_UV2: { - - if (s->format & VS::ARRAY_COMPRESS_TEX_UV2) { - vd.format = RD::DATA_FORMAT_R16G16_SFLOAT; - stride += sizeof(int16_t) * 2; - } else { - vd.format = RD::DATA_FORMAT_R32G32_SFLOAT; - stride += sizeof(float) * 2; - } - - } break; - case VS::ARRAY_BONES: { - //assumed weights too - - //unique format, internally 16 bits, exposed as single array for 32 - - vd.format = RD::DATA_FORMAT_R32G32B32A32_UINT; - stride += sizeof(int32_t) * 4; - - } break; - } - } - - if (!(p_input_mask & (1 << i))) { - continue; // Shader does not need this, skip it - } - - attributes.push_back(vd); - buffers.push_back(buffer); - } - - //update final stride - for (int i = 0; i < attributes.size(); i++) { - if (attributes[i].stride == 1) { - attributes.write[i].stride = stride; - } - } - - v.input_mask = p_input_mask; - v.vertex_format = RD::get_singleton()->vertex_format_create(attributes); - v.vertex_array = RD::get_singleton()->vertex_array_create(s->vertex_count, v.vertex_format, buffers); -} - -////////////////// MULTIMESH - -RID RasterizerStorageRD::multimesh_create() { - - return multimesh_owner.make_rid(MultiMesh()); -} - -void RasterizerStorageRD::multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors, bool p_use_custom_data) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - - if (multimesh->instances == p_instances && multimesh->xform_format == p_transform_format && multimesh->uses_colors == p_use_colors && multimesh->uses_custom_data == p_use_custom_data) { - return; - } - - if (multimesh->buffer.is_valid()) { - RD::get_singleton()->free(multimesh->buffer); - multimesh->buffer = RID(); - multimesh->uniform_set_3d = RID(); //cleared by dependency - } - - if (multimesh->data_cache_dirty_regions) { - memdelete_arr(multimesh->data_cache_dirty_regions); - multimesh->data_cache_dirty_regions = nullptr; - multimesh->data_cache_used_dirty_regions = 0; - } - - multimesh->instances = p_instances; - multimesh->xform_format = p_transform_format; - multimesh->uses_colors = p_use_colors; - multimesh->color_offset_cache = p_transform_format == VS::MULTIMESH_TRANSFORM_2D ? 8 : 12; - multimesh->uses_custom_data = p_use_custom_data; - multimesh->custom_data_offset_cache = multimesh->color_offset_cache + (p_use_colors ? 4 : 0); - multimesh->stride_cache = multimesh->custom_data_offset_cache + (p_use_custom_data ? 4 : 0); - multimesh->buffer_set = false; - - //print_line("allocate, elements: " + itos(p_instances) + " 2D: " + itos(p_transform_format == VS::MULTIMESH_TRANSFORM_2D) + " colors " + itos(multimesh->uses_colors) + " data " + itos(multimesh->uses_custom_data) + " stride " + itos(multimesh->stride_cache) + " total size " + itos(multimesh->stride_cache * multimesh->instances)); - multimesh->data_cache = Vector(); - multimesh->aabb = AABB(); - multimesh->aabb_dirty = false; - multimesh->visible_instances = MIN(multimesh->visible_instances, multimesh->instances); - - if (multimesh->instances) { - - multimesh->buffer = RD::get_singleton()->storage_buffer_create(multimesh->instances * multimesh->stride_cache * 4); - } -} - -int RasterizerStorageRD::multimesh_get_instance_count(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - return multimesh->instances; -} - -void RasterizerStorageRD::multimesh_set_mesh(RID p_multimesh, RID p_mesh) { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - if (multimesh->mesh == p_mesh) { - return; - } - multimesh->mesh = p_mesh; - - if (multimesh->instances == 0) { - return; - } - - if (multimesh->data_cache.size()) { - //we have a data cache, just mark it dirt - _multimesh_mark_all_dirty(multimesh, false, true); - } else if (multimesh->instances) { - //need to re-create AABB unfortunately, calling this has a penalty - if (multimesh->buffer_set) { - Vector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - const uint8_t *r = buffer.ptr(); - const float *data = (const float *)r; - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - } - } - - multimesh->instance_dependency.instance_notify_changed(true, true); -} - -#define MULTIMESH_DIRTY_REGION_SIZE 512 - -void RasterizerStorageRD::_multimesh_make_local(MultiMesh *multimesh) const { - if (multimesh->data_cache.size() > 0) { - return; //already local - } - ERR_FAIL_COND(multimesh->data_cache.size() > 0); - // this means that the user wants to load/save individual elements, - // for this, the data must reside on CPU, so just copy it there. - multimesh->data_cache.resize(multimesh->instances * multimesh->stride_cache); - { - float *w = multimesh->data_cache.ptrw(); - - if (multimesh->buffer_set) { - Vector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - { - - const uint8_t *r = buffer.ptr(); - copymem(w, r, buffer.size()); - } - } else { - zeromem(w, multimesh->instances * multimesh->stride_cache * sizeof(float)); - } - } - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - multimesh->data_cache_dirty_regions = memnew_arr(bool, data_cache_dirty_region_count); - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = 0; - } - multimesh->data_cache_used_dirty_regions = 0; -} - -void RasterizerStorageRD::_multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb) { - - uint32_t region_index = p_index / MULTIMESH_DIRTY_REGION_SIZE; -#ifdef DEBUG_ENABLED - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - ERR_FAIL_UNSIGNED_INDEX(region_index, data_cache_dirty_region_count); //bug -#endif - if (!multimesh->data_cache_dirty_regions[region_index]) { - multimesh->data_cache_dirty_regions[region_index] = true; - multimesh->data_cache_used_dirty_regions++; - } - - if (p_aabb) { - multimesh->aabb_dirty = true; - } - - if (!multimesh->dirty) { - multimesh->dirty_list = multimesh_dirty_list; - multimesh_dirty_list = multimesh; - multimesh->dirty = true; - } -} - -void RasterizerStorageRD::_multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb) { - if (p_data) { - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - if (!multimesh->data_cache_dirty_regions[i]) { - multimesh->data_cache_dirty_regions[i] = true; - multimesh->data_cache_used_dirty_regions++; - } - } - } - - if (p_aabb) { - multimesh->aabb_dirty = true; - } - - if (!multimesh->dirty) { - multimesh->dirty_list = multimesh_dirty_list; - multimesh_dirty_list = multimesh; - multimesh->dirty = true; - } -} - -void RasterizerStorageRD::_multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances) { - - ERR_FAIL_COND(multimesh->mesh.is_null()); - AABB aabb; - AABB mesh_aabb = mesh_get_aabb(multimesh->mesh); - for (int i = 0; i < p_instances; i++) { - const float *data = p_data + multimesh->stride_cache * i; - Transform t; - - if (multimesh->xform_format == VS::MULTIMESH_TRANSFORM_3D) { - - t.basis.elements[0][0] = data[0]; - t.basis.elements[0][1] = data[1]; - t.basis.elements[0][2] = data[2]; - t.origin.x = data[3]; - t.basis.elements[1][0] = data[4]; - t.basis.elements[1][1] = data[5]; - t.basis.elements[1][2] = data[6]; - t.origin.y = data[7]; - t.basis.elements[2][0] = data[8]; - t.basis.elements[2][1] = data[9]; - t.basis.elements[2][2] = data[10]; - t.origin.z = data[11]; - - } else { - - t.basis.elements[0].x = data[0]; - t.basis.elements[1].x = data[1]; - t.origin.x = data[3]; - - t.basis.elements[0].y = data[4]; - t.basis.elements[1].y = data[5]; - t.origin.y = data[7]; - } - - if (i == 0) { - aabb = t.xform(mesh_aabb); - } else { - aabb.merge_with(t.xform(mesh_aabb)); - } - } - - multimesh->aabb = aabb; -} - -void RasterizerStorageRD::multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_3D); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - } - - _multimesh_mark_dirty(multimesh, p_index, true); -} - -void RasterizerStorageRD::multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_2D); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - } - - _multimesh_mark_dirty(multimesh, p_index, true); -} -void RasterizerStorageRD::multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(!multimesh->uses_colors); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->color_offset_cache; - - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - _multimesh_mark_dirty(multimesh, p_index, false); -} -void RasterizerStorageRD::multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_INDEX(p_index, multimesh->instances); - ERR_FAIL_COND(!multimesh->uses_custom_data); - - _multimesh_make_local(multimesh); - - { - float *w = multimesh->data_cache.ptrw(); - - float *dataptr = w + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; - - dataptr[0] = p_color.r; - dataptr[1] = p_color.g; - dataptr[2] = p_color.b; - dataptr[3] = p_color.a; - } - - _multimesh_mark_dirty(multimesh, p_index, false); -} - -RID RasterizerStorageRD::multimesh_get_mesh(RID p_multimesh) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, RID()); - - return multimesh->mesh; -} - -Transform RasterizerStorageRD::multimesh_instance_get_transform(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform()); - ERR_FAIL_COND_V(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_3D, Transform()); - - _multimesh_make_local(multimesh); - - Transform t; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache; - - t.basis.elements[0][0] = dataptr[0]; - t.basis.elements[0][1] = dataptr[1]; - t.basis.elements[0][2] = dataptr[2]; - t.origin.x = dataptr[3]; - t.basis.elements[1][0] = dataptr[4]; - t.basis.elements[1][1] = dataptr[5]; - t.basis.elements[1][2] = dataptr[6]; - t.origin.y = dataptr[7]; - t.basis.elements[2][0] = dataptr[8]; - t.basis.elements[2][1] = dataptr[9]; - t.basis.elements[2][2] = dataptr[10]; - t.origin.z = dataptr[11]; - } - - return t; -} -Transform2D RasterizerStorageRD::multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Transform2D()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Transform2D()); - ERR_FAIL_COND_V(multimesh->xform_format != VS::MULTIMESH_TRANSFORM_2D, Transform2D()); - - _multimesh_make_local(multimesh); - - Transform2D t; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache; - - t.elements[0][0] = dataptr[0]; - t.elements[1][0] = dataptr[1]; - t.elements[2][0] = dataptr[3]; - t.elements[0][1] = dataptr[4]; - t.elements[1][1] = dataptr[5]; - t.elements[2][1] = dataptr[7]; - } - - return t; -} -Color RasterizerStorageRD::multimesh_instance_get_color(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); - ERR_FAIL_COND_V(!multimesh->uses_colors, Color()); - - _multimesh_make_local(multimesh); - - Color c; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->color_offset_cache; - - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - } - - return c; -} -Color RasterizerStorageRD::multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Color()); - ERR_FAIL_INDEX_V(p_index, multimesh->instances, Color()); - ERR_FAIL_COND_V(!multimesh->uses_custom_data, Color()); - - _multimesh_make_local(multimesh); - - Color c; - { - const float *r = multimesh->data_cache.ptr(); - - const float *dataptr = r + p_index * multimesh->stride_cache + multimesh->custom_data_offset_cache; - - c.r = dataptr[0]; - c.g = dataptr[1]; - c.b = dataptr[2]; - c.a = dataptr[3]; - } - - return c; -} - -void RasterizerStorageRD::multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(p_buffer.size() != (multimesh->instances * (int)multimesh->stride_cache)); - - { - const float *r = p_buffer.ptr(); - RD::get_singleton()->buffer_update(multimesh->buffer, 0, p_buffer.size() * sizeof(float), r, false); - multimesh->buffer_set = true; - } - - if (multimesh->data_cache.size()) { - //if we have a data cache, just update it - multimesh->data_cache = p_buffer; - { - //clear dirty since nothing will be dirty anymore - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - multimesh->data_cache_used_dirty_regions = 0; - } - - _multimesh_mark_all_dirty(multimesh, false, true); //update AABB - } else if (multimesh->mesh.is_valid()) { - //if we have a mesh set, we need to re-generate the AABB from the new data - const float *data = p_buffer.ptr(); - - _multimesh_re_create_aabb(multimesh, data, multimesh->instances); - multimesh->instance_dependency.instance_notify_changed(true, false); - } -} - -Vector RasterizerStorageRD::multimesh_get_buffer(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, Vector()); - if (multimesh->buffer.is_null()) { - return Vector(); - } else if (multimesh->data_cache.size()) { - return multimesh->data_cache; - } else { - //get from memory - - Vector buffer = RD::get_singleton()->buffer_get_data(multimesh->buffer); - Vector ret; - ret.resize(multimesh->instances); - { - float *w = multimesh->data_cache.ptrw(); - const uint8_t *r = buffer.ptr(); - copymem(w, r, buffer.size()); - } - - return ret; - } -} - -void RasterizerStorageRD::multimesh_set_visible_instances(RID p_multimesh, int p_visible) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND(!multimesh); - ERR_FAIL_COND(p_visible < -1 || p_visible > multimesh->instances); - if (multimesh->visible_instances == p_visible) { - return; - } - - if (multimesh->data_cache.size()) { - //there is a data cache.. - _multimesh_mark_all_dirty(multimesh, false, true); - } - - multimesh->visible_instances = p_visible; -} -int RasterizerStorageRD::multimesh_get_visible_instances(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, 0); - return multimesh->visible_instances; -} - -AABB RasterizerStorageRD::multimesh_get_aabb(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - ERR_FAIL_COND_V(!multimesh, AABB()); - if (multimesh->aabb_dirty) { - const_cast(this)->_update_dirty_multimeshes(); - } - return multimesh->aabb; -} - -void RasterizerStorageRD::_update_dirty_multimeshes() { - - while (multimesh_dirty_list) { - - MultiMesh *multimesh = multimesh_dirty_list; - - if (multimesh->data_cache.size()) { //may have been cleared, so only process if it exists - const float *data = multimesh->data_cache.ptr(); - - uint32_t visible_instances = multimesh->visible_instances >= 0 ? multimesh->visible_instances : multimesh->instances; - - if (multimesh->data_cache_used_dirty_regions) { - - uint32_t data_cache_dirty_region_count = (multimesh->instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - uint32_t visible_region_count = (visible_instances - 1) / MULTIMESH_DIRTY_REGION_SIZE + 1; - - uint32_t region_size = multimesh->stride_cache * MULTIMESH_DIRTY_REGION_SIZE * sizeof(float); - - if (multimesh->data_cache_used_dirty_regions > 32 || multimesh->data_cache_used_dirty_regions > visible_region_count / 2) { - //if there too many dirty regions, or represent the majority of regions, just copy all, else transfer cost piles up too much - RD::get_singleton()->buffer_update(multimesh->buffer, 0, MIN(visible_region_count * region_size, multimesh->instances * multimesh->stride_cache * sizeof(float)), data, false); - } else { - //not that many regions? update them all - for (uint32_t i = 0; i < visible_region_count; i++) { - if (multimesh->data_cache_dirty_regions[i]) { - uint64_t offset = i * region_size; - uint64_t size = multimesh->stride_cache * multimesh->instances * sizeof(float); - RD::get_singleton()->buffer_update(multimesh->buffer, offset, MIN(region_size, size - offset), &data[i * region_size], false); - } - } - } - - for (uint32_t i = 0; i < data_cache_dirty_region_count; i++) { - multimesh->data_cache_dirty_regions[i] = false; - } - - multimesh->data_cache_used_dirty_regions = 0; - } - - if (multimesh->aabb_dirty) { - //aabb is dirty.. - _multimesh_re_create_aabb(multimesh, data, visible_instances); - multimesh->aabb_dirty = false; - multimesh->instance_dependency.instance_notify_changed(true, false); - } - } - - multimesh_dirty_list = multimesh->dirty_list; - - multimesh->dirty_list = nullptr; - multimesh->dirty = false; - } - - multimesh_dirty_list = nullptr; -} - -/* SKELETON */ - -/* SKELETON API */ - -RID RasterizerStorageRD::skeleton_create() { - - return skeleton_owner.make_rid(Skeleton()); -} - -void RasterizerStorageRD::_skeleton_make_dirty(Skeleton *skeleton) { - - if (!skeleton->dirty) { - skeleton->dirty = true; - skeleton->dirty_list = skeleton_dirty_list; - skeleton_dirty_list = skeleton; - } -} - -void RasterizerStorageRD::skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND(!skeleton); - ERR_FAIL_COND(p_bones < 0); - - if (skeleton->size == p_bones && skeleton->use_2d == p_2d_skeleton) - return; - - skeleton->size = p_bones; - skeleton->use_2d = p_2d_skeleton; - skeleton->uniform_set_3d = RID(); - - if (skeleton->buffer.is_valid()) { - RD::get_singleton()->free(skeleton->buffer); - skeleton->buffer = RID(); - skeleton->data.resize(0); - } - - if (skeleton->size) { - - skeleton->data.resize(skeleton->size * (skeleton->use_2d ? 8 : 12)); - skeleton->buffer = RD::get_singleton()->storage_buffer_create(skeleton->data.size() * sizeof(float)); - zeromem(skeleton->data.ptrw(), skeleton->data.size() * sizeof(float)); - - _skeleton_make_dirty(skeleton); - } -} -int RasterizerStorageRD::skeleton_get_bone_count(RID p_skeleton) const { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND_V(!skeleton, 0); - - return skeleton->size; -} - -void RasterizerStorageRD::skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(skeleton->use_2d); - - float *dataptr = skeleton->data.ptrw() + p_bone * 12; - - dataptr[0] = p_transform.basis.elements[0][0]; - dataptr[1] = p_transform.basis.elements[0][1]; - dataptr[2] = p_transform.basis.elements[0][2]; - dataptr[3] = p_transform.origin.x; - dataptr[4] = p_transform.basis.elements[1][0]; - dataptr[5] = p_transform.basis.elements[1][1]; - dataptr[6] = p_transform.basis.elements[1][2]; - dataptr[7] = p_transform.origin.y; - dataptr[8] = p_transform.basis.elements[2][0]; - dataptr[9] = p_transform.basis.elements[2][1]; - dataptr[10] = p_transform.basis.elements[2][2]; - dataptr[11] = p_transform.origin.z; - - _skeleton_make_dirty(skeleton); -} - -Transform RasterizerStorageRD::skeleton_bone_get_transform(RID p_skeleton, int p_bone) const { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform()); - ERR_FAIL_COND_V(skeleton->use_2d, Transform()); - - const float *dataptr = skeleton->data.ptr() + p_bone * 12; - - Transform t; - - t.basis.elements[0][0] = dataptr[0]; - t.basis.elements[0][1] = dataptr[1]; - t.basis.elements[0][2] = dataptr[2]; - t.origin.x = dataptr[3]; - t.basis.elements[1][0] = dataptr[4]; - t.basis.elements[1][1] = dataptr[5]; - t.basis.elements[1][2] = dataptr[6]; - t.origin.y = dataptr[7]; - t.basis.elements[2][0] = dataptr[8]; - t.basis.elements[2][1] = dataptr[9]; - t.basis.elements[2][2] = dataptr[10]; - t.origin.z = dataptr[11]; - - return t; -} -void RasterizerStorageRD::skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(!skeleton); - ERR_FAIL_INDEX(p_bone, skeleton->size); - ERR_FAIL_COND(!skeleton->use_2d); - - float *dataptr = skeleton->data.ptrw() + p_bone * 8; - - dataptr[0] = p_transform.elements[0][0]; - dataptr[1] = p_transform.elements[1][0]; - dataptr[2] = 0; - dataptr[3] = p_transform.elements[2][0]; - dataptr[4] = p_transform.elements[0][1]; - dataptr[5] = p_transform.elements[1][1]; - dataptr[6] = 0; - dataptr[7] = p_transform.elements[2][1]; - - _skeleton_make_dirty(skeleton); -} -Transform2D RasterizerStorageRD::skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND_V(!skeleton, Transform2D()); - ERR_FAIL_INDEX_V(p_bone, skeleton->size, Transform2D()); - ERR_FAIL_COND_V(!skeleton->use_2d, Transform2D()); - - const float *dataptr = skeleton->data.ptr() + p_bone * 8; - - Transform2D t; - t.elements[0][0] = dataptr[0]; - t.elements[1][0] = dataptr[1]; - t.elements[2][0] = dataptr[3]; - t.elements[0][1] = dataptr[4]; - t.elements[1][1] = dataptr[5]; - t.elements[2][1] = dataptr[7]; - - return t; -} - -void RasterizerStorageRD::skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - - ERR_FAIL_COND(!skeleton->use_2d); - - skeleton->base_transform_2d = p_base_transform; -} - -void RasterizerStorageRD::_update_dirty_skeletons() { - - while (skeleton_dirty_list) { - - Skeleton *skeleton = skeleton_dirty_list; - - if (skeleton->size) { - - RD::get_singleton()->buffer_update(skeleton->buffer, 0, skeleton->data.size() * sizeof(float), skeleton->data.ptr(), false); - } - - skeleton_dirty_list = skeleton->dirty_list; - - skeleton->instance_dependency.instance_notify_changed(true, false); - - skeleton->dirty = false; - skeleton->dirty_list = nullptr; - } - - skeleton_dirty_list = nullptr; -} - -/* LIGHT */ - -RID RasterizerStorageRD::light_create(VS::LightType p_type) { - - Light light; - light.type = p_type; - - light.param[VS::LIGHT_PARAM_ENERGY] = 1.0; - light.param[VS::LIGHT_PARAM_INDIRECT_ENERGY] = 1.0; - light.param[VS::LIGHT_PARAM_SPECULAR] = 0.5; - light.param[VS::LIGHT_PARAM_RANGE] = 1.0; - light.param[VS::LIGHT_PARAM_SPOT_ANGLE] = 45; - light.param[VS::LIGHT_PARAM_CONTACT_SHADOW_SIZE] = 45; - light.param[VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE] = 0; - light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET] = 0.1; - light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET] = 0.3; - light.param[VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET] = 0.6; - light.param[VS::LIGHT_PARAM_SHADOW_FADE_START] = 0.8; - light.param[VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS] = 0.1; - light.param[VS::LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE] = 0.1; - - return light_owner.make_rid(light); -} - -void RasterizerStorageRD::light_set_color(RID p_light, const Color &p_color) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->color = p_color; -} -void RasterizerStorageRD::light_set_param(RID p_light, VS::LightParam p_param, float p_value) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - ERR_FAIL_INDEX(p_param, VS::LIGHT_PARAM_MAX); - - switch (p_param) { - case VS::LIGHT_PARAM_RANGE: - case VS::LIGHT_PARAM_SPOT_ANGLE: - case VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE: - case VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET: - case VS::LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET: - case VS::LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET: - case VS::LIGHT_PARAM_SHADOW_NORMAL_BIAS: - case VS::LIGHT_PARAM_SHADOW_BIAS: { - - light->version++; - light->instance_dependency.instance_notify_changed(true, false); - } break; - default: { - } - } - - light->param[p_param] = p_value; -} -void RasterizerStorageRD::light_set_shadow(RID p_light, bool p_enabled) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - light->shadow = p_enabled; - - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::light_set_shadow_color(RID p_light, const Color &p_color) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - light->shadow_color = p_color; -} - -void RasterizerStorageRD::light_set_projector(RID p_light, RID p_texture) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->projector = p_texture; -} - -void RasterizerStorageRD::light_set_negative(RID p_light, bool p_enable) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->negative = p_enable; -} -void RasterizerStorageRD::light_set_cull_mask(RID p_light, uint32_t p_mask) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->cull_mask = p_mask; - - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->reverse_cull = p_enabled; - - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::light_set_use_gi(RID p_light, bool p_enabled) { - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->use_gi = p_enabled; - - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} -void RasterizerStorageRD::light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->omni_shadow_mode = p_mode; - - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} - -VS::LightOmniShadowMode RasterizerStorageRD::light_omni_get_shadow_mode(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_OMNI_SHADOW_CUBE); - - return light->omni_shadow_mode; -} - -void RasterizerStorageRD::light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->directional_shadow_mode = p_mode; - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::light_directional_set_blend_splits(RID p_light, bool p_enable) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->directional_blend_splits = p_enable; - light->version++; - light->instance_dependency.instance_notify_changed(true, false); -} - -bool RasterizerStorageRD::light_directional_get_blend_splits(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, false); - - return light->directional_blend_splits; -} - -VS::LightDirectionalShadowMode RasterizerStorageRD::light_directional_get_shadow_mode(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); - - return light->directional_shadow_mode; -} - -void RasterizerStorageRD::light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode) { - - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND(!light); - - light->directional_range_mode = p_range_mode; -} - -VS::LightDirectionalShadowDepthRangeMode RasterizerStorageRD::light_directional_get_shadow_depth_range_mode(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); - - return light->directional_range_mode; -} - -bool RasterizerStorageRD::light_get_use_gi(RID p_light) { - Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, false); - - return light->use_gi; -} - -uint64_t RasterizerStorageRD::light_get_version(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, 0); - - return light->version; -} - -AABB RasterizerStorageRD::light_get_aabb(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, AABB()); - - switch (light->type) { - - case VS::LIGHT_SPOT: { - - float len = light->param[VS::LIGHT_PARAM_RANGE]; - float size = Math::tan(Math::deg2rad(light->param[VS::LIGHT_PARAM_SPOT_ANGLE])) * len; - return AABB(Vector3(-size, -size, -len), Vector3(size * 2, size * 2, len)); - }; - case VS::LIGHT_OMNI: { - - float r = light->param[VS::LIGHT_PARAM_RANGE]; - return AABB(-Vector3(r, r, r), Vector3(r, r, r) * 2); - }; - case VS::LIGHT_DIRECTIONAL: { - - return AABB(); - }; - } - - ERR_FAIL_V(AABB()); -} - -/* REFLECTION PROBE */ - -RID RasterizerStorageRD::reflection_probe_create() { - - return reflection_probe_owner.make_rid(ReflectionProbe()); -} - -void RasterizerStorageRD::reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->update_mode = p_mode; - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::reflection_probe_set_intensity(RID p_probe, float p_intensity) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->intensity = p_intensity; -} - -void RasterizerStorageRD::reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior_ambient = p_ambient; -} - -void RasterizerStorageRD::reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior_ambient_energy = p_energy; -} - -void RasterizerStorageRD::reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior_ambient_probe_contrib = p_contrib; -} - -void RasterizerStorageRD::reflection_probe_set_max_distance(RID p_probe, float p_distance) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->max_distance = p_distance; - - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} -void RasterizerStorageRD::reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->extents = p_extents; - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} -void RasterizerStorageRD::reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->origin_offset = p_offset; - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::reflection_probe_set_as_interior(RID p_probe, bool p_enable) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->interior = p_enable; - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} -void RasterizerStorageRD::reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->box_projection = p_enable; -} - -void RasterizerStorageRD::reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->enable_shadows = p_enable; - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} -void RasterizerStorageRD::reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - - reflection_probe->cull_mask = p_layers; - reflection_probe->instance_dependency.instance_notify_changed(true, false); -} - -void RasterizerStorageRD::reflection_probe_set_resolution(RID p_probe, int p_resolution) { - - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND(!reflection_probe); - ERR_FAIL_COND(p_resolution < 32); - - reflection_probe->resolution = p_resolution; -} - -AABB RasterizerStorageRD::reflection_probe_get_aabb(RID p_probe) const { - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, AABB()); - - AABB aabb; - aabb.position = -reflection_probe->extents; - aabb.size = reflection_probe->extents * 2.0; - - return aabb; -} -VS::ReflectionProbeUpdateMode RasterizerStorageRD::reflection_probe_get_update_mode(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, VS::REFLECTION_PROBE_UPDATE_ALWAYS); - - return reflection_probe->update_mode; -} - -uint32_t RasterizerStorageRD::reflection_probe_get_cull_mask(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->cull_mask; -} - -Vector3 RasterizerStorageRD::reflection_probe_get_extents(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Vector3()); - - return reflection_probe->extents; -} -Vector3 RasterizerStorageRD::reflection_probe_get_origin_offset(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Vector3()); - - return reflection_probe->origin_offset; -} - -bool RasterizerStorageRD::reflection_probe_renders_shadows(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); - - return reflection_probe->enable_shadows; -} - -float RasterizerStorageRD::reflection_probe_get_origin_max_distance(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->max_distance; -} - -int RasterizerStorageRD::reflection_probe_get_resolution(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->resolution; -} - -float RasterizerStorageRD::reflection_probe_get_intensity(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->intensity; -} -bool RasterizerStorageRD::reflection_probe_is_interior(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); - - return reflection_probe->interior; -} -bool RasterizerStorageRD::reflection_probe_is_box_projection(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, false); - - return reflection_probe->box_projection; -} - -Color RasterizerStorageRD::reflection_probe_get_interior_ambient(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, Color()); - - return reflection_probe->interior_ambient; -} -float RasterizerStorageRD::reflection_probe_get_interior_ambient_energy(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->interior_ambient_energy; -} -float RasterizerStorageRD::reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const { - - const ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_probe); - ERR_FAIL_COND_V(!reflection_probe, 0); - - return reflection_probe->interior_ambient_probe_contrib; -} - -RID RasterizerStorageRD::gi_probe_create() { - - return gi_probe_owner.make_rid(GIProbe()); -} - -void RasterizerStorageRD::gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - if (gi_probe->octree_buffer.is_valid()) { - RD::get_singleton()->free(gi_probe->octree_buffer); - RD::get_singleton()->free(gi_probe->data_buffer); - if (gi_probe->sdf_texture.is_valid()) { - RD::get_singleton()->free(gi_probe->sdf_texture); - } - - gi_probe->sdf_texture = RID(); - gi_probe->octree_buffer = RID(); - gi_probe->data_buffer = RID(); - gi_probe->octree_buffer_size = 0; - gi_probe->data_buffer_size = 0; - gi_probe->cell_count = 0; - } - - gi_probe->to_cell_xform = p_to_cell_xform; - gi_probe->bounds = p_aabb; - gi_probe->octree_size = p_octree_size; - gi_probe->level_counts = p_level_counts; - - if (p_octree_cells.size()) { - ERR_FAIL_COND(p_octree_cells.size() % 32 != 0); //cells size must be a multiple of 32 - - uint32_t cell_count = p_octree_cells.size() / 32; - - ERR_FAIL_COND(p_data_cells.size() != (int)cell_count * 16); //see that data size matches - - gi_probe->cell_count = cell_count; - gi_probe->octree_buffer = RD::get_singleton()->storage_buffer_create(p_octree_cells.size(), p_octree_cells); - gi_probe->octree_buffer_size = p_octree_cells.size(); - gi_probe->data_buffer = RD::get_singleton()->storage_buffer_create(p_data_cells.size(), p_data_cells); - gi_probe->data_buffer_size = p_data_cells.size(); - - if (p_distance_field.size()) { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = gi_probe->octree_size.x; - tf.height = gi_probe->octree_size.y; - tf.depth = gi_probe->octree_size.z; - tf.type = RD::TEXTURE_TYPE_3D; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - Vector> s; - s.push_back(p_distance_field); - gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView(), s); - } -#if 0 - { - RD::TextureFormat tf; - tf.format = RD::DATA_FORMAT_R8_UNORM; - tf.width = gi_probe->octree_size.x; - tf.height = gi_probe->octree_size.y; - tf.depth = gi_probe->octree_size.z; - tf.type = RD::TEXTURE_TYPE_3D; - tf.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_STORAGE_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UNORM); - tf.shareable_formats.push_back(RD::DATA_FORMAT_R8_UINT); - gi_probe->sdf_texture = RD::get_singleton()->texture_create(tf, RD::TextureView()); - } - RID shared_tex; - { - - RD::TextureView tv; - tv.format_override = RD::DATA_FORMAT_R8_UINT; - shared_tex = RD::get_singleton()->texture_create_shared(tv, gi_probe->sdf_texture); - } - //update SDF texture - Vector uniforms; - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 1; - u.ids.push_back(gi_probe->octree_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 2; - u.ids.push_back(gi_probe->data_buffer); - uniforms.push_back(u); - } - { - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_IMAGE; - u.binding = 3; - u.ids.push_back(shared_tex); - uniforms.push_back(u); - } - - RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, giprobe_sdf_shader_version_shader, 0); - - { - uint32_t push_constant[4] = { 0, 0, 0, 0 }; - - for (int i = 0; i < gi_probe->level_counts.size() - 1; i++) { - push_constant[0] += gi_probe->level_counts[i]; - } - push_constant[1] = push_constant[0] + gi_probe->level_counts[gi_probe->level_counts.size() - 1]; - - print_line("offset: " + itos(push_constant[0])); - print_line("size: " + itos(push_constant[1])); - //create SDF - RD::ComputeListID compute_list = RD::get_singleton()->compute_list_begin(); - RD::get_singleton()->compute_list_bind_compute_pipeline(compute_list, giprobe_sdf_shader_pipeline); - RD::get_singleton()->compute_list_bind_uniform_set(compute_list, uniform_set, 0); - RD::get_singleton()->compute_list_set_push_constant(compute_list, push_constant, sizeof(uint32_t) * 4); - RD::get_singleton()->compute_list_dispatch(compute_list, gi_probe->octree_size.x / 4, gi_probe->octree_size.y / 4, gi_probe->octree_size.z / 4); - RD::get_singleton()->compute_list_end(); - } - - RD::get_singleton()->free(uniform_set); - RD::get_singleton()->free(shared_tex); - } -#endif - } - - gi_probe->version++; - gi_probe->data_version++; - - gi_probe->instance_dependency.instance_notify_changed(true, false); -} - -AABB RasterizerStorageRD::gi_probe_get_bounds(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, AABB()); - - return gi_probe->bounds; -} - -Vector3i RasterizerStorageRD::gi_probe_get_octree_size(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector3i()); - return gi_probe->octree_size; -} -Vector RasterizerStorageRD::gi_probe_get_octree_cells(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); - - if (gi_probe->octree_buffer.is_valid()) { - return RD::get_singleton()->buffer_get_data(gi_probe->octree_buffer); - } - return Vector(); -} -Vector RasterizerStorageRD::gi_probe_get_data_cells(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); - - if (gi_probe->data_buffer.is_valid()) { - return RD::get_singleton()->buffer_get_data(gi_probe->data_buffer); - } - return Vector(); -} -Vector RasterizerStorageRD::gi_probe_get_distance_field(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); - - if (gi_probe->data_buffer.is_valid()) { - return RD::get_singleton()->texture_get_data(gi_probe->sdf_texture, 0); - } - return Vector(); -} -Vector RasterizerStorageRD::gi_probe_get_level_counts(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Vector()); - - return gi_probe->level_counts; -} -Transform RasterizerStorageRD::gi_probe_get_to_cell_xform(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, Transform()); - - return gi_probe->to_cell_xform; -} - -void RasterizerStorageRD::gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->dynamic_range = p_range; - gi_probe->version++; -} -float RasterizerStorageRD::gi_probe_get_dynamic_range(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - - return gi_probe->dynamic_range; -} - -void RasterizerStorageRD::gi_probe_set_propagation(RID p_gi_probe, float p_range) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->propagation = p_range; - gi_probe->version++; -} -float RasterizerStorageRD::gi_probe_get_propagation(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->propagation; -} - -void RasterizerStorageRD::gi_probe_set_energy(RID p_gi_probe, float p_energy) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->energy = p_energy; -} -float RasterizerStorageRD::gi_probe_get_energy(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->energy; -} - -void RasterizerStorageRD::gi_probe_set_ao(RID p_gi_probe, float p_ao) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->ao = p_ao; -} -float RasterizerStorageRD::gi_probe_get_ao(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->ao; -} - -void RasterizerStorageRD::gi_probe_set_ao_size(RID p_gi_probe, float p_strength) { - - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->ao_size = p_strength; -} - -float RasterizerStorageRD::gi_probe_get_ao_size(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->ao_size; -} - -void RasterizerStorageRD::gi_probe_set_bias(RID p_gi_probe, float p_bias) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->bias = p_bias; -} -float RasterizerStorageRD::gi_probe_get_bias(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->bias; -} - -void RasterizerStorageRD::gi_probe_set_normal_bias(RID p_gi_probe, float p_normal_bias) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->normal_bias = p_normal_bias; -} -float RasterizerStorageRD::gi_probe_get_normal_bias(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->normal_bias; -} - -void RasterizerStorageRD::gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) { - - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->anisotropy_strength = p_strength; -} - -float RasterizerStorageRD::gi_probe_get_anisotropy_strength(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->anisotropy_strength; -} - -void RasterizerStorageRD::gi_probe_set_interior(RID p_gi_probe, bool p_enable) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->interior = p_enable; -} - -void RasterizerStorageRD::gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND(!gi_probe); - - gi_probe->use_two_bounces = p_enable; - gi_probe->version++; -} - -bool RasterizerStorageRD::gi_probe_is_using_two_bounces(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, false); - return gi_probe->use_two_bounces; -} - -bool RasterizerStorageRD::gi_probe_is_interior(RID p_gi_probe) const { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->interior; -} - -uint32_t RasterizerStorageRD::gi_probe_get_version(RID p_gi_probe) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->version; -} - -uint32_t RasterizerStorageRD::gi_probe_get_data_version(RID p_gi_probe) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, 0); - return gi_probe->data_version; -} - -RID RasterizerStorageRD::gi_probe_get_octree_buffer(RID p_gi_probe) const { - - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); - return gi_probe->octree_buffer; -} -RID RasterizerStorageRD::gi_probe_get_data_buffer(RID p_gi_probe) const { - - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); - return gi_probe->data_buffer; -} - -RID RasterizerStorageRD::gi_probe_get_sdf_texture(RID p_gi_probe) { - GIProbe *gi_probe = gi_probe_owner.getornull(p_gi_probe); - ERR_FAIL_COND_V(!gi_probe, RID()); - - return gi_probe->sdf_texture; -} - -/* RENDER TARGET API */ - -void RasterizerStorageRD::_clear_render_target(RenderTarget *rt) { - - //free in reverse dependency order - if (rt->framebuffer.is_valid()) { - RD::get_singleton()->free(rt->framebuffer); - } - - if (rt->color.is_valid()) { - RD::get_singleton()->free(rt->color); - } - - if (rt->backbuffer.is_valid()) { - RD::get_singleton()->free(rt->backbuffer); - rt->backbuffer = RID(); - rt->backbuffer_fb = RID(); - for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { - //just erase copies, since the rest are erased by dependency - RD::get_singleton()->free(rt->backbuffer_mipmaps[i].mipmap_copy); - } - rt->backbuffer_mipmaps.clear(); - if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) { - RD::get_singleton()->free(rt->backbuffer_uniform_set); - } - rt->backbuffer_uniform_set = RID(); - } - - rt->framebuffer = RID(); - rt->color = RID(); -} - -void RasterizerStorageRD::_update_render_target(RenderTarget *rt) { - - if (rt->texture.is_null()) { - //create a placeholder until updated - rt->texture = texture_2d_placeholder_create(); - Texture *tex = texture_owner.getornull(rt->texture); - tex->is_render_target = true; - } - - _clear_render_target(rt); - - if (rt->size.width == 0 || rt->size.height == 0) { - return; - } - //until we implement support for HDR monitors (and render target is attached to screen), this is enough. - rt->color_format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - rt->color_format_srgb = RD::DATA_FORMAT_R8G8B8A8_SRGB; - rt->image_format = rt->flags[RENDER_TARGET_TRANSPARENT] ? Image::FORMAT_RGBA8 : Image::FORMAT_RGB8; - - RD::TextureFormat rd_format; - RD::TextureView rd_view; - { //attempt register - rd_format.format = rt->color_format; - rd_format.width = rt->size.width; - rd_format.height = rt->size.height; - rd_format.depth = 1; - rd_format.array_layers = 1; - rd_format.mipmaps = 1; - rd_format.type = RD::TEXTURE_TYPE_2D; - rd_format.samples = RD::TEXTURE_SAMPLES_1; - rd_format.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT; - rd_format.shareable_formats.push_back(rt->color_format); - rd_format.shareable_formats.push_back(rt->color_format_srgb); - } - - rt->color = RD::get_singleton()->texture_create(rd_format, rd_view); - ERR_FAIL_COND(rt->color.is_null()); - - Vector fb_textures; - fb_textures.push_back(rt->color); - rt->framebuffer = RD::get_singleton()->framebuffer_create(fb_textures); - if (rt->framebuffer.is_null()) { - _clear_render_target(rt); - ERR_FAIL_COND(rt->framebuffer.is_null()); - } - - { //update texture - - Texture *tex = texture_owner.getornull(rt->texture); - - //free existing textures - if (RD::get_singleton()->texture_is_valid(tex->rd_texture)) { - RD::get_singleton()->free(tex->rd_texture); - } - if (RD::get_singleton()->texture_is_valid(tex->rd_texture_srgb)) { - RD::get_singleton()->free(tex->rd_texture_srgb); - } - - tex->rd_texture = RID(); - tex->rd_texture_srgb = RID(); - - //create shared textures to the color buffer, - //so transparent can be supported - RD::TextureView view; - view.format_override = rt->color_format; - if (!rt->flags[RENDER_TARGET_TRANSPARENT]) { - view.swizzle_a = RD::TEXTURE_SWIZZLE_ONE; - } - tex->rd_texture = RD::get_singleton()->texture_create_shared(view, rt->color); - if (rt->color_format_srgb != RD::DATA_FORMAT_MAX) { - view.format_override = rt->color_format_srgb; - tex->rd_texture_srgb = RD::get_singleton()->texture_create_shared(view, rt->color); - } - tex->rd_view = view; - tex->width = rt->size.width; - tex->height = rt->size.height; - tex->width_2d = rt->size.width; - tex->height_2d = rt->size.height; - tex->rd_format = rt->color_format; - tex->rd_format_srgb = rt->color_format_srgb; - tex->format = rt->image_format; - - Vector proxies = tex->proxies; //make a copy, since update may change it - for (int i = 0; i < proxies.size(); i++) { - texture_proxy_update(proxies[i], rt->texture); - } - } -} - -void RasterizerStorageRD::_create_render_target_backbuffer(RenderTarget *rt) { - ERR_FAIL_COND(rt->backbuffer.is_valid()); - - uint32_t mipmaps_required = Image::get_image_required_mipmaps(rt->size.width, rt->size.height, Image::FORMAT_RGBA8); - RD::TextureFormat tf; - tf.format = rt->color_format; - tf.width = rt->size.width; - tf.height = rt->size.height; - tf.type = RD::TEXTURE_TYPE_2D; - tf.usage_bits = RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT | RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT; - tf.mipmaps = mipmaps_required; - - rt->backbuffer = RD::get_singleton()->texture_create(tf, RD::TextureView()); - - { - Vector backbuffer_att; - RID backbuffer_fb_tex = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, 0); - backbuffer_att.push_back(backbuffer_fb_tex); - rt->backbuffer_fb = RD::get_singleton()->framebuffer_create(backbuffer_att); - } - - //create mipmaps - for (uint32_t i = 1; i < mipmaps_required; i++) { - - RenderTarget::BackbufferMipmap mm; - { - mm.mipmap = RD::get_singleton()->texture_create_shared_from_slice(RD::TextureView(), rt->backbuffer, 0, i); - Vector mm_fb_at; - mm_fb_at.push_back(mm.mipmap); - mm.mipmap_fb = RD::get_singleton()->framebuffer_create(mm_fb_at); - } - - { - Size2 mm_size = Image::get_image_mipmap_size(tf.width, tf.height, Image::FORMAT_RGBA8, i); - - RD::TextureFormat mmtf = tf; - mmtf.width = mm_size.width; - mmtf.height = mm_size.height; - mmtf.mipmaps = 1; - - mm.mipmap_copy = RD::get_singleton()->texture_create(mmtf, RD::TextureView()); - Vector mm_fb_at; - mm_fb_at.push_back(mm.mipmap_copy); - mm.mipmap_copy_fb = RD::get_singleton()->framebuffer_create(mm_fb_at); - } - - rt->backbuffer_mipmaps.push_back(mm); - } -} - -RID RasterizerStorageRD::render_target_create() { - RenderTarget render_target; - - render_target.was_used = false; - render_target.clear_requested = false; - - for (int i = 0; i < RENDER_TARGET_FLAG_MAX; i++) { - render_target.flags[i] = false; - } - _update_render_target(&render_target); - return render_target_owner.make_rid(render_target); -} - -void RasterizerStorageRD::render_target_set_position(RID p_render_target, int p_x, int p_y) { - //unused for this render target -} - -void RasterizerStorageRD::render_target_set_size(RID p_render_target, int p_width, int p_height) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->size.x = p_width; - rt->size.y = p_height; - _update_render_target(rt); -} - -RID RasterizerStorageRD::render_target_get_texture(RID p_render_target) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); - - return rt->texture; -} - -void RasterizerStorageRD::render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id) { -} - -void RasterizerStorageRD::render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->flags[p_flag] = p_value; - _update_render_target(rt); -} - -bool RasterizerStorageRD::render_target_was_used(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, false); - return rt->was_used; -} - -void RasterizerStorageRD::render_target_set_as_unused(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->was_used = false; -} - -Size2 RasterizerStorageRD::render_target_get_size(RID p_render_target) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, Size2()); - - return rt->size; -} - -RID RasterizerStorageRD::render_target_get_rd_framebuffer(RID p_render_target) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); - - return rt->framebuffer; -} - -void RasterizerStorageRD::render_target_request_clear(RID p_render_target, const Color &p_clear_color) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->clear_requested = true; - rt->clear_color = p_clear_color; -} - -bool RasterizerStorageRD::render_target_is_clear_requested(RID p_render_target) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, false); - return rt->clear_requested; -} - -Color RasterizerStorageRD::render_target_get_clear_request_color(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, Color()); - return rt->clear_color; -} - -void RasterizerStorageRD::render_target_disable_clear_request(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - rt->clear_requested = false; -} - -void RasterizerStorageRD::render_target_do_clear_request(RID p_render_target) { - - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - if (!rt->clear_requested) { - return; - } - Vector clear_colors; - clear_colors.push_back(rt->clear_color); - RD::get_singleton()->draw_list_begin(rt->framebuffer, RD::INITIAL_ACTION_CLEAR, RD::FINAL_ACTION_READ, RD::INITIAL_ACTION_KEEP, RD::FINAL_ACTION_DISCARD, clear_colors); - RD::get_singleton()->draw_list_end(); - rt->clear_requested = false; -} - -void RasterizerStorageRD::render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND(!rt); - if (!rt->backbuffer.is_valid()) { - _create_render_target_backbuffer(rt); - } - - Rect2i region = p_region; - Rect2 blur_region; - if (region == Rect2i()) { - region.size = rt->size; - } else { - blur_region = region; - blur_region.position /= rt->size; - blur_region.size /= rt->size; - } - - //single texture copy for backbuffer - RD::get_singleton()->texture_copy(rt->color, rt->backbuffer, Vector3(region.position.x, region.position.y, 0), Vector3(region.position.x, region.position.y, 0), Vector3(region.size.x, region.size.y, 1), 0, 0, 0, 0, true); - //effects.copy(rt->color, rt->backbuffer_fb, blur_region); - - //then mipmap blur - RID prev_texture = rt->color; //use color, not backbuffer, as bb has mipmaps. - Vector2 pixel_size = Vector2(1.0 / rt->size.width, 1.0 / rt->size.height); - - for (int i = 0; i < rt->backbuffer_mipmaps.size(); i++) { - pixel_size *= 2.0; //go halfway - const RenderTarget::BackbufferMipmap &mm = rt->backbuffer_mipmaps[i]; - effects.gaussian_blur(prev_texture, mm.mipmap_copy_fb, mm.mipmap_copy, mm.mipmap_fb, pixel_size, blur_region); - prev_texture = mm.mipmap; - } -} - -RID RasterizerStorageRD::render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader) { - RenderTarget *rt = render_target_owner.getornull(p_render_target); - ERR_FAIL_COND_V(!rt, RID()); - - if (!rt->backbuffer.is_valid()) { - _create_render_target_backbuffer(rt); - } - - if (rt->backbuffer_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(rt->backbuffer_uniform_set)) { - return rt->backbuffer_uniform_set; //if still valid, return/reuse it. - } - - //create otherwise - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_TEXTURE; - u.binding = 0; - u.ids.push_back(rt->backbuffer); - uniforms.push_back(u); - - rt->backbuffer_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, p_base_shader, 3); - ERR_FAIL_COND_V(!rt->backbuffer_uniform_set.is_valid(), RID()); - - return rt->backbuffer_uniform_set; -} - -void RasterizerStorageRD::base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance) { - if (mesh_owner.owns(p_base)) { - Mesh *mesh = mesh_owner.getornull(p_base); - p_instance->update_dependency(&mesh->instance_dependency); - } else if (multimesh_owner.owns(p_base)) { - - MultiMesh *multimesh = multimesh_owner.getornull(p_base); - p_instance->update_dependency(&multimesh->instance_dependency); - if (multimesh->mesh.is_valid()) { - base_update_dependency(multimesh->mesh, p_instance); - } - } else if (reflection_probe_owner.owns(p_base)) { - ReflectionProbe *rp = reflection_probe_owner.getornull(p_base); - p_instance->update_dependency(&rp->instance_dependency); - } else if (gi_probe_owner.owns(p_base)) { - GIProbe *gip = gi_probe_owner.getornull(p_base); - p_instance->update_dependency(&gip->instance_dependency); - } else if (light_owner.owns(p_base)) { - Light *l = light_owner.getornull(p_base); - p_instance->update_dependency(&l->instance_dependency); - } -} - -void RasterizerStorageRD::skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance) { - - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND(!skeleton); - - p_instance->update_dependency(&skeleton->instance_dependency); -} - -VS::InstanceType RasterizerStorageRD::get_base_type(RID p_rid) const { - - if (mesh_owner.owns(p_rid)) { - return VS::INSTANCE_MESH; - } - if (multimesh_owner.owns(p_rid)) { - return VS::INSTANCE_MULTIMESH; - } - if (reflection_probe_owner.owns(p_rid)) { - return VS::INSTANCE_REFLECTION_PROBE; - } - if (gi_probe_owner.owns(p_rid)) { - return VS::INSTANCE_GI_PROBE; - } - if (light_owner.owns(p_rid)) { - return VS::INSTANCE_LIGHT; - } - - return VS::INSTANCE_NONE; -} -void RasterizerStorageRD::update_dirty_resources() { - _update_queued_materials(); - _update_dirty_multimeshes(); - _update_dirty_skeletons(); -} - -bool RasterizerStorageRD::has_os_feature(const String &p_feature) const { - - if (p_feature == "rgtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC5_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if (p_feature == "s3tc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC1_RGB_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if (p_feature == "bptc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_BC7_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if ((p_feature == "etc" || p_feature == "etc2") && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - if (p_feature == "pvrtc" && RD::get_singleton()->texture_is_format_supported_for_usage(RD::DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, RD::TEXTURE_USAGE_SAMPLING_BIT)) { - return true; - } - - return false; -} -bool RasterizerStorageRD::free(RID p_rid) { - - if (texture_owner.owns(p_rid)) { - Texture *t = texture_owner.getornull(p_rid); - - ERR_FAIL_COND_V(t->is_render_target, false); - - if (RD::get_singleton()->texture_is_valid(t->rd_texture_srgb)) { - //erase this first, as it's a dependency of the one below - RD::get_singleton()->free(t->rd_texture_srgb); - } - if (RD::get_singleton()->texture_is_valid(t->rd_texture)) { - RD::get_singleton()->free(t->rd_texture); - } - - if (t->is_proxy && t->proxy_to.is_valid()) { - Texture *proxy_to = texture_owner.getornull(t->proxy_to); - if (proxy_to) { - proxy_to->proxies.erase(p_rid); - } - } - - for (int i = 0; i < t->proxies.size(); i++) { - Texture *p = texture_owner.getornull(t->proxies[i]); - ERR_CONTINUE(!p); - p->proxy_to = RID(); - p->rd_texture = RID(); - p->rd_texture_srgb = RID(); - } - texture_owner.free(p_rid); - - } else if (shader_owner.owns(p_rid)) { - Shader *shader = shader_owner.getornull(p_rid); - //make material unreference this - while (shader->owners.size()) { - material_set_shader(shader->owners.front()->get()->self, RID()); - } - //clear data if exists - if (shader->data) { - memdelete(shader->data); - } - shader_owner.free(p_rid); - - } else if (material_owner.owns(p_rid)) { - Material *material = material_owner.getornull(p_rid); - if (material->update_requested) { - _update_queued_materials(); - } - material_set_shader(p_rid, RID()); //clean up shader - material->instance_dependency.instance_notify_deleted(p_rid); - material_owner.free(p_rid); - } else if (mesh_owner.owns(p_rid)) { - mesh_clear(p_rid); - Mesh *mesh = mesh_owner.getornull(p_rid); - mesh->instance_dependency.instance_notify_deleted(p_rid); - mesh_owner.free(p_rid); - } else if (multimesh_owner.owns(p_rid)) { - _update_dirty_multimeshes(); - multimesh_allocate(p_rid, 0, VS::MULTIMESH_TRANSFORM_2D); - MultiMesh *multimesh = multimesh_owner.getornull(p_rid); - multimesh->instance_dependency.instance_notify_deleted(p_rid); - multimesh_owner.free(p_rid); - } else if (skeleton_owner.owns(p_rid)) { - _update_dirty_skeletons(); - skeleton_allocate(p_rid, 0); - Skeleton *skeleton = skeleton_owner.getornull(p_rid); - skeleton->instance_dependency.instance_notify_deleted(p_rid); - skeleton_owner.free(p_rid); - } else if (reflection_probe_owner.owns(p_rid)) { - ReflectionProbe *reflection_probe = reflection_probe_owner.getornull(p_rid); - reflection_probe->instance_dependency.instance_notify_deleted(p_rid); - reflection_probe_owner.free(p_rid); - } else if (gi_probe_owner.owns(p_rid)) { - gi_probe_allocate(p_rid, Transform(), AABB(), Vector3i(), Vector(), Vector(), Vector(), Vector()); //deallocate - GIProbe *gi_probe = gi_probe_owner.getornull(p_rid); - gi_probe->instance_dependency.instance_notify_deleted(p_rid); - gi_probe_owner.free(p_rid); - - } else if (light_owner.owns(p_rid)) { - - // delete the texture - Light *light = light_owner.getornull(p_rid); - light->instance_dependency.instance_notify_deleted(p_rid); - light_owner.free(p_rid); - - } else if (render_target_owner.owns(p_rid)) { - RenderTarget *rt = render_target_owner.getornull(p_rid); - - _clear_render_target(rt); - - if (rt->texture.is_valid()) { - Texture *tex = texture_owner.getornull(rt->texture); - tex->is_render_target = false; - free(rt->texture); - } - - render_target_owner.free(p_rid); - } else { - return false; - } - - return true; -} - -RasterizerEffectsRD *RasterizerStorageRD::get_effects() { - return &effects; -} - -void RasterizerStorageRD::capture_timestamps_begin() { - RD::get_singleton()->capture_timestamp("Frame Begin", false); -} - -void RasterizerStorageRD::capture_timestamp(const String &p_name) { - RD::get_singleton()->capture_timestamp(p_name, true); -} - -uint32_t RasterizerStorageRD::get_captured_timestamps_count() const { - return RD::get_singleton()->get_captured_timestamps_count(); -} -uint64_t RasterizerStorageRD::get_captured_timestamps_frame() const { - return RD::get_singleton()->get_captured_timestamps_frame(); -} - -uint64_t RasterizerStorageRD::get_captured_timestamp_gpu_time(uint32_t p_index) const { - return RD::get_singleton()->get_captured_timestamp_gpu_time(p_index); -} -uint64_t RasterizerStorageRD::get_captured_timestamp_cpu_time(uint32_t p_index) const { - return RD::get_singleton()->get_captured_timestamp_cpu_time(p_index); -} -String RasterizerStorageRD::get_captured_timestamp_name(uint32_t p_index) const { - return RD::get_singleton()->get_captured_timestamp_name(p_index); -} - -RasterizerStorageRD::RasterizerStorageRD() { - - for (int i = 0; i < SHADER_TYPE_MAX; i++) { - shader_data_request_func[i] = NULL; - } - - material_update_list = NULL; - { //create default textures - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_2D; - - Vector pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 255); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 255); - } - - { - Vector> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 128); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_NORMAL] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 255); - pv.set(i * 4 + 1, 128); - pv.set(i * 4 + 2, 255); - pv.set(i * 4 + 3, 255); - } - - { - Vector> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_ANISO] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - default_rd_textures[DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER] = RD::get_singleton()->texture_buffer_create(16, RD::DATA_FORMAT_R8G8B8A8_UNORM, pv); - } - - { //create default cubemap - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_CUBE_ARRAY; - - Vector pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default cubemap array - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.array_layers = 6; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_CUBE; - - Vector pv; - pv.resize(16 * 4); - for (int i = 0; i < 16; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector> vpv; - for (int i = 0; i < 6; i++) { - vpv.push_back(pv); - } - default_rd_textures[DEFAULT_RD_TEXTURE_CUBEMAP_BLACK] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - { //create default 3D - - RD::TextureFormat tformat; - tformat.format = RD::DATA_FORMAT_R8G8B8A8_UNORM; - tformat.width = 4; - tformat.height = 4; - tformat.depth = 4; - tformat.usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_UPDATE_BIT; - tformat.type = RD::TEXTURE_TYPE_3D; - - Vector pv; - pv.resize(64 * 4); - for (int i = 0; i < 64; i++) { - pv.set(i * 4 + 0, 0); - pv.set(i * 4 + 1, 0); - pv.set(i * 4 + 2, 0); - pv.set(i * 4 + 3, 0); - } - - { - Vector> vpv; - vpv.push_back(pv); - default_rd_textures[DEFAULT_RD_TEXTURE_3D_WHITE] = RD::get_singleton()->texture_create(tformat, RD::TextureView(), vpv); - } - } - - //default samplers - for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - RD::SamplerState sampler_state; - switch (i) { - case VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.max_lod = 0; - } break; - case VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { - - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.max_lod = 0; - } break; - case VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } break; - case VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - - } break; - case VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy"); - } break; - case VS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = GLOBAL_GET("rendering/quality/filters/max_anisotropy"); - - } break; - default: { - } - } - switch (j) { - case VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { - - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - - } break; - case VS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; - } break; - case VS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - } break; - default: { - } - } - - default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); - } - } - - //default rd buffers - { - - { //vertex - - Vector buffer; - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_VERTEX] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} - -{ //normal - Vector buffer; - buffer.resize(sizeof(float) * 3); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_NORMAL] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} - -{ //tangent - Vector buffer; - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TANGENT] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} - -{ //color - Vector buffer; - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 1.0; - fptr[1] = 1.0; - fptr[2] = 1.0; - fptr[3] = 1.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_COLOR] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} - -{ //tex uv 1 - Vector buffer; - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} -{ //tex uv 2 - Vector buffer; - buffer.resize(sizeof(float) * 2); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_TEX_UV2] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} - -{ //bones - Vector buffer; - buffer.resize(sizeof(uint32_t) * 4); - { - uint8_t *w = buffer.ptrw(); - uint32_t *fptr = (uint32_t *)w; - fptr[0] = 0; - fptr[1] = 0; - fptr[2] = 0; - fptr[3] = 0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_BONES] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} - -{ //weights - Vector buffer; - buffer.resize(sizeof(float) * 4); - { - uint8_t *w = buffer.ptrw(); - float *fptr = (float *)w; - fptr[0] = 0.0; - fptr[1] = 0.0; - fptr[2] = 0.0; - fptr[3] = 0.0; - } - mesh_default_rd_buffers[DEFAULT_RD_BUFFER_WEIGHTS] = RD::get_singleton()->vertex_buffer_create(buffer.size(), buffer); -} -} - -{ - Vector sdf_versions; - sdf_versions.push_back(""); //one only - giprobe_sdf_shader.initialize(sdf_versions); - giprobe_sdf_shader_version = giprobe_sdf_shader.version_create(); - giprobe_sdf_shader.version_set_compute_code(giprobe_sdf_shader_version, "", "", "", Vector()); - giprobe_sdf_shader_version_shader = giprobe_sdf_shader.version_get_shader(giprobe_sdf_shader_version, 0); - giprobe_sdf_shader_pipeline = RD::get_singleton()->compute_pipeline_create(giprobe_sdf_shader_version_shader); -} -} - -RasterizerStorageRD::~RasterizerStorageRD() { - - //def textures - for (int i = 0; i < DEFAULT_RD_TEXTURE_MAX; i++) { - RD::get_singleton()->free(default_rd_textures[i]); - } - - //def samplers - for (int i = 1; i < VS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - RD::get_singleton()->free(default_rd_samplers[i][j]); - } - } - - //def buffers - for (int i = 0; i < DEFAULT_RD_BUFFER_MAX; i++) { - RD::get_singleton()->free(mesh_default_rd_buffers[i]); - } - giprobe_sdf_shader.version_free(giprobe_sdf_shader_version); -} diff --git a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h b/servers/visual/rasterizer_rd/rasterizer_storage_rd.h deleted file mode 100644 index 410cd4adb4..0000000000 --- a/servers/visual/rasterizer_rd/rasterizer_storage_rd.h +++ /dev/null @@ -1,1135 +0,0 @@ -/*************************************************************************/ -/* rasterizer_storage_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RASTERIZER_STORAGE_RD_H -#define RASTERIZER_STORAGE_RD_H - -#include "core/rid_owner.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual/rasterizer_rd/rasterizer_effects_rd.h" -#include "servers/visual/rasterizer_rd/shader_compiler_rd.h" -#include "servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl.gen.h" -#include "servers/visual/rendering_device.h" - -class RasterizerStorageRD : public RasterizerStorage { -public: - enum ShaderType { - SHADER_TYPE_2D, - SHADER_TYPE_3D, - SHADER_TYPE_PARTICLES, - SHADER_TYPE_SKY, - SHADER_TYPE_MAX - }; - - struct ShaderData { - virtual void set_code(const String &p_Code) = 0; - virtual void set_default_texture_param(const StringName &p_name, RID p_texture) = 0; - virtual void get_param_list(List *p_param_list) const = 0; - virtual bool is_param_texture(const StringName &p_param) const = 0; - virtual bool is_animated() const = 0; - virtual bool casts_shadows() const = 0; - virtual Variant get_default_parameter(const StringName &p_parameter) const = 0; - virtual ~ShaderData() {} - }; - - typedef ShaderData *(*ShaderDataRequestFunction)(); - - struct MaterialData { - - void update_uniform_buffer(const Map &p_uniforms, const uint32_t *p_uniform_offsets, const Map &p_parameters, uint8_t *p_buffer, uint32_t p_buffer_size, bool p_use_linear_color); - void update_textures(const Map &p_parameters, const Map &p_default_textures, const Vector &p_texture_uniforms, RID *p_textures, bool p_use_linear_color); - - virtual void set_render_priority(int p_priority) = 0; - virtual void set_next_pass(RID p_pass) = 0; - virtual void update_parameters(const Map &p_parameters, bool p_uniform_dirty, bool p_textures_dirty) = 0; - virtual ~MaterialData() {} - }; - typedef MaterialData *(*MaterialDataRequestFunction)(ShaderData *); - - enum DefaultRDTexture { - DEFAULT_RD_TEXTURE_WHITE, - DEFAULT_RD_TEXTURE_BLACK, - DEFAULT_RD_TEXTURE_NORMAL, - DEFAULT_RD_TEXTURE_ANISO, - DEFAULT_RD_TEXTURE_MULTIMESH_BUFFER, - DEFAULT_RD_TEXTURE_CUBEMAP_BLACK, - DEFAULT_RD_TEXTURE_CUBEMAP_ARRAY_BLACK, - DEFAULT_RD_TEXTURE_3D_WHITE, - DEFAULT_RD_TEXTURE_MAX - }; - - enum DefaultRDBuffer { - DEFAULT_RD_BUFFER_VERTEX, - DEFAULT_RD_BUFFER_NORMAL, - DEFAULT_RD_BUFFER_TANGENT, - DEFAULT_RD_BUFFER_COLOR, - DEFAULT_RD_BUFFER_TEX_UV, - DEFAULT_RD_BUFFER_TEX_UV2, - DEFAULT_RD_BUFFER_BONES, - DEFAULT_RD_BUFFER_WEIGHTS, - DEFAULT_RD_BUFFER_MAX, - }; - -private: - /* TEXTURE API */ - struct Texture { - - enum Type { - TYPE_2D, - TYPE_LAYERED, - TYPE_3D - }; - - Type type; - - RenderingDevice::TextureType rd_type; - RID rd_texture; - RID rd_texture_srgb; - RenderingDevice::DataFormat rd_format; - RenderingDevice::DataFormat rd_format_srgb; - - RD::TextureView rd_view; - - Image::Format format; - Image::Format validated_format; - - int width; - int height; - int depth; - int layers; - int mipmaps; - - int height_2d; - int width_2d; - - bool is_render_target; - bool is_proxy; - - Ref image_cache_2d; - String path; - - RID proxy_to; - Vector proxies; - - VS::TextureDetectCallback detect_3d_callback = nullptr; - void *detect_3d_callback_ud = nullptr; - - VS::TextureDetectCallback detect_normal_callback = nullptr; - void *detect_normal_callback_ud = nullptr; - - VS::TextureDetectRoughnessCallback detect_roughness_callback = nullptr; - void *detect_roughness_callback_ud = nullptr; - }; - - struct TextureToRDFormat { - RD::DataFormat format; - RD::DataFormat format_srgb; - RD::TextureSwizzle swizzle_r; - RD::TextureSwizzle swizzle_g; - RD::TextureSwizzle swizzle_b; - RD::TextureSwizzle swizzle_a; - TextureToRDFormat() { - format = RD::DATA_FORMAT_MAX; - format_srgb = RD::DATA_FORMAT_MAX; - swizzle_r = RD::TEXTURE_SWIZZLE_R; - swizzle_g = RD::TEXTURE_SWIZZLE_G; - swizzle_b = RD::TEXTURE_SWIZZLE_B; - swizzle_a = RD::TEXTURE_SWIZZLE_A; - } - }; - - //textures can be created from threads, so this RID_Owner is thread safe - mutable RID_Owner texture_owner; - - Ref _validate_texture_format(const Ref &p_image, TextureToRDFormat &r_format); - - RID default_rd_textures[DEFAULT_RD_TEXTURE_MAX]; - RID default_rd_samplers[VS::CANVAS_ITEM_TEXTURE_FILTER_MAX][VS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - - /* SHADER */ - - struct Material; - - struct Shader { - ShaderData *data; - String code; - ShaderType type; - Map default_texture_parameter; - Set owners; - }; - - ShaderDataRequestFunction shader_data_request_func[SHADER_TYPE_MAX]; - mutable RID_Owner shader_owner; - - /* Material */ - - struct Material { - RID self; - MaterialData *data; - Shader *shader; - //shortcut to shader data and type - ShaderType shader_type; - bool update_requested; - bool uniform_dirty; - bool texture_dirty; - Material *update_next; - Map params; - int32_t priority; - RID next_pass; - RasterizerScene::InstanceDependency instance_dependency; - }; - - MaterialDataRequestFunction material_data_request_func[SHADER_TYPE_MAX]; - mutable RID_Owner material_owner; - - Material *material_update_list; - void _material_queue_update(Material *material, bool p_uniform, bool p_texture); - void _update_queued_materials(); - - /* Mesh */ - - struct Mesh { - - struct Surface { - VS::PrimitiveType primitive; - uint32_t format = 0; - - RID vertex_buffer; - uint32_t vertex_count = 0; - - // A different pipeline needs to be allocated - // depending on the inputs available in the - // material. - // There are never that many geometry/material - // combinations, so a simple array is the most - // cache-efficient structure. - - struct Version { - uint32_t input_mask; - RD::VertexFormatID vertex_format; - RID vertex_array; - }; - - SpinLock version_lock; //needed to access versions - Version *versions = nullptr; //allocated on demand - uint32_t version_count = 0; - - RID index_buffer; - RID index_array; - uint32_t index_count = 0; - - struct LOD { - float edge_length; - RID index_buffer; - RID index_array; - }; - - LOD *lods = nullptr; - uint32_t lod_count = 0; - - AABB aabb; - - Vector bone_aabbs; - - Vector blend_shapes; - RID blend_shape_base_buffer; //source buffer goes here when using blend shapes, and main one is uncompressed - - RID material; - - uint32_t render_index = 0; - uint64_t render_pass = 0; - - uint32_t multimesh_render_index = 0; - uint64_t multimesh_render_pass = 0; - }; - - uint32_t blend_shape_count = 0; - VS::BlendShapeMode blend_shape_mode = VS::BLEND_SHAPE_MODE_NORMALIZED; - - Surface **surfaces = nullptr; - uint32_t surface_count = 0; - - Vector bone_aabbs; - - AABB aabb; - AABB custom_aabb; - - Vector material_cache; - - RasterizerScene::InstanceDependency instance_dependency; - }; - - mutable RID_Owner mesh_owner; - - void _mesh_surface_generate_version_for_input_mask(Mesh::Surface *s, uint32_t p_input_mask); - - RID mesh_default_rd_buffers[DEFAULT_RD_BUFFER_MAX]; - - /* MultiMesh */ - struct MultiMesh { - RID mesh; - int instances = 0; - VS::MultimeshTransformFormat xform_format = VS::MULTIMESH_TRANSFORM_3D; - bool uses_colors = false; - bool uses_custom_data = false; - int visible_instances = -1; - AABB aabb; - bool aabb_dirty = false; - bool buffer_set = false; - uint32_t stride_cache = 0; - uint32_t color_offset_cache = 0; - uint32_t custom_data_offset_cache = 0; - - Vector data_cache; //used if individual setting is used - bool *data_cache_dirty_regions = nullptr; - uint32_t data_cache_used_dirty_regions = 0; - - RID buffer; //storage buffer - RID uniform_set_3d; - - bool dirty = false; - MultiMesh *dirty_list = nullptr; - - RasterizerScene::InstanceDependency instance_dependency; - }; - - mutable RID_Owner multimesh_owner; - - MultiMesh *multimesh_dirty_list = nullptr; - - _FORCE_INLINE_ void _multimesh_make_local(MultiMesh *multimesh) const; - _FORCE_INLINE_ void _multimesh_mark_dirty(MultiMesh *multimesh, int p_index, bool p_aabb); - _FORCE_INLINE_ void _multimesh_mark_all_dirty(MultiMesh *multimesh, bool p_data, bool p_aabb); - _FORCE_INLINE_ void _multimesh_re_create_aabb(MultiMesh *multimesh, const float *p_data, int p_instances); - void _update_dirty_multimeshes(); - - /* Skeleton */ - - struct Skeleton { - bool use_2d = false; - int size = 0; - Vector data; - RID buffer; - - bool dirty = false; - Skeleton *dirty_list = nullptr; - Transform2D base_transform_2d; - - RID uniform_set_3d; - - RasterizerScene::InstanceDependency instance_dependency; - }; - - mutable RID_Owner skeleton_owner; - - _FORCE_INLINE_ void _skeleton_make_dirty(Skeleton *skeleton); - - Skeleton *skeleton_dirty_list = nullptr; - - void _update_dirty_skeletons(); - - /* LIGHT */ - - struct Light { - - VS::LightType type; - float param[VS::LIGHT_PARAM_MAX]; - Color color = Color(1, 1, 1, 1); - Color shadow_color; - RID projector; - bool shadow = false; - bool negative = false; - bool reverse_cull = false; - bool use_gi = true; - uint32_t cull_mask = 0xFFFFFFFF; - VS::LightOmniShadowMode omni_shadow_mode = VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID; - VS::LightDirectionalShadowMode directional_shadow_mode = VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL; - VS::LightDirectionalShadowDepthRangeMode directional_range_mode = VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE; - bool directional_blend_splits = false; - uint64_t version = 0; - - RasterizerScene::InstanceDependency instance_dependency; - }; - - mutable RID_Owner light_owner; - - /* REFLECTION PROBE */ - - struct ReflectionProbe { - - VS::ReflectionProbeUpdateMode update_mode = VS::REFLECTION_PROBE_UPDATE_ONCE; - int resolution = 256; - float intensity = 1.0; - Color interior_ambient; - float interior_ambient_energy = 1.0; - float interior_ambient_probe_contrib = 0.0; - float max_distance = 0; - Vector3 extents = Vector3(1, 1, 1); - Vector3 origin_offset; - bool interior = false; - bool box_projection = false; - bool enable_shadows = false; - uint32_t cull_mask = (1 << 20) - 1; - - RasterizerScene::InstanceDependency instance_dependency; - }; - - mutable RID_Owner reflection_probe_owner; - - /* GI PROBE */ - - struct GIProbe { - - RID octree_buffer; - RID data_buffer; - RID sdf_texture; - - uint32_t octree_buffer_size = 0; - uint32_t data_buffer_size = 0; - - Vector level_counts; - - int cell_count = 0; - - Transform to_cell_xform; - AABB bounds; - Vector3i octree_size; - - float dynamic_range = 4.0; - float energy = 1.0; - float ao = 0.0; - float ao_size = 0.5; - float bias = 1.4; - float normal_bias = 0.0; - float propagation = 0.7; - bool interior = false; - bool use_two_bounces = false; - - float anisotropy_strength = 0.5; - - uint32_t version = 1; - uint32_t data_version = 1; - - RasterizerScene::InstanceDependency instance_dependency; - }; - - GiprobeSdfShaderRD giprobe_sdf_shader; - RID giprobe_sdf_shader_version; - RID giprobe_sdf_shader_version_shader; - RID giprobe_sdf_shader_pipeline; - - mutable RID_Owner gi_probe_owner; - - /* RENDER TARGET */ - - struct RenderTarget { - - Size2i size; - RID framebuffer; - RID color; - - //used for retrieving from CPU - RD::DataFormat color_format; - RD::DataFormat color_format_srgb; - Image::Format image_format; - - bool flags[RENDER_TARGET_FLAG_MAX]; - - RID backbuffer; //used for effects - RID backbuffer_fb; - - struct BackbufferMipmap { - RID mipmap; - RID mipmap_fb; - RID mipmap_copy; - RID mipmap_copy_fb; - }; - - Vector backbuffer_mipmaps; - RID backbuffer_uniform_set; - - //texture generated for this owner (nor RD). - RID texture; - bool was_used; - - //clear request - bool clear_requested; - Color clear_color; - }; - - RID_Owner render_target_owner; - - void _clear_render_target(RenderTarget *rt); - void _update_render_target(RenderTarget *rt); - void _create_render_target_backbuffer(RenderTarget *rt); - - /* EFFECTS */ - - RasterizerEffectsRD effects; - -public: - /* TEXTURE API */ - - virtual RID texture_2d_create(const Ref &p_image); - virtual RID texture_2d_layered_create(const Vector> &p_layers, VS::TextureLayeredType p_layered_type); - virtual RID texture_3d_create(const Vector> &p_slices); //all slices, then all the mipmaps, must be coherent - virtual RID texture_proxy_create(RID p_base); - - virtual void _texture_2d_update(RID p_texture, const Ref &p_image, int p_layer, bool p_immediate); - - virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0); //mostly used for video and streaming - virtual void texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0); - virtual void texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap); - virtual void texture_proxy_update(RID p_texture, RID p_proxy_to); - - //these two APIs can be used together or in combination with the others. - virtual RID texture_2d_placeholder_create(); - virtual RID texture_2d_layered_placeholder_create(); - virtual RID texture_3d_placeholder_create(); - - virtual Ref texture_2d_get(RID p_texture) const; - virtual Ref texture_2d_layer_get(RID p_texture, int p_layer) const; - virtual Ref texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const; - - virtual void texture_replace(RID p_texture, RID p_by_texture); - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height); - - virtual void texture_set_path(RID p_texture, const String &p_path); - virtual String texture_get_path(RID p_texture) const; - - virtual void texture_set_detect_3d_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_normal_callback(RID p_texture, VS::TextureDetectCallback p_callback, void *p_userdata); - virtual void texture_set_detect_roughness_callback(RID p_texture, VS::TextureDetectRoughnessCallback p_callback, void *p_userdata); - - virtual void texture_debug_usage(List *r_info); - - virtual void texture_set_proxy(RID p_proxy, RID p_base); - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable); - - virtual Size2 texture_size_with_proxy(RID p_proxy); - - //internal usage - - _FORCE_INLINE_ RID texture_get_rd_texture(RID p_texture, bool p_srgb = false) { - if (p_texture.is_null()) { - return RID(); - } - Texture *tex = texture_owner.getornull(p_texture); - - if (!tex) { - return RID(); - } - return (p_srgb && tex->rd_texture_srgb.is_valid()) ? tex->rd_texture_srgb : tex->rd_texture; - } - - _FORCE_INLINE_ Size2i texture_2d_get_size(RID p_texture) { - if (p_texture.is_null()) { - return Size2i(); - } - Texture *tex = texture_owner.getornull(p_texture); - - if (!tex) { - return Size2i(); - } - return Size2i(tex->width_2d, tex->height_2d); - } - - _FORCE_INLINE_ RID texture_rd_get_default(DefaultRDTexture p_texture) { - return default_rd_textures[p_texture]; - } - _FORCE_INLINE_ RID sampler_rd_get_default(VS::CanvasItemTextureFilter p_filter, VS::CanvasItemTextureRepeat p_repeat) { - return default_rd_samplers[p_filter][p_repeat]; - } - - /* SHADER API */ - - RID shader_create(); - - void shader_set_code(RID p_shader, const String &p_code); - String shader_get_code(RID p_shader) const; - void shader_get_param_list(RID p_shader, List *p_param_list) const; - - void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture); - RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const; - Variant shader_get_param_default(RID p_shader, const StringName &p_param) const; - void shader_set_data_request_function(ShaderType p_shader_type, ShaderDataRequestFunction p_function); - - /* COMMON MATERIAL API */ - - RID material_create(); - - void material_set_shader(RID p_material, RID p_shader); - - void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value); - Variant material_get_param(RID p_material, const StringName &p_param) const; - - void material_set_next_pass(RID p_material, RID p_next_material); - void material_set_render_priority(RID p_material, int priority); - - bool material_is_animated(RID p_material); - bool material_casts_shadows(RID p_material); - - void material_update_dependency(RID p_material, RasterizerScene::InstanceBase *p_instance); - void material_force_update_textures(RID p_material, ShaderType p_shader_type); - - void material_set_data_request_function(ShaderType p_shader_type, MaterialDataRequestFunction p_function); - - _FORCE_INLINE_ MaterialData *material_get_data(RID p_material, ShaderType p_shader_type) { - Material *material = material_owner.getornull(p_material); - if (!material || material->shader_type != p_shader_type) { - return NULL; - } else { - return material->data; - } - } - - /* MESH API */ - - virtual RID mesh_create(); - - /// Return stride - virtual void mesh_add_surface(RID p_mesh, const VS::SurfaceData &p_surface); - - virtual int mesh_get_blend_shape_count(RID p_mesh) const; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, VS::BlendShapeMode p_mode); - virtual VS::BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const; - - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data); - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material); - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const; - - virtual VS::SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const; - - virtual int mesh_get_surface_count(RID p_mesh) const; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb); - virtual AABB mesh_get_custom_aabb(RID p_mesh) const; - - virtual AABB mesh_get_aabb(RID p_mesh, RID p_skeleton = RID()); - - virtual void mesh_clear(RID p_mesh); - - _FORCE_INLINE_ const RID *mesh_get_surface_count_and_materials(RID p_mesh, uint32_t &r_surface_count) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, NULL); - r_surface_count = mesh->surface_count; - if (r_surface_count == 0) { - return NULL; - } - if (mesh->material_cache.empty()) { - mesh->material_cache.resize(mesh->surface_count); - for (uint32_t i = 0; i < r_surface_count; i++) { - mesh->material_cache.write[i] = mesh->surfaces[i]->material; - } - } - - return mesh->material_cache.ptr(); - } - - _FORCE_INLINE_ VS::PrimitiveType mesh_surface_get_primitive(RID p_mesh, uint32_t p_surface_index) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND_V(!mesh, VS::PRIMITIVE_MAX); - ERR_FAIL_UNSIGNED_INDEX_V(p_surface_index, mesh->surface_count, VS::PRIMITIVE_MAX); - - return mesh->surfaces[p_surface_index]->primitive; - } - - _FORCE_INLINE_ void mesh_surface_get_arrays_and_format(RID p_mesh, uint32_t p_surface_index, uint32_t p_input_mask, RID &r_vertex_array_rd, RID &r_index_array_rd, RD::VertexFormatID &r_vertex_format) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - ERR_FAIL_COND(!mesh); - ERR_FAIL_UNSIGNED_INDEX(p_surface_index, mesh->surface_count); - - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - r_index_array_rd = s->index_array; - - s->version_lock.lock(); - - //there will never be more than, at much, 3 or 4 versions, so iterating is the fastest way - - for (uint32_t i = 0; i < s->version_count; i++) { - if (s->versions[i].input_mask != p_input_mask) { - continue; - } - //we have this version, hooray - r_vertex_format = s->versions[i].vertex_format; - r_vertex_array_rd = s->versions[i].vertex_array; - s->version_lock.unlock(); - return; - } - - uint32_t version = s->version_count; //gets added at the end - - _mesh_surface_generate_version_for_input_mask(s, p_input_mask); - - r_vertex_format = s->versions[version].vertex_format; - r_vertex_array_rd = s->versions[version].vertex_array; - - s->version_lock.unlock(); - } - - _FORCE_INLINE_ RID mesh_get_default_rd_buffer(DefaultRDBuffer p_buffer) { - ERR_FAIL_INDEX_V(p_buffer, DEFAULT_RD_BUFFER_MAX, RID()); - return mesh_default_rd_buffers[p_buffer]; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->render_pass != p_render_pass) { - (*r_index)++; - s->render_pass = p_render_pass; - s->render_index = *r_index; - } - - return s->render_index; - } - - _FORCE_INLINE_ uint32_t mesh_surface_get_multimesh_render_pass_index(RID p_mesh, uint32_t p_surface_index, uint64_t p_render_pass, uint32_t *r_index) { - Mesh *mesh = mesh_owner.getornull(p_mesh); - Mesh::Surface *s = mesh->surfaces[p_surface_index]; - - if (s->multimesh_render_pass != p_render_pass) { - (*r_index)++; - s->multimesh_render_pass = p_render_pass; - s->multimesh_render_index = *r_index; - } - - return s->multimesh_render_index; - } - - /* MULTIMESH API */ - - RID multimesh_create(); - - void multimesh_allocate(RID p_multimesh, int p_instances, VS::MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false); - int multimesh_get_instance_count(RID p_multimesh) const; - - void multimesh_set_mesh(RID p_multimesh, RID p_mesh); - void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform); - void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform); - void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color); - void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color); - - RID multimesh_get_mesh(RID p_multimesh) const; - - Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const; - Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const; - Color multimesh_instance_get_color(RID p_multimesh, int p_index) const; - Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const; - - void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer); - Vector multimesh_get_buffer(RID p_multimesh) const; - - void multimesh_set_visible_instances(RID p_multimesh, int p_visible); - int multimesh_get_visible_instances(RID p_multimesh) const; - - AABB multimesh_get_aabb(RID p_multimesh) const; - - _FORCE_INLINE_ VS::MultimeshTransformFormat multimesh_get_transform_format(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - return multimesh->xform_format; - } - - _FORCE_INLINE_ bool multimesh_uses_colors(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - return multimesh->uses_colors; - } - - _FORCE_INLINE_ bool multimesh_uses_custom_data(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - return multimesh->uses_custom_data; - } - - _FORCE_INLINE_ uint32_t multimesh_get_instances_to_draw(RID p_multimesh) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - if (multimesh->visible_instances >= 0) { - return multimesh->visible_instances; - } - return multimesh->instances; - } - - _FORCE_INLINE_ RID multimesh_get_3d_uniform_set(RID p_multimesh, RID p_shader, uint32_t p_set) const { - MultiMesh *multimesh = multimesh_owner.getornull(p_multimesh); - if (!multimesh->uniform_set_3d.is_valid()) { - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.ids.push_back(multimesh->buffer); - uniforms.push_back(u); - multimesh->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return multimesh->uniform_set_3d; - } - - /* IMMEDIATE API */ - - RID immediate_create() { return RID(); } - void immediate_begin(RID p_immediate, VS::PrimitiveType p_rimitive, RID p_texture = RID()) {} - void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) {} - void immediate_normal(RID p_immediate, const Vector3 &p_normal) {} - void immediate_tangent(RID p_immediate, const Plane &p_tangent) {} - void immediate_color(RID p_immediate, const Color &p_color) {} - void immediate_uv(RID p_immediate, const Vector2 &tex_uv) {} - void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) {} - void immediate_end(RID p_immediate) {} - void immediate_clear(RID p_immediate) {} - void immediate_set_material(RID p_immediate, RID p_material) {} - RID immediate_get_material(RID p_immediate) const { return RID(); } - AABB immediate_get_aabb(RID p_immediate) const { return AABB(); } - - /* SKELETON API */ - - RID skeleton_create(); - void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false); - void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform); - void skeleton_set_world_transform(RID p_skeleton, bool p_enable, const Transform &p_world_transform); - int skeleton_get_bone_count(RID p_skeleton) const; - void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform); - Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const; - void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform); - Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const; - - _FORCE_INLINE_ RID skeleton_get_3d_uniform_set(RID p_skeleton, RID p_shader, uint32_t p_set) const { - Skeleton *skeleton = skeleton_owner.getornull(p_skeleton); - ERR_FAIL_COND_V(!skeleton, RID()); - ERR_FAIL_COND_V(skeleton->size == 0, RID()); - if (skeleton->use_2d) { - return RID(); - } - if (!skeleton->uniform_set_3d.is_valid()) { - Vector uniforms; - RD::Uniform u; - u.type = RD::UNIFORM_TYPE_STORAGE_BUFFER; - u.binding = 0; - u.ids.push_back(skeleton->buffer); - uniforms.push_back(u); - skeleton->uniform_set_3d = RD::get_singleton()->uniform_set_create(uniforms, p_shader, p_set); - } - - return skeleton->uniform_set_3d; - } - /* Light API */ - - RID light_create(VS::LightType p_type); - - RID directional_light_create() { return light_create(VS::LIGHT_DIRECTIONAL); } - RID omni_light_create() { return light_create(VS::LIGHT_OMNI); } - RID spot_light_create() { return light_create(VS::LIGHT_SPOT); } - - void light_set_color(RID p_light, const Color &p_color); - void light_set_param(RID p_light, VS::LightParam p_param, float p_value); - void light_set_shadow(RID p_light, bool p_enabled); - void light_set_shadow_color(RID p_light, const Color &p_color); - void light_set_projector(RID p_light, RID p_texture); - void light_set_negative(RID p_light, bool p_enable); - void light_set_cull_mask(RID p_light, uint32_t p_mask); - void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled); - void light_set_use_gi(RID p_light, bool p_enabled); - - void light_omni_set_shadow_mode(RID p_light, VS::LightOmniShadowMode p_mode); - - void light_directional_set_shadow_mode(RID p_light, VS::LightDirectionalShadowMode p_mode); - void light_directional_set_blend_splits(RID p_light, bool p_enable); - bool light_directional_get_blend_splits(RID p_light) const; - void light_directional_set_shadow_depth_range_mode(RID p_light, VS::LightDirectionalShadowDepthRangeMode p_range_mode); - VS::LightDirectionalShadowDepthRangeMode light_directional_get_shadow_depth_range_mode(RID p_light) const; - - VS::LightDirectionalShadowMode light_directional_get_shadow_mode(RID p_light); - VS::LightOmniShadowMode light_omni_get_shadow_mode(RID p_light); - - _FORCE_INLINE_ VS::LightType light_get_type(RID p_light) const { - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); - - return light->type; - } - AABB light_get_aabb(RID p_light) const; - - _FORCE_INLINE_ float light_get_param(RID p_light, VS::LightParam p_param) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, 0); - - return light->param[p_param]; - } - - _FORCE_INLINE_ Color light_get_color(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, Color()); - - return light->color; - } - - _FORCE_INLINE_ Color light_get_shadow_color(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, Color()); - - return light->shadow_color; - } - - _FORCE_INLINE_ uint32_t light_get_cull_mask(RID p_light) { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, 0); - - return light->cull_mask; - } - - _FORCE_INLINE_ bool light_has_shadow(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); - - return light->shadow; - } - - _FORCE_INLINE_ bool light_is_negative(RID p_light) const { - - const Light *light = light_owner.getornull(p_light); - ERR_FAIL_COND_V(!light, VS::LIGHT_DIRECTIONAL); - - return light->negative; - } - - bool light_get_use_gi(RID p_light); - uint64_t light_get_version(RID p_light) const; - - /* PROBE API */ - - RID reflection_probe_create(); - - void reflection_probe_set_update_mode(RID p_probe, VS::ReflectionProbeUpdateMode p_mode); - void reflection_probe_set_intensity(RID p_probe, float p_intensity); - void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_ambient); - void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy); - void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib); - void reflection_probe_set_max_distance(RID p_probe, float p_distance); - void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents); - void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset); - void reflection_probe_set_as_interior(RID p_probe, bool p_enable); - void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable); - void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable); - void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers); - void reflection_probe_set_resolution(RID p_probe, int p_resolution); - - AABB reflection_probe_get_aabb(RID p_probe) const; - VS::ReflectionProbeUpdateMode reflection_probe_get_update_mode(RID p_probe) const; - uint32_t reflection_probe_get_cull_mask(RID p_probe) const; - Vector3 reflection_probe_get_extents(RID p_probe) const; - Vector3 reflection_probe_get_origin_offset(RID p_probe) const; - float reflection_probe_get_origin_max_distance(RID p_probe) const; - int reflection_probe_get_resolution(RID p_probe) const; - bool reflection_probe_renders_shadows(RID p_probe) const; - - float reflection_probe_get_intensity(RID p_probe) const; - bool reflection_probe_is_interior(RID p_probe) const; - bool reflection_probe_is_box_projection(RID p_probe) const; - Color reflection_probe_get_interior_ambient(RID p_probe) const; - float reflection_probe_get_interior_ambient_energy(RID p_probe) const; - float reflection_probe_get_interior_ambient_probe_contribution(RID p_probe) const; - - void base_update_dependency(RID p_base, RasterizerScene::InstanceBase *p_instance); - void skeleton_update_dependency(RID p_skeleton, RasterizerScene::InstanceBase *p_instance); - - /* GI PROBE API */ - - RID gi_probe_create(); - - void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts); - - AABB gi_probe_get_bounds(RID p_gi_probe) const; - Vector3i gi_probe_get_octree_size(RID p_gi_probe) const; - Vector gi_probe_get_octree_cells(RID p_gi_probe) const; - Vector gi_probe_get_data_cells(RID p_gi_probe) const; - Vector gi_probe_get_distance_field(RID p_gi_probe) const; - - Vector gi_probe_get_level_counts(RID p_gi_probe) const; - Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const; - - void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range); - float gi_probe_get_dynamic_range(RID p_gi_probe) const; - - void gi_probe_set_propagation(RID p_gi_probe, float p_range); - float gi_probe_get_propagation(RID p_gi_probe) const; - - void gi_probe_set_energy(RID p_gi_probe, float p_energy); - float gi_probe_get_energy(RID p_gi_probe) const; - - void gi_probe_set_ao(RID p_gi_probe, float p_ao); - float gi_probe_get_ao(RID p_gi_probe) const; - - void gi_probe_set_ao_size(RID p_gi_probe, float p_strength); - float gi_probe_get_ao_size(RID p_gi_probe) const; - - void gi_probe_set_bias(RID p_gi_probe, float p_bias); - float gi_probe_get_bias(RID p_gi_probe) const; - - void gi_probe_set_normal_bias(RID p_gi_probe, float p_range); - float gi_probe_get_normal_bias(RID p_gi_probe) const; - - void gi_probe_set_interior(RID p_gi_probe, bool p_enable); - bool gi_probe_is_interior(RID p_gi_probe) const; - - void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable); - bool gi_probe_is_using_two_bounces(RID p_gi_probe) const; - - void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength); - float gi_probe_get_anisotropy_strength(RID p_gi_probe) const; - - uint32_t gi_probe_get_version(RID p_probe); - uint32_t gi_probe_get_data_version(RID p_probe); - - RID gi_probe_get_octree_buffer(RID p_gi_probe) const; - RID gi_probe_get_data_buffer(RID p_gi_probe) const; - - RID gi_probe_get_sdf_texture(RID p_gi_probe); - - /* LIGHTMAP CAPTURE */ - - void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) {} - AABB lightmap_capture_get_bounds(RID p_capture) const { return AABB(); } - void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) {} - RID lightmap_capture_create() { - return RID(); - } - Vector lightmap_capture_get_octree(RID p_capture) const { - return Vector(); - } - void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) {} - Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const { return Transform(); } - void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) {} - int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const { return 0; } - void lightmap_capture_set_energy(RID p_capture, float p_energy) {} - float lightmap_capture_get_energy(RID p_capture) const { return 0.0; } - const Vector *lightmap_capture_get_octree_ptr(RID p_capture) const { - return NULL; - } - - /* PARTICLES */ - - RID particles_create() { return RID(); } - - void particles_set_emitting(RID p_particles, bool p_emitting) {} - void particles_set_amount(RID p_particles, int p_amount) {} - void particles_set_lifetime(RID p_particles, float p_lifetime) {} - void particles_set_one_shot(RID p_particles, bool p_one_shot) {} - void particles_set_pre_process_time(RID p_particles, float p_time) {} - void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) {} - void particles_set_randomness_ratio(RID p_particles, float p_ratio) {} - void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) {} - void particles_set_speed_scale(RID p_particles, float p_scale) {} - void particles_set_use_local_coordinates(RID p_particles, bool p_enable) {} - void particles_set_process_material(RID p_particles, RID p_material) {} - void particles_set_fixed_fps(RID p_particles, int p_fps) {} - void particles_set_fractional_delta(RID p_particles, bool p_enable) {} - void particles_restart(RID p_particles) {} - - void particles_set_draw_order(RID p_particles, VS::ParticlesDrawOrder p_order) {} - - void particles_set_draw_passes(RID p_particles, int p_count) {} - void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) {} - - void particles_request_process(RID p_particles) {} - AABB particles_get_current_aabb(RID p_particles) { return AABB(); } - AABB particles_get_aabb(RID p_particles) const { return AABB(); } - - void particles_set_emission_transform(RID p_particles, const Transform &p_transform) {} - - bool particles_get_emitting(RID p_particles) { return false; } - int particles_get_draw_passes(RID p_particles) const { return 0; } - RID particles_get_draw_pass_mesh(RID p_particles, int p_pass) const { return RID(); } - - virtual bool particles_is_inactive(RID p_particles) const { return false; } - - /* RENDER TARGET API */ - - RID render_target_create(); - void render_target_set_position(RID p_render_target, int p_x, int p_y); - void render_target_set_size(RID p_render_target, int p_width, int p_height); - RID render_target_get_texture(RID p_render_target); - void render_target_set_external_texture(RID p_render_target, unsigned int p_texture_id); - void render_target_set_flag(RID p_render_target, RenderTargetFlags p_flag, bool p_value); - bool render_target_was_used(RID p_render_target); - void render_target_set_as_unused(RID p_render_target); - void render_target_copy_to_back_buffer(RID p_render_target, const Rect2i &p_region); - RID render_target_get_back_buffer_uniform_set(RID p_render_target, RID p_base_shader); - - virtual void render_target_request_clear(RID p_render_target, const Color &p_clear_color); - virtual bool render_target_is_clear_requested(RID p_render_target); - virtual Color render_target_get_clear_request_color(RID p_render_target); - virtual void render_target_disable_clear_request(RID p_render_target); - virtual void render_target_do_clear_request(RID p_render_target); - - Size2 render_target_get_size(RID p_render_target); - RID render_target_get_rd_framebuffer(RID p_render_target); - - VS::InstanceType get_base_type(RID p_rid) const; - - bool free(RID p_rid); - - bool has_os_feature(const String &p_feature) const; - - void update_dirty_resources(); - - void set_debug_generate_wireframes(bool p_generate) {} - - void render_info_begin_capture() {} - void render_info_end_capture() {} - int get_captured_render_info(VS::RenderInfo p_info) { return 0; } - - int get_render_info(VS::RenderInfo p_info) { return 0; } - String get_video_adapter_name() const { return String(); } - String get_video_adapter_vendor() const { return String(); } - - virtual void capture_timestamps_begin(); - virtual void capture_timestamp(const String &p_name); - virtual uint32_t get_captured_timestamps_count() const; - virtual uint64_t get_captured_timestamps_frame() const; - virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const; - virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const; - virtual String get_captured_timestamp_name(uint32_t p_index) const; - - static RasterizerStorage *base_singleton; - - RasterizerEffectsRD *get_effects(); - - RasterizerStorageRD(); - ~RasterizerStorageRD(); -}; - -#endif // RASTERIZER_STORAGE_RD_H diff --git a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp deleted file mode 100644 index 4ee020aa69..0000000000 --- a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************/ -/* render_pipeline_vertex_format_cache_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "render_pipeline_vertex_format_cache_rd.h" -#include "core/os/memory.h" - -RID RenderPipelineVertexFormatCacheRD::_generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { - - RD::PipelineMultisampleState multisample_state_version = multisample_state; - multisample_state_version.sample_count = RD::get_singleton()->framebuffer_format_get_texture_samples(p_framebuffer_format_id); - - RID pipeline = RD::get_singleton()->render_pipeline_create(shader, p_framebuffer_format_id, p_vertex_format_id, render_primitive, rasterization_state, multisample_state_version, depth_stencil_state, blend_state, dynamic_state_flags); - ERR_FAIL_COND_V(pipeline.is_null(), RID()); - versions = (Version *)memrealloc(versions, sizeof(Version) * (version_count + 1)); - versions[version_count].framebuffer_id = p_framebuffer_format_id; - versions[version_count].vertex_id = p_vertex_format_id; - versions[version_count].pipeline = pipeline; - version_count++; - return pipeline; -} - -void RenderPipelineVertexFormatCacheRD::_clear() { - - if (versions) { - for (uint32_t i = 0; i < version_count; i++) { - //shader may be gone, so this may not be valid - if (RD::get_singleton()->render_pipeline_is_valid(versions[i].pipeline)) { - RD::get_singleton()->free(versions[i].pipeline); - } - } - version_count = 0; - memfree(versions); - versions = NULL; - } -} - -void RenderPipelineVertexFormatCacheRD::setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags) { - ERR_FAIL_COND(p_shader.is_null()); - _clear(); - shader = p_shader; - input_mask = RD::get_singleton()->shader_get_vertex_input_attribute_mask(p_shader); - render_primitive = p_primitive; - rasterization_state = p_rasterization_state; - multisample_state = p_multisample; - depth_stencil_state = p_depth_stencil_state; - blend_state = p_blend_state; - dynamic_state_flags = p_dynamic_state_flags; -} - -void RenderPipelineVertexFormatCacheRD::update_shader(RID p_shader) { - ERR_FAIL_COND(p_shader.is_null()); - _clear(); - setup(p_shader, render_primitive, rasterization_state, multisample_state, depth_stencil_state, blend_state, dynamic_state_flags); -} - -void RenderPipelineVertexFormatCacheRD::clear() { - _clear(); - shader = RID(); //clear shader - input_mask = 0; -} - -RenderPipelineVertexFormatCacheRD::RenderPipelineVertexFormatCacheRD() { - version_count = 0; - versions = NULL; - input_mask = 0; -} - -RenderPipelineVertexFormatCacheRD::~RenderPipelineVertexFormatCacheRD() { - _clear(); -} diff --git a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h b/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h deleted file mode 100644 index 05c5968360..0000000000 --- a/servers/visual/rasterizer_rd/render_pipeline_vertex_format_cache_rd.h +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************/ -/* render_pipeline_vertex_format_cache_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RENDER_PIPELINE_CACHE_RD_H -#define RENDER_PIPELINE_CACHE_RD_H - -#include "core/spin_lock.h" -#include "servers/visual/rendering_device.h" - -class RenderPipelineVertexFormatCacheRD { - - SpinLock spin_lock; - - RID shader; - uint32_t input_mask; - - RD::RenderPrimitive render_primitive; - RD::PipelineRasterizationState rasterization_state; - RD::PipelineMultisampleState multisample_state; - RD::PipelineDepthStencilState depth_stencil_state; - RD::PipelineColorBlendState blend_state; - int dynamic_state_flags; - - struct Version { - RD::VertexFormatID vertex_id; - RD::FramebufferFormatID framebuffer_id; - RID pipeline; - }; - - Version *versions; - uint32_t version_count; - - RID _generate_version(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id); - - void _clear(); - -public: - void setup(RID p_shader, RD::RenderPrimitive p_primitive, const RD::PipelineRasterizationState &p_rasterization_state, RD::PipelineMultisampleState p_multisample, const RD::PipelineDepthStencilState &p_depth_stencil_state, const RD::PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0); - void update_shader(RID p_shader); - - _FORCE_INLINE_ RID get_render_pipeline(RD::VertexFormatID p_vertex_format_id, RD::FramebufferFormatID p_framebuffer_format_id) { -#ifdef DEBUG_ENABLED - ERR_FAIL_COND_V_MSG(shader.is_null(), RID(), - "Attempted to use an unused shader variant (shader is null),"); -#endif - - spin_lock.lock(); - RID result; - for (uint32_t i = 0; i < version_count; i++) { - if (versions[i].vertex_id == p_vertex_format_id && versions[i].framebuffer_id == p_framebuffer_format_id) { - result = versions[i].pipeline; - spin_lock.unlock(); - return result; - } - } - result = _generate_version(p_vertex_format_id, p_framebuffer_format_id); - spin_lock.unlock(); - return result; - } - - _FORCE_INLINE_ uint32_t get_vertex_input_mask() const { - return input_mask; - } - void clear(); - RenderPipelineVertexFormatCacheRD(); - ~RenderPipelineVertexFormatCacheRD(); -}; - -#endif // RENDER_PIPELINE_CACHE_RD_H diff --git a/servers/visual/rasterizer_rd/shader_compiler_rd.cpp b/servers/visual/rasterizer_rd/shader_compiler_rd.cpp deleted file mode 100644 index ecff8d81f6..0000000000 --- a/servers/visual/rasterizer_rd/shader_compiler_rd.cpp +++ /dev/null @@ -1,1243 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shader_compiler_rd.h" - -#include "core/os/os.h" -#include "core/project_settings.h" - -#define SL ShaderLanguage - -static String _mktab(int p_level) { - - String tb; - for (int i = 0; i < p_level; i++) { - tb += "\t"; - } - - return tb; -} - -static String _typestr(SL::DataType p_type) { - - String type = ShaderLanguage::get_datatype_name(p_type); - if (ShaderLanguage::is_sampler_type(p_type)) { - type = type.replace("sampler", "texture"); //we use textures instead of samplers - } - return type; -} - -static int _get_datatype_size(SL::DataType p_type) { - - switch (p_type) { - - case SL::TYPE_VOID: return 0; - case SL::TYPE_BOOL: return 4; - case SL::TYPE_BVEC2: return 8; - case SL::TYPE_BVEC3: return 12; - case SL::TYPE_BVEC4: return 16; - case SL::TYPE_INT: return 4; - case SL::TYPE_IVEC2: return 8; - case SL::TYPE_IVEC3: return 12; - case SL::TYPE_IVEC4: return 16; - case SL::TYPE_UINT: return 4; - case SL::TYPE_UVEC2: return 8; - case SL::TYPE_UVEC3: return 12; - case SL::TYPE_UVEC4: return 16; - case SL::TYPE_FLOAT: return 4; - case SL::TYPE_VEC2: return 8; - case SL::TYPE_VEC3: return 12; - case SL::TYPE_VEC4: return 16; - case SL::TYPE_MAT2: - return 32; //4 * 4 + 4 * 4 - case SL::TYPE_MAT3: - return 48; // 4 * 4 + 4 * 4 + 4 * 4 - case SL::TYPE_MAT4: return 64; - case SL::TYPE_SAMPLER2D: return 16; - case SL::TYPE_ISAMPLER2D: return 16; - case SL::TYPE_USAMPLER2D: return 16; - case SL::TYPE_SAMPLER2DARRAY: return 16; - case SL::TYPE_ISAMPLER2DARRAY: return 16; - case SL::TYPE_USAMPLER2DARRAY: return 16; - case SL::TYPE_SAMPLER3D: return 16; - case SL::TYPE_ISAMPLER3D: return 16; - case SL::TYPE_USAMPLER3D: return 16; - case SL::TYPE_SAMPLERCUBE: return 16; - case SL::TYPE_STRUCT: return 0; - } - - ERR_FAIL_V(0); -} - -static int _get_datatype_alignment(SL::DataType p_type) { - - switch (p_type) { - - case SL::TYPE_VOID: return 0; - case SL::TYPE_BOOL: return 4; - case SL::TYPE_BVEC2: return 8; - case SL::TYPE_BVEC3: return 16; - case SL::TYPE_BVEC4: return 16; - case SL::TYPE_INT: return 4; - case SL::TYPE_IVEC2: return 8; - case SL::TYPE_IVEC3: return 16; - case SL::TYPE_IVEC4: return 16; - case SL::TYPE_UINT: return 4; - case SL::TYPE_UVEC2: return 8; - case SL::TYPE_UVEC3: return 16; - case SL::TYPE_UVEC4: return 16; - case SL::TYPE_FLOAT: return 4; - case SL::TYPE_VEC2: return 8; - case SL::TYPE_VEC3: return 16; - case SL::TYPE_VEC4: return 16; - case SL::TYPE_MAT2: return 16; - case SL::TYPE_MAT3: return 16; - case SL::TYPE_MAT4: return 16; - case SL::TYPE_SAMPLER2D: return 16; - case SL::TYPE_ISAMPLER2D: return 16; - case SL::TYPE_USAMPLER2D: return 16; - case SL::TYPE_SAMPLER2DARRAY: return 16; - case SL::TYPE_ISAMPLER2DARRAY: return 16; - case SL::TYPE_USAMPLER2DARRAY: return 16; - case SL::TYPE_SAMPLER3D: return 16; - case SL::TYPE_ISAMPLER3D: return 16; - case SL::TYPE_USAMPLER3D: return 16; - case SL::TYPE_SAMPLERCUBE: return 16; - case SL::TYPE_STRUCT: return 0; - } - - ERR_FAIL_V(0); -} -static String _interpstr(SL::DataInterpolation p_interp) { - - switch (p_interp) { - case SL::INTERPOLATION_FLAT: return "flat "; - case SL::INTERPOLATION_SMOOTH: return ""; - } - return ""; -} - -static String _prestr(SL::DataPrecision p_pres) { - - switch (p_pres) { - case SL::PRECISION_LOWP: return "lowp "; - case SL::PRECISION_MEDIUMP: return "mediump "; - case SL::PRECISION_HIGHP: return "highp "; - case SL::PRECISION_DEFAULT: return ""; - } - return ""; -} - -static String _qualstr(SL::ArgumentQualifier p_qual) { - - switch (p_qual) { - case SL::ARGUMENT_QUALIFIER_IN: return ""; - case SL::ARGUMENT_QUALIFIER_OUT: return "out "; - case SL::ARGUMENT_QUALIFIER_INOUT: return "inout "; - } - return ""; -} - -static String _opstr(SL::Operator p_op) { - - return SL::get_operator_text(p_op); -} - -static String _mkid(const String &p_id) { - - String id = "m_" + p_id.replace("__", "_dus_"); - return id.replace("__", "_dus_"); //doubleunderscore is reserved in glsl -} - -static String f2sp0(float p_float) { - - String num = rtoss(p_float); - if (num.find(".") == -1 && num.find("e") == -1) { - num += ".0"; - } - return num; -} - -static String get_constant_text(SL::DataType p_type, const Vector &p_values) { - - switch (p_type) { - case SL::TYPE_BOOL: return p_values[0].boolean ? "true" : "false"; - case SL::TYPE_BVEC2: - case SL::TYPE_BVEC3: - case SL::TYPE_BVEC4: { - - String text = "bvec" + itos(p_type - SL::TYPE_BOOL + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += p_values[i].boolean ? "true" : "false"; - } - text += ")"; - return text; - } - - case SL::TYPE_INT: return itos(p_values[0].sint); - case SL::TYPE_IVEC2: - case SL::TYPE_IVEC3: - case SL::TYPE_IVEC4: { - - String text = "ivec" + itos(p_type - SL::TYPE_INT + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += itos(p_values[i].sint); - } - text += ")"; - return text; - - } break; - case SL::TYPE_UINT: return itos(p_values[0].uint) + "u"; - case SL::TYPE_UVEC2: - case SL::TYPE_UVEC3: - case SL::TYPE_UVEC4: { - - String text = "uvec" + itos(p_type - SL::TYPE_UINT + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += itos(p_values[i].uint) + "u"; - } - text += ")"; - return text; - } break; - case SL::TYPE_FLOAT: return f2sp0(p_values[0].real); - case SL::TYPE_VEC2: - case SL::TYPE_VEC3: - case SL::TYPE_VEC4: { - - String text = "vec" + itos(p_type - SL::TYPE_FLOAT + 1) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += f2sp0(p_values[i].real); - } - text += ")"; - return text; - - } break; - case SL::TYPE_MAT2: - case SL::TYPE_MAT3: - case SL::TYPE_MAT4: { - - String text = "mat" + itos(p_type - SL::TYPE_MAT2 + 2) + "("; - for (int i = 0; i < p_values.size(); i++) { - if (i > 0) - text += ","; - - text += f2sp0(p_values[i].real); - } - text += ")"; - return text; - - } break; - default: ERR_FAIL_V(String()); - } -} - -String ShaderCompilerRD::_get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat) { - if (p_filter == ShaderLanguage::FILTER_DEFAULT) { - ERR_FAIL_COND_V(actions.default_filter == ShaderLanguage::FILTER_DEFAULT, String()); - p_filter = actions.default_filter; - } - if (p_repeat == ShaderLanguage::REPEAT_DEFAULT) { - ERR_FAIL_COND_V(actions.default_repeat == ShaderLanguage::REPEAT_DEFAULT, String()); - p_repeat = actions.default_repeat; - } - return actions.sampler_array_name + "[" + itos(p_filter + (p_repeat == ShaderLanguage::REPEAT_ENABLE ? ShaderLanguage::FILTER_DEFAULT : 0)) + "]"; -} - -void ShaderCompilerRD::_dump_function_deps(const SL::ShaderNode *p_node, const StringName &p_for_func, const Map &p_func_code, String &r_to_add, Set &added) { - - int fidx = -1; - - for (int i = 0; i < p_node->functions.size(); i++) { - if (p_node->functions[i].name == p_for_func) { - fidx = i; - break; - } - } - - ERR_FAIL_COND(fidx == -1); - - for (Set::Element *E = p_node->functions[fidx].uses_function.front(); E; E = E->next()) { - - if (added.has(E->get())) { - continue; //was added already - } - - _dump_function_deps(p_node, E->get(), p_func_code, r_to_add, added); - - SL::FunctionNode *fnode = NULL; - - for (int i = 0; i < p_node->functions.size(); i++) { - if (p_node->functions[i].name == E->get()) { - fnode = p_node->functions[i].function; - break; - } - } - - ERR_FAIL_COND(!fnode); - - r_to_add += "\n"; - - String header; - if (fnode->return_type == SL::TYPE_STRUCT) { - header = _mkid(fnode->return_struct_name) + " " + _mkid(fnode->name) + "("; - } else { - header = _typestr(fnode->return_type) + " " + _mkid(fnode->name) + "("; - } - for (int i = 0; i < fnode->arguments.size(); i++) { - - if (i > 0) - header += ", "; - if (fnode->arguments[i].type == SL::TYPE_STRUCT) { - header += _qualstr(fnode->arguments[i].qualifier) + _mkid(fnode->arguments[i].type_str) + " " + _mkid(fnode->arguments[i].name); - } else { - header += _qualstr(fnode->arguments[i].qualifier) + _prestr(fnode->arguments[i].precision) + _typestr(fnode->arguments[i].type) + " " + _mkid(fnode->arguments[i].name); - } - } - - header += ")\n"; - r_to_add += header; - r_to_add += p_func_code[E->get()]; - - added.insert(E->get()); - } -} - -String ShaderCompilerRD::_dump_node_code(const SL::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning) { - - String code; - - switch (p_node->type) { - - case SL::Node::TYPE_SHADER: { - - SL::ShaderNode *pnode = (SL::ShaderNode *)p_node; - - for (int i = 0; i < pnode->render_modes.size(); i++) { - - if (p_default_actions.render_mode_defines.has(pnode->render_modes[i]) && !used_rmode_defines.has(pnode->render_modes[i])) { - - r_gen_code.defines.push_back(p_default_actions.render_mode_defines[pnode->render_modes[i]]); - used_rmode_defines.insert(pnode->render_modes[i]); - } - - if (p_actions.render_mode_flags.has(pnode->render_modes[i])) { - *p_actions.render_mode_flags[pnode->render_modes[i]] = true; - } - - if (p_actions.render_mode_values.has(pnode->render_modes[i])) { - Pair &p = p_actions.render_mode_values[pnode->render_modes[i]]; - *p.first = p.second; - } - } - - // structs - - for (int i = 0; i < pnode->vstructs.size(); i++) { - - SL::StructNode *st = pnode->vstructs[i].shader_struct; - String struct_code; - - struct_code += "struct "; - struct_code += _mkid(pnode->vstructs[i].name); - struct_code += " "; - struct_code += "{\n"; - for (int j = 0; j < st->members.size(); j++) { - SL::MemberNode *m = st->members[j]; - if (m->datatype == SL::TYPE_STRUCT) { - struct_code += _mkid(m->struct_name); - } else { - struct_code += _prestr(m->precision); - struct_code += _typestr(m->datatype); - } - struct_code += " "; - struct_code += m->name; - if (m->array_size > 0) { - struct_code += "["; - struct_code += itos(m->array_size); - struct_code += "]"; - } - struct_code += ";\n"; - } - struct_code += "}"; - struct_code += ";\n"; - - r_gen_code.vertex_global += struct_code; - r_gen_code.fragment_global += struct_code; - } - - int max_texture_uniforms = 0; - int max_uniforms = 0; - - for (Map::Element *E = pnode->uniforms.front(); E; E = E->next()) { - if (SL::is_sampler_type(E->get().type)) - max_texture_uniforms++; - else - max_uniforms++; - } - - r_gen_code.texture_uniforms.resize(max_texture_uniforms); - - Vector uniform_sizes; - Vector uniform_alignments; - Vector uniform_defines; - uniform_sizes.resize(max_uniforms); - uniform_alignments.resize(max_uniforms); - uniform_defines.resize(max_uniforms); - bool uses_uniforms = false; - - for (Map::Element *E = pnode->uniforms.front(); E; E = E->next()) { - - String ucode; - - if (SL::is_sampler_type(E->get().type)) { - ucode = "layout(set = " + itos(actions.texture_layout_set) + ", binding = " + itos(actions.base_texture_binding_index + E->get().texture_order) + ") uniform "; - } - - ucode += _prestr(E->get().precision); - ucode += _typestr(E->get().type); - ucode += " " + _mkid(E->key()); - ucode += ";\n"; - if (SL::is_sampler_type(E->get().type)) { - r_gen_code.vertex_global += ucode; - r_gen_code.fragment_global += ucode; - - GeneratedCode::Texture texture; - texture.name = E->key(); - texture.hint = E->get().hint; - texture.type = E->get().type; - texture.filter = E->get().filter; - texture.repeat = E->get().repeat; - - r_gen_code.texture_uniforms.write[E->get().texture_order] = texture; - } else { - if (!uses_uniforms) { - - r_gen_code.defines.push_back(String("#define USE_MATERIAL_UNIFORMS\n")); - uses_uniforms = true; - } - uniform_defines.write[E->get().order] = ucode; - uniform_sizes.write[E->get().order] = _get_datatype_size(E->get().type); - uniform_alignments.write[E->get().order] = _get_datatype_alignment(E->get().type); - } - - p_actions.uniforms->insert(E->key(), E->get()); - } - - for (int i = 0; i < max_uniforms; i++) { - r_gen_code.uniforms += uniform_defines[i]; - } - -#if 1 - // add up - int offset = 0; - for (int i = 0; i < uniform_sizes.size(); i++) { - - int align = offset % uniform_alignments[i]; - - if (align != 0) { - offset += uniform_alignments[i] - align; - } - - r_gen_code.uniform_offsets.push_back(offset); - - offset += uniform_sizes[i]; - } - - r_gen_code.uniform_total_size = offset; - - if (r_gen_code.uniform_total_size % 16 != 0) { //UBO sizes must be multiples of 16 - r_gen_code.uniform_total_size += 16 - (r_gen_code.uniform_total_size % 16); - } -#else - // add up - for (int i = 0; i < uniform_sizes.size(); i++) { - - if (i > 0) { - - int align = uniform_sizes[i - 1] % uniform_alignments[i]; - if (align != 0) { - uniform_sizes[i - 1] += uniform_alignments[i] - align; - } - - uniform_sizes[i] = uniform_sizes[i] + uniform_sizes[i - 1]; - } - } - //offset - r_gen_code.uniform_offsets.resize(uniform_sizes.size()); - for (int i = 0; i < uniform_sizes.size(); i++) { - - if (i > 0) - r_gen_code.uniform_offsets[i] = uniform_sizes[i - 1]; - else - r_gen_code.uniform_offsets[i] = 0; - } - /* - for(Map::Element *E=pnode->uniforms.front();E;E=E->next()) { - - if (SL::is_sampler_type(E->get().type)) { - continue; - } - - } - -*/ - if (uniform_sizes.size()) { - r_gen_code.uniform_total_size = uniform_sizes[uniform_sizes.size() - 1]; - } else { - r_gen_code.uniform_total_size = 0; - } -#endif - - uint32_t index = p_default_actions.base_varying_index; - - for (Map::Element *E = pnode->varyings.front(); E; E = E->next()) { - - String vcode; - String interp_mode = _interpstr(E->get().interpolation); - vcode += _prestr(E->get().precision); - vcode += _typestr(E->get().type); - vcode += " " + _mkid(E->key()); - if (E->get().array_size > 0) { - vcode += "["; - vcode += itos(E->get().array_size); - vcode += "]"; - } - vcode += ";\n"; - r_gen_code.vertex_global += "layout(location=" + itos(index) + ") " + interp_mode + "out " + vcode; - r_gen_code.fragment_global += "layout(location=" + itos(index) + ") " + interp_mode + "in " + vcode; - index++; - } - - for (Map::Element *E = pnode->constants.front(); E; E = E->next()) { - String gcode; - gcode += "const "; - gcode += _prestr(E->get().precision); - if (E->get().type == SL::TYPE_STRUCT) { - gcode += _mkid(E->get().type_str); - } else { - gcode += _typestr(E->get().type); - } - gcode += " " + _mkid(E->key()); - gcode += "="; - gcode += _dump_node_code(E->get().initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - gcode += ";\n"; - r_gen_code.vertex_global += gcode; - r_gen_code.fragment_global += gcode; - } - - Map function_code; - - //code for functions - for (int i = 0; i < pnode->functions.size(); i++) { - SL::FunctionNode *fnode = pnode->functions[i].function; - function = fnode; - current_func_name = fnode->name; - function_code[fnode->name] = _dump_node_code(fnode->body, p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - function = NULL; - } - - //place functions in actual code - - Set added_vtx; - Set added_fragment; //share for light - - for (int i = 0; i < pnode->functions.size(); i++) { - - SL::FunctionNode *fnode = pnode->functions[i].function; - - function = fnode; - - current_func_name = fnode->name; - - if (fnode->name == vertex_name) { - - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.vertex_global, added_vtx); - r_gen_code.vertex = function_code[vertex_name]; - } - - if (fnode->name == fragment_name) { - - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.fragment = function_code[fragment_name]; - } - - if (fnode->name == light_name) { - - _dump_function_deps(pnode, fnode->name, function_code, r_gen_code.fragment_global, added_fragment); - r_gen_code.light = function_code[light_name]; - } - function = NULL; - } - - //code+=dump_node_code(pnode->body,p_level); - } break; - case SL::Node::TYPE_STRUCT: { - - } break; - case SL::Node::TYPE_FUNCTION: { - - } break; - case SL::Node::TYPE_BLOCK: { - SL::BlockNode *bnode = (SL::BlockNode *)p_node; - - //variables - if (!bnode->single_statement) { - code += _mktab(p_level - 1) + "{\n"; - } - - for (int i = 0; i < bnode->statements.size(); i++) { - - String scode = _dump_node_code(bnode->statements[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - - if (bnode->statements[i]->type == SL::Node::TYPE_CONTROL_FLOW || bnode->single_statement) { - code += scode; //use directly - } else { - code += _mktab(p_level) + scode + ";\n"; - } - } - if (!bnode->single_statement) { - code += _mktab(p_level - 1) + "}\n"; - } - - } break; - case SL::Node::TYPE_VARIABLE_DECLARATION: { - SL::VariableDeclarationNode *vdnode = (SL::VariableDeclarationNode *)p_node; - - String declaration; - if (vdnode->is_const) { - declaration += "const "; - } - if (vdnode->datatype == SL::TYPE_STRUCT) { - declaration += _mkid(vdnode->struct_name); - } else { - declaration += _prestr(vdnode->precision) + _typestr(vdnode->datatype); - } - for (int i = 0; i < vdnode->declarations.size(); i++) { - if (i > 0) { - declaration += ","; - } else { - declaration += " "; - } - declaration += _mkid(vdnode->declarations[i].name); - if (vdnode->declarations[i].initializer) { - declaration += "="; - declaration += _dump_node_code(vdnode->declarations[i].initializer, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - } - - code += declaration; - } break; - case SL::Node::TYPE_VARIABLE: { - SL::VariableNode *vnode = (SL::VariableNode *)p_node; - - if (p_assigning && p_actions.write_flag_pointers.has(vnode->name)) { - *p_actions.write_flag_pointers[vnode->name] = true; - } - - if (p_default_actions.usage_defines.has(vnode->name) && !used_name_defines.has(vnode->name)) { - String define = p_default_actions.usage_defines[vnode->name]; - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[define.substr(1, define.length())]; - } - r_gen_code.defines.push_back(define); - used_name_defines.insert(vnode->name); - } - - if (p_actions.usage_flag_pointers.has(vnode->name) && !used_flag_pointers.has(vnode->name)) { - *p_actions.usage_flag_pointers[vnode->name] = true; - used_flag_pointers.insert(vnode->name); - } - - if (p_default_actions.renames.has(vnode->name)) - code = p_default_actions.renames[vnode->name]; - else { - code = _mkid(vnode->name); - if (actions.base_uniform_string != String() && shader->uniforms.has(vnode->name) && shader->uniforms[vnode->name].texture_order < 0) { - code = actions.base_uniform_string + code; - } - } - - if (vnode->name == time_name) { - if (current_func_name == vertex_name) { - r_gen_code.uses_vertex_time = true; - } - if (current_func_name == fragment_name || current_func_name == light_name) { - r_gen_code.uses_fragment_time = true; - } - } - - } break; - case SL::Node::TYPE_ARRAY_CONSTRUCT: { - SL::ArrayConstructNode *acnode = (SL::ArrayConstructNode *)p_node; - int sz = acnode->initializer.size(); - if (acnode->datatype == SL::TYPE_STRUCT) { - code += _mkid(acnode->struct_name); - } else { - code += _typestr(acnode->datatype); - } - code += "["; - code += itos(acnode->initializer.size()); - code += "]"; - code += "("; - for (int i = 0; i < sz; i++) { - code += _dump_node_code(acnode->initializer[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (i != sz - 1) { - code += ", "; - } - } - code += ")"; - } break; - case SL::Node::TYPE_ARRAY_DECLARATION: { - - SL::ArrayDeclarationNode *adnode = (SL::ArrayDeclarationNode *)p_node; - String declaration; - if (adnode->is_const) { - declaration += "const "; - } - if (adnode->datatype == SL::TYPE_STRUCT) { - declaration += _mkid(adnode->struct_name); - } else { - declaration = _prestr(adnode->precision) + _typestr(adnode->datatype); - } - for (int i = 0; i < adnode->declarations.size(); i++) { - if (i > 0) { - declaration += ","; - } else { - declaration += " "; - } - declaration += _mkid(adnode->declarations[i].name); - declaration += "["; - declaration += itos(adnode->declarations[i].size); - declaration += "]"; - int sz = adnode->declarations[i].initializer.size(); - if (sz > 0) { - declaration += "="; - if (adnode->datatype == SL::TYPE_STRUCT) { - declaration += _mkid(adnode->struct_name); - } else { - declaration += _typestr(adnode->datatype); - } - declaration += "["; - declaration += itos(sz); - declaration += "]"; - declaration += "("; - for (int j = 0; j < sz; j++) { - declaration += _dump_node_code(adnode->declarations[i].initializer[j], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (j != sz - 1) { - declaration += ", "; - } - } - declaration += ")"; - } - } - - code += declaration; - } break; - case SL::Node::TYPE_ARRAY: { - SL::ArrayNode *anode = (SL::ArrayNode *)p_node; - - if (p_assigning && p_actions.write_flag_pointers.has(anode->name)) { - *p_actions.write_flag_pointers[anode->name] = true; - } - - if (p_default_actions.usage_defines.has(anode->name) && !used_name_defines.has(anode->name)) { - String define = p_default_actions.usage_defines[anode->name]; - if (define.begins_with("@")) { - define = p_default_actions.usage_defines[define.substr(1, define.length())]; - } - r_gen_code.defines.push_back(define); - used_name_defines.insert(anode->name); - } - - if (p_actions.usage_flag_pointers.has(anode->name) && !used_flag_pointers.has(anode->name)) { - *p_actions.usage_flag_pointers[anode->name] = true; - used_flag_pointers.insert(anode->name); - } - - if (p_default_actions.renames.has(anode->name)) - code = p_default_actions.renames[anode->name]; - else - code = _mkid(anode->name); - - if (anode->call_expression != NULL) { - code += "."; - code += _dump_node_code(anode->call_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - } - - if (anode->index_expression != NULL) { - code += "["; - code += _dump_node_code(anode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "]"; - } - - if (anode->name == time_name) { - if (current_func_name == vertex_name) { - r_gen_code.uses_vertex_time = true; - } - if (current_func_name == fragment_name || current_func_name == light_name) { - r_gen_code.uses_fragment_time = true; - } - } - - } break; - case SL::Node::TYPE_CONSTANT: { - SL::ConstantNode *cnode = (SL::ConstantNode *)p_node; - return get_constant_text(cnode->datatype, cnode->values); - - } break; - case SL::Node::TYPE_OPERATOR: { - SL::OperatorNode *onode = (SL::OperatorNode *)p_node; - - switch (onode->op) { - - case SL::OP_ASSIGN: - case SL::OP_ASSIGN_ADD: - case SL::OP_ASSIGN_SUB: - case SL::OP_ASSIGN_MUL: - case SL::OP_ASSIGN_DIV: - case SL::OP_ASSIGN_SHIFT_LEFT: - case SL::OP_ASSIGN_SHIFT_RIGHT: - case SL::OP_ASSIGN_MOD: - case SL::OP_ASSIGN_BIT_AND: - case SL::OP_ASSIGN_BIT_OR: - case SL::OP_ASSIGN_BIT_XOR: - code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, true) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - break; - case SL::OP_BIT_INVERT: - case SL::OP_NEGATE: - case SL::OP_NOT: - case SL::OP_DECREMENT: - case SL::OP_INCREMENT: - code = _opstr(onode->op) + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - break; - case SL::OP_POST_DECREMENT: - case SL::OP_POST_INCREMENT: - code = _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op); - break; - case SL::OP_CALL: - case SL::OP_STRUCT: - case SL::OP_CONSTRUCT: { - - ERR_FAIL_COND_V(onode->arguments[0]->type != SL::Node::TYPE_VARIABLE, String()); - - SL::VariableNode *vnode = (SL::VariableNode *)onode->arguments[0]; - - bool is_texture_func = false; - if (onode->op == SL::OP_STRUCT) { - code += _mkid(vnode->name); - } else if (onode->op == SL::OP_CONSTRUCT) { - code += String(vnode->name); - } else { - - if (internal_functions.has(vnode->name)) { - code += vnode->name; - is_texture_func = texture_functions.has(vnode->name); - } else if (p_default_actions.renames.has(vnode->name)) { - code += p_default_actions.renames[vnode->name]; - } else { - code += _mkid(vnode->name); - } - } - - code += "("; - - for (int i = 1; i < onode->arguments.size(); i++) { - if (i > 1) - code += ", "; - String node_code = _dump_node_code(onode->arguments[i], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - if (is_texture_func && i == 1 && onode->arguments[i]->type == SL::Node::TYPE_VARIABLE) { - - //need to map from texture to sampler in order to sample - const SL::VariableNode *varnode = static_cast(onode->arguments[i]); - - StringName texture_uniform = varnode->name; - - String sampler_name; - - if (actions.custom_samplers.has(texture_uniform)) { - sampler_name = actions.custom_samplers[texture_uniform]; - } else { - if (shader->uniforms.has(texture_uniform)) { - sampler_name = _get_sampler_name(shader->uniforms[texture_uniform].filter, shader->uniforms[texture_uniform].repeat); - } else { - bool found = false; - - for (int j = 0; j < function->arguments.size(); j++) { - if (function->arguments[j].name == texture_uniform) { - if (function->arguments[j].tex_builtin_check) { - ERR_CONTINUE(!actions.custom_samplers.has(function->arguments[j].tex_builtin)); - sampler_name = actions.custom_samplers[function->arguments[j].tex_builtin]; - found = true; - break; - } - if (function->arguments[j].tex_argument_check) { - sampler_name = _get_sampler_name(function->arguments[j].tex_argument_filter, function->arguments[j].tex_argument_repeat); - found = true; - break; - } - } - } - if (!found) { - //function was most likely unused, so use anything (compiler will remove it anyway) - sampler_name = _get_sampler_name(ShaderLanguage::FILTER_DEFAULT, ShaderLanguage::REPEAT_DEFAULT); - } - } - } - - code += ShaderLanguage::get_datatype_name(onode->arguments[i]->get_datatype()) + "(" + node_code + ", " + sampler_name + ")"; - } else { - code += node_code; - } - } - code += ")"; - } break; - case SL::OP_INDEX: { - - code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "["; - code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "]"; - - } break; - case SL::OP_SELECT_IF: { - - code += "("; - code += _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "?"; - code += _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ":"; - code += _dump_node_code(onode->arguments[2], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += ")"; - - } break; - - default: { - - code = "(" + _dump_node_code(onode->arguments[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + _opstr(onode->op) + _dump_node_code(onode->arguments[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")"; - break; - } - } - - } break; - case SL::Node::TYPE_CONTROL_FLOW: { - SL::ControlFlowNode *cfnode = (SL::ControlFlowNode *)p_node; - if (cfnode->flow_op == SL::FLOW_OP_IF) { - - code += _mktab(p_level) + "if (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - if (cfnode->blocks.size() == 2) { - - code += _mktab(p_level) + "else\n"; - code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } - } else if (cfnode->flow_op == SL::FLOW_OP_SWITCH) { - - code += _mktab(p_level) + "switch (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_CASE) { - - code += _mktab(p_level) + "case " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ":\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_DEFAULT) { - - code += _mktab(p_level) + "default:\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_DO) { - - code += _mktab(p_level) + "do"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ");"; - } else if (cfnode->flow_op == SL::FLOW_OP_WHILE) { - - code += _mktab(p_level) + "while (" + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ")\n"; - code += _dump_node_code(cfnode->blocks[0], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - } else if (cfnode->flow_op == SL::FLOW_OP_FOR) { - - String left = _dump_node_code(cfnode->blocks[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String middle = _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - String right = _dump_node_code(cfnode->expressions[1], p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += _mktab(p_level) + "for (" + left + ";" + middle + ";" + right + ")\n"; - code += _dump_node_code(cfnode->blocks[1], p_level + 1, r_gen_code, p_actions, p_default_actions, p_assigning); - - } else if (cfnode->flow_op == SL::FLOW_OP_RETURN) { - - if (cfnode->expressions.size()) { - code = "return " + _dump_node_code(cfnode->expressions[0], p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + ";"; - } else { - code = "return;"; - } - } else if (cfnode->flow_op == SL::FLOW_OP_DISCARD) { - - if (p_actions.usage_flag_pointers.has("DISCARD") && !used_flag_pointers.has("DISCARD")) { - *p_actions.usage_flag_pointers["DISCARD"] = true; - used_flag_pointers.insert("DISCARD"); - } - - code = "discard;"; - } else if (cfnode->flow_op == SL::FLOW_OP_CONTINUE) { - - code = "continue;"; - } else if (cfnode->flow_op == SL::FLOW_OP_BREAK) { - - code = "break;"; - } - - } break; - case SL::Node::TYPE_MEMBER: { - SL::MemberNode *mnode = (SL::MemberNode *)p_node; - code = _dump_node_code(mnode->owner, p_level, r_gen_code, p_actions, p_default_actions, p_assigning) + "." + mnode->name; - if (mnode->index_expression != NULL) { - code += "["; - code += _dump_node_code(mnode->index_expression, p_level, r_gen_code, p_actions, p_default_actions, p_assigning); - code += "]"; - } - - } break; - } - - return code; -} - -Error ShaderCompilerRD::compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code) { - - Error err = parser.compile(p_code, ShaderTypes::get_singleton()->get_functions(p_mode), ShaderTypes::get_singleton()->get_modes(p_mode), ShaderTypes::get_singleton()->get_types()); - - if (err != OK) { - - Vector shader = p_code.split("\n"); - for (int i = 0; i < shader.size(); i++) { - print_line(itos(i + 1) + " " + shader[i]); - } - - _err_print_error(NULL, p_path.utf8().get_data(), parser.get_error_line(), parser.get_error_text().utf8().get_data(), ERR_HANDLER_SHADER); - return err; - } - - r_gen_code.defines.clear(); - r_gen_code.vertex = String(); - r_gen_code.vertex_global = String(); - r_gen_code.fragment = String(); - r_gen_code.fragment_global = String(); - r_gen_code.light = String(); - r_gen_code.uses_fragment_time = false; - r_gen_code.uses_vertex_time = false; - - used_name_defines.clear(); - used_rmode_defines.clear(); - used_flag_pointers.clear(); - - shader = parser.get_shader(); - function = NULL; - _dump_node_code(shader, 1, r_gen_code, *p_actions, actions, false); - - return OK; -} - -void ShaderCompilerRD::initialize(DefaultIdentifierActions p_actions) { - actions = p_actions; - - vertex_name = "vertex"; - fragment_name = "fragment"; - light_name = "light"; - time_name = "TIME"; - - List func_list; - - ShaderLanguage::get_builtin_funcs(&func_list); - - for (List::Element *E = func_list.front(); E; E = E->next()) { - internal_functions.insert(E->get()); - } - texture_functions.insert("texture"); - texture_functions.insert("textureProj"); - texture_functions.insert("textureLod"); - texture_functions.insert("textureProjLod"); - texture_functions.insert("textureGrad"); -} - -ShaderCompilerRD::ShaderCompilerRD() { -#if 0 - - /** SPATIAL SHADER **/ - - actions[VS::SHADER_SPATIAL].renames["WORLD_MATRIX"] = "world_transform"; - actions[VS::SHADER_SPATIAL].renames["INV_CAMERA_MATRIX"] = "camera_inverse_matrix"; - actions[VS::SHADER_SPATIAL].renames["CAMERA_MATRIX"] = "camera_matrix"; - actions[VS::SHADER_SPATIAL].renames["PROJECTION_MATRIX"] = "projection_matrix"; - actions[VS::SHADER_SPATIAL].renames["INV_PROJECTION_MATRIX"] = "inv_projection_matrix"; - actions[VS::SHADER_SPATIAL].renames["MODELVIEW_MATRIX"] = "modelview"; - - actions[VS::SHADER_SPATIAL].renames["VERTEX"] = "vertex.xyz"; - actions[VS::SHADER_SPATIAL].renames["NORMAL"] = "normal"; - actions[VS::SHADER_SPATIAL].renames["TANGENT"] = "tangent"; - actions[VS::SHADER_SPATIAL].renames["BINORMAL"] = "binormal"; - actions[VS::SHADER_SPATIAL].renames["POSITION"] = "position"; - actions[VS::SHADER_SPATIAL].renames["UV"] = "uv_interp"; - actions[VS::SHADER_SPATIAL].renames["UV2"] = "uv2_interp"; - actions[VS::SHADER_SPATIAL].renames["COLOR"] = "color_interp"; - actions[VS::SHADER_SPATIAL].renames["POINT_SIZE"] = "gl_PointSize"; - actions[VS::SHADER_SPATIAL].renames["INSTANCE_ID"] = "gl_InstanceID"; - - //builtins - - actions[VS::SHADER_SPATIAL].renames["TIME"] = "time"; - actions[VS::SHADER_SPATIAL].renames["VIEWPORT_SIZE"] = "viewport_size"; - - actions[VS::SHADER_SPATIAL].renames["FRAGCOORD"] = "gl_FragCoord"; - actions[VS::SHADER_SPATIAL].renames["FRONT_FACING"] = "gl_FrontFacing"; - actions[VS::SHADER_SPATIAL].renames["NORMALMAP"] = "normalmap"; - actions[VS::SHADER_SPATIAL].renames["NORMALMAP_DEPTH"] = "normaldepth"; - actions[VS::SHADER_SPATIAL].renames["ALBEDO"] = "albedo"; - actions[VS::SHADER_SPATIAL].renames["ALPHA"] = "alpha"; - actions[VS::SHADER_SPATIAL].renames["METALLIC"] = "metallic"; - actions[VS::SHADER_SPATIAL].renames["SPECULAR"] = "specular"; - actions[VS::SHADER_SPATIAL].renames["ROUGHNESS"] = "roughness"; - actions[VS::SHADER_SPATIAL].renames["RIM"] = "rim"; - actions[VS::SHADER_SPATIAL].renames["RIM_TINT"] = "rim_tint"; - actions[VS::SHADER_SPATIAL].renames["CLEARCOAT"] = "clearcoat"; - actions[VS::SHADER_SPATIAL].renames["CLEARCOAT_GLOSS"] = "clearcoat_gloss"; - actions[VS::SHADER_SPATIAL].renames["ANISOTROPY"] = "anisotropy"; - actions[VS::SHADER_SPATIAL].renames["ANISOTROPY_FLOW"] = "anisotropy_flow"; - actions[VS::SHADER_SPATIAL].renames["SSS_STRENGTH"] = "sss_strength"; - actions[VS::SHADER_SPATIAL].renames["TRANSMISSION"] = "transmission"; - actions[VS::SHADER_SPATIAL].renames["AO"] = "ao"; - actions[VS::SHADER_SPATIAL].renames["AO_LIGHT_AFFECT"] = "ao_light_affect"; - actions[VS::SHADER_SPATIAL].renames["EMISSION"] = "emission"; - actions[VS::SHADER_SPATIAL].renames["POINT_COORD"] = "gl_PointCoord"; - actions[VS::SHADER_SPATIAL].renames["INSTANCE_CUSTOM"] = "instance_custom"; - actions[VS::SHADER_SPATIAL].renames["SCREEN_UV"] = "screen_uv"; - actions[VS::SHADER_SPATIAL].renames["SCREEN_TEXTURE"] = "screen_texture"; - actions[VS::SHADER_SPATIAL].renames["DEPTH_TEXTURE"] = "depth_buffer"; - actions[VS::SHADER_SPATIAL].renames["DEPTH"] = "gl_FragDepth"; - actions[VS::SHADER_SPATIAL].renames["ALPHA_SCISSOR"] = "alpha_scissor"; - actions[VS::SHADER_SPATIAL].renames["OUTPUT_IS_SRGB"] = "SHADER_IS_SRGB"; - - //for light - actions[VS::SHADER_SPATIAL].renames["VIEW"] = "view"; - actions[VS::SHADER_SPATIAL].renames["LIGHT_COLOR"] = "light_color"; - actions[VS::SHADER_SPATIAL].renames["LIGHT"] = "light"; - actions[VS::SHADER_SPATIAL].renames["ATTENUATION"] = "attenuation"; - actions[VS::SHADER_SPATIAL].renames["DIFFUSE_LIGHT"] = "diffuse_light"; - actions[VS::SHADER_SPATIAL].renames["SPECULAR_LIGHT"] = "specular_light"; - - actions[VS::SHADER_SPATIAL].usage_defines["TANGENT"] = "#define ENABLE_TANGENT_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["BINORMAL"] = "@TANGENT"; - actions[VS::SHADER_SPATIAL].usage_defines["RIM"] = "#define LIGHT_USE_RIM\n"; - actions[VS::SHADER_SPATIAL].usage_defines["RIM_TINT"] = "@RIM"; - actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT"] = "#define LIGHT_USE_CLEARCOAT\n"; - actions[VS::SHADER_SPATIAL].usage_defines["CLEARCOAT_GLOSS"] = "@CLEARCOAT"; - actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY"] = "#define LIGHT_USE_ANISOTROPY\n"; - actions[VS::SHADER_SPATIAL].usage_defines["ANISOTROPY_FLOW"] = "@ANISOTROPY"; - actions[VS::SHADER_SPATIAL].usage_defines["AO"] = "#define ENABLE_AO\n"; - actions[VS::SHADER_SPATIAL].usage_defines["AO_LIGHT_AFFECT"] = "#define ENABLE_AO\n"; - actions[VS::SHADER_SPATIAL].usage_defines["UV"] = "#define ENABLE_UV_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["UV2"] = "#define ENABLE_UV2_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP"] = "#define ENABLE_NORMALMAP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["NORMALMAP_DEPTH"] = "@NORMALMAP"; - actions[VS::SHADER_SPATIAL].usage_defines["COLOR"] = "#define ENABLE_COLOR_INTERP\n"; - actions[VS::SHADER_SPATIAL].usage_defines["INSTANCE_CUSTOM"] = "#define ENABLE_INSTANCE_CUSTOM\n"; - actions[VS::SHADER_SPATIAL].usage_defines["ALPHA_SCISSOR"] = "#define ALPHA_SCISSOR_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["POSITION"] = "#define OVERRIDE_POSITION\n"; - - actions[VS::SHADER_SPATIAL].usage_defines["SSS_STRENGTH"] = "#define ENABLE_SSS\n"; - actions[VS::SHADER_SPATIAL].usage_defines["TRANSMISSION"] = "#define TRANSMISSION_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_TEXTURE"] = "#define SCREEN_TEXTURE_USED\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SCREEN_UV"] = "#define SCREEN_UV_USED\n"; - - actions[VS::SHADER_SPATIAL].usage_defines["DIFFUSE_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - actions[VS::SHADER_SPATIAL].usage_defines["SPECULAR_LIGHT"] = "#define USE_LIGHT_SHADER_CODE\n"; - - actions[VS::SHADER_SPATIAL].render_mode_defines["skip_vertex_transform"] = "#define SKIP_TRANSFORM_USED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["world_vertex_coords"] = "#define VERTEX_WORLD_COORDS_USED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["ensure_correct_normals"] = "#define ENSURE_CORRECT_NORMALS\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["cull_front"] = "#define DO_SIDE_CHECK\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["cull_disabled"] = "#define DO_SIDE_CHECK\n"; - - bool force_lambert = GLOBAL_GET("rendering/quality/shading/force_lambert_over_burley"); - - if (!force_lambert) { - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_burley"] = "#define DIFFUSE_BURLEY\n"; - } - - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_oren_nayar"] = "#define DIFFUSE_OREN_NAYAR\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_lambert_wrap"] = "#define DIFFUSE_LAMBERT_WRAP\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["diffuse_toon"] = "#define DIFFUSE_TOON\n"; - - bool force_blinn = GLOBAL_GET("rendering/quality/shading/force_blinn_over_ggx"); - - if (!force_blinn) { - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_SCHLICK_GGX\n"; - } else { - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_schlick_ggx"] = "#define SPECULAR_BLINN\n"; - } - - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_blinn"] = "#define SPECULAR_BLINN\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_phong"] = "#define SPECULAR_PHONG\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_toon"] = "#define SPECULAR_TOON\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["specular_disabled"] = "#define SPECULAR_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["shadows_disabled"] = "#define SHADOWS_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["ambient_light_disabled"] = "#define AMBIENT_LIGHT_DISABLED\n"; - actions[VS::SHADER_SPATIAL].render_mode_defines["shadow_to_opacity"] = "#define USE_SHADOW_TO_OPACITY\n"; - - /* PARTICLES SHADER */ - - actions[VS::SHADER_PARTICLES].renames["COLOR"] = "out_color"; - actions[VS::SHADER_PARTICLES].renames["VELOCITY"] = "out_velocity_active.xyz"; - actions[VS::SHADER_PARTICLES].renames["MASS"] = "mass"; - actions[VS::SHADER_PARTICLES].renames["ACTIVE"] = "shader_active"; - actions[VS::SHADER_PARTICLES].renames["RESTART"] = "restart"; - actions[VS::SHADER_PARTICLES].renames["CUSTOM"] = "out_custom"; - actions[VS::SHADER_PARTICLES].renames["TRANSFORM"] = "xform"; - actions[VS::SHADER_PARTICLES].renames["TIME"] = "time"; - actions[VS::SHADER_PARTICLES].renames["LIFETIME"] = "lifetime"; - actions[VS::SHADER_PARTICLES].renames["DELTA"] = "local_delta"; - actions[VS::SHADER_PARTICLES].renames["NUMBER"] = "particle_number"; - actions[VS::SHADER_PARTICLES].renames["INDEX"] = "index"; - actions[VS::SHADER_PARTICLES].renames["GRAVITY"] = "current_gravity"; - actions[VS::SHADER_PARTICLES].renames["EMISSION_TRANSFORM"] = "emission_transform"; - actions[VS::SHADER_PARTICLES].renames["RANDOM_SEED"] = "random_seed"; - - actions[VS::SHADER_PARTICLES].render_mode_defines["disable_force"] = "#define DISABLE_FORCE\n"; - actions[VS::SHADER_PARTICLES].render_mode_defines["disable_velocity"] = "#define DISABLE_VELOCITY\n"; - actions[VS::SHADER_PARTICLES].render_mode_defines["keep_data"] = "#define ENABLE_KEEP_DATA\n"; -#endif -} diff --git a/servers/visual/rasterizer_rd/shader_compiler_rd.h b/servers/visual/rasterizer_rd/shader_compiler_rd.h deleted file mode 100644 index 95e1f0aa23..0000000000 --- a/servers/visual/rasterizer_rd/shader_compiler_rd.h +++ /dev/null @@ -1,123 +0,0 @@ -/*************************************************************************/ -/* shader_compiler_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHADER_COMPILER_RD_H -#define SHADER_COMPILER_RD_H - -#include "core/pair.h" -#include "servers/visual/shader_language.h" -#include "servers/visual/shader_types.h" -#include "servers/visual_server.h" - -class ShaderCompilerRD { -public: - struct IdentifierActions { - - Map> render_mode_values; - Map render_mode_flags; - Map usage_flag_pointers; - Map write_flag_pointers; - - Map *uniforms; - }; - - struct GeneratedCode { - - Vector defines; - struct Texture { - StringName name; - ShaderLanguage::DataType type; - ShaderLanguage::ShaderNode::Uniform::Hint hint; - ShaderLanguage::TextureFilter filter; - ShaderLanguage::TextureRepeat repeat; - }; - - Vector texture_uniforms; - - Vector uniform_offsets; - uint32_t uniform_total_size; - String uniforms; - String vertex_global; - String vertex; - String fragment_global; - String fragment; - String light; - - bool uses_fragment_time; - bool uses_vertex_time; - }; - - struct DefaultIdentifierActions { - - Map renames; - Map render_mode_defines; - Map usage_defines; - Map custom_samplers; - ShaderLanguage::TextureFilter default_filter; - ShaderLanguage::TextureRepeat default_repeat; - String sampler_array_name; - int base_texture_binding_index = 0; - int texture_layout_set = 0; - String base_uniform_string; - uint32_t base_varying_index = 0; - }; - -private: - ShaderLanguage parser; - - String _get_sampler_name(ShaderLanguage::TextureFilter p_filter, ShaderLanguage::TextureRepeat p_repeat); - - void _dump_function_deps(const ShaderLanguage::ShaderNode *p_node, const StringName &p_for_func, const Map &p_func_code, String &r_to_add, Set &added); - String _dump_node_code(const ShaderLanguage::Node *p_node, int p_level, GeneratedCode &r_gen_code, IdentifierActions &p_actions, const DefaultIdentifierActions &p_default_actions, bool p_assigning); - - const ShaderLanguage::ShaderNode *shader; - const ShaderLanguage::FunctionNode *function; - StringName current_func_name; - StringName vertex_name; - StringName fragment_name; - StringName light_name; - StringName time_name; - Set texture_functions; - - Set used_name_defines; - Set used_flag_pointers; - Set used_rmode_defines; - Set internal_functions; - - DefaultIdentifierActions actions; - -public: - Error compile(VS::ShaderMode p_mode, const String &p_code, IdentifierActions *p_actions, const String &p_path, GeneratedCode &r_gen_code); - - void initialize(DefaultIdentifierActions p_actions); - ShaderCompilerRD(); -}; - -#endif // SHADERCOMPILERRD_H diff --git a/servers/visual/rasterizer_rd/shader_rd.cpp b/servers/visual/rasterizer_rd/shader_rd.cpp deleted file mode 100644 index 74edaee983..0000000000 --- a/servers/visual/rasterizer_rd/shader_rd.cpp +++ /dev/null @@ -1,495 +0,0 @@ -/*************************************************************************/ -/* shader_rd.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shader_rd.h" - -#include "core/string_builder.h" -#include "rasterizer_rd.h" -#include "servers/visual/rendering_device.h" - -void ShaderRD::setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name) { - - name = p_name; - //split vertex and shader code (thank you, shader compiler programmers from you know what company). - if (p_vertex_code) { - String defines_tag = "\nVERSION_DEFINES"; - String globals_tag = "\nVERTEX_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nVERTEX_SHADER_CODE"; - String code = p_vertex_code; - - int cpos = code.find(defines_tag); - if (cpos != -1) { - vertex_codev = code.substr(0, cpos).ascii(); - code = code.substr(cpos + defines_tag.length(), code.length()); - } - - cpos = code.find(material_tag); - - if (cpos == -1) { - vertex_code0 = code.ascii(); - } else { - vertex_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + material_tag.length(), code.length()); - - cpos = code.find(globals_tag); - - if (cpos == -1) { - vertex_code1 = code.ascii(); - } else { - - vertex_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code2.find(code_tag); - if (cpos == -1) { - vertex_code2 = code2.ascii(); - } else { - - vertex_code2 = code2.substr(0, cpos).ascii(); - vertex_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); - } - } - } - } - - if (p_fragment_code) { - String defines_tag = "\nVERSION_DEFINES"; - String globals_tag = "\nFRAGMENT_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nFRAGMENT_SHADER_CODE"; - String light_code_tag = "\nLIGHT_SHADER_CODE"; - String code = p_fragment_code; - - int cpos = code.find(defines_tag); - if (cpos != -1) { - fragment_codev = code.substr(0, cpos).ascii(); - code = code.substr(cpos + defines_tag.length(), code.length()); - } - - cpos = code.find(material_tag); - if (cpos == -1) { - fragment_code0 = code.ascii(); - } else { - fragment_code0 = code.substr(0, cpos).ascii(); - //print_line("CODE0:\n"+String(fragment_code0.get_data())); - code = code.substr(cpos + material_tag.length(), code.length()); - cpos = code.find(globals_tag); - - if (cpos == -1) { - fragment_code1 = code.ascii(); - } else { - - fragment_code1 = code.substr(0, cpos).ascii(); - //print_line("CODE1:\n"+String(fragment_code1.get_data())); - - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - cpos = code2.find(light_code_tag); - - if (cpos == -1) { - fragment_code2 = code2.ascii(); - } else { - - fragment_code2 = code2.substr(0, cpos).ascii(); - //print_line("CODE2:\n"+String(fragment_code2.get_data())); - - String code3 = code2.substr(cpos + light_code_tag.length(), code2.length()); - - cpos = code3.find(code_tag); - if (cpos == -1) { - fragment_code3 = code3.ascii(); - } else { - - fragment_code3 = code3.substr(0, cpos).ascii(); - //print_line("CODE3:\n"+String(fragment_code3.get_data())); - fragment_code4 = code3.substr(cpos + code_tag.length(), code3.length()).ascii(); - //print_line("CODE4:\n"+String(fragment_code4.get_data())); - } - } - } - } - } - - if (p_compute_code) { - is_compute = true; - - String defines_tag = "\nVERSION_DEFINES"; - String globals_tag = "\nCOMPUTE_SHADER_GLOBALS"; - String material_tag = "\nMATERIAL_UNIFORMS"; - String code_tag = "\nCOMPUTE_SHADER_CODE"; - String code = p_compute_code; - - int cpos = code.find(defines_tag); - if (cpos != -1) { - compute_codev = code.substr(0, cpos).ascii(); - code = code.substr(cpos + defines_tag.length(), code.length()); - } - - cpos = code.find(material_tag); - - if (cpos == -1) { - compute_code0 = code.ascii(); - } else { - compute_code0 = code.substr(0, cpos).ascii(); - code = code.substr(cpos + material_tag.length(), code.length()); - - cpos = code.find(globals_tag); - - if (cpos == -1) { - compute_code1 = code.ascii(); - } else { - - compute_code1 = code.substr(0, cpos).ascii(); - String code2 = code.substr(cpos + globals_tag.length(), code.length()); - - cpos = code2.find(code_tag); - if (cpos == -1) { - compute_code2 = code2.ascii(); - } else { - - compute_code2 = code2.substr(0, cpos).ascii(); - compute_code3 = code2.substr(cpos + code_tag.length(), code2.length()).ascii(); - } - } - } - } -} - -RID ShaderRD::version_create() { - - //initialize() was never called - ERR_FAIL_COND_V(variant_defines.size() == 0, RID()); - - Version version; - version.dirty = true; - version.valid = false; - version.initialize_needed = true; - version.variants = NULL; - return version_owner.make_rid(version); -} - -void ShaderRD::_clear_version(Version *p_version) { - //clear versions if they exist - if (p_version->variants) { - for (int i = 0; i < variant_defines.size(); i++) { - RD::get_singleton()->free(p_version->variants[i]); - } - - memdelete_arr(p_version->variants); - p_version->variants = NULL; - } -} - -void ShaderRD::_compile_variant(uint32_t p_variant, Version *p_version) { - - Vector stages; - - String error; - String current_source; - RD::ShaderStage current_stage = RD::SHADER_STAGE_VERTEX; - bool build_ok = true; - - if (!is_compute) { - //vertex stage - - StringBuilder builder; - - builder.append(vertex_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(general_defines.get_data()); - builder.append(variant_defines[p_variant].get_data()); - - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } - - builder.append(vertex_code0.get_data()); //first part of vertex - - builder.append(p_version->uniforms.get_data()); //uniforms (same for vertex and fragment) - - builder.append(vertex_code1.get_data()); //second part of vertex - - builder.append(p_version->vertex_globals.get_data()); // vertex globals - - builder.append(vertex_code2.get_data()); //third part of vertex - - builder.append(p_version->vertex_code.get_data()); // code - - builder.append(vertex_code3.get_data()); //fourth of vertex - - current_source = builder.as_string(); - RD::ShaderStageData stage; - stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_VERTEX, current_source, RD::SHADER_LANGUAGE_GLSL, &error); - if (stage.spir_v.size() == 0) { - build_ok = false; - } else { - - stage.shader_stage = RD::SHADER_STAGE_VERTEX; - stages.push_back(stage); - } - } - - if (!is_compute && build_ok) { - //fragment stage - current_stage = RD::SHADER_STAGE_FRAGMENT; - - StringBuilder builder; - - builder.append(fragment_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - - builder.append(general_defines.get_data()); - builder.append(variant_defines[p_variant].get_data()); - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } - - builder.append(fragment_code0.get_data()); //first part of fragment - - builder.append(p_version->uniforms.get_data()); //uniforms (same for fragment and fragment) - - builder.append(fragment_code1.get_data()); //first part of fragment - - builder.append(p_version->fragment_globals.get_data()); // fragment globals - - builder.append(fragment_code2.get_data()); //third part of fragment - - builder.append(p_version->fragment_light.get_data()); // fragment light - - builder.append(fragment_code3.get_data()); //fourth part of fragment - - builder.append(p_version->fragment_code.get_data()); // fragment code - - builder.append(fragment_code4.get_data()); //fourth part of fragment - - current_source = builder.as_string(); - RD::ShaderStageData stage; - stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_FRAGMENT, current_source, RD::SHADER_LANGUAGE_GLSL, &error); - if (stage.spir_v.size() == 0) { - build_ok = false; - } else { - - stage.shader_stage = RD::SHADER_STAGE_FRAGMENT; - stages.push_back(stage); - } - } - - if (is_compute) { - //compute stage - current_stage = RD::SHADER_STAGE_COMPUTE; - - StringBuilder builder; - - builder.append(compute_codev.get_data()); // version info (if exists) - builder.append("\n"); //make sure defines begin at newline - builder.append(general_defines.get_data()); - builder.append(variant_defines[p_variant].get_data()); - - for (int j = 0; j < p_version->custom_defines.size(); j++) { - builder.append(p_version->custom_defines[j].get_data()); - } - - builder.append(compute_code0.get_data()); //first part of compute - - builder.append(p_version->uniforms.get_data()); //uniforms (same for compute and fragment) - - builder.append(compute_code1.get_data()); //second part of compute - - builder.append(p_version->compute_globals.get_data()); // compute globals - - builder.append(compute_code2.get_data()); //third part of compute - - builder.append(p_version->compute_code.get_data()); // code - - builder.append(compute_code3.get_data()); //fourth of compute - - current_source = builder.as_string(); - RD::ShaderStageData stage; - stage.spir_v = RD::get_singleton()->shader_compile_from_source(RD::SHADER_STAGE_COMPUTE, current_source, RD::SHADER_LANGUAGE_GLSL, &error); - if (stage.spir_v.size() == 0) { - build_ok = false; - } else { - - stage.shader_stage = RD::SHADER_STAGE_COMPUTE; - stages.push_back(stage); - } - } - - if (!build_ok) { - MutexLock lock(variant_set_mutex); //properly print the errors - ERR_PRINT("Error compiling " + String(current_stage == RD::SHADER_STAGE_COMPUTE ? "Compute " : (current_stage == RD::SHADER_STAGE_VERTEX ? "Vertex" : "Fragment")) + " shader, variant #" + itos(p_variant) + " (" + variant_defines[p_variant].get_data() + ")."); - ERR_PRINT(error); - -#ifdef DEBUG_ENABLED - ERR_PRINT("code:\n" + current_source.get_with_code_lines()); -#endif - return; - } - - RID shader = RD::get_singleton()->shader_create(stages); - { - MutexLock lock(variant_set_mutex); - p_version->variants[p_variant] = shader; - } -} - -void ShaderRD::_compile_version(Version *p_version) { - - _clear_version(p_version); - - p_version->valid = false; - p_version->dirty = false; - - p_version->variants = memnew_arr(RID, variant_defines.size()); -#if 1 - - RasterizerRD::thread_work_pool.do_work(variant_defines.size(), this, &ShaderRD::_compile_variant, p_version); -#else - for (int i = 0; i < variant_defines.size(); i++) { - - _compile_variant(i, p_version); - } -#endif - - bool all_valid = true; - for (int i = 0; i < variant_defines.size(); i++) { - if (p_version->variants[i].is_null()) { - all_valid = false; - break; - } - } - - if (!all_valid) { - //clear versions if they exist - for (int i = 0; i < variant_defines.size(); i++) { - if (!p_version->variants[i].is_null()) { - RD::get_singleton()->free(p_version->variants[i]); - } - } - memdelete_arr(p_version->variants); - p_version->variants = NULL; - return; - } - - p_version->valid = true; -} - -void ShaderRD::version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector &p_custom_defines) { - - ERR_FAIL_COND(is_compute); - - Version *version = version_owner.getornull(p_version); - ERR_FAIL_COND(!version); - version->vertex_globals = p_vertex_globals.utf8(); - version->vertex_code = p_vertex_code.utf8(); - version->fragment_light = p_fragment_light.utf8(); - version->fragment_globals = p_fragment_globals.utf8(); - version->fragment_code = p_fragment_code.utf8(); - version->uniforms = p_uniforms.utf8(); - - version->custom_defines.clear(); - for (int i = 0; i < p_custom_defines.size(); i++) { - version->custom_defines.push_back(p_custom_defines[i].utf8()); - } - - version->dirty = true; - if (version->initialize_needed) { - _compile_version(version); - version->initialize_needed = false; - } -} - -void ShaderRD::version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector &p_custom_defines) { - - ERR_FAIL_COND(!is_compute); - - Version *version = version_owner.getornull(p_version); - ERR_FAIL_COND(!version); - version->compute_globals = p_compute_globals.utf8(); - version->compute_code = p_compute_code.utf8(); - version->uniforms = p_uniforms.utf8(); - - version->custom_defines.clear(); - for (int i = 0; i < p_custom_defines.size(); i++) { - version->custom_defines.push_back(p_custom_defines[i].utf8()); - } - - version->dirty = true; - if (version->initialize_needed) { - _compile_version(version); - version->initialize_needed = false; - } -} - -bool ShaderRD::version_is_valid(RID p_version) { - Version *version = version_owner.getornull(p_version); - ERR_FAIL_COND_V(!version, false); - - if (version->dirty) { - _compile_version(version); - } - - return version->valid; -} - -bool ShaderRD::version_free(RID p_version) { - - if (version_owner.owns(p_version)) { - Version *version = version_owner.getornull(p_version); - _clear_version(version); - version_owner.free(p_version); - } else { - return false; - } - - return true; -} - -void ShaderRD::initialize(const Vector &p_variant_defines, const String &p_general_defines) { - ERR_FAIL_COND(variant_defines.size()); - ERR_FAIL_COND(p_variant_defines.size() == 0); - general_defines = p_general_defines.utf8(); - for (int i = 0; i < p_variant_defines.size(); i++) { - - variant_defines.push_back(p_variant_defines[i].utf8()); - } -} - -ShaderRD::~ShaderRD() { - List remaining; - version_owner.get_owned_list(&remaining); - if (remaining.size()) { - ERR_PRINT(itos(remaining.size()) + " shaders of type " + name + " were never freed"); - while (remaining.size()) { - version_free(remaining.front()->get()); - remaining.pop_front(); - } - } -} diff --git a/servers/visual/rasterizer_rd/shader_rd.h b/servers/visual/rasterizer_rd/shader_rd.h deleted file mode 100644 index 6635b08cc8..0000000000 --- a/servers/visual/rasterizer_rd/shader_rd.h +++ /dev/null @@ -1,136 +0,0 @@ -/*************************************************************************/ -/* shader_rd.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHADER_RD_H -#define SHADER_RD_H - -#include "core/hash_map.h" -#include "core/map.h" -#include "core/os/mutex.h" -#include "core/rid_owner.h" -#include "core/variant.h" - -#include -/** - @author Juan Linietsky -*/ - -class ShaderRD { - - //versions - CharString general_defines; - Vector variant_defines; - - struct Version { - CharString uniforms; - CharString vertex_globals; - CharString vertex_code; - CharString compute_globals; - CharString compute_code; - CharString fragment_light; - CharString fragment_globals; - CharString fragment_code; - Vector custom_defines; - - RID *variants; //same size as version defines - - bool valid; - bool dirty; - bool initialize_needed; - }; - - Mutex variant_set_mutex; - - void _compile_variant(uint32_t p_variant, Version *p_version); - - void _clear_version(Version *p_version); - void _compile_version(Version *p_version); - - RID_Owner version_owner; - - CharString fragment_codev; //for version and extensions - CharString fragment_code0; - CharString fragment_code1; - CharString fragment_code2; - CharString fragment_code3; - CharString fragment_code4; - - CharString vertex_codev; //for version and extensions - CharString vertex_code0; - CharString vertex_code1; - CharString vertex_code2; - CharString vertex_code3; - - bool is_compute = false; - - CharString compute_codev; //for version and extensions - CharString compute_code0; - CharString compute_code1; - CharString compute_code2; - CharString compute_code3; - - const char *name; - -protected: - ShaderRD() {} - void setup(const char *p_vertex_code, const char *p_fragment_code, const char *p_compute_code, const char *p_name); - -public: - RID version_create(); - - void version_set_code(RID p_version, const String &p_uniforms, const String &p_vertex_globals, const String &p_vertex_code, const String &p_fragment_globals, const String &p_fragment_light, const String &p_fragment_code, const Vector &p_custom_defines); - void version_set_compute_code(RID p_version, const String &p_uniforms, const String &p_compute_globals, const String &p_compute_code, const Vector &p_custom_defines); - - _FORCE_INLINE_ RID version_get_shader(RID p_version, int p_variant) { - ERR_FAIL_INDEX_V(p_variant, variant_defines.size(), RID()); - - Version *version = version_owner.getornull(p_version); - ERR_FAIL_COND_V(!version, RID()); - - if (version->dirty) { - _compile_version(version); - } - - if (!version->valid) { - return RID(); - } - - return version->variants[p_variant]; - } - - bool version_is_valid(RID p_version); - - bool version_free(RID p_version); - - void initialize(const Vector &p_variant_defines, const String &p_general_defines = ""); - virtual ~ShaderRD(); -}; - -#endif diff --git a/servers/visual/rasterizer_rd/shaders/SCsub b/servers/visual/rasterizer_rd/shaders/SCsub deleted file mode 100644 index 2dcb2a703f..0000000000 --- a/servers/visual/rasterizer_rd/shaders/SCsub +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env python - -Import('env') - -if 'RD_GLSL' in env['BUILDERS']: - env.RD_GLSL('canvas.glsl'); - env.RD_GLSL('canvas_occlusion.glsl'); - env.RD_GLSL('blur.glsl'); - env.RD_GLSL('cubemap_roughness.glsl'); - env.RD_GLSL('cubemap_downsampler.glsl'); - env.RD_GLSL('cubemap_filter.glsl'); - env.RD_GLSL('scene_high_end.glsl'); - env.RD_GLSL('sky.glsl'); - env.RD_GLSL('tonemap.glsl'); - env.RD_GLSL('copy.glsl'); - env.RD_GLSL('giprobe.glsl'); - env.RD_GLSL('giprobe_debug.glsl'); - env.RD_GLSL('giprobe_sdf.glsl'); - env.RD_GLSL('luminance_reduce.glsl'); - env.RD_GLSL('bokeh_dof.glsl'); - env.RD_GLSL('ssao.glsl'); - env.RD_GLSL('ssao_minify.glsl'); - env.RD_GLSL('ssao_blur.glsl'); - env.RD_GLSL('roughness_limiter.glsl'); diff --git a/servers/visual/rasterizer_rd/shaders/blur.glsl b/servers/visual/rasterizer_rd/shaders/blur.glsl deleted file mode 100644 index 87c20ebaef..0000000000 --- a/servers/visual/rasterizer_rd/shaders/blur.glsl +++ /dev/null @@ -1,294 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -#include "blur_inc.glsl" - -layout(location = 0) out vec2 uv_interp; -/* clang-format on */ - -void main() { - - vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv_interp = base_arr[gl_VertexIndex]; - - if (bool(blur.flags & FLAG_USE_BLUR_SECTION)) { - uv_interp = blur.section.xy + uv_interp * blur.section.zw; - } - - gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); - - if (bool(blur.flags & FLAG_FLIP_Y)) { - uv_interp.y = 1.0 - uv_interp.y; - } -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -#include "blur_inc.glsl" - -layout(location = 0) in vec2 uv_interp; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform sampler2D source_color; - -#ifdef MODE_SSAO_MERGE -layout(set = 1, binding = 0) uniform sampler2D source_ssao; -#endif - -#ifdef GLOW_USE_AUTO_EXPOSURE -layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; -#endif - -layout(location = 0) out vec4 frag_color; - -//DOF -#if defined(MODE_DOF_FAR_BLUR) || defined(MODE_DOF_NEAR_BLUR) - -layout(set = 1, binding = 0) uniform sampler2D dof_source_depth; - -#ifdef DOF_NEAR_BLUR_MERGE -layout(set = 2, binding = 0) uniform sampler2D source_dof_original; -#endif - -#ifdef DOF_QUALITY_LOW -const int dof_kernel_size = 5; -const int dof_kernel_from = 2; -const float dof_kernel[5] = float[](0.153388, 0.221461, 0.250301, 0.221461, 0.153388); -#endif - -#ifdef DOF_QUALITY_MEDIUM -const int dof_kernel_size = 11; -const int dof_kernel_from = 5; -const float dof_kernel[11] = float[](0.055037, 0.072806, 0.090506, 0.105726, 0.116061, 0.119726, 0.116061, 0.105726, 0.090506, 0.072806, 0.055037); - -#endif - -#ifdef DOF_QUALITY_HIGH -const int dof_kernel_size = 21; -const int dof_kernel_from = 10; -const float dof_kernel[21] = float[](0.028174, 0.032676, 0.037311, 0.041944, 0.046421, 0.050582, 0.054261, 0.057307, 0.059587, 0.060998, 0.061476, 0.060998, 0.059587, 0.057307, 0.054261, 0.050582, 0.046421, 0.041944, 0.037311, 0.032676, 0.028174); -#endif - -#endif - -void main() { - -#ifdef MODE_MIPMAP - - vec2 pix_size = blur.pixel_size; - vec4 color = texture(source_color, uv_interp + vec2(-0.5, -0.5) * pix_size); - color += texture(source_color, uv_interp + vec2(0.5, -0.5) * pix_size); - color += texture(source_color, uv_interp + vec2(0.5, 0.5) * pix_size); - color += texture(source_color, uv_interp + vec2(-0.5, 0.5) * pix_size); - frag_color = color / 4.0; - -#endif - -#ifdef MODE_GAUSSIAN_BLUR - - //Simpler blur uses SIGMA2 for the gaussian kernel for a stronger effect - - if (bool(blur.flags & FLAG_HORIZONTAL)) { - - vec2 pix_size = blur.pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.214607; - color += texture(source_color, uv_interp + vec2(1.0, 0.0) * pix_size) * 0.189879; - color += texture(source_color, uv_interp + vec2(2.0, 0.0) * pix_size) * 0.131514; - color += texture(source_color, uv_interp + vec2(3.0, 0.0) * pix_size) * 0.071303; - color += texture(source_color, uv_interp + vec2(-1.0, 0.0) * pix_size) * 0.189879; - color += texture(source_color, uv_interp + vec2(-2.0, 0.0) * pix_size) * 0.131514; - color += texture(source_color, uv_interp + vec2(-3.0, 0.0) * pix_size) * 0.071303; - frag_color = color; - } else { - - vec2 pix_size = blur.pixel_size; - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.38774; - color += texture(source_color, uv_interp + vec2(0.0, 1.0) * pix_size) * 0.24477; - color += texture(source_color, uv_interp + vec2(0.0, 2.0) * pix_size) * 0.06136; - color += texture(source_color, uv_interp + vec2(0.0, -1.0) * pix_size) * 0.24477; - color += texture(source_color, uv_interp + vec2(0.0, -2.0) * pix_size) * 0.06136; - frag_color = color; - } -#endif - -#ifdef MODE_GAUSSIAN_GLOW - - //Glow uses larger sigma 1 for a more rounded blur effect - -#define GLOW_ADD(m_ofs, m_mult) \ - { \ - vec2 ofs = uv_interp + m_ofs * pix_size; \ - vec4 c = texture(source_color, ofs) * m_mult; \ - if (any(lessThan(ofs, vec2(0.0))) || any(greaterThan(ofs, vec2(1.0)))) { \ - c *= 0.0; \ - } \ - color += c; \ - } - - if (bool(blur.flags & FLAG_HORIZONTAL)) { - - vec2 pix_size = blur.pixel_size; - pix_size *= 0.5; //reading from larger buffer, so use more samples - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.174938; - GLOW_ADD(vec2(1.0, 0.0), 0.165569); - GLOW_ADD(vec2(2.0, 0.0), 0.140367); - GLOW_ADD(vec2(3.0, 0.0), 0.106595); - GLOW_ADD(vec2(-1.0, 0.0), 0.165569); - GLOW_ADD(vec2(-2.0, 0.0), 0.140367); - GLOW_ADD(vec2(-3.0, 0.0), 0.106595); - color *= blur.glow_strength; - frag_color = color; - } else { - - vec2 pix_size = blur.pixel_size; - vec4 color = texture(source_color, uv_interp + vec2(0.0, 0.0) * pix_size) * 0.288713; - GLOW_ADD(vec2(0.0, 1.0), 0.233062); - GLOW_ADD(vec2(0.0, 2.0), 0.122581); - GLOW_ADD(vec2(0.0, -1.0), 0.233062); - GLOW_ADD(vec2(0.0, -2.0), 0.122581); - color *= blur.glow_strength; - frag_color = color; - } - -#undef GLOW_ADD - - if (bool(blur.flags & FLAG_GLOW_FIRST_PASS)) { -#ifdef GLOW_USE_AUTO_EXPOSURE - - frag_color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / blur.glow_auto_exposure_grey; -#endif - frag_color *= blur.glow_exposure; - - float luminance = max(frag_color.r, max(frag_color.g, frag_color.b)); - float feedback = max(smoothstep(blur.glow_hdr_threshold, blur.glow_hdr_threshold + blur.glow_hdr_scale, luminance), blur.glow_bloom); - - frag_color = min(frag_color * feedback, vec4(blur.glow_luminance_cap)); - } - -#endif - -#ifdef MODE_DOF_FAR_BLUR - - vec4 color_accum = vec4(0.0); - - float depth = texture(dof_source_depth, uv_interp, 0.0).r; - depth = depth * 2.0 - 1.0; - - if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { - depth = ((depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; - } else { - depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - depth * (blur.camera_z_far - blur.camera_z_near)); - } - - float amount = smoothstep(blur.dof_begin, blur.dof_end, depth); - float k_accum = 0.0; - - for (int i = 0; i < dof_kernel_size; i++) { - - int int_ofs = i - dof_kernel_from; - vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * amount * blur.dof_radius; - - float tap_k = dof_kernel[i]; - - float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; - tap_depth = tap_depth * 2.0 - 1.0; - - if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { - - tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; - } else { - tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near)); - } - - float tap_amount = mix(smoothstep(blur.dof_begin, blur.dof_end, tap_depth), 1.0, int_ofs == 0); - tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect - - vec4 tap_color = texture(source_color, tap_uv, 0.0) * tap_k; - - k_accum += tap_k * tap_amount; - color_accum += tap_color * tap_amount; - } - - if (k_accum > 0.0) { - color_accum /= k_accum; - } - - frag_color = color_accum; ///k_accum; - -#endif - -#ifdef MODE_DOF_NEAR_BLUR - - vec4 color_accum = vec4(0.0); - - float max_accum = 0.0; - - for (int i = 0; i < dof_kernel_size; i++) { - - int int_ofs = i - dof_kernel_from; - vec2 tap_uv = uv_interp + blur.dof_dir * float(int_ofs) * blur.dof_radius; - float ofs_influence = max(0.0, 1.0 - float(abs(int_ofs)) / float(dof_kernel_from)); - - float tap_k = dof_kernel[i]; - - vec4 tap_color = texture(source_color, tap_uv, 0.0); - - float tap_depth = texture(dof_source_depth, tap_uv, 0.0).r; - tap_depth = tap_depth * 2.0 - 1.0; - if (bool(blur.flags & FLAG_USE_ORTHOGONAL_PROJECTION)) { - - tap_depth = ((tap_depth + (blur.camera_z_far + blur.camera_z_near) / (blur.camera_z_far - blur.camera_z_near)) * (blur.camera_z_far - blur.camera_z_near)) / 2.0; - } else { - tap_depth = 2.0 * blur.camera_z_near * blur.camera_z_far / (blur.camera_z_far + blur.camera_z_near - tap_depth * (blur.camera_z_far - blur.camera_z_near)); - } - float tap_amount = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth); - tap_amount *= tap_amount * tap_amount; //prevent undesired glow effect - - if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) { - tap_color.a = 1.0 - smoothstep(blur.dof_end, blur.dof_begin, tap_depth); - } - - max_accum = max(max_accum, tap_amount * ofs_influence); - - color_accum += tap_color * tap_k; - } - - color_accum.a = max(color_accum.a, sqrt(max_accum)); - -#ifdef DOF_NEAR_BLUR_MERGE - { - vec4 original = texture(source_dof_original, uv_interp, 0.0); - color_accum = mix(original, color_accum, color_accum.a); - } -#endif - - if (bool(blur.flags & FLAG_DOF_NEAR_FIRST_TAP)) { - frag_color = color_accum; - } -#endif - -#ifdef MODE_SIMPLE_COPY - vec4 color = texture(source_color, uv_interp, 0.0); - if (bool(blur.flags & FLAG_COPY_FORCE_LUMINANCE)) { - color.rgb = vec3(max(max(color.r, color.g), color.b)); - } - frag_color = color; -#endif - -#ifdef MODE_SSAO_MERGE - vec4 color = texture(source_color, uv_interp, 0.0); - float ssao = texture(source_ssao, uv_interp, 0.0).r; - frag_color = vec4(mix(color.rgb, color.rgb * mix(blur.ssao_color.rgb, vec3(1.0), ssao), color.a), 1.0); - -#endif -} diff --git a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl b/servers/visual/rasterizer_rd/shaders/blur_inc.glsl deleted file mode 100644 index 33ba9de7bb..0000000000 --- a/servers/visual/rasterizer_rd/shaders/blur_inc.glsl +++ /dev/null @@ -1,35 +0,0 @@ -#define FLAG_HORIZONTAL (1 << 0) -#define FLAG_USE_BLUR_SECTION (1 << 1) -#define FLAG_USE_ORTHOGONAL_PROJECTION (1 << 2) -#define FLAG_DOF_NEAR_FIRST_TAP (1 << 3) -#define FLAG_GLOW_FIRST_PASS (1 << 4) -#define FLAG_FLIP_Y (1 << 5) -#define FLAG_COPY_FORCE_LUMINANCE (1 << 6) - -layout(push_constant, binding = 1, std430) uniform Blur { - vec4 section; - vec2 pixel_size; - uint flags; - uint pad; - // Glow. - float glow_strength; - float glow_bloom; - float glow_hdr_threshold; - float glow_hdr_scale; - float glow_exposure; - float glow_white; - float glow_luminance_cap; - float glow_auto_exposure_grey; - // DOF. - float dof_begin; - float dof_end; - float dof_radius; - float dof_pad; - - vec2 dof_dir; - float camera_z_far; - float camera_z_near; - - vec4 ssao_color; -} -blur; diff --git a/servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl b/servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl deleted file mode 100644 index 7153fe6b17..0000000000 --- a/servers/visual/rasterizer_rd/shaders/bokeh_dof.glsl +++ /dev/null @@ -1,258 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -#define BLOCK_SIZE 8 - -layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; -/* clang-format on */ - -#ifdef MODE_GEN_BLUR_SIZE -layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image; -layout(set = 1, binding = 0) uniform sampler2D source_depth; -#endif - -#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL) || defined(MODE_BOKEH_CIRCULAR) -layout(set = 1, binding = 0) uniform sampler2D color_texture; -layout(rgba16f, set = 0, binding = 0) uniform restrict writeonly image2D bokeh_image; -#endif - -#ifdef MODE_COMPOSITE_BOKEH -layout(rgba16f, set = 0, binding = 0) uniform restrict image2D color_image; -layout(set = 1, binding = 0) uniform sampler2D source_bokeh; -#endif - -// based on https://www.shadertoy.com/view/Xd3GDl - -layout(push_constant, binding = 1, std430) uniform Params { - ivec2 size; - float z_far; - float z_near; - - bool orthogonal; - float blur_size; - float blur_scale; - int blur_steps; - - bool blur_near_active; - float blur_near_begin; - float blur_near_end; - bool blur_far_active; - - float blur_far_begin; - float blur_far_end; - bool second_pass; - bool half_size; - - bool use_jitter; - float jitter_seed; - uint pad[2]; -} -params; - -//used to work around downsampling filter -#define DEPTH_GAP 0.0 - -#ifdef MODE_GEN_BLUR_SIZE - -float get_depth_at_pos(vec2 uv) { - float depth = textureLod(source_depth, uv, 0.0).x; - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } - return depth; -} - -float get_blur_size(float depth) { - - if (params.blur_near_active && depth < params.blur_near_begin) { - return -(1.0 - smoothstep(params.blur_near_end, params.blur_near_begin, depth)) * params.blur_size - DEPTH_GAP; //near blur is negative - } - - if (params.blur_far_active && depth > params.blur_far_begin) { - return smoothstep(params.blur_far_begin, params.blur_far_end, depth) * params.blur_size + DEPTH_GAP; - } - - return 0.0; -} - -#endif - -const float GOLDEN_ANGLE = 2.39996323; - -//note: uniform pdf rand [0;1[ -float hash12n(vec2 p) { - p = fract(p * vec2(5.3987, 5.4421)); - p += dot(p.yx, p.xy + vec2(21.5351, 14.3137)); - return fract(p.x * p.y * 95.4307); -} - -#if defined(MODE_BOKEH_BOX) || defined(MODE_BOKEH_HEXAGONAL) - -vec4 weighted_filter_dir(vec2 dir, vec2 uv, vec2 pixel_size) { - - dir *= pixel_size; - vec4 color = texture(color_texture, uv); - - vec4 accum = color; - float total = 1.0; - - float blur_scale = params.blur_size / float(params.blur_steps); - - if (params.use_jitter) { - uv += dir * (hash12n(uv + params.jitter_seed) - 0.5); - } - - for (int i = -params.blur_steps; i <= params.blur_steps; i++) { - - if (i == 0) { - continue; - } - float radius = float(i) * blur_scale; - vec2 suv = uv + dir * radius; - radius = abs(radius); - - vec4 sample_color = texture(color_texture, suv); - float limit; - - if (sample_color.a < color.a) { - limit = abs(sample_color.a); - } else { - limit = abs(color.a); - } - - limit -= DEPTH_GAP; - - float m = smoothstep(radius - 0.5, radius + 0.5, limit); - - accum += mix(color, sample_color, m); - - total += 1.0; - } - - return accum / total; -} - -#endif - -void main() { - - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - - if (any(greaterThan(pos, params.size))) { //too large, do nothing - return; - } - - vec2 pixel_size = 1.0 / vec2(params.size); - vec2 uv = vec2(pos) / vec2(params.size); - -#ifdef MODE_GEN_BLUR_SIZE - uv += pixel_size * 0.5; - //precompute size in alpha channel - float depth = get_depth_at_pos(uv); - float size = get_blur_size(depth); - - vec4 color = imageLoad(color_image, pos); - color.a = size; - imageStore(color_image, pos, color); -#endif - -#ifdef MODE_BOKEH_BOX - - //pixel_size*=0.5; //resolution is doubled - if (params.second_pass || !params.half_size) { - uv += pixel_size * 0.5; //half pixel to read centers - } else { - uv += pixel_size * 0.25; //half pixel to read centers from full res - } - - vec2 dir = (params.second_pass ? vec2(0.0, 1.0) : vec2(1.0, 0.0)); - - vec4 color = weighted_filter_dir(dir, uv, pixel_size); - - imageStore(bokeh_image, pos, color); - -#endif - -#ifdef MODE_BOKEH_HEXAGONAL - - //pixel_size*=0.5; //resolution is doubled - if (params.second_pass || !params.half_size) { - uv += pixel_size * 0.5; //half pixel to read centers - } else { - uv += pixel_size * 0.25; //half pixel to read centers from full res - } - - vec2 dir = (params.second_pass ? normalize(vec2(1.0, 0.577350269189626)) : vec2(0.0, 1.0)); - - vec4 color = weighted_filter_dir(dir, uv, pixel_size); - - if (params.second_pass) { - dir = normalize(vec2(-1.0, 0.577350269189626)); - - vec4 color2 = weighted_filter_dir(dir, uv, pixel_size); - - color.rgb = min(color.rgb, color2.rgb); - color.a = (color.a + color2.a) * 0.5; - } - - imageStore(bokeh_image, pos, color); - -#endif - -#ifdef MODE_BOKEH_CIRCULAR - - if (params.half_size) { - pixel_size *= 0.5; //resolution is doubled - } - - uv += pixel_size * 0.5; //half pixel to read centers - - vec4 color = texture(color_texture, uv); - float accum = 1.0; - float radius = params.blur_scale; - - for (float ang = 0.0; radius < params.blur_size; ang += GOLDEN_ANGLE) { - - vec2 suv = uv + vec2(cos(ang), sin(ang)) * pixel_size * radius; - vec4 sample_color = texture(color_texture, suv); - float sample_size = abs(sample_color.a); - if (sample_color.a > color.a) { - sample_size = clamp(sample_size, 0.0, abs(color.a) * 2.0); - } - - float m = smoothstep(radius - 0.5, radius + 0.5, sample_size); - color += mix(color / accum, sample_color, m); - accum += 1.0; - radius += params.blur_scale / radius; - } - - color /= accum; - - imageStore(bokeh_image, pos, color); -#endif - -#ifdef MODE_COMPOSITE_BOKEH - - uv += pixel_size * 0.5; - vec4 color = imageLoad(color_image, pos); - vec4 bokeh = texture(source_bokeh, uv); - - float mix_amount; - if (bokeh.a < color.a) { - mix_amount = min(1.0, max(0.0, max(abs(color.a), abs(bokeh.a)) - DEPTH_GAP)); - } else { - mix_amount = min(1.0, max(0.0, abs(color.a) - DEPTH_GAP)); - } - - color.rgb = mix(color.rgb, bokeh.rgb, mix_amount); //blend between hires and lowres - - color.a = 0; //reset alpha - imageStore(color_image, pos, color); -#endif -} diff --git a/servers/visual/rasterizer_rd/shaders/canvas.glsl b/servers/visual/rasterizer_rd/shaders/canvas.glsl deleted file mode 100644 index 28135fce31..0000000000 --- a/servers/visual/rasterizer_rd/shaders/canvas.glsl +++ /dev/null @@ -1,584 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -#ifdef USE_ATTRIBUTES -layout(location = 0) in vec2 vertex_attrib; -/* clang-format on */ -layout(location = 3) in vec4 color_attrib; -layout(location = 4) in vec2 uv_attrib; - -layout(location = 6) in uvec4 bones_attrib; - -#endif - -#include "canvas_uniforms_inc.glsl" - -layout(location = 0) out vec2 uv_interp; -layout(location = 1) out vec4 color_interp; -layout(location = 2) out vec2 vertex_interp; - -#ifdef USE_NINEPATCH - -layout(location = 3) out vec2 pixel_size_interp; - -#endif - -#ifdef USE_MATERIAL_UNIFORMS -layout(set = 1, binding = 1, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ -} material; -#endif - -/* clang-format off */ -VERTEX_SHADER_GLOBALS -/* clang-format on */ - -void main() { - - vec4 instance_custom = vec4(0.0); -#ifdef USE_PRIMITIVE - - //weird bug, - //this works - vec2 vertex; - vec2 uv; - vec4 color; - - if (gl_VertexIndex == 0) { - vertex = draw_data.points[0]; - uv = draw_data.uvs[0]; - color = vec4(unpackHalf2x16(draw_data.colors[0]), unpackHalf2x16(draw_data.colors[1])); - } else if (gl_VertexIndex == 1) { - vertex = draw_data.points[1]; - uv = draw_data.uvs[1]; - color = vec4(unpackHalf2x16(draw_data.colors[2]), unpackHalf2x16(draw_data.colors[3])); - } else { - vertex = draw_data.points[2]; - uv = draw_data.uvs[2]; - color = vec4(unpackHalf2x16(draw_data.colors[4]), unpackHalf2x16(draw_data.colors[5])); - } - uvec4 bones = uvec4(0, 0, 0, 0); - -#elif defined(USE_ATTRIBUTES) - - vec2 vertex = vertex_attrib; - vec4 color = color_attrib; - vec2 uv = uv_attrib; - - uvec4 bones = bones_attrib; -#else - - vec2 vertex_base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - vec2 vertex_base = vertex_base_arr[gl_VertexIndex]; - - vec2 uv = draw_data.src_rect.xy + abs(draw_data.src_rect.zw) * ((draw_data.flags & FLAGS_TRANSPOSE_RECT) != 0 ? vertex_base.yx : vertex_base.xy); - vec4 color = draw_data.modulation; - vec2 vertex = draw_data.dst_rect.xy + abs(draw_data.dst_rect.zw) * mix(vertex_base, vec2(1.0, 1.0) - vertex_base, lessThan(draw_data.src_rect.zw, vec2(0.0, 0.0))); - uvec4 bones = uvec4(0, 0, 0, 0); - -#endif - - mat4 world_matrix = mat4(vec4(draw_data.world_x, 0.0, 0.0), vec4(draw_data.world_y, 0.0, 0.0), vec4(0.0, 0.0, 1.0, 0.0), vec4(draw_data.world_ofs, 0.0, 1.0)); - -#if 0 - if (draw_data.flags & FLAGS_INSTANCING_ENABLED) { - - uint offset = draw_data.flags & FLAGS_INSTANCING_STRIDE_MASK; - offset *= gl_InstanceIndex; - mat4 instance_xform = mat4( - vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), 0.0, texelFetch(instancing_buffer, offset + 3)), - vec4(texelFetch(instancing_buffer, offset + 4), texelFetch(instancing_buffer, offset + 5), 0.0, texelFetch(instancing_buffer, offset + 7)), - vec4(0.0, 0.0, 1.0, 0.0), - vec4(0.0, 0.0, 0.0, 1.0)); - offset += 8; - if (draw_data.flags & FLAGS_INSTANCING_HAS_COLORS) { - vec4 instance_color; - if (draw_data.flags & FLAGS_INSTANCING_COLOR_8_BIT) { - uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset)); - instance_color = unpackUnorm4x8(bits); - offset += 1; - } else { - instance_color = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); - offser += 4; - } - - color *= instance_color; - } - if (draw_data.flags & FLAGS_INSTANCING_HAS_CUSTOM_DATA) { - if (draw_data.flags & FLAGS_INSTANCING_CUSTOM_DATA_8_BIT) { - uint bits = floatBitsToUint(texelFetch(instancing_buffer, offset)); - instance_custom = unpackUnorm4x8(bits); - } else { - instance_custom = vec4(texelFetch(instancing_buffer, offset + 0), texelFetch(instancing_buffer, offset + 1), texelFetch(instancing_buffer, offset + 2), texelFetch(instancing_buffer, offset + 3)); - } - } - } - -#endif - -#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) - if (bool(draw_data.flags & FLAGS_USING_PARTICLES)) { - //scale by texture size - vertex /= draw_data.color_texture_pixel_size; - } -#endif - -#ifdef USE_POINT_SIZE - float point_size = 1.0; -#endif - { - /* clang-format off */ -VERTEX_SHADER_CODE - /* clang-format on */ - } - -#ifdef USE_NINEPATCH - pixel_size_interp = abs(draw_data.dst_rect.zw) * vertex_base; -#endif - -#if !defined(SKIP_TRANSFORM_USED) - vertex = (world_matrix * vec4(vertex, 0.0, 1.0)).xy; -#endif - - color_interp = color; - - if (bool(draw_data.flags & FLAGS_USE_PIXEL_SNAP)) { - - vertex = floor(vertex + 0.5); - // precision issue on some hardware creates artifacts within texture - // offset uv by a small amount to avoid - uv += 1e-5; - } - -#ifdef USE_ATTRIBUTES -#if 0 - if (bool(draw_data.flags & FLAGS_USE_SKELETON) && bone_weights != vec4(0.0)) { //must be a valid bone - //skeleton transform - - ivec4 bone_indicesi = ivec4(bone_indices); - - uvec2 tex_ofs = bone_indicesi.x * 2; - - mat2x4 m; - m = mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.x; - - tex_ofs = bone_indicesi.y * 2; - - m += mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.y; - - tex_ofs = bone_indicesi.z * 2; - - m += mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.z; - - tex_ofs = bone_indicesi.w * 2; - - m += mat2x4( - texelFetch(skeleton_buffer, tex_ofs + 0), - texelFetch(skeleton_buffer, tex_ofs + 1)) * - bone_weights.w; - - mat4 bone_matrix = skeleton_data.skeleton_transform * transpose(mat4(m[0], m[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))) * skeleton_data.skeleton_transform_inverse; - - //outvec = bone_matrix * outvec; - } -#endif -#endif - - vertex = (canvas_data.canvas_transform * vec4(vertex, 0.0, 1.0)).xy; - - vertex_interp = vertex; - uv_interp = uv; - - gl_Position = canvas_data.screen_transform * vec4(vertex, 0.0, 1.0); - -#ifdef USE_POINT_SIZE - gl_PointSize = point_size; -#endif -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -#include "canvas_uniforms_inc.glsl" - -layout(location = 0) in vec2 uv_interp; -/* clang-format on */ -layout(location = 1) in vec4 color_interp; -layout(location = 2) in vec2 vertex_interp; - -#ifdef USE_NINEPATCH - -layout(location = 3) in vec2 pixel_size_interp; - -#endif - -layout(location = 0) out vec4 frag_color; - -#ifdef USE_MATERIAL_UNIFORMS -layout(set = 1, binding = 1, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ -} material; -#endif - -/* clang-format off */ -FRAGMENT_SHADER_GLOBALS -/* clang-format on */ - -#ifdef LIGHT_SHADER_CODE_USED - -vec4 light_compute( - vec3 light_vertex, - vec3 light_position, - vec3 normal, - vec4 light_color, - float light_energy, - vec4 specular_shininess, - inout vec4 shadow_modulate, - vec2 screen_uv, - vec2 uv, - vec4 color) { - - vec4 light = vec4(0.0); - /* clang-format off */ -LIGHT_SHADER_CODE - /* clang-format on */ - return light; -} - -#endif - -#ifdef USE_NINEPATCH - -float map_ninepatch_axis(float pixel, float draw_size, float tex_pixel_size, float margin_begin, float margin_end, int np_repeat, inout int draw_center) { - - float tex_size = 1.0 / tex_pixel_size; - - if (pixel < margin_begin) { - return pixel * tex_pixel_size; - } else if (pixel >= draw_size - margin_end) { - return (tex_size - (draw_size - pixel)) * tex_pixel_size; - } else { - if (!bool(draw_data.flags & FLAGS_NINEPACH_DRAW_CENTER)) { - draw_center--; - } - - // np_repeat is passed as uniform using NinePatchRect::AxisStretchMode enum. - if (np_repeat == 0) { // Stretch. - // Convert to ratio. - float ratio = (pixel - margin_begin) / (draw_size - margin_begin - margin_end); - // Scale to source texture. - return (margin_begin + ratio * (tex_size - margin_begin - margin_end)) * tex_pixel_size; - } else if (np_repeat == 1) { // Tile. - // Convert to offset. - float ofs = mod((pixel - margin_begin), tex_size - margin_begin - margin_end); - // Scale to source texture. - return (margin_begin + ofs) * tex_pixel_size; - } else if (np_repeat == 2) { // Tile Fit. - // Calculate scale. - float src_area = draw_size - margin_begin - margin_end; - float dst_area = tex_size - margin_begin - margin_end; - float scale = max(1.0, floor(src_area / max(dst_area, 0.0000001) + 0.5)); - // Convert to ratio. - float ratio = (pixel - margin_begin) / src_area; - ratio = mod(ratio * scale, 1.0); - // Scale to source texture. - return (margin_begin + ratio * dst_area) * tex_pixel_size; - } else { // Shouldn't happen, but silences compiler warning. - return 0.0; - } - } -} - -#endif - -void main() { - - vec4 color = color_interp; - vec2 uv = uv_interp; - vec2 vertex = vertex_interp; - -#if !defined(USE_ATTRIBUTES) && !defined(USE_PRIMITIVE) - -#ifdef USE_NINEPATCH - - int draw_center = 2; - uv = vec2( - map_ninepatch_axis(pixel_size_interp.x, abs(draw_data.dst_rect.z), draw_data.color_texture_pixel_size.x, draw_data.ninepatch_margins.x, draw_data.ninepatch_margins.z, int(draw_data.flags >> FLAGS_NINEPATCH_H_MODE_SHIFT) & 0x3, draw_center), - map_ninepatch_axis(pixel_size_interp.y, abs(draw_data.dst_rect.w), draw_data.color_texture_pixel_size.y, draw_data.ninepatch_margins.y, draw_data.ninepatch_margins.w, int(draw_data.flags >> FLAGS_NINEPATCH_V_MODE_SHIFT) & 0x3, draw_center)); - - if (draw_center == 0) { - color.a = 0.0; - } - - uv = uv * draw_data.src_rect.zw + draw_data.src_rect.xy; //apply region if needed - -#endif - if (bool(draw_data.flags & FLAGS_CLIP_RECT_UV)) { - - uv = clamp(uv, draw_data.src_rect.xy, draw_data.src_rect.xy + abs(draw_data.src_rect.zw)); - } - -#endif - - color *= texture(sampler2D(color_texture, texture_sampler), uv); - - uint light_count = (draw_data.flags >> FLAGS_LIGHT_COUNT_SHIFT) & 0xF; //max 16 lights - - vec3 normal; - -#if defined(NORMAL_USED) - - bool normal_used = true; -#else - bool normal_used = false; -#endif - - if (normal_used || (light_count > 0 && bool(draw_data.flags & FLAGS_DEFAULT_NORMAL_MAP_USED))) { - normal.xy = texture(sampler2D(normal_texture, texture_sampler), uv).xy * vec2(2.0, -2.0) - vec2(1.0, -1.0); - normal.z = sqrt(1.0 - dot(normal.xy, normal.xy)); - normal_used = true; - } else { - normal = vec3(0.0, 0.0, 1.0); - } - - vec4 specular_shininess; - -#if defined(SPECULAR_SHININESS_USED) - - bool specular_shininess_used = true; -#else - bool specular_shininess_used = false; -#endif - - if (specular_shininess_used || (light_count > 0 && normal_used && bool(draw_data.flags & FLAGS_DEFAULT_SPECULAR_MAP_USED))) { - specular_shininess = texture(sampler2D(specular_texture, texture_sampler), uv); - specular_shininess *= unpackUnorm4x8(draw_data.specular_shininess); - specular_shininess_used = true; - } else { - specular_shininess = vec4(1.0); - } - -#if defined(SCREEN_UV_USED) - vec2 screen_uv = gl_FragCoord.xy * canvas_data.screen_pixel_size; -#else - vec2 screen_uv = vec2(0.0); -#endif - - vec3 light_vertex = vec3(vertex, 0.0); - vec2 shadow_vertex = vertex; - - { - float normal_depth = 1.0; - -#if defined(NORMALMAP_USED) - vec3 normal_map = vec3(0.0, 0.0, 1.0); - normal_used = true; -#endif - - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ - -#if defined(NORMALMAP_USED) - normal = mix(vec3(0.0, 0.0, 1.0), normal_map * vec3(2.0, -2.0, 1.0) - vec3(1.0, -1.0, 0.0), normal_depth); -#endif - } - - if (normal_used) { - //convert by item transform - normal.xy = mat2(normalize(draw_data.world_x), normalize(draw_data.world_y)) * normal.xy; - //convert by canvas transform - normal = normalize((canvas_data.canvas_normal_transform * vec4(normal, 0.0)).xyz); - } - - vec4 base_color = color; - if (bool(draw_data.flags & FLAGS_USING_LIGHT_MASK)) { - color = vec4(0.0); //invisible by default due to using light mask - } - - color *= canvas_data.canvas_modulation; -#ifdef USE_LIGHTING - for (uint i = 0; i < MAX_LIGHT_TEXTURES; i++) { - if (i >= light_count) { - break; - } - uint light_base; - if (i < 8) { - if (i < 4) { - light_base = draw_data.lights[0]; - } else { - light_base = draw_data.lights[1]; - } - } else { - if (i < 12) { - light_base = draw_data.lights[2]; - } else { - light_base = draw_data.lights[3]; - } - } - light_base >>= (i & 3) * 8; - light_base &= 0xFF; - - vec2 tex_uv = (vec4(vertex, 0.0, 1.0) * mat4(light_array.data[light_base].texture_matrix[0], light_array.data[light_base].texture_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. - vec4 light_color = texture(sampler2D(light_textures[i], texture_sampler), tex_uv); - vec4 light_base_color = light_array.data[light_base].color; - -#ifdef LIGHT_SHADER_CODE_USED - - vec4 shadow_modulate = vec4(1.0); - vec3 light_position = vec3(light_array.data[light_base].position, light_array.data[light_base].height); - - light_color.rgb *= light_base_color.rgb; - light_color = light_compute(light_vertex, light_position, normal, light_color, light_base_color.a, specular_shininess, shadow_modulate, screen_uv, color, uv); -#else - - light_color.rgb *= light_base_color.rgb * light_base_color.a; - - if (normal_used) { - - vec3 light_pos = vec3(light_array.data[light_base].position, light_array.data[light_base].height); - vec3 pos = light_vertex; - vec3 light_vec = normalize(light_pos - pos); - float cNdotL = max(0.0, dot(normal, light_vec)); - - if (specular_shininess_used) { - //blinn - vec3 view = vec3(0.0, 0.0, 1.0); // not great but good enough - vec3 half_vec = normalize(view + light_vec); - - float cNdotV = max(dot(normal, view), 0.0); - float cNdotH = max(dot(normal, half_vec), 0.0); - float cVdotH = max(dot(view, half_vec), 0.0); - float cLdotH = max(dot(light_vec, half_vec), 0.0); - float shininess = exp2(15.0 * specular_shininess.a + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess); - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - float s = (blinn) / max(4.0 * cNdotV * cNdotL, 0.75); - - light_color.rgb = specular_shininess.rgb * light_base_color.rgb * s + light_color.rgb * cNdotL; - } else { - light_color.rgb *= cNdotL; - } - } -#endif - if (any(lessThan(tex_uv, vec2(0.0, 0.0))) || any(greaterThanEqual(tex_uv, vec2(1.0, 1.0)))) { - //if outside the light texture, light color is zero - light_color.a = 0.0; - } - - if (bool(light_array.data[light_base].flags & LIGHT_FLAGS_HAS_SHADOW)) { - - vec2 shadow_pos = (vec4(shadow_vertex, 0.0, 1.0) * mat4(light_array.data[light_base].shadow_matrix[0], light_array.data[light_base].shadow_matrix[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0))).xy; //multiply inverse given its transposed. Optimizer removes useless operations. - - vec2 pos_norm = normalize(shadow_pos); - vec2 pos_abs = abs(pos_norm); - vec2 pos_box = pos_norm / max(pos_abs.x, pos_abs.y); - vec2 pos_rot = pos_norm * mat2(vec2(0.7071067811865476, -0.7071067811865476), vec2(0.7071067811865476, 0.7071067811865476)); //is there a faster way to 45 degrees rot? - float tex_ofs; - float distance; - if (pos_rot.y > 0) { - if (pos_rot.x > 0) { - tex_ofs = pos_box.y * 0.125 + 0.125; - distance = shadow_pos.x; - } else { - tex_ofs = pos_box.x * -0.125 + (0.25 + 0.125); - distance = shadow_pos.y; - } - } else { - if (pos_rot.x < 0) { - tex_ofs = pos_box.y * -0.125 + (0.5 + 0.125); - distance = -shadow_pos.x; - } else { - tex_ofs = pos_box.x * 0.125 + (0.75 + 0.125); - distance = -shadow_pos.y; - } - } - - //float distance = length(shadow_pos); - float shadow; - uint shadow_mode = light_array.data[light_base].flags & LIGHT_FLAGS_FILTER_MASK; - - vec4 shadow_uv = vec4(tex_ofs, 0.0, distance, 1.0); - - if (shadow_mode == LIGHT_FLAGS_SHADOW_NEAREST) { - shadow = textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; - } else if (shadow_mode == LIGHT_FLAGS_SHADOW_PCF5) { - vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); - shadow = 0.0; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x; - shadow /= 5.0; - } else { //PCF13 - vec4 shadow_pixel_size = vec4(light_array.data[light_base].shadow_pixel_size, 0.0, 0.0, 0.0); - shadow = 0.0; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 6.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 5.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 4.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 3.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size * 2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv - shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 2.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 3.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 4.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 5.0).x; - shadow += textureProj(sampler2DShadow(shadow_textures[i], shadow_sampler), shadow_uv + shadow_pixel_size * 6.0).x; - shadow /= 13.0; - } - - vec4 shadow_color = light_array.data[light_base].shadow_color; -#ifdef LIGHT_SHADER_CODE_USED - shadow_color *= shadow_modulate; -#endif - light_color = mix(light_color, shadow_color, shadow); - } - - uint blend_mode = light_array.data[light_base].flags & LIGHT_FLAGS_BLEND_MASK; - - switch (blend_mode) { - case LIGHT_FLAGS_BLEND_MODE_ADD: { - color.rgb += light_color.rgb * light_color.a; - } break; - case LIGHT_FLAGS_BLEND_MODE_SUB: { - color.rgb -= light_color.rgb * light_color.a; - } break; - case LIGHT_FLAGS_BLEND_MODE_MIX: { - color.rgb = mix(color.rgb, light_color.rgb, light_color.a); - } break; - case LIGHT_FLAGS_BLEND_MODE_MASK: { - light_color.a *= base_color.a; - color.rgb = mix(color.rgb, light_color.rgb, light_color.a); - } break; - } - } -#endif - - frag_color = color; -} diff --git a/servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl b/servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl deleted file mode 100644 index 7b30cc8fe9..0000000000 --- a/servers/visual/rasterizer_rd/shaders/canvas_occlusion.glsl +++ /dev/null @@ -1,40 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -layout(location = 0) in highp vec3 vertex; -/* clang-format on */ - -layout(push_constant, binding = 0, std430) uniform Constants { - - mat4 projection; - mat2x4 modelview; - vec2 direction; - vec2 pad; -} -constants; - -layout(location = 0) out highp float depth; - -void main() { - - highp vec4 vtx = vec4(vertex, 1.0) * mat4(constants.modelview[0], constants.modelview[1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); - depth = dot(constants.direction, vtx.xy); - - gl_Position = constants.projection * vtx; -} - -/* clang-format off */ -[fragment] - -#version 450 - -layout(location = 0) in highp float depth; -/* clang-format on */ -layout(location = 0) out highp float distance_buf; - -void main() { - - distance_buf = depth; -} diff --git a/servers/visual/rasterizer_rd/shaders/canvas_uniforms_inc.glsl b/servers/visual/rasterizer_rd/shaders/canvas_uniforms_inc.glsl deleted file mode 100644 index 1ac43480cd..0000000000 --- a/servers/visual/rasterizer_rd/shaders/canvas_uniforms_inc.glsl +++ /dev/null @@ -1,141 +0,0 @@ -#define M_PI 3.14159265359 - -#define FLAGS_INSTANCING_STRIDE_MASK 0xF -#define FLAGS_INSTANCING_ENABLED (1 << 4) -#define FLAGS_INSTANCING_HAS_COLORS (1 << 5) -#define FLAGS_INSTANCING_COLOR_8BIT (1 << 6) -#define FLAGS_INSTANCING_HAS_CUSTOM_DATA (1 << 7) -#define FLAGS_INSTANCING_CUSTOM_DATA_8_BIT (1 << 8) - -#define FLAGS_CLIP_RECT_UV (1 << 9) -#define FLAGS_TRANSPOSE_RECT (1 << 10) -#define FLAGS_USING_LIGHT_MASK (1 << 11) -#define FLAGS_NINEPACH_DRAW_CENTER (1 << 12) -#define FLAGS_USING_PARTICLES (1 << 13) -#define FLAGS_USE_PIXEL_SNAP (1 << 14) - -#define FLAGS_NINEPATCH_H_MODE_SHIFT 16 -#define FLAGS_NINEPATCH_V_MODE_SHIFT 18 - -#define FLAGS_LIGHT_COUNT_SHIFT 20 - -#define FLAGS_DEFAULT_NORMAL_MAP_USED (1 << 26) -#define FLAGS_DEFAULT_SPECULAR_MAP_USED (1 << 27) - -// In vulkan, sets should always be ordered using the following logic: -// Lower Sets: Sets that change format and layout less often -// Higher sets: Sets that change format and layout very often -// This is because changing a set for another with a different layout or format, -// invalidates all the upper ones. - -/* SET0: Draw Primitive */ - -layout(push_constant, binding = 0, std430) uniform DrawData { - vec2 world_x; - vec2 world_y; - vec2 world_ofs; - uint flags; - uint specular_shininess; -#ifdef USE_PRIMITIVE - vec2 points[3]; - vec2 uvs[3]; - uint colors[6]; -#else - vec4 modulation; - vec4 ninepatch_margins; - vec4 dst_rect; //for built-in rect and UV - vec4 src_rect; - vec2 pad; - -#endif - vec2 color_texture_pixel_size; - uint lights[4]; -} -draw_data; - -// The values passed per draw primitives are cached within it - -layout(set = 0, binding = 1) uniform texture2D color_texture; -layout(set = 0, binding = 2) uniform texture2D normal_texture; -layout(set = 0, binding = 3) uniform texture2D specular_texture; -layout(set = 0, binding = 4) uniform sampler texture_sampler; - -layout(set = 0, binding = 5) uniform textureBuffer instancing_buffer; - -/* SET1: Is reserved for the material */ - -#ifdef USE_MATERIAL_SAMPLERS - -layout(set = 1, binding = 0) uniform sampler material_samplers[12]; - -#endif - -/* SET2: Canvas Item State (including lighting) */ - -layout(set = 2, binding = 0, std140) uniform CanvasData { - mat4 canvas_transform; - mat4 screen_transform; - mat4 canvas_normal_transform; - vec4 canvas_modulation; - vec2 screen_pixel_size; - float time; - float time_pad; - //uint light_count; -} -canvas_data; - -layout(set = 2, binding = 1) uniform textureBuffer skeleton_buffer; - -layout(set = 2, binding = 2, std140) uniform SkeletonData { - mat4 skeleton_transform; //in world coordinates - mat4 skeleton_transform_inverse; -} -skeleton_data; - -#ifdef USE_LIGHTING - -#define LIGHT_FLAGS_BLEND_MASK (3 << 16) -#define LIGHT_FLAGS_BLEND_MODE_ADD (0 << 16) -#define LIGHT_FLAGS_BLEND_MODE_SUB (1 << 16) -#define LIGHT_FLAGS_BLEND_MODE_MIX (2 << 16) -#define LIGHT_FLAGS_BLEND_MODE_MASK (3 << 16) -#define LIGHT_FLAGS_HAS_SHADOW (1 << 20) -#define LIGHT_FLAGS_FILTER_SHIFT 22 -#define LIGHT_FLAGS_FILTER_MASK (3 << 22) -#define LIGHT_FLAGS_SHADOW_NEAREST (0 << 22) -#define LIGHT_FLAGS_SHADOW_PCF5 (1 << 22) -#define LIGHT_FLAGS_SHADOW_PCF13 (2 << 22) - -struct Light { - mat2x4 texture_matrix; //light to texture coordinate matrix (transposed) - mat2x4 shadow_matrix; //light to shadow coordinate matrix (transposed) - vec4 color; - vec4 shadow_color; - vec2 position; - uint flags; //index to light texture - float height; - float shadow_pixel_size; - float pad0; - float pad1; - float pad2; -}; - -layout(set = 2, binding = 3, std140) uniform LightData { - Light data[MAX_LIGHTS]; -} -light_array; - -layout(set = 2, binding = 4) uniform texture2D light_textures[MAX_LIGHT_TEXTURES]; -layout(set = 2, binding = 5) uniform texture2D shadow_textures[MAX_LIGHT_TEXTURES]; - -layout(set = 2, binding = 6) uniform sampler shadow_sampler; - -#endif - -/* SET3: Render Target Data */ - -#ifdef SCREEN_TEXTURE_USED - -layout(set = 3, binding = 0) uniform texture2D screen_texture; - -#endif diff --git a/servers/visual/rasterizer_rd/shaders/copy.glsl b/servers/visual/rasterizer_rd/shaders/copy.glsl deleted file mode 100644 index cbb9b546a3..0000000000 --- a/servers/visual/rasterizer_rd/shaders/copy.glsl +++ /dev/null @@ -1,86 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -layout(location = 0) out vec2 uv_interp; -/* clang-format on */ - -void main() { - - vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv_interp = base_arr[gl_VertexIndex]; - - gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -layout(location = 0) in vec2 uv_interp; -/* clang-format on */ - -#ifdef MODE_CUBE_TO_DP - -layout(set = 0, binding = 0) uniform samplerCube source_cube; - -layout(push_constant, binding = 0, std430) uniform Params { - float bias; - float z_far; - float z_near; - bool z_flip; -} -params; - -layout(location = 0) out float depth_buffer; - -#endif - -void main() { - -#ifdef MODE_CUBE_TO_DP - - vec3 normal = vec3(uv_interp * 2.0 - 1.0, 0.0); - - normal.z = 0.5 - 0.5 * ((normal.x * normal.x) + (normal.y * normal.y)); - normal = normalize(normal); - - normal.y = -normal.y; //needs to be flipped to match projection matrix - if (!params.z_flip) { - normal.z = -normal.z; - } - - float depth = texture(source_cube, normal).r; - - // absolute values for direction cosines, bigger value equals closer to basis axis - vec3 unorm = abs(normal); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = vec3(1.0, 0.0, 0.0); - } - - float depth_fix = 1.0 / dot(normal, unorm); - - depth = 2.0 * depth - 1.0; - float linear_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - depth_buffer = (linear_depth * depth_fix + params.bias) / params.z_far; - -#endif -} diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl deleted file mode 100644 index 9f3ecf6053..0000000000 --- a/servers/visual/rasterizer_rd/shaders/cubemap_downsampler.glsl +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2016 Activision Publishing, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -#define BLOCK_SIZE 8 - -layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform samplerCube source_cubemap; - -layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap; - -layout(push_constant, binding = 1, std430) uniform Params { - uint face_size; -} -params; - -#define M_PI 3.14159265359 - -void get_dir_0(out vec3 dir, in float u, in float v) { - dir[0] = 1.0; - dir[1] = v; - dir[2] = -u; -} -void get_dir_1(out vec3 dir, in float u, in float v) { - dir[0] = -1.0; - dir[1] = v; - dir[2] = u; -} -void get_dir_2(out vec3 dir, in float u, in float v) { - dir[0] = u; - dir[1] = 1.0; - dir[2] = -v; -} -void get_dir_3(out vec3 dir, in float u, in float v) { - dir[0] = u; - dir[1] = -1.0; - dir[2] = v; -} -void get_dir_4(out vec3 dir, in float u, in float v) { - dir[0] = u; - dir[1] = v; - dir[2] = 1.0; -} -void get_dir_5(out vec3 dir, in float u, in float v) { - dir[0] = -u; - dir[1] = v; - dir[2] = -1.0; -} - -float calcWeight(float u, float v) { - float val = u * u + v * v + 1.0; - return val * sqrt(val); -} - -void main() { - uvec3 id = gl_GlobalInvocationID; - uint face_size = params.face_size; - - if (id.x < face_size && id.y < face_size) { - float inv_face_size = 1.0 / float(face_size); - - float u0 = (float(id.x) * 2.0 + 1.0 - 0.75) * inv_face_size - 1.0; - float u1 = (float(id.x) * 2.0 + 1.0 + 0.75) * inv_face_size - 1.0; - - float v0 = (float(id.y) * 2.0 + 1.0 - 0.75) * -inv_face_size + 1.0; - float v1 = (float(id.y) * 2.0 + 1.0 + 0.75) * -inv_face_size + 1.0; - - float weights[4]; - weights[0] = calcWeight(u0, v0); - weights[1] = calcWeight(u1, v0); - weights[2] = calcWeight(u0, v1); - weights[3] = calcWeight(u1, v1); - - const float wsum = 0.5 / (weights[0] + weights[1] + weights[2] + weights[3]); - for (int i = 0; i < 4; i++) { - weights[i] = weights[i] * wsum + .125; - } - - vec3 dir; - vec4 color; - switch (id.z) { - case 0: - get_dir_0(dir, u0, v0); - color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; - - get_dir_0(dir, u1, v0); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; - - get_dir_0(dir, u0, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; - - get_dir_0(dir, u1, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; - break; - case 1: - get_dir_1(dir, u0, v0); - color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; - - get_dir_1(dir, u1, v0); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; - - get_dir_1(dir, u0, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; - - get_dir_1(dir, u1, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; - break; - case 2: - get_dir_2(dir, u0, v0); - color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; - - get_dir_2(dir, u1, v0); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; - - get_dir_2(dir, u0, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; - - get_dir_2(dir, u1, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; - break; - case 3: - get_dir_3(dir, u0, v0); - color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; - - get_dir_3(dir, u1, v0); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; - - get_dir_3(dir, u0, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; - - get_dir_3(dir, u1, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; - break; - case 4: - get_dir_4(dir, u0, v0); - color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; - - get_dir_4(dir, u1, v0); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; - - get_dir_4(dir, u0, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; - - get_dir_4(dir, u1, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; - break; - default: - get_dir_5(dir, u0, v0); - color = textureLod(source_cubemap, normalize(dir), 0.0) * weights[0]; - - get_dir_5(dir, u1, v0); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[1]; - - get_dir_5(dir, u0, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[2]; - - get_dir_5(dir, u1, v1); - color += textureLod(source_cubemap, normalize(dir), 0.0) * weights[3]; - break; - } - imageStore(dest_cubemap, ivec3(id), color); - } -} diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl deleted file mode 100644 index 193d0a8a3c..0000000000 --- a/servers/visual/rasterizer_rd/shaders/cubemap_filter.glsl +++ /dev/null @@ -1,328 +0,0 @@ -// Copyright 2016 Activision Publishing, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the Software -// is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -#define GROUP_SIZE 64 - -layout(local_size_x = GROUP_SIZE, local_size_y = 1, local_size_z = 1) in; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform samplerCube source_cubemap; -layout(rgba16f, set = 2, binding = 0) uniform restrict writeonly imageCube dest_cubemap0; -layout(rgba16f, set = 2, binding = 1) uniform restrict writeonly imageCube dest_cubemap1; -layout(rgba16f, set = 2, binding = 2) uniform restrict writeonly imageCube dest_cubemap2; -layout(rgba16f, set = 2, binding = 3) uniform restrict writeonly imageCube dest_cubemap3; -layout(rgba16f, set = 2, binding = 4) uniform restrict writeonly imageCube dest_cubemap4; -layout(rgba16f, set = 2, binding = 5) uniform restrict writeonly imageCube dest_cubemap5; -layout(rgba16f, set = 2, binding = 6) uniform restrict writeonly imageCube dest_cubemap6; - -#ifdef USE_HIGH_QUALITY -#define NUM_TAPS 32 -#else -#define NUM_TAPS 8 -#endif - -#define BASE_RESOLUTION 128 - -#ifdef USE_HIGH_QUALITY -layout(set = 1, binding = 0, std430) buffer restrict readonly Data { - vec4[7][5][3][24] coeffs; -} -data; -#else -layout(set = 1, binding = 0, std430) buffer restrict readonly Data { - vec4[7][5][6] coeffs; -} -data; -#endif - -void get_dir(out vec3 dir, in vec2 uv, in uint face) { - switch (face) { - case 0: - dir = vec3(1.0, uv[1], -uv[0]); - break; - case 1: - dir = vec3(-1.0, uv[1], uv[0]); - break; - case 2: - dir = vec3(uv[0], 1.0, -uv[1]); - break; - case 3: - dir = vec3(uv[0], -1.0, uv[1]); - break; - case 4: - dir = vec3(uv[0], uv[1], 1.0); - break; - default: - dir = vec3(-uv[0], uv[1], -1.0); - break; - } -} - -void main() { - // INPUT: - // id.x = the linear address of the texel (ignoring face) - // id.y = the face - // -> use to index output texture - // id.x = texel x - // id.y = texel y - // id.z = face - uvec3 id = gl_GlobalInvocationID; - - // determine which texel this is -#ifndef USE_TEXTURE_ARRAY - // NOTE (macOS/MoltenVK): Do not rename, "level" variable name conflicts with the Metal "level(float lod)" mipmap sampling function name. - int mip_level = 0; - if (id.x < (128 * 128)) { - mip_level = 0; - } else if (id.x < (128 * 128 + 64 * 64)) { - mip_level = 1; - id.x -= (128 * 128); - } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32)) { - mip_level = 2; - id.x -= (128 * 128 + 64 * 64); - } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16)) { - mip_level = 3; - id.x -= (128 * 128 + 64 * 64 + 32 * 32); - } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8)) { - mip_level = 4; - id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16); - } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4)) { - mip_level = 5; - id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8); - } else if (id.x < (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4 + 2 * 2)) { - mip_level = 6; - id.x -= (128 * 128 + 64 * 64 + 32 * 32 + 16 * 16 + 8 * 8 + 4 * 4); - } else { - return; - } - int res = BASE_RESOLUTION >> mip_level; -#else // Using Texture Arrays so all levels are the same resolution - int res = BASE_RESOLUTION; - int mip_level = int(id.x / (BASE_RESOLUTION * BASE_RESOLUTION)); - id.x -= mip_level * BASE_RESOLUTION * BASE_RESOLUTION; -#endif - - // determine dir / pos for the texel - vec3 dir, adir, frameZ; - { - id.z = id.y; - id.y = id.x / res; - id.x -= id.y * res; - - vec2 uv; - uv.x = (float(id.x) * 2.0 + 1.0) / float(res) - 1.0; - uv.y = -(float(id.y) * 2.0 + 1.0) / float(res) + 1.0; - - get_dir(dir, uv, id.z); - frameZ = normalize(dir); - - adir = abs(dir); - } - - // GGX gather colors - vec4 color = vec4(0.0); - for (int axis = 0; axis < 3; axis++) { - const int otherAxis0 = 1 - (axis & 1) - (axis >> 1); - const int otherAxis1 = 2 - (axis >> 1); - - float frameweight = (max(adir[otherAxis0], adir[otherAxis1]) - .75) / .25; - if (frameweight > 0.0) { - // determine frame - vec3 UpVector; - switch (axis) { - case 0: - UpVector = vec3(1, 0, 0); - break; - case 1: - UpVector = vec3(0, 1, 0); - break; - default: - UpVector = vec3(0, 0, 1); - break; - } - - vec3 frameX = normalize(cross(UpVector, frameZ)); - vec3 frameY = cross(frameZ, frameX); - - // calculate parametrization for polynomial - float Nx = dir[otherAxis0]; - float Ny = dir[otherAxis1]; - float Nz = adir[axis]; - - float NmaxXY = max(abs(Ny), abs(Nx)); - Nx /= NmaxXY; - Ny /= NmaxXY; - - float theta; - if (Ny < Nx) { - if (Ny <= -0.999) - theta = Nx; - else - theta = Ny; - } else { - if (Ny >= 0.999) - theta = -Nx; - else - theta = -Ny; - } - - float phi; - if (Nz <= -0.999) - phi = -NmaxXY; - else if (Nz >= 0.999) - phi = NmaxXY; - else - phi = Nz; - - float theta2 = theta * theta; - float phi2 = phi * phi; - - // sample - for (int iSuperTap = 0; iSuperTap < NUM_TAPS / 4; iSuperTap++) { - const int index = (NUM_TAPS / 4) * axis + iSuperTap; - -#ifdef USE_HIGH_QUALITY - vec4 coeffsDir0[3]; - vec4 coeffsDir1[3]; - vec4 coeffsDir2[3]; - vec4 coeffsLevel[3]; - vec4 coeffsWeight[3]; - - for (int iCoeff = 0; iCoeff < 3; iCoeff++) { - coeffsDir0[iCoeff] = data.coeffs[mip_level][0][iCoeff][index]; - coeffsDir1[iCoeff] = data.coeffs[mip_level][1][iCoeff][index]; - coeffsDir2[iCoeff] = data.coeffs[mip_level][2][iCoeff][index]; - coeffsLevel[iCoeff] = data.coeffs[mip_level][3][iCoeff][index]; - coeffsWeight[iCoeff] = data.coeffs[mip_level][4][iCoeff][index]; - } - - for (int iSubTap = 0; iSubTap < 4; iSubTap++) { - // determine sample attributes (dir, weight, mip_level) - vec3 sample_dir = frameX * (coeffsDir0[0][iSubTap] + coeffsDir0[1][iSubTap] * theta2 + coeffsDir0[2][iSubTap] * phi2) + frameY * (coeffsDir1[0][iSubTap] + coeffsDir1[1][iSubTap] * theta2 + coeffsDir1[2][iSubTap] * phi2) + frameZ * (coeffsDir2[0][iSubTap] + coeffsDir2[1][iSubTap] * theta2 + coeffsDir2[2][iSubTap] * phi2); - - float sample_level = coeffsLevel[0][iSubTap] + coeffsLevel[1][iSubTap] * theta2 + coeffsLevel[2][iSubTap] * phi2; - - float sample_weight = coeffsWeight[0][iSubTap] + coeffsWeight[1][iSubTap] * theta2 + coeffsWeight[2][iSubTap] * phi2; -#else - vec4 coeffsDir0 = data.coeffs[mip_level][0][index]; - vec4 coeffsDir1 = data.coeffs[mip_level][1][index]; - vec4 coeffsDir2 = data.coeffs[mip_level][2][index]; - vec4 coeffsLevel = data.coeffs[mip_level][3][index]; - vec4 coeffsWeight = data.coeffs[mip_level][4][index]; - - for (int iSubTap = 0; iSubTap < 4; iSubTap++) { - // determine sample attributes (dir, weight, mip_level) - vec3 sample_dir = frameX * coeffsDir0[iSubTap] + frameY * coeffsDir1[iSubTap] + frameZ * coeffsDir2[iSubTap]; - - float sample_level = coeffsLevel[iSubTap]; - - float sample_weight = coeffsWeight[iSubTap]; -#endif - - sample_weight *= frameweight; - - // adjust for jacobian - sample_dir /= max(abs(sample_dir[0]), max(abs(sample_dir[1]), abs(sample_dir[2]))); - sample_level += 0.75 * log2(dot(sample_dir, sample_dir)); -#ifndef USE_TEXTURE_ARRAY - sample_level += float(mip_level) / 6.0; // Hack to increase the perceived roughness and reduce upscaling artifacts -#endif - // sample cubemap - color.xyz += textureLod(source_cubemap, normalize(sample_dir), sample_level).xyz * sample_weight; - color.w += sample_weight; - } - } - } - } - color /= color.w; - - // write color - color.xyz = max(vec3(0.0), color.xyz); - color.w = 1.0; -#ifdef USE_TEXTURE_ARRAY - id.xy *= uvec2(2, 2); -#endif - - switch (mip_level) { - case 0: - imageStore(dest_cubemap0, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap0, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap0, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - case 1: - imageStore(dest_cubemap1, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap1, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap1, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - case 2: - imageStore(dest_cubemap2, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap2, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap2, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - case 3: - imageStore(dest_cubemap3, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap3, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap3, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - case 4: - imageStore(dest_cubemap4, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap4, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap4, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - case 5: - imageStore(dest_cubemap5, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap5, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap5, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - default: - imageStore(dest_cubemap6, ivec3(id), color); -#ifdef USE_TEXTURE_ARRAY - imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 0.0, 0.0), color); - imageStore(dest_cubemap6, ivec3(id) + ivec3(0.0, 1.0, 0.0), color); - imageStore(dest_cubemap6, ivec3(id) + ivec3(1.0, 1.0, 0.0), color); -#endif - break; - } -} diff --git a/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl b/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl deleted file mode 100644 index e85996fa1a..0000000000 --- a/servers/visual/rasterizer_rd/shaders/cubemap_roughness.glsl +++ /dev/null @@ -1,147 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -#define GROUP_SIZE 8 - -layout(local_size_x = GROUP_SIZE, local_size_y = GROUP_SIZE, local_size_z = 1) in; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform samplerCube source_cube; - -layout(rgba16f, set = 1, binding = 0) uniform restrict writeonly imageCube dest_cubemap; - -layout(push_constant, binding = 1, std430) uniform Params { - uint face_id; - uint sample_count; - float roughness; - bool use_direct_write; - float face_size; -} -params; - -#define M_PI 3.14159265359 - -vec3 texelCoordToVec(vec2 uv, uint faceID) { - mat3 faceUvVectors[6]; - - // -x - faceUvVectors[1][0] = vec3(0.0, 0.0, 1.0); // u -> +z - faceUvVectors[1][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[1][2] = vec3(-1.0, 0.0, 0.0); // -x face - - // +x - faceUvVectors[0][0] = vec3(0.0, 0.0, -1.0); // u -> -z - faceUvVectors[0][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[0][2] = vec3(1.0, 0.0, 0.0); // +x face - - // -y - faceUvVectors[3][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[3][1] = vec3(0.0, 0.0, -1.0); // v -> -z - faceUvVectors[3][2] = vec3(0.0, -1.0, 0.0); // -y face - - // +y - faceUvVectors[2][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[2][1] = vec3(0.0, 0.0, 1.0); // v -> +z - faceUvVectors[2][2] = vec3(0.0, 1.0, 0.0); // +y face - - // -z - faceUvVectors[5][0] = vec3(-1.0, 0.0, 0.0); // u -> -x - faceUvVectors[5][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[5][2] = vec3(0.0, 0.0, -1.0); // -z face - - // +z - faceUvVectors[4][0] = vec3(1.0, 0.0, 0.0); // u -> +x - faceUvVectors[4][1] = vec3(0.0, -1.0, 0.0); // v -> -y - faceUvVectors[4][2] = vec3(0.0, 0.0, 1.0); // +z face - - // out = u * s_faceUv[0] + v * s_faceUv[1] + s_faceUv[2]. - vec3 result = (faceUvVectors[faceID][0] * uv.x) + (faceUvVectors[faceID][1] * uv.y) + faceUvVectors[faceID][2]; - return normalize(result); -} - -vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N) { - float a = Roughness * Roughness; // DISNEY'S ROUGHNESS [see Burley'12 siggraph] - - // Compute distribution direction - float Phi = 2.0 * M_PI * Xi.x; - float CosTheta = sqrt((1.0 - Xi.y) / (1.0 + (a * a - 1.0) * Xi.y)); - float SinTheta = sqrt(1.0 - CosTheta * CosTheta); - - // Convert to spherical direction - vec3 H; - H.x = SinTheta * cos(Phi); - H.y = SinTheta * sin(Phi); - H.z = CosTheta; - - vec3 UpVector = abs(N.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(1.0, 0.0, 0.0); - vec3 TangentX = normalize(cross(UpVector, N)); - vec3 TangentY = cross(N, TangentX); - - // Tangent to world space - return TangentX * H.x + TangentY * H.y + N * H.z; -} - -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float GGX(float NdotV, float a) { - float k = a / 2.0; - return NdotV / (NdotV * (1.0 - k) + k); -} - -// http://graphicrants.blogspot.com.au/2013/08/specular-brdf-reference.html -float G_Smith(float a, float nDotV, float nDotL) { - return GGX(nDotL, a * a) * GGX(nDotV, a * a); -} - -float radicalInverse_VdC(uint bits) { - bits = (bits << 16u) | (bits >> 16u); - bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u); - bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u); - bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u); - bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u); - return float(bits) * 2.3283064365386963e-10; // / 0x100000000 -} - -vec2 Hammersley(uint i, uint N) { - return vec2(float(i) / float(N), radicalInverse_VdC(i)); -} - -void main() { - uvec3 id = gl_GlobalInvocationID; - id.z += params.face_id; - - vec2 uv = ((vec2(id.xy) * 2.0 + 1.0) / (params.face_size) - 1.0); - vec3 N = texelCoordToVec(uv, id.z); - - //vec4 color = color_interp; - - if (params.use_direct_write) { - - imageStore(dest_cubemap, ivec3(id), vec4(texture(source_cube, N).rgb, 1.0)); - } else { - - vec4 sum = vec4(0.0, 0.0, 0.0, 0.0); - - for (uint sampleNum = 0u; sampleNum < params.sample_count; sampleNum++) { - vec2 xi = Hammersley(sampleNum, params.sample_count); - - vec3 H = ImportanceSampleGGX(xi, params.roughness, N); - vec3 V = N; - vec3 L = (2.0 * dot(V, H) * H - V); - - float ndotl = clamp(dot(N, L), 0.0, 1.0); - - if (ndotl > 0.0) { - - sum.rgb += textureLod(source_cube, L, 0.0).rgb * ndotl; - sum.a += ndotl; - } - } - sum /= sum.a; - - imageStore(dest_cubemap, ivec3(id), vec4(sum.rgb, 1.0)); - } -} diff --git a/servers/visual/rasterizer_rd/shaders/giprobe.glsl b/servers/visual/rasterizer_rd/shaders/giprobe.glsl deleted file mode 100644 index fd09f96a57..0000000000 --- a/servers/visual/rasterizer_rd/shaders/giprobe.glsl +++ /dev/null @@ -1,788 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -#ifdef MODE_DYNAMIC -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -#else -layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; -#endif -/* clang-format on */ - -#ifndef MODE_DYNAMIC - -#define NO_CHILDREN 0xFFFFFFFF -#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) - -struct CellChildren { - uint children[8]; -}; - -layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { - CellChildren data[]; -} -cell_children; - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; - -layout(set = 0, binding = 2, std430) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -#endif // MODE DYNAMIC - -#define LIGHT_TYPE_DIRECTIONAL 0 -#define LIGHT_TYPE_OMNI 1 -#define LIGHT_TYPE_SPOT 2 - -#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) - -struct Light { - - uint type; - float energy; - float radius; - float attenuation; - - vec3 color; - float spot_angle_radians; - - vec3 position; - float spot_attenuation; - - vec3 direction; - bool has_shadow; -}; - -layout(set = 0, binding = 3, std140) uniform Lights { - Light data[MAX_LIGHTS]; -} -lights; - -#endif // MODE COMPUTE LIGHT - -#ifdef MODE_SECOND_BOUNCE - -layout(set = 0, binding = 5) uniform texture3D color_texture; - -#ifdef MODE_ANISOTROPIC -layout(set = 0, binding = 7) uniform texture3D aniso_pos_texture; -layout(set = 0, binding = 8) uniform texture3D aniso_neg_texture; -#endif // MODE ANISOTROPIC - -#endif // MODE_SECOND_BOUNCE - -#ifndef MODE_DYNAMIC - -layout(push_constant, binding = 0, std430) uniform Params { - ivec3 limits; - uint stack_size; - - float emission_scale; - float propagation; - float dynamic_range; - - uint light_count; - uint cell_offset; - uint cell_count; - float aniso_strength; - uint pad; -} -params; - -layout(set = 0, binding = 4, std430) buffer Outputs { - vec4 data[]; -} -outputs; - -#endif // MODE DYNAMIC - -layout(set = 0, binding = 9) uniform texture3D texture_sdf; -layout(set = 0, binding = 10) uniform sampler texture_sampler; - -#ifdef MODE_WRITE_TEXTURE - -layout(rgba8, set = 0, binding = 5) uniform restrict writeonly image3D color_tex; - -#ifdef MODE_ANISOTROPIC - -layout(r16ui, set = 0, binding = 6) uniform restrict writeonly uimage3D aniso_pos_tex; -layout(r16ui, set = 0, binding = 7) uniform restrict writeonly uimage3D aniso_neg_tex; - -#endif - -#endif - -#ifdef MODE_DYNAMIC - -layout(push_constant, binding = 0, std430) uniform Params { - ivec3 limits; - uint light_count; //when not lighting - ivec3 x_dir; - float z_base; - ivec3 y_dir; - float z_sign; - ivec3 z_dir; - float pos_multiplier; - ivec2 rect_pos; - ivec2 rect_size; - ivec2 prev_rect_ofs; - ivec2 prev_rect_size; - bool flip_x; - bool flip_y; - float dynamic_range; - bool on_mipmap; - float propagation; - float pad[3]; -} -params; - -#ifdef MODE_DYNAMIC_LIGHTING - -layout(rgba8, set = 0, binding = 5) uniform restrict readonly image2D source_albedo; -layout(rgba8, set = 0, binding = 6) uniform restrict readonly image2D source_normal; -layout(rgba8, set = 0, binding = 7) uniform restrict readonly image2D source_orm; -//layout (set=0,binding=8) uniform texture2D source_depth; -layout(rgba16f, set = 0, binding = 11) uniform restrict image2D emission; -layout(r32f, set = 0, binding = 12) uniform restrict image2D depth; - -#endif - -#ifdef MODE_DYNAMIC_SHRINK - -layout(rgba16f, set = 0, binding = 5) uniform restrict readonly image2D source_light; -layout(r32f, set = 0, binding = 6) uniform restrict readonly image2D source_depth; - -#ifdef MODE_DYNAMIC_SHRINK_WRITE - -layout(rgba16f, set = 0, binding = 7) uniform restrict writeonly image2D light; -layout(r32f, set = 0, binding = 8) uniform restrict writeonly image2D depth; - -#endif // MODE_DYNAMIC_SHRINK_WRITE - -#ifdef MODE_DYNAMIC_SHRINK_PLOT - -layout(rgba8, set = 0, binding = 11) uniform restrict image3D color_texture; - -#ifdef MODE_ANISOTROPIC - -layout(r16ui, set = 0, binding = 12) uniform restrict writeonly uimage3D aniso_pos_texture; -layout(r16ui, set = 0, binding = 13) uniform restrict writeonly uimage3D aniso_neg_texture; - -#endif // MODE ANISOTROPIC - -#endif //MODE_DYNAMIC_SHRINK_PLOT - -#endif // MODE_DYNAMIC_SHRINK - -//layout (rgba8,set=0,binding=5) uniform restrict writeonly image3D color_tex; - -#endif // MODE DYNAMIC - -#if defined(MODE_COMPUTE_LIGHT) || defined(MODE_DYNAMIC_LIGHTING) - -float raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { - - vec3 cell_size = 1.0 / vec3(params.limits); - float occlusion = 1.0; - while (distance > 0.5) { //use this to avoid precision errors - float advance = texture(sampler3D(texture_sdf, texture_sampler), from * cell_size).r * 255.0 - 1.0; - if (advance < 0.0) { - occlusion = 0.0; - break; - } - - occlusion = min(advance, occlusion); - - advance = max(distance_adv, advance - mod(advance, distance_adv)); //should always advance in multiples of distance_adv - - from += direction * advance; - distance -= advance; - } - - return occlusion; //max(0.0,distance); -} - -bool compute_light_vector(uint light, vec3 pos, out float attenuation, out vec3 light_pos) { - - if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { - - light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); - attenuation = 1.0; - - } else { - - light_pos = lights.data[light].position; - float distance = length(pos - light_pos); - if (distance >= lights.data[light].radius) { - return false; - } - - attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation); - - if (lights.data[light].type == LIGHT_TYPE_SPOT) { - - vec3 rel = normalize(pos - light_pos); - float angle = acos(dot(rel, lights.data[light].direction)); - if (angle > lights.data[light].spot_angle_radians) { - return false; - } - - float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1); - attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation); - } - } - - return true; -} - -float get_normal_advance(vec3 p_normal) { - - vec3 normal = p_normal; - vec3 unorm = abs(normal); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = vec3(1.0, 0.0, 0.0); - } - - return 1.0 / dot(normal, unorm); -} - -void clip_segment(vec4 plane, vec3 begin, inout vec3 end) { - - vec3 segment = begin - end; - float den = dot(plane.xyz, segment); - - //printf("den is %i\n",den); - if (den < 0.0001) { - return; - } - - float dist = (dot(plane.xyz, begin) - plane.w) / den; - - if (dist < 0.0001 || dist > 1.0001) { - return; - } - - end = begin + segment * -dist; -} - -bool compute_light_at_pos(uint index, vec3 pos, vec3 normal, inout vec3 light, inout vec3 light_dir) { - float attenuation; - vec3 light_pos; - - if (!compute_light_vector(index, pos, attenuation, light_pos)) { - return false; - } - - light_dir = normalize(pos - light_pos); - - if (attenuation < 0.01 || (length(normal) > 0.2 && dot(normal, light_dir) >= 0)) { - return false; //not facing the light, or attenuation is near zero - } - - if (lights.data[index].has_shadow) { - - float distance_adv = get_normal_advance(light_dir); - - vec3 to = pos; - if (length(normal) > 0.2) { - to += normal * distance_adv * 0.51; - } else { - to -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion - } - - //clip - clip_segment(mix(vec4(-1.0, 0.0, 0.0, 0.0), vec4(1.0, 0.0, 0.0, float(params.limits.x - 1)), bvec4(light_dir.x < 0.0)), to, light_pos); - clip_segment(mix(vec4(0.0, -1.0, 0.0, 0.0), vec4(0.0, 1.0, 0.0, float(params.limits.y - 1)), bvec4(light_dir.y < 0.0)), to, light_pos); - clip_segment(mix(vec4(0.0, 0.0, -1.0, 0.0), vec4(0.0, 0.0, 1.0, float(params.limits.z - 1)), bvec4(light_dir.z < 0.0)), to, light_pos); - - float distance = length(to - light_pos); - if (distance < 0.1) { - return false; // hit - } - - distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always - light_pos = to - light_dir * distance; - - //from -= sign(light_dir)*0.45; //go near the edge towards the light direction to avoid self occlusion - - /*float dist = raymarch(distance,distance_adv,light_pos,light_dir); - - if (dist > distance_adv) { - return false; - } - - attenuation *= 1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); - */ - - float occlusion = raymarch(distance, distance_adv, light_pos, light_dir); - - if (occlusion == 0.0) { - return false; - } - - attenuation *= occlusion; //1.0 - smoothstep(0.1*distance_adv,distance_adv,dist); - } - - light = lights.data[index].color * attenuation * lights.data[index].energy; - return true; -} - -#endif // MODE COMPUTE LIGHT - -void main() { - -#ifndef MODE_DYNAMIC - - uint cell_index = gl_GlobalInvocationID.x; - if (cell_index >= params.cell_count) { - return; - } - cell_index += params.cell_offset; - - uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); - vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo); - -#endif - - /////////////////COMPUTE LIGHT/////////////////////////////// - -#ifdef MODE_COMPUTE_LIGHT - - vec3 pos = vec3(posu) + vec3(0.5); - - vec3 emission = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); - vec3 normal = unpackSnorm4x8(cell_data.data[cell_index].normal).xyz; - -#ifdef MODE_ANISOTROPIC - vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); -#else - vec3 accum = vec3(0.0); -#endif - - for (uint i = 0; i < params.light_count; i++) { - - vec3 light; - vec3 light_dir; - if (!compute_light_at_pos(i, pos, normal.xyz, light, light_dir)) { - continue; - } - - light *= albedo.rgb; - -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - - accum[j] += max(0.0, dot(accum_dirs[j], -light_dir)) * light; - } -#else - if (length(normal) > 0.2) { - accum += max(0.0, dot(normal, -light_dir)) * light; - } else { - //all directions - accum += light; - } -#endif - } - -#ifdef MODE_ANISOTROPIC - - for (uint i = 0; i < 6; i++) { - vec3 light = accum[i]; - if (length(normal) > 0.2) { - light += max(0.0, dot(accum_dirs[i], -normal)) * emission; - } else { - light += emission; - } - - outputs.data[cell_index * 6 + i] = vec4(light, 0.0); - } - -#else - outputs.data[cell_index] = vec4(accum + emission, 0.0); - -#endif - -#endif //MODE_COMPUTE_LIGHT - - /////////////////SECOND BOUNCE/////////////////////////////// - -#ifdef MODE_SECOND_BOUNCE - vec3 pos = vec3(posu) + vec3(0.5); - ivec3 ipos = ivec3(posu); - vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); - -#ifdef MODE_ANISOTROPIC - vec3 accum[6]; - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); - - /*vec3 src_color = texelFetch(sampler3D(color_texture,texture_sampler),ipos,0).rgb * params.dynamic_range; - vec3 src_aniso_pos = texelFetch(sampler3D(aniso_pos_texture,texture_sampler),ipos,0).rgb; - vec3 src_anisp_neg = texelFetch(sampler3D(anisp_neg_texture,texture_sampler),ipos,0).rgb; - accum[0]=src_col * src_aniso_pos.x; - accum[1]=src_col * src_aniso_neg.x; - accum[2]=src_col * src_aniso_pos.y; - accum[3]=src_col * src_aniso_neg.y; - accum[4]=src_col * src_aniso_pos.z; - accum[5]=src_col * src_aniso_neg.z;*/ - - accum[0] = outputs.data[cell_index * 6 + 0].rgb; - accum[1] = outputs.data[cell_index * 6 + 1].rgb; - accum[2] = outputs.data[cell_index * 6 + 2].rgb; - accum[3] = outputs.data[cell_index * 6 + 3].rgb; - accum[4] = outputs.data[cell_index * 6 + 4].rgb; - accum[5] = outputs.data[cell_index * 6 + 5].rgb; - -#else - vec3 accum = outputs.data[cell_index].rgb; - -#endif - - if (length(normal.xyz) > 0.2) { - - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal.xyz)); - vec3 bitangent = normalize(cross(tangent, normal.xyz)); - mat3 normal_mat = mat3(tangent, bitangent, normal.xyz); - -#define MAX_CONE_DIRS 6 - - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); - float tan_half_angle = 0.577; - - for (int i = 0; i < MAX_CONE_DIRS; i++) { - - vec3 direction = normal_mat * cone_dirs[i]; - vec4 color = vec4(0.0); - { - - float dist = 1.5; - float max_distance = length(vec3(params.limits)); - vec3 cell_size = 1.0 / vec3(params.limits); - -#ifdef MODE_ANISOTROPIC - vec3 aniso_normal = mix(direction, normal.xyz, params.aniso_strength); -#endif - while (dist < max_distance && color.a < 0.95) { - float diameter = max(1.0, 2.0 * tan_half_angle * dist); - vec3 uvw_pos = (pos + dist * direction) * cell_size; - float half_diameter = diameter * 0.5; - //check if outside, then break - //if ( any(greaterThan(abs(uvw_pos - 0.5),vec3(0.5f + half_diameter * cell_size)) ) ) { - // break; - //} - - float log2_diameter = log2(diameter); - vec4 scolor = textureLod(sampler3D(color_texture, texture_sampler), uvw_pos, log2_diameter); -#ifdef MODE_ANISOTROPIC - - vec3 aniso_neg = textureLod(sampler3D(aniso_neg_texture, texture_sampler), uvw_pos, log2_diameter).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos_texture, texture_sampler), uvw_pos, log2_diameter).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (aniso_normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-aniso_normal * aniso_neg)), vec3(1.0)); -#endif - float a = (1.0 - color.a); - color += a * scolor; - dist += half_diameter; - } - } - color *= cone_weights[i] * vec4(albedo.rgb, 1.0) * params.dynamic_range; //restore range -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - - accum[j] += max(0.0, dot(accum_dirs[j], direction)) * color.rgb; - } -#else - accum += color.rgb; -#endif - } - } - -#ifdef MODE_ANISOTROPIC - - outputs.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); - outputs.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); - outputs.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); - outputs.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); - outputs.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); - outputs.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); -#else - outputs.data[cell_index] = vec4(accum, 0.0); - -#endif - -#endif // MODE_SECOND_BOUNCE - - /////////////////UPDATE MIPMAPS/////////////////////////////// - -#ifdef MODE_UPDATE_MIPMAPS - - { -#ifdef MODE_ANISOTROPIC - vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); -#else - vec3 light_accum = vec3(0.0); -#endif - float count = 0.0; - for (uint i = 0; i < 8; i++) { - uint child_index = cell_children.data[cell_index].children[i]; - if (child_index == NO_CHILDREN) { - continue; - } -#ifdef MODE_ANISOTROPIC - light_accum[0] += outputs.data[child_index * 6 + 0].rgb; - light_accum[1] += outputs.data[child_index * 6 + 1].rgb; - light_accum[2] += outputs.data[child_index * 6 + 2].rgb; - light_accum[3] += outputs.data[child_index * 6 + 3].rgb; - light_accum[4] += outputs.data[child_index * 6 + 4].rgb; - light_accum[5] += outputs.data[child_index * 6 + 5].rgb; - -#else - light_accum += outputs.data[child_index].rgb; - -#endif - - count += 1.0; - } - - float divisor = mix(8.0, count, params.propagation); -#ifdef MODE_ANISOTROPIC - outputs.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); - outputs.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); - outputs.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); - outputs.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); - outputs.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); - outputs.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); - -#else - outputs.data[cell_index] = vec4(light_accum / divisor, 0.0); -#endif - } -#endif - - ///////////////////WRITE TEXTURE///////////////////////////// - -#ifdef MODE_WRITE_TEXTURE - { - -#ifdef MODE_ANISOTROPIC - vec3 accum_total = vec3(0.0); - accum_total += outputs.data[cell_index * 6 + 0].rgb; - accum_total += outputs.data[cell_index * 6 + 1].rgb; - accum_total += outputs.data[cell_index * 6 + 2].rgb; - accum_total += outputs.data[cell_index * 6 + 3].rgb; - accum_total += outputs.data[cell_index * 6 + 4].rgb; - accum_total += outputs.data[cell_index * 6 + 5].rgb; - - float accum_total_energy = max(dot(accum_total, GREY_VEC), 0.00001); - vec3 iso_positive = vec3(dot(outputs.data[cell_index * 6 + 0].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 2].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 4].rgb, GREY_VEC)) / vec3(accum_total_energy); - vec3 iso_negative = vec3(dot(outputs.data[cell_index * 6 + 1].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 3].rgb, GREY_VEC), dot(outputs.data[cell_index * 6 + 5].rgb, GREY_VEC)) / vec3(accum_total_energy); - - { - uint aniso_pos = uint(clamp(iso_positive.b * 31.0, 0.0, 31.0)); - aniso_pos |= uint(clamp(iso_positive.g * 63.0, 0.0, 63.0)) << 5; - aniso_pos |= uint(clamp(iso_positive.r * 31.0, 0.0, 31.0)) << 11; - imageStore(aniso_pos_tex, ivec3(posu), uvec4(aniso_pos)); - } - - { - uint aniso_neg = uint(clamp(iso_negative.b * 31.0, 0.0, 31.0)); - aniso_neg |= uint(clamp(iso_negative.g * 63.0, 0.0, 63.0)) << 5; - aniso_neg |= uint(clamp(iso_negative.r * 31.0, 0.0, 31.0)) << 11; - imageStore(aniso_neg_tex, ivec3(posu), uvec4(aniso_neg)); - } - - imageStore(color_tex, ivec3(posu), vec4(accum_total / params.dynamic_range, albedo.a)); - -#else - - imageStore(color_tex, ivec3(posu), vec4(outputs.data[cell_index].rgb / params.dynamic_range, albedo.a)); - -#endif - } -#endif - - ///////////////////DYNAMIC LIGHTING///////////////////////////// - -#ifdef MODE_DYNAMIC - - ivec2 pos_xy = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThanEqual(pos_xy, params.rect_size))) { - return; //out of bounds - } - - ivec2 uv_xy = pos_xy; - if (params.flip_x) { - uv_xy.x = params.rect_size.x - pos_xy.x - 1; - } - if (params.flip_y) { - uv_xy.y = params.rect_size.y - pos_xy.y - 1; - } - -#ifdef MODE_DYNAMIC_LIGHTING - - { - float z = params.z_base + imageLoad(depth, uv_xy).x * params.z_sign; - - ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(z); - - vec3 normal = imageLoad(source_normal, uv_xy).xyz * 2.0 - 1.0; - normal = vec3(params.x_dir) * normal.x * mix(1.0, -1.0, params.flip_x) + vec3(params.y_dir) * normal.y * mix(1.0, -1.0, params.flip_y) - vec3(params.z_dir) * normal.z; - - vec4 albedo = imageLoad(source_albedo, uv_xy); - - //determine the position in space - - vec3 accum = vec3(0.0); - for (uint i = 0; i < params.light_count; i++) { - - vec3 light; - vec3 light_dir; - if (!compute_light_at_pos(i, vec3(pos) * params.pos_multiplier, normal, light, light_dir)) { - continue; - } - - light *= albedo.rgb; - - accum += max(0.0, dot(normal, -light_dir)) * light; - } - - accum += imageLoad(emission, uv_xy).xyz; - - imageStore(emission, uv_xy, vec4(accum, albedo.a)); - imageStore(depth, uv_xy, vec4(z)); - } - -#endif // MODE DYNAMIC LIGHTING - -#ifdef MODE_DYNAMIC_SHRINK - - { - vec4 accum = vec4(0.0); - float accum_z = 0.0; - float count = 0.0; - - for (int i = 0; i < 4; i++) { - ivec2 ofs = pos_xy * 2 + ivec2(i & 1, i >> 1) - params.prev_rect_ofs; - if (any(lessThan(ofs, ivec2(0))) || any(greaterThanEqual(ofs, params.prev_rect_size))) { - continue; - } - if (params.flip_x) { - ofs.x = params.prev_rect_size.x - ofs.x - 1; - } - if (params.flip_y) { - ofs.y = params.prev_rect_size.y - ofs.y - 1; - } - - vec4 light = imageLoad(source_light, ofs); - if (light.a == 0.0) { //ignore empty - continue; - } - accum += light; - float z = imageLoad(source_depth, ofs).x; - accum_z += z * 0.5; //shrink half too - count += 1.0; - } - - if (params.on_mipmap) { - accum.rgb /= mix(8.0, count, params.propagation); - accum.a /= 8.0; - } else { - accum /= 4.0; - } - - if (count == 0.0) { - accum_z = 0.0; //avoid nan - } else { - accum_z /= count; - } - -#ifdef MODE_DYNAMIC_SHRINK_WRITE - - imageStore(light, uv_xy, accum); - imageStore(depth, uv_xy, vec4(accum_z)); -#endif - -#ifdef MODE_DYNAMIC_SHRINK_PLOT - - if (accum.a < 0.001) { - return; //do not blit if alpha is too low - } - - ivec3 pos = params.x_dir * (params.rect_pos.x + pos_xy.x) + params.y_dir * (params.rect_pos.y + pos_xy.y) + abs(params.z_dir) * int(accum_z); - - float z_frac = fract(accum_z); - - for (int i = 0; i < 2; i++) { - ivec3 pos3d = pos + abs(params.z_dir) * i; - if (any(lessThan(pos3d, ivec3(0))) || any(greaterThanEqual(pos3d, params.limits))) { - //skip if offlimits - continue; - } - vec4 color_blit = accum * (i == 0 ? 1.0 - z_frac : z_frac); - vec4 color = imageLoad(color_texture, pos3d); - color.rgb *= params.dynamic_range; - -#if 0 - color.rgb = mix(color.rgb,color_blit.rgb,color_blit.a); - color.a+=color_blit.a; -#else - - float sa = 1.0 - color_blit.a; - vec4 result; - result.a = color.a * sa + color_blit.a; - if (result.a == 0.0) { - result = vec4(0.0); - } else { - result.rgb = (color.rgb * color.a * sa + color_blit.rgb * color_blit.a) / result.a; - color = result; - } - -#endif - color.rgb /= params.dynamic_range; - imageStore(color_texture, pos3d, color); - //imageStore(color_texture,pos3d,vec4(1,1,1,1)); - -#ifdef MODE_ANISOTROPIC - //do not care about anisotropy for dynamic objects, just store full lit in all directions - imageStore(aniso_pos_texture, pos3d, uvec4(0xFFFF)); - imageStore(aniso_neg_texture, pos3d, uvec4(0xFFFF)); - -#endif // ANISOTROPIC - } -#endif // MODE_DYNAMIC_SHRINK_PLOT - } -#endif - -#endif // MODE DYNAMIC -} diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl deleted file mode 100644 index b1784e7eee..0000000000 --- a/servers/visual/rasterizer_rd/shaders/giprobe_debug.glsl +++ /dev/null @@ -1,208 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; -/* clang-format on */ - -layout(set = 0, binding = 1, std140) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -layout(set = 0, binding = 2) uniform texture3D color_tex; - -layout(set = 0, binding = 3) uniform sampler tex_sampler; - -#ifdef USE_ANISOTROPY -layout(set = 0, binding = 4) uniform texture3D aniso_pos_tex; -layout(set = 0, binding = 5) uniform texture3D aniso_neg_tex; -#endif - -layout(push_constant, binding = 0, std430) uniform Params { - - mat4 projection; - uint cell_offset; - float dynamic_range; - float alpha; - uint level; - ivec3 bounds; - uint pad; -} -params; - -layout(location = 0) out vec4 color_interp; - -void main() { - - const vec3 cube_triangles[36] = vec3[]( - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, -1.0f, 1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(-1.0f, -1.0f, 1.0f), - vec3(-1.0f, -1.0f, -1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(-1.0f, -1.0f, 1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(1.0f, -1.0f, -1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(1.0f, -1.0f, 1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(1.0f, 1.0f, -1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(-1.0f, 1.0f, -1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(1.0f, 1.0f, 1.0f), - vec3(-1.0f, 1.0f, 1.0f), - vec3(1.0f, -1.0f, 1.0f)); - - vec3 vertex = cube_triangles[gl_VertexIndex] * 0.5 + 0.5; -#ifdef MODE_DEBUG_LIGHT_FULL - uvec3 posu = uvec3(gl_InstanceIndex % params.bounds.x, (gl_InstanceIndex / params.bounds.x) % params.bounds.y, gl_InstanceIndex / (params.bounds.y * params.bounds.x)); -#else - uint cell_index = gl_InstanceIndex + params.cell_offset; - - uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); -#endif - -#ifdef MODE_DEBUG_EMISSION - color_interp.xyz = vec3(uvec3(cell_data.data[cell_index].emission & 0x1ff, (cell_data.data[cell_index].emission >> 9) & 0x1ff, (cell_data.data[cell_index].emission >> 18) & 0x1ff)) * pow(2.0, float(cell_data.data[cell_index].emission >> 27) - 15.0 - 9.0); -#endif - -#ifdef MODE_DEBUG_COLOR - color_interp.xyz = unpackUnorm4x8(cell_data.data[cell_index].albedo).xyz; -#endif - -#ifdef MODE_DEBUG_LIGHT - -#ifdef USE_ANISOTROPY - -#define POS_X 0 -#define POS_Y 1 -#define POS_Z 2 -#define NEG_X 3 -#define NEG_Y 4 -#define NEG_Z 5 - - const uint triangle_aniso[12] = uint[]( - NEG_X, - NEG_Z, - NEG_Y, - NEG_Z, - NEG_X, - NEG_Y, - POS_Z, - POS_X, - POS_X, - POS_Y, - POS_Y, - POS_Z); - - color_interp.xyz = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)).xyz * params.dynamic_range; - vec3 aniso_pos = texelFetch(sampler3D(aniso_pos_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; - vec3 aniso_neg = texelFetch(sampler3D(aniso_neg_tex, tex_sampler), ivec3(posu), int(params.level)).xyz; - uint side = triangle_aniso[gl_VertexIndex / 3]; - - float strength = 0.0; - switch (side) { - case POS_X: strength = aniso_pos.x; break; - case POS_Y: strength = aniso_pos.y; break; - case POS_Z: strength = aniso_pos.z; break; - case NEG_X: strength = aniso_neg.x; break; - case NEG_Y: strength = aniso_neg.y; break; - case NEG_Z: strength = aniso_neg.z; break; - } - - color_interp.xyz *= strength; - -#else - color_interp = texelFetch(sampler3D(color_tex, tex_sampler), ivec3(posu), int(params.level)); - color_interp.xyz *params.dynamic_range; - -#endif - -#endif - float scale = (1 << params.level); - - gl_Position = params.projection * vec4((vec3(posu) + vertex) * scale, 1.0); - -#ifdef MODE_DEBUG_LIGHT_FULL - if (color_interp.a == 0.0) { - gl_Position = vec4(0.0); //force clip and not draw - } -#else - color_interp.a = params.alpha; -#endif -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -layout(location = 0) in vec4 color_interp; -/* clang-format on */ -layout(location = 0) out vec4 frag_color; - -void main() { - - frag_color = color_interp; - -#ifdef MODE_DEBUG_LIGHT_FULL - - //there really is no alpha, so use dither - - int x = int(gl_FragCoord.x) % 4; - int y = int(gl_FragCoord.y) % 4; - int index = x + y * 4; - float limit = 0.0; - if (x < 8) { - if (index == 0) limit = 0.0625; - if (index == 1) limit = 0.5625; - if (index == 2) limit = 0.1875; - if (index == 3) limit = 0.6875; - if (index == 4) limit = 0.8125; - if (index == 5) limit = 0.3125; - if (index == 6) limit = 0.9375; - if (index == 7) limit = 0.4375; - if (index == 8) limit = 0.25; - if (index == 9) limit = 0.75; - if (index == 10) limit = 0.125; - if (index == 11) limit = 0.625; - if (index == 12) limit = 1.0; - if (index == 13) limit = 0.5; - if (index == 14) limit = 0.875; - if (index == 15) limit = 0.375; - } - if (frag_color.a < limit) { - discard; - } -#endif -} diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl deleted file mode 100644 index d089236723..0000000000 --- a/servers/visual/rasterizer_rd/shaders/giprobe_sdf.glsl +++ /dev/null @@ -1,187 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 4, local_size_y = 4, local_size_z = 4) in; -/* clang-format on */ - -#define MAX_DISTANCE 100000 - -#define NO_CHILDREN 0xFFFFFFFF -#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) - -struct CellChildren { - uint children[8]; -}; - -layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { - CellChildren data[]; -} -cell_children; - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; - -layout(set = 0, binding = 2, std430) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -layout(r8ui, set = 0, binding = 3) uniform restrict writeonly uimage3D sdf_tex; - -layout(push_constant, binding = 0, std430) uniform Params { - uint offset; - uint end; - uint pad0; - uint pad1; -} -params; - -void main() { - - vec3 pos = vec3(gl_GlobalInvocationID); - float closest_dist = 100000.0; - - for (uint i = params.offset; i < params.end; i++) { - vec3 posu = vec3(uvec3(cell_data.data[i].position & 0x7FF, (cell_data.data[i].position >> 11) & 0x3FF, cell_data.data[i].position >> 21)); - float dist = length(pos - posu); - if (dist < closest_dist) { - closest_dist = dist; - } - } - - uint dist_8; - - if (closest_dist < 0.0001) { // same cell - dist_8 = 0; //equals to -1 - } else { - dist_8 = clamp(uint(closest_dist), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid - } - - imageStore(sdf_tex, ivec3(gl_GlobalInvocationID), uvec4(dist_8)); - //imageStore(sdf_tex,pos,uvec4(pos*2,0)); -} - -#if 0 -layout(push_constant, binding = 0, std430) uniform Params { - - ivec3 limits; - uint stack_size; -} params; - -float distance_to_aabb(ivec3 pos, ivec3 aabb_pos, ivec3 aabb_size) { - - vec3 delta = vec3(max(ivec3(0), max(aabb_pos - pos, pos - (aabb_pos + aabb_size - ivec3(1))))); - return length(delta); -} - -void main() { - - ivec3 pos = ivec3(gl_GlobalInvocationID); - - uint stack[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - uint stack_indices[10] = uint[](0, 0, 0, 0, 0, 0, 0, 0, 0, 0); - ivec3 stack_positions[10] = ivec3[](ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0), ivec3(0)); - - const uint cell_orders[8] = uint[]( - 0x11f58d1, - 0xe2e70a, - 0xd47463, - 0xbb829c, - 0x8d11f5, - 0x70ae2e, - 0x463d47, - 0x29cbb8); - - bool cell_found = false; - bool cell_found_exact = false; - ivec3 closest_cell_pos; - float closest_distance = MAX_DISTANCE; - int stack_pos = 0; - - while (true) { - - uint index = stack_indices[stack_pos] >> 24; - - if (index == 8) { - //go up - if (stack_pos == 0) { - break; //done going through octree - } - stack_pos--; - continue; - } - - stack_indices[stack_pos] = (stack_indices[stack_pos] & ((1 << 24) - 1)) | ((index + 1) << 24); - - uint cell_index = (stack_indices[stack_pos] >> (index * 3)) & 0x7; - uint child_cell = cell_children.data[stack[stack_pos]].children[cell_index]; - - if (child_cell == NO_CHILDREN) { - continue; - } - - ivec3 child_cell_size = params.limits >> (stack_pos + 1); - ivec3 child_cell_pos = stack_positions[stack_pos]; - - child_cell_pos += mix(ivec3(0), child_cell_size, bvec3(uvec3(index & 1, index & 2, index & 4) != uvec3(0))); - - bool is_leaf = stack_pos == (params.stack_size - 2); - - if (child_cell_pos == pos && is_leaf) { - //we may actually end up in the exact cell. - //if this happens, just abort - cell_found_exact = true; - break; - } - - if (cell_found) { - //discard by distance - float distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); - if (distance >= closest_distance) { - continue; //pointless, just test next child - } else if (is_leaf) { - //closer than what we have AND end of stack, save and continue - closest_cell_pos = child_cell_pos; - closest_distance = distance; - continue; - } - } else if (is_leaf) { - //first solid cell we find, save and continue - closest_distance = distance_to_aabb(pos, child_cell_pos, child_cell_size); - closest_cell_pos = child_cell_pos; - cell_found = true; - continue; - } - - bvec3 direction = greaterThan((pos - (child_cell_pos + (child_cell_size >> 1))), ivec3(0)); - uint cell_order = 0; - cell_order |= mix(0, 1, direction.x); - cell_order |= mix(0, 2, direction.y); - cell_order |= mix(0, 4, direction.z); - - stack[stack_pos + 1] = child_cell; - stack_indices[stack_pos + 1] = cell_orders[cell_order]; //start counting - stack_positions[stack_pos + 1] = child_cell_pos; - stack_pos++; //go up stack - } - - uint dist_8; - - if (cell_found_exact) { - dist_8 = 0; //equals to -1 - } else { - float closest_distance = length(vec3(pos - closest_cell_pos)); - dist_8 = clamp(uint(closest_distance), 0, 254) + 1; //conservative, 0 is 1, so <1 is considered solid - } - - imageStore(sdf_tex, pos, uvec4(dist_8)); -} -#endif diff --git a/servers/visual/rasterizer_rd/shaders/giprobe_write.glsl b/servers/visual/rasterizer_rd/shaders/giprobe_write.glsl deleted file mode 100644 index c832223b1e..0000000000 --- a/servers/visual/rasterizer_rd/shaders/giprobe_write.glsl +++ /dev/null @@ -1,335 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 64, local_size_y = 1, local_size_z = 1) in; -/* clang-format on */ - -#define NO_CHILDREN 0xFFFFFFFF -#define GREY_VEC vec3(0.33333, 0.33333, 0.33333) - -struct CellChildren { - uint children[8]; -}; - -layout(set = 0, binding = 1, std430) buffer CellChildrenBuffer { - CellChildren data[]; -} -cell_children; - -struct CellData { - uint position; // xyz 10 bits - uint albedo; //rgb albedo - uint emission; //rgb normalized with e as multiplier - uint normal; //RGB normal encoded -}; - -layout(set = 0, binding = 2, std430) buffer CellDataBuffer { - CellData data[]; -} -cell_data; - -#define LIGHT_TYPE_DIRECTIONAL 0 -#define LIGHT_TYPE_OMNI 1 -#define LIGHT_TYPE_SPOT 2 - -#ifdef MODE_COMPUTE_LIGHT - -struct Light { - uint type; - float energy; - float radius; - float attenuation; - - vec3 color; - float spot_angle_radians; - - vec3 position; - float spot_attenuation; - - vec3 direction; - bool has_shadow; -}; - -layout(set = 0, binding = 3, std140) uniform Lights { - Light data[MAX_LIGHTS]; -} -lights; - -#endif - -layout(push_constant, binding = 0, std430) uniform Params { - ivec3 limits; - uint stack_size; - - float emission_scale; - float propagation; - float dynamic_range; - - uint light_count; - uint cell_offset; - uint cell_count; - uint pad[2]; -} -params; - -layout(set = 0, binding = 4, std140) uniform Outputs { - vec4 data[]; -} -output; - -#ifdef MODE_COMPUTE_LIGHT - -uint raymarch(float distance, float distance_adv, vec3 from, vec3 direction) { - - uint result = NO_CHILDREN; - - ivec3 size = ivec3(max(max(params.limits.x, params.limits.y), params.limits.z)); - - while (distance > -distance_adv) { //use this to avoid precision errors - - uint cell = 0; - - ivec3 pos = ivec3(from); - - if (all(greaterThanEqual(pos, ivec3(0))) && all(lessThan(pos, size))) { - - ivec3 ofs = ivec3(0); - ivec3 half_size = size / 2; - - for (int i = 0; i < params.stack_size - 1; i++) { - - bvec3 greater = greaterThanEqual(pos, ofs + half_size); - - ofs += mix(ivec3(0), half_size, greater); - - uint child = 0; //wonder if this can be done faster - if (greater.x) { - child |= 1; - } - if (greater.y) { - child |= 2; - } - if (greater.z) { - child |= 4; - } - - cell = cell_children.data[cell].children[child]; - if (cell == NO_CHILDREN) - break; - - half_size >>= ivec3(1); - } - - if (cell != NO_CHILDREN) { - return cell; //found cell! - } - } - - from += direction * distance_adv; - distance -= distance_adv; - } - - return NO_CHILDREN; -} - -bool compute_light_vector(uint light, uint cell, vec3 pos, out float attenuation, out vec3 light_pos) { - - if (lights.data[light].type == LIGHT_TYPE_DIRECTIONAL) { - - light_pos = pos - lights.data[light].direction * length(vec3(params.limits)); - attenuation = 1.0; - - } else { - - light_pos = lights.data[light].position; - float distance = length(pos - light_pos); - if (distance >= lights.data[light].radius) { - return false; - } - - attenuation = pow(clamp(1.0 - distance / lights.data[light].radius, 0.0001, 1.0), lights.data[light].attenuation); - - if (lights.data[light].type == LIGHT_TYPE_SPOT) { - - vec3 rel = normalize(pos - light_pos); - float angle = acos(dot(rel, lights.data[light].direction)); - if (angle > lights.data[light].spot_angle_radians) { - return false; - } - - float d = clamp(angle / lights.data[light].spot_angle_radians, 0, 1); - attenuation *= pow(1.0 - d, lights.data[light].spot_attenuation); - } - } - - return true; -} - -float get_normal_advance(vec3 p_normal) { - - vec3 normal = p_normal; - vec3 unorm = abs(normal); - - if ((unorm.x >= unorm.y) && (unorm.x >= unorm.z)) { - // x code - unorm = normal.x > 0.0 ? vec3(1.0, 0.0, 0.0) : vec3(-1.0, 0.0, 0.0); - } else if ((unorm.y > unorm.x) && (unorm.y >= unorm.z)) { - // y code - unorm = normal.y > 0.0 ? vec3(0.0, 1.0, 0.0) : vec3(0.0, -1.0, 0.0); - } else if ((unorm.z > unorm.x) && (unorm.z > unorm.y)) { - // z code - unorm = normal.z > 0.0 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 0.0, -1.0); - } else { - // oh-no we messed up code - // has to be - unorm = vec3(1.0, 0.0, 0.0); - } - - return 1.0 / dot(normal, unorm); -} - -#endif - -void main() { - - uint cell_index = gl_GlobalInvocationID.x; - if (cell_index >= params.cell_count) { - return; - } - cell_index += params.cell_offset; - - uvec3 posu = uvec3(cell_data.data[cell_index].position & 0x7FF, (cell_data.data[cell_index].position >> 11) & 0x3FF, cell_data.data[cell_index].position >> 21); - vec4 albedo = unpackUnorm4x8(cell_data.data[cell_index].albedo); - -#ifdef MODE_COMPUTE_LIGHT - - vec3 pos = vec3(posu) + vec3(0.5); - - vec3 emission = vec3(ivec3(cell_data.data[cell_index].emission & 0x3FF, (cell_data.data[cell_index].emission >> 10) & 0x7FF, cell_data.data[cell_index].emission >> 21)) * params.emission_scale; - vec4 normal = unpackSnorm4x8(cell_data.data[cell_index].normal); - -#ifdef MODE_ANISOTROPIC - vec3 accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); - const vec3 accum_dirs[6] = vec3[](vec3(1.0, 0.0, 0.0), vec3(-1.0, 0.0, 0.0), vec3(0.0, 1.0, 0.0), vec3(0.0, -1.0, 0.0), vec3(0.0, 0.0, 1.0), vec3(0.0, 0.0, -1.0)); -#else - vec3 accum = vec3(0.0); -#endif - - for (uint i = 0; i < params.light_count; i++) { - - float attenuation; - vec3 light_pos; - - if (!compute_light_vector(i, cell_index, pos, attenuation, light_pos)) { - continue; - } - - vec3 light_dir = pos - light_pos; - float distance = length(light_dir); - light_dir = normalize(light_dir); - - if (length(normal.xyz) > 0.2 && dot(normal.xyz, light_dir) >= 0) { - continue; //not facing the light - } - - if (lights.data[i].has_shadow) { - - float distance_adv = get_normal_advance(light_dir); - - distance += distance_adv - mod(distance, distance_adv); //make it reach the center of the box always - - vec3 from = pos - light_dir * distance; //approximate - from -= sign(light_dir) * 0.45; //go near the edge towards the light direction to avoid self occlusion - - uint result = raymarch(distance, distance_adv, from, light_dir); - - if (result != cell_index) { - continue; //was occluded - } - } - - vec3 light = lights.data[i].color * albedo.rgb * attenuation * lights.data[i].energy; - -#ifdef MODE_ANISOTROPIC - for (uint j = 0; j < 6; j++) { - accum[j] += max(0.0, dot(accum_dir, -light_dir)) * light + emission; - } -#else - if (length(normal.xyz) > 0.2) { - accum += max(0.0, dot(normal.xyz, -light_dir)) * light + emission; - } else { - //all directions - accum += light + emission; - } -#endif - } - -#ifdef MODE_ANISOTROPIC - - output.data[cell_index * 6 + 0] = vec4(accum[0], 0.0); - output.data[cell_index * 6 + 1] = vec4(accum[1], 0.0); - output.data[cell_index * 6 + 2] = vec4(accum[2], 0.0); - output.data[cell_index * 6 + 3] = vec4(accum[3], 0.0); - output.data[cell_index * 6 + 4] = vec4(accum[4], 0.0); - output.data[cell_index * 6 + 5] = vec4(accum[5], 0.0); -#else - output.data[cell_index] = vec4(accum, 0.0); - -#endif - -#endif //MODE_COMPUTE_LIGHT - -#ifdef MODE_UPDATE_MIPMAPS - - { -#ifdef MODE_ANISOTROPIC - vec3 light_accum[6] = vec3[](vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0)); -#else - vec3 light_accum = vec3(0.0); -#endif - float count = 0.0; - for (uint i = 0; i < 8; i++) { - uint child_index = cell_children.data[cell_index].children[i]; - if (child_index == NO_CHILDREN) { - continue; - } -#ifdef MODE_ANISOTROPIC - light_accum[1] += output.data[child_index * 6 + 0].rgb; - light_accum[2] += output.data[child_index * 6 + 1].rgb; - light_accum[3] += output.data[child_index * 6 + 2].rgb; - light_accum[4] += output.data[child_index * 6 + 3].rgb; - light_accum[5] += output.data[child_index * 6 + 4].rgb; - light_accum[6] += output.data[child_index * 6 + 5].rgb; - -#else - light_accum += output.data[child_index].rgb; - -#endif - - count += 1.0; - } - - float divisor = mix(8.0, count, params.propagation); -#ifdef MODE_ANISOTROPIC - output.data[cell_index * 6 + 0] = vec4(light_accum[0] / divisor, 0.0); - output.data[cell_index * 6 + 1] = vec4(light_accum[1] / divisor, 0.0); - output.data[cell_index * 6 + 2] = vec4(light_accum[2] / divisor, 0.0); - output.data[cell_index * 6 + 3] = vec4(light_accum[3] / divisor, 0.0); - output.data[cell_index * 6 + 4] = vec4(light_accum[4] / divisor, 0.0); - output.data[cell_index * 6 + 5] = vec4(light_accum[5] / divisor, 0.0); - -#else - output.data[cell_index] = vec4(light_accum / divisor, 0.0); -#endif - } -#endif - -#ifdef MODE_WRITE_TEXTURE - { - } -#endif -} diff --git a/servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl b/servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl deleted file mode 100644 index 4bf5b7e7f1..0000000000 --- a/servers/visual/rasterizer_rd/shaders/luminance_reduce.glsl +++ /dev/null @@ -1,87 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -#define BLOCK_SIZE 8 - -layout(local_size_x = BLOCK_SIZE, local_size_y = BLOCK_SIZE, local_size_z = 1) in; -/* clang-format on */ - -shared float tmp_data[BLOCK_SIZE * BLOCK_SIZE]; - -#ifdef READ_TEXTURE - -//use for main texture -layout(set = 0, binding = 0) uniform sampler2D source_texture; - -#else - -//use for intermediate textures -layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_luminance; - -#endif - -layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_luminance; - -#ifdef WRITE_LUMINANCE -layout(set = 2, binding = 0) uniform sampler2D prev_luminance; -#endif - -layout(push_constant, binding = 1, std430) uniform Params { - ivec2 source_size; - float max_luminance; - float min_luminance; - float exposure_adjust; - float pad[3]; -} -params; - -void main() { - - uint t = gl_LocalInvocationID.y * BLOCK_SIZE + gl_LocalInvocationID.x; - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - - if (any(lessThan(pos, params.source_size))) { - -#ifdef READ_TEXTURE - vec3 v = texelFetch(source_texture, pos, 0).rgb; - tmp_data[t] = max(v.r, max(v.g, v.b)); -#else - tmp_data[t] = imageLoad(source_luminance, pos).r; -#endif - } else { - tmp_data[t] = 0.0; - } - - groupMemoryBarrier(); - barrier(); - - uint size = (BLOCK_SIZE * BLOCK_SIZE) >> 1; - - do { - if (t < size) { - tmp_data[t] += tmp_data[t + size]; - } - groupMemoryBarrier(); - barrier(); - - size >>= 1; - - } while (size >= 1); - - if (t == 0) { - //compute rect size - ivec2 rect_size = min(params.source_size - pos, ivec2(BLOCK_SIZE)); - float avg = tmp_data[0] / float(rect_size.x * rect_size.y); - //float avg = tmp_data[0] / float(BLOCK_SIZE*BLOCK_SIZE); - pos /= ivec2(BLOCK_SIZE); -#ifdef WRITE_LUMINANCE - float prev_lum = texelFetch(prev_luminance, ivec2(0, 0), 0).r; //1 pixel previous exposure - avg = clamp(prev_lum + (avg - prev_lum) * params.exposure_adjust, params.min_luminance, params.max_luminance); -#endif - imageStore(dest_luminance, pos, vec4(avg)); - } -} diff --git a/servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl b/servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl deleted file mode 100644 index 3637b1abb2..0000000000 --- a/servers/visual/rasterizer_rd/shaders/roughness_limiter.glsl +++ /dev/null @@ -1,73 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform sampler2D source_normal; -layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_roughness; - -layout(push_constant, binding = 1, std430) uniform Params { - ivec2 screen_size; - float curve; - uint pad; -} -params; - -#define HALF_PI 1.5707963267948966 - -void main() { - - // Pixel being shaded - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(pos, params.screen_size))) { //too large, do nothing - return; - } - - vec3 normal_accum = vec3(0.0); - float accum = 0.0; - for (int i = 0; i <= 1; i++) { - for (int j = 0; j <= 1; j++) { - normal_accum += normalize(texelFetch(source_normal, pos + ivec2(i, j), 0).xyz * 2.0 - 1.0); - accum += 1.0; - } - } - - normal_accum /= accum; - - float r = length(normal_accum); - - float limit; - - if (r < 1.0) { - float threshold = 0.4; - - /* - //Formula from Filament, does not make sense to me. - - float r2 = r * r; - float kappa = (3.0f * r - r * r2) / (1.0f - r2); - float variance = 0.25f / kappa; - limit = sqrt(min(2.0f * variance, threshold * threshold)); -//*/ - /* - //Formula based on probability distribution graph - - float width = acos(max(0.0,r)); // convert to angle (width) - float roughness = pow(width,1.7)*0.854492; //approximate (crappy) formula to convert to roughness - limit = min(sqrt(roughness), threshold); //convert to perceptual roughness and apply threshold -//*/ - - limit = min(sqrt(pow(acos(max(0.0, r)) / HALF_PI, params.curve)), threshold); //convert to perceptual roughness and apply threshold - - //limit = 0.5; - } else { - limit = 0.0; - } - - imageStore(dest_roughness, pos, vec4(limit)); -} diff --git a/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl deleted file mode 100644 index 07f4770b14..0000000000 --- a/servers/visual/rasterizer_rd/shaders/scene_high_end.glsl +++ /dev/null @@ -1,1718 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -#include "scene_high_end_inc.glsl" - -/* INPUT ATTRIBS */ - -layout(location = 0) in vec3 vertex_attrib; -/* clang-format on */ -layout(location = 1) in vec3 normal_attrib; -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 2) in vec4 tangent_attrib; -#endif - -#if defined(COLOR_USED) -layout(location = 3) in vec4 color_attrib; -#endif - -#if defined(UV_USED) -layout(location = 4) in vec2 uv_attrib; -#endif - -#if defined(UV2_USED) || defined(USE_LIGHTMAP) -layout(location = 5) in vec2 uv2_attrib; -#endif - -layout(location = 6) in uvec4 bone_attrib; // always bound, even if unused - -/* Varyings */ - -layout(location = 0) out vec3 vertex_interp; -layout(location = 1) out vec3 normal_interp; - -#if defined(COLOR_USED) -layout(location = 2) out vec4 color_interp; -#endif - -#if defined(UV_USED) -layout(location = 3) out vec2 uv_interp; -#endif - -#if defined(UV2_USED) || defined(USE_LIGHTMAP) -layout(location = 4) out vec2 uv2_interp; -#endif - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 5) out vec3 tangent_interp; -layout(location = 6) out vec3 binormal_interp; -#endif - -#ifdef USE_MATERIAL_UNIFORMS -layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ -} material; -#endif - -/* clang-format off */ - -VERTEX_SHADER_GLOBALS - -/* clang-format on */ - -// FIXME: This triggers a Mesa bug that breaks rendering, so disabled for now. -// See GH-13450 and https://bugs.freedesktop.org/show_bug.cgi?id=100316 -invariant gl_Position; - -layout(location = 7) flat out uint instance_index; - -#ifdef MODE_DUAL_PARABOLOID - -layout(location = 8) out float dp_clip; - -#endif - -void main() { - - instance_index = draw_call.instance_index; - vec4 instance_custom = vec4(0.0); -#if defined(COLOR_USED) - color_interp = color_attrib; -#endif - - mat4 world_matrix = instances.data[instance_index].transform; - mat3 world_normal_matrix = mat3(instances.data[instance_index].normal_transform); - - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH)) { - //multimesh, instances are for it - uint offset = (instances.data[instance_index].flags >> INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT) & INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK; - offset *= gl_InstanceIndex; - - mat4 matrix; - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_FORMAT_2D)) { - matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], vec4(0.0, 0.0, 1.0, 0.0), vec4(0.0, 0.0, 0.0, 1.0)); - offset += 2; - } else { - matrix = mat4(transforms.data[offset + 0], transforms.data[offset + 1], transforms.data[offset + 2], vec4(0.0, 0.0, 0.0, 1.0)); - offset += 3; - } - - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_COLOR)) { -#ifdef COLOR_USED - color_interp *= transforms.data[offset]; -#endif - offset += 1; - } - - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA)) { - instance_custom = transforms.data[offset]; - } - - //transpose - matrix = transpose(matrix); - world_matrix = world_matrix * matrix; - world_normal_matrix = world_normal_matrix * mat3(matrix); - - } else { - //not a multimesh, instances are for multiple draw calls - instance_index += gl_InstanceIndex; - } - - vec3 vertex = vertex_attrib; - vec3 normal = normal_attrib; - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 tangent = tangent_attrib.xyz; - float binormalf = tangent_attrib.a; - vec3 binormal = normalize(cross(normal, tangent) * binormalf); -#endif - - if (bool(instances.data[instance_index].flags & INSTANCE_FLAGS_SKELETON)) { - //multimesh, instances are for it - - uvec2 bones_01 = uvec2(bone_attrib.x & 0xFFFF, bone_attrib.x >> 16) * 3; - uvec2 bones_23 = uvec2(bone_attrib.y & 0xFFFF, bone_attrib.y >> 16) * 3; - vec2 weights_01 = unpackUnorm2x16(bone_attrib.z); - vec2 weights_23 = unpackUnorm2x16(bone_attrib.w); - - mat4 m = mat4(transforms.data[bones_01.x], transforms.data[bones_01.x + 1], transforms.data[bones_01.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.x; - m += mat4(transforms.data[bones_01.y], transforms.data[bones_01.y + 1], transforms.data[bones_01.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_01.y; - m += mat4(transforms.data[bones_23.x], transforms.data[bones_23.x + 1], transforms.data[bones_23.x + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.x; - m += mat4(transforms.data[bones_23.y], transforms.data[bones_23.y + 1], transforms.data[bones_23.y + 2], vec4(0.0, 0.0, 0.0, 1.0)) * weights_23.y; - - //reverse order because its transposed - vertex = (vec4(vertex, 1.0) * m).xyz; - normal = (vec4(normal, 0.0) * m).xyz; - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - - tangent = (vec4(tangent, 0.0) * m).xyz; - binormal = (vec4(binormal, 0.0) * m).xyz; -#endif - } - -#if defined(UV_USED) - uv_interp = uv_attrib; -#endif - -#if defined(UV2_USED) || defined(USE_LIGHTMAP) - uv2_interp = uv2_attrib; -#endif - -#ifdef USE_OVERRIDE_POSITION - vec4 position; -#endif - - mat4 projection_matrix = scene_data.projection_matrix; - -//using world coordinates -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - - vertex = (world_matrix * vec4(vertex, 1.0)).xyz; - - normal = world_normal_matrix * normal; - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - - tangent = world_normal_matrix * tangent; - binormal = world_normal_matrix * binormal; - -#endif -#endif - - float roughness = 1.0; - - mat4 modelview = scene_data.inv_camera_matrix * world_matrix; - mat3 modelview_normal = mat3(scene_data.inv_camera_matrix) * world_normal_matrix; - - { - /* clang-format off */ - -VERTEX_SHADER_CODE - - /* clang-format on */ - } - -// using local coordinates (default) -#if !defined(SKIP_TRANSFORM_USED) && !defined(VERTEX_WORLD_COORDS_USED) - - vertex = (modelview * vec4(vertex, 1.0)).xyz; - normal = modelview_normal * normal; -#endif - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - - binormal = modelview_normal * binormal; - tangent = modelview_normal * tangent; -#endif - -//using world coordinates -#if !defined(SKIP_TRANSFORM_USED) && defined(VERTEX_WORLD_COORDS_USED) - - vertex = (scene_data.inv_camera_matrix * vec4(vertex, 1.0)).xyz; - normal = mat3(scene_data.inverse_normal_matrix) * normal; - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - - binormal = mat3(scene_data.camera_inverse_binormal_matrix) * binormal; - tangent = mat3(scene_data.camera_inverse_tangent_matrix) * tangent; -#endif -#endif - - vertex_interp = vertex; - normal_interp = normal; - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - tangent_interp = tangent; - binormal_interp = binormal; -#endif - -#ifdef MODE_RENDER_DEPTH - -#ifdef MODE_DUAL_PARABOLOID - - vertex_interp.z *= scene_data.dual_paraboloid_side; - normal_interp.z *= scene_data.dual_paraboloid_side; - - dp_clip = vertex_interp.z; //this attempts to avoid noise caused by objects sent to the other parabolloid side due to bias - - //for dual paraboloid shadow mapping, this is the fastest but least correct way, as it curves straight edges - - vec3 vtx = vertex_interp + normalize(vertex_interp) * scene_data.z_offset; - float distance = length(vtx); - vtx = normalize(vtx); - vtx.xy /= 1.0 - vtx.z; - vtx.z = (distance / scene_data.z_far); - vtx.z = vtx.z * 2.0 - 1.0; - - vertex_interp = vtx; -#else - - float z_ofs = scene_data.z_offset; - z_ofs += max(0.0, 1.0 - abs(normalize(normal_interp).z)) * scene_data.z_slope_scale; - vertex_interp.z -= z_ofs; - -#endif - -#endif //MODE_RENDER_DEPTH - -#ifdef USE_OVERRIDE_POSITION - gl_Position = position; -#else - gl_Position = projection_matrix * vec4(vertex_interp, 1.0); -#endif -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -#include "scene_high_end_inc.glsl" - -/* Varyings */ - -layout(location = 0) in vec3 vertex_interp; -/* clang-format on */ -layout(location = 1) in vec3 normal_interp; - -#if defined(COLOR_USED) -layout(location = 2) in vec4 color_interp; -#endif - -#if defined(UV_USED) -layout(location = 3) in vec2 uv_interp; -#endif - -#if defined(UV2_USED) || defined(USE_LIGHTMAP) -layout(location = 4) in vec2 uv2_interp; -#endif - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) -layout(location = 5) in vec3 tangent_interp; -layout(location = 6) in vec3 binormal_interp; -#endif - -layout(location = 7) flat in uint instance_index; - -#ifdef MODE_DUAL_PARABOLOID - -layout(location = 8) in float dp_clip; - -#endif - -//defines to keep compatibility with vertex - -#define world_matrix instances.data[instance_index].transform -#define world_normal_matrix instances.data[instance_index].normal_transform -#define projection_matrix scene_data.projection_matrix - -#ifdef USE_MATERIAL_UNIFORMS -layout(set = 5, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ -MATERIAL_UNIFORMS - /* clang-format on */ -} material; -#endif - -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ - -#ifdef MODE_RENDER_DEPTH - -#ifdef MODE_RENDER_MATERIAL - -layout(location = 0) out vec4 albedo_output_buffer; -layout(location = 1) out vec4 normal_output_buffer; -layout(location = 2) out vec4 orm_output_buffer; -layout(location = 3) out vec4 emission_output_buffer; -layout(location = 4) out float depth_output_buffer; - -#endif - -#ifdef MODE_RENDER_NORMAL -layout(location = 0) out vec4 normal_output_buffer; -#ifdef MODE_RENDER_ROUGHNESS -layout(location = 1) out float roughness_output_buffer; -#endif //MODE_RENDER_ROUGHNESS -#endif //MODE_RENDER_NORMAL -#else // RENDER DEPTH - -#ifdef MODE_MULTIPLE_RENDER_TARGETS - -layout(location = 0) out vec4 diffuse_buffer; //diffuse (rgb) and roughness -layout(location = 1) out vec4 specular_buffer; //specular and SSS (subsurface scatter) -#else - -layout(location = 0) out vec4 frag_color; -#endif - -#endif // RENDER DEPTH - -// This returns the G_GGX function divided by 2 cos_theta_m, where in practice cos_theta_m is either N.L or N.V. -// We're dividing this factor off because the overall term we'll end up looks like -// (see, for example, the first unnumbered equation in B. Burley, "Physically Based Shading at Disney", SIGGRAPH 2012): -// -// F(L.V) D(N.H) G(N.L) G(N.V) / (4 N.L N.V) -// -// We're basically regouping this as -// -// F(L.V) D(N.H) [G(N.L)/(2 N.L)] [G(N.V) / (2 N.V)] -// -// and thus, this function implements the [G(N.m)/(2 N.m)] part with m = L or V. -// -// The contents of the D and G (G1) functions (GGX) are taken from -// E. Heitz, "Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs", J. Comp. Graph. Tech. 3 (2) (2014). -// Eqns 71-72 and 85-86 (see also Eqns 43 and 80). - -#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - -float G_GGX_2cos(float cos_theta_m, float alpha) { - // Schlick's approximation - // C. Schlick, "An Inexpensive BRDF Model for Physically-based Rendering", Computer Graphics Forum. 13 (3): 233 (1994) - // Eq. (19), although see Heitz (2014) the about the problems with his derivation. - // It nevertheless approximates GGX well with k = alpha/2. - float k = 0.5 * alpha; - return 0.5 / (cos_theta_m * (1.0 - k) + k); - - // float cos2 = cos_theta_m * cos_theta_m; - // float sin2 = (1.0 - cos2); - // return 1.0 / (cos_theta_m + sqrt(cos2 + alpha * alpha * sin2)); -} - -float D_GGX(float cos_theta_m, float alpha) { - float alpha2 = alpha * alpha; - float d = 1.0 + (alpha2 - 1.0) * cos_theta_m * cos_theta_m; - return alpha2 / (M_PI * d * d); -} - -float G_GGX_anisotropic_2cos(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { - float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float s_x = alpha_x * cos_phi; - float s_y = alpha_y * sin_phi; - return 1.0 / max(cos_theta_m + sqrt(cos2 + (s_x * s_x + s_y * s_y) * sin2), 0.001); -} - -float D_GGX_anisotropic(float cos_theta_m, float alpha_x, float alpha_y, float cos_phi, float sin_phi) { - float cos2 = cos_theta_m * cos_theta_m; - float sin2 = (1.0 - cos2); - float r_x = cos_phi / alpha_x; - float r_y = sin_phi / alpha_y; - float d = cos2 + sin2 * (r_x * r_x + r_y * r_y); - return 1.0 / max(M_PI * alpha_x * alpha_y * d * d, 0.001); -} - -float SchlickFresnel(float u) { - float m = 1.0 - u; - float m2 = m * m; - return m2 * m2 * m; // pow(m,5) -} - -float GTR1(float NdotH, float a) { - if (a >= 1.0) return 1.0 / M_PI; - float a2 = a * a; - float t = 1.0 + (a2 - 1.0) * NdotH * NdotH; - return (a2 - 1.0) / (M_PI * log(a2) * t); -} - -vec3 F0(float metallic, float specular, vec3 albedo) { - float dielectric = 0.16 * specular * specular; - // use albedo * metallic as colored specular reflectance at 0 angle for metallic materials; - // see https://google.github.io/filament/Filament.md.html - return mix(vec3(dielectric), albedo, vec3(metallic)); -} - -void light_compute(vec3 N, vec3 L, vec3 V, vec3 light_color, vec3 attenuation, vec3 diffuse_color, float roughness, float metallic, float specular, float specular_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - vec3 transmission, -#endif -#ifdef LIGHT_RIM_USED - float rim, float rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - float clearcoat, float clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - vec3 B, vec3 T, float anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif - inout vec3 diffuse_light, inout vec3 specular_light) { - -#if defined(USE_LIGHT_SHADER_CODE) - // light is written by the light shader - - vec3 normal = N; - vec3 albedo = diffuse_color; - vec3 light = L; - vec3 view = V; - - /* clang-format off */ - -LIGHT_SHADER_CODE - - /* clang-format on */ - -#else - float NdotL = dot(N, L); - float cNdotL = max(NdotL, 0.0); // clamped NdotL - float NdotV = dot(N, V); - float cNdotV = max(NdotV, 0.0); - -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) - vec3 H = normalize(V + L); -#endif - -#if defined(SPECULAR_BLINN) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) - float cNdotH = max(dot(N, H), 0.0); -#endif - -#if defined(DIFFUSE_BURLEY) || defined(SPECULAR_SCHLICK_GGX) || defined(LIGHT_CLEARCOAT_USED) - float cLdotH = max(dot(L, H), 0.0); -#endif - - if (metallic < 1.0) { -#if defined(DIFFUSE_OREN_NAYAR) - vec3 diffuse_brdf_NL; -#else - float diffuse_brdf_NL; // BRDF times N.L for calculating diffuse radiance -#endif - -#if defined(DIFFUSE_LAMBERT_WRAP) - // energy conserving lambert wrap shader - diffuse_brdf_NL = max(0.0, (NdotL + roughness) / ((1.0 + roughness) * (1.0 + roughness))); - -#elif defined(DIFFUSE_OREN_NAYAR) - - { - // see http://mimosa-pudica.net/improved-oren-nayar.html - float LdotV = dot(L, V); - - float s = LdotV - NdotL * NdotV; - float t = mix(1.0, max(NdotL, NdotV), step(0.0, s)); - - float sigma2 = roughness * roughness; // TODO: this needs checking - vec3 A = 1.0 + sigma2 * (-0.5 / (sigma2 + 0.33) + 0.17 * diffuse_color / (sigma2 + 0.13)); - float B = 0.45 * sigma2 / (sigma2 + 0.09); - - diffuse_brdf_NL = cNdotL * (A + vec3(B) * s / t) * (1.0 / M_PI); - } - -#elif defined(DIFFUSE_TOON) - - diffuse_brdf_NL = smoothstep(-roughness, max(roughness, 0.01), NdotL); - -#elif defined(DIFFUSE_BURLEY) - - { - float FD90_minus_1 = 2.0 * cLdotH * cLdotH * roughness - 0.5; - float FdV = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotV); - float FdL = 1.0 + FD90_minus_1 * SchlickFresnel(cNdotL); - diffuse_brdf_NL = (1.0 / M_PI) * FdV * FdL * cNdotL; - /* - float energyBias = mix(roughness, 0.0, 0.5); - float energyFactor = mix(roughness, 1.0, 1.0 / 1.51); - float fd90 = energyBias + 2.0 * VoH * VoH * roughness; - float f0 = 1.0; - float lightScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotL, 5.0); - float viewScatter = f0 + (fd90 - f0) * pow(1.0 - cNdotV, 5.0); - - diffuse_brdf_NL = lightScatter * viewScatter * energyFactor; - */ - } -#else - // lambert - diffuse_brdf_NL = cNdotL * (1.0 / M_PI); -#endif - - diffuse_light += light_color * diffuse_color * diffuse_brdf_NL * attenuation; - -#if defined(LIGHT_TRANSMISSION_USED) - diffuse_light += light_color * diffuse_color * (vec3(1.0 / M_PI) - diffuse_brdf_NL) * transmission * attenuation; -#endif - -#if defined(LIGHT_RIM_USED) - float rim_light = pow(max(0.0, 1.0 - cNdotV), max(0.0, (1.0 - roughness) * 16.0)); - diffuse_light += rim_light * rim * mix(vec3(1.0), diffuse_color, rim_tint) * light_color; -#endif - } - - if (roughness > 0.0) { // FIXME: roughness == 0 should not disable specular light entirely - - // D - -#if defined(SPECULAR_BLINN) - - //normalized blinn - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float blinn = pow(cNdotH, shininess) * cNdotL; - blinn *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - float intensity = blinn; - - specular_light += light_color * intensity * specular_blob_intensity * attenuation; - -#elif defined(SPECULAR_PHONG) - - vec3 R = normalize(-reflect(L, N)); - float cRdotV = max(0.0, dot(R, V)); - float shininess = exp2(15.0 * (1.0 - roughness) + 1.0) * 0.25; - float phong = pow(cRdotV, shininess); - phong *= (shininess + 8.0) * (1.0 / (8.0 * M_PI)); - float intensity = (phong) / max(4.0 * cNdotV * cNdotL, 0.75); - - specular_light += light_color * intensity * specular_blob_intensity * attenuation; - -#elif defined(SPECULAR_TOON) - - vec3 R = normalize(-reflect(L, N)); - float RdotV = dot(R, V); - float mid = 1.0 - roughness; - mid *= mid; - float intensity = smoothstep(mid - roughness * 0.5, mid + roughness * 0.5, RdotV) * mid; - diffuse_light += light_color * intensity * specular_blob_intensity * attenuation; // write to diffuse_light, as in toon shading you generally want no reflection - -#elif defined(SPECULAR_DISABLED) - // none.. - -#elif defined(SPECULAR_SCHLICK_GGX) - // shlick+ggx as default - -#if defined(LIGHT_ANISOTROPY_USED) - - float alpha_ggx = roughness * roughness; - float aspect = sqrt(1.0 - anisotropy * 0.9); - float ax = alpha_ggx / aspect; - float ay = alpha_ggx * aspect; - float XdotH = dot(T, H); - float YdotH = dot(B, H); - float D = D_GGX_anisotropic(cNdotH, ax, ay, XdotH, YdotH); - float G = G_GGX_anisotropic_2cos(cNdotL, ax, ay, XdotH, YdotH) * G_GGX_anisotropic_2cos(cNdotV, ax, ay, XdotH, YdotH); - -#else - float alpha_ggx = roughness * roughness; - float D = D_GGX(cNdotH, alpha_ggx); - float G = G_GGX_2cos(cNdotL, alpha_ggx) * G_GGX_2cos(cNdotV, alpha_ggx); -#endif - // F - vec3 f0 = F0(metallic, specular, diffuse_color); - float cLdotH5 = SchlickFresnel(cLdotH); - vec3 F = mix(vec3(cLdotH5), vec3(1.0), f0); - - vec3 specular_brdf_NL = cNdotL * D * F * G; - - specular_light += specular_brdf_NL * light_color * specular_blob_intensity * attenuation; -#endif - -#if defined(LIGHT_CLEARCOAT_USED) - -#if !defined(SPECULAR_SCHLICK_GGX) - float cLdotH5 = SchlickFresnel(cLdotH); -#endif - float Dr = GTR1(cNdotH, mix(.1, .001, clearcoat_gloss)); - float Fr = mix(.04, 1.0, cLdotH5); - float Gr = G_GGX_2cos(cNdotL, .25) * G_GGX_2cos(cNdotV, .25); - - float clearcoat_specular_brdf_NL = 0.25 * clearcoat * Gr * Fr * Dr * cNdotL; - - specular_light += clearcoat_specular_brdf_NL * light_color * specular_blob_intensity * attenuation; -#endif - } - -#ifdef USE_SHADOW_TO_OPACITY - alpha = min(alpha, clamp(1.0 - length(attenuation), 0.0, 1.0)); -#endif - -#endif //defined(USE_LIGHT_SHADER_CODE) -} - -#ifndef USE_NO_SHADOWS - -float sample_shadow(texture2D shadow, vec2 shadow_pixel_size, vec4 coord) { - - //todo optimize - vec2 pos = coord.xy; - float depth = coord.z; - -#ifdef SHADOW_MODE_PCF_13 - - float avg = textureProj(shadow, vec4(pos, depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, -shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x * 2.0, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y * 2.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y * 2.0), depth, 1.0)); - return avg * (1.0 / 13.0); -#endif - -#ifdef SHADOW_MODE_PCF_5 - - float avg = textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(-shadow_pixel_size.x, 0.0), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, shadow_pixel_size.y), depth, 1.0)); - avg += textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos + vec2(0.0, -shadow_pixel_size.y), depth, 1.0)); - return avg * (1.0 / 5.0); - -#endif - -#if !defined(SHADOW_MODE_PCF_5) || !defined(SHADOW_MODE_PCF_13) - - return textureProj(sampler2DShadow(shadow, shadow_sampler), vec4(pos, depth, 1.0)); - -#endif -} - -#endif //USE_NO_SHADOWS - -void light_process_omni(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - vec3 transmission, -#endif -#ifdef LIGHT_RIM_USED - float rim, float rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - float clearcoat, float clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - vec3 binormal, vec3 tangent, float anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif - inout vec3 diffuse_light, inout vec3 specular_light) { - - vec3 light_rel_vec = lights.data[idx].position - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length * lights.data[idx].inv_radius; - vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); - float omni_attenuation = pow(max(1.0 - normalized_distance, 0.0), attenuation_energy.x); - vec3 light_attenuation = vec3(omni_attenuation); - vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular); - color_specular.rgb *= attenuation_energy.y; - -#ifndef USE_NO_SHADOWS - vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled); - if (shadow_color_enabled.w > 0.5) { - // there is a shadowmap - - vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)); - float shadow_len = length(splane); - splane = normalize(splane); - vec4 clamp_rect = lights.data[idx].atlas_rect; - - if (splane.z >= 0.0) { - - splane.z += 1.0; - - clamp_rect.y += clamp_rect.w; - - } else { - - splane.z = 1.0 - splane.z; - } - - splane.xy /= splane.z; - splane.xy = splane.xy * 0.5 + 0.5; - splane.z = shadow_len * lights.data[idx].inv_radius; - splane.xy = clamp_rect.xy + splane.xy * clamp_rect.zw; - splane.w = 1.0; //needed? i think it should be 1 already - float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane); - - light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow); - } -#endif //USE_NO_SHADOWS - - light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - transmission, -#endif -#ifdef LIGHT_RIM_USED - rim * omni_attenuation, rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - binormal, tangent, anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif - diffuse_light, - specular_light); -} - -void light_process_spot(uint idx, vec3 vertex, vec3 eye_vec, vec3 normal, vec3 albedo, float roughness, float metallic, float specular, float p_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - vec3 transmission, -#endif -#ifdef LIGHT_RIM_USED - float rim, float rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - float clearcoat, float clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - vec3 binormal, vec3 tangent, float anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - inout float alpha, -#endif - inout vec3 diffuse_light, - inout vec3 specular_light) { - - vec3 light_rel_vec = lights.data[idx].position - vertex; - float light_length = length(light_rel_vec); - float normalized_distance = light_length * lights.data[idx].inv_radius; - vec2 attenuation_energy = unpackHalf2x16(lights.data[idx].attenuation_energy); - float spot_attenuation = pow(max(1.0 - normalized_distance, 0.001), attenuation_energy.x); - vec3 spot_dir = lights.data[idx].direction; - vec2 spot_att_angle = unpackHalf2x16(lights.data[idx].cone_attenuation_angle); - float scos = max(dot(-normalize(light_rel_vec), spot_dir), spot_att_angle.y); - float spot_rim = max(0.0001, (1.0 - scos) / (1.0 - spot_att_angle.y)); - spot_attenuation *= 1.0 - pow(spot_rim, spot_att_angle.x); - vec3 light_attenuation = vec3(spot_attenuation); - vec4 color_specular = unpackUnorm4x8(lights.data[idx].color_specular); - color_specular.rgb *= attenuation_energy.y; - -/* - if (lights.data[idx].atlas_rect!=vec4(0.0)) { - //use projector texture - } - */ -#ifndef USE_NO_SHADOWS - vec4 shadow_color_enabled = unpackUnorm4x8(lights.data[idx].shadow_color_enabled); - if (shadow_color_enabled.w > 0.5) { - //there is a shadowmap - vec4 splane = (lights.data[idx].shadow_matrix * vec4(vertex, 1.0)); - splane /= splane.w; - float shadow = sample_shadow(shadow_atlas, scene_data.shadow_atlas_pixel_size, splane); - - light_attenuation *= mix(shadow_color_enabled.rgb, vec3(1.0), shadow); - } - -#endif //USE_NO_SHADOWS - - light_compute(normal, normalize(light_rel_vec), eye_vec, color_specular.rgb, light_attenuation, albedo, roughness, metallic, specular, color_specular.a * p_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - transmission, -#endif -#ifdef LIGHT_RIM_USED - rim * spot_attenuation, rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - binormal, tangent, anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif - diffuse_light, specular_light); -} - -void reflection_process(uint ref_index, vec3 vertex, vec3 normal, float roughness, vec3 ambient_light, vec3 specular_light, inout vec4 ambient_accum, inout vec4 reflection_accum) { - - vec3 box_extents = reflections.data[ref_index].box_extents; - vec3 local_pos = (reflections.data[ref_index].local_matrix * vec4(vertex, 1.0)).xyz; - - if (any(greaterThan(abs(local_pos), box_extents))) { //out of the reflection box - return; - } - - vec3 ref_vec = normalize(reflect(vertex, normal)); - - vec3 inner_pos = abs(local_pos / box_extents); - float blend = max(inner_pos.x, max(inner_pos.y, inner_pos.z)); - //make blend more rounded - blend = mix(length(inner_pos), blend, blend); - blend *= blend; - blend = max(0.0, 1.0 - blend); - - if (reflections.data[ref_index].params.x > 0.0) { // compute reflection - - vec3 local_ref_vec = (reflections.data[ref_index].local_matrix * vec4(ref_vec, 0.0)).xyz; - - if (reflections.data[ref_index].params.w > 0.5) { //box project - - vec3 nrdir = normalize(local_ref_vec); - vec3 rbmax = (box_extents - local_pos) / nrdir; - vec3 rbmin = (-box_extents - local_pos) / nrdir; - - vec3 rbminmax = mix(rbmin, rbmax, greaterThan(nrdir, vec3(0.0, 0.0, 0.0))); - - float fa = min(min(rbminmax.x, rbminmax.y), rbminmax.z); - vec3 posonbox = local_pos + nrdir * fa; - local_ref_vec = posonbox - reflections.data[ref_index].box_offset; - } - - vec4 reflection; - - reflection.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_ref_vec, reflections.data[ref_index].index), roughness * MAX_ROUGHNESS_LOD).rgb; - - if (reflections.data[ref_index].params.z < 0.5) { - reflection.rgb = mix(specular_light, reflection.rgb, blend); - } - - reflection.rgb *= reflections.data[ref_index].params.x; - reflection.a = blend; - reflection.rgb *= reflection.a; - - reflection_accum += reflection; - } - -#if !defined(USE_LIGHTMAP) && !defined(USE_VOXEL_CONE_TRACING) - if (reflections.data[ref_index].ambient.a > 0.0) { //compute ambient using skybox - - vec3 local_amb_vec = (reflections.data[ref_index].local_matrix * vec4(normal, 0.0)).xyz; - - vec4 ambient_out; - - ambient_out.rgb = textureLod(samplerCubeArray(reflection_atlas, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(local_amb_vec, reflections.data[ref_index].index), MAX_ROUGHNESS_LOD).rgb; - - ambient_out.a = blend; - ambient_out.rgb = mix(reflections.data[ref_index].ambient.rgb, ambient_out.rgb, reflections.data[ref_index].ambient.a); - if (reflections.data[ref_index].params.z < 0.5) { - ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); - } - - ambient_out.rgb *= ambient_out.a; - ambient_accum += ambient_out; - } else { - - vec4 ambient_out; - ambient_out.a = blend; - ambient_out.rgb = reflections.data[ref_index].ambient.rgb; - if (reflections.data[ref_index].params.z < 0.5) { - ambient_out.rgb = mix(ambient_light, ambient_out.rgb, blend); - } - ambient_out.rgb *= ambient_out.a; - ambient_accum += ambient_out; - } -#endif //USE_LIGHTMAP or VCT -} - -#ifdef USE_VOXEL_CONE_TRACING - -//standard voxel cone trace -vec4 voxel_cone_trace(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - - float dist = p_bias; - vec4 color = vec4(0.0); - - while (dist < max_distance && color.a < 0.95) { - float diameter = max(1.0, 2.0 * tan_half_angle * dist); - vec3 uvw_pos = (pos + dist * direction) * cell_size; - float half_diameter = diameter * 0.5; - //check if outside, then break - if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { - break; - } - vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2(diameter)); - float a = (1.0 - color.a); - color += a * scolor; - dist += half_diameter; - } - - return color; -} - -#ifndef GI_PROBE_HIGH_QUALITY -//faster version for 45 degrees - -#ifdef GI_PROBE_USE_ANISOTROPY - -vec4 voxel_cone_trace_anisotropic_45_degrees(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - - float dist = p_bias; - vec4 color = vec4(0.0); - float radius = max(0.5, tan_half_angle * dist); - float lod_level = log2(radius * 2.0); - - while (dist < max_distance && color.a < 0.95) { - vec3 uvw_pos = (pos + dist * direction) * cell_size; - //check if outside, then break - if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { - break; - } - - vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level); - vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0)); - lod_level += 1.0; - - float a = (1.0 - color.a); - scolor *= a; - color += scolor; - dist += radius; - radius = max(0.5, tan_half_angle * dist); - } - - return color; -} -#else - -vec4 voxel_cone_trace_45_degrees(texture3D probe, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - - float dist = p_bias; - vec4 color = vec4(0.0); - float radius = max(0.5, tan_half_angle * dist); - float lod_level = log2(radius * 2.0); - - while (dist < max_distance && color.a < 0.95) { - vec3 uvw_pos = (pos + dist * direction) * cell_size; - - //check if outside, then break - if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + radius * cell_size)))) { - break; - } - vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, lod_level); - lod_level += 1.0; - - float a = (1.0 - color.a); - scolor *= a; - color += scolor; - dist += radius; - radius = max(0.5, tan_half_angle * dist); - } - - return color; -} - -#endif - -#elif defined(GI_PROBE_USE_ANISOTROPY) - -//standard voxel cone trace -vec4 voxel_cone_trace_anisotropic(texture3D probe, texture3D aniso_pos, texture3D aniso_neg, vec3 normal, vec3 cell_size, vec3 pos, vec3 direction, float tan_half_angle, float max_distance, float p_bias) { - - float dist = p_bias; - vec4 color = vec4(0.0); - - while (dist < max_distance && color.a < 0.95) { - float diameter = max(1.0, 2.0 * tan_half_angle * dist); - vec3 uvw_pos = (pos + dist * direction) * cell_size; - float half_diameter = diameter * 0.5; - //check if outside, then break - if (any(greaterThan(abs(uvw_pos - 0.5), vec3(0.5f + half_diameter * cell_size)))) { - break; - } - float log2_diameter = log2(diameter); - vec4 scolor = textureLod(sampler3D(probe, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter); - vec3 aniso_neg = textureLod(sampler3D(aniso_neg, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb; - vec3 aniso_pos = textureLod(sampler3D(aniso_pos, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), uvw_pos, log2_diameter).rgb; - - scolor.rgb *= dot(max(vec3(0.0), (normal * aniso_pos)), vec3(1.0)) + dot(max(vec3(0.0), (-normal * aniso_neg)), vec3(1.0)); - - float a = (1.0 - color.a); - scolor *= a; - color += scolor; - dist += half_diameter; - } - - return color; -} - -#endif - -void gi_probe_compute(uint index, vec3 position, vec3 normal, vec3 ref_vec, mat3 normal_xform, float roughness, vec3 ambient, vec3 environment, inout vec4 out_spec, inout vec4 out_diff) { - - position = (gi_probes.data[index].xform * vec4(position, 1.0)).xyz; - ref_vec = normalize((gi_probes.data[index].xform * vec4(ref_vec, 0.0)).xyz); - normal = normalize((gi_probes.data[index].xform * vec4(normal, 0.0)).xyz); - - position += normal * gi_probes.data[index].normal_bias; - - //this causes corrupted pixels, i have no idea why.. - if (any(bvec2(any(lessThan(position, vec3(0.0))), any(greaterThan(position, gi_probes.data[index].bounds))))) { - return; - } - - vec3 blendv = abs(position / gi_probes.data[index].bounds * 2.0 - 1.0); - float blend = clamp(1.0 - max(blendv.x, max(blendv.y, blendv.z)), 0.0, 1.0); - //float blend=1.0; - - float max_distance = length(gi_probes.data[index].bounds); - vec3 cell_size = 1.0 / gi_probes.data[index].bounds; - - //radiance - -#ifdef GI_PROBE_HIGH_QUALITY - -#define MAX_CONE_DIRS 6 - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0), - vec3(0.866025, 0.0, 0.5), - vec3(0.267617, 0.823639, 0.5), - vec3(-0.700629, 0.509037, 0.5), - vec3(-0.700629, -0.509037, 0.5), - vec3(0.267617, -0.823639, 0.5)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.15, 0.15, 0.15, 0.15, 0.15); - float cone_angle_tan = 0.577; - -#elif defined(GI_PROBE_LOW_QUALITY) - -#define MAX_CONE_DIRS 1 - - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.0, 0.0, 1.0)); - - float cone_weights[MAX_CONE_DIRS] = float[](1.0); - float cone_angle_tan = 4; //~76 degrees -#else // MEDIUM QUALITY - -#define MAX_CONE_DIRS 4 - - vec3 cone_dirs[MAX_CONE_DIRS] = vec3[]( - vec3(0.707107, 0.0, 0.707107), - vec3(0.0, 0.707107, 0.707107), - vec3(-0.707107, 0.0, 0.707107), - vec3(0.0, -0.707107, 0.707107)); - - float cone_weights[MAX_CONE_DIRS] = float[](0.25, 0.25, 0.25, 0.25); - float cone_angle_tan = 0.98269; - -#endif - vec3 light = vec3(0.0); - - for (int i = 0; i < MAX_CONE_DIRS; i++) { - - vec3 dir = normalize((gi_probes.data[index].xform * vec4(normal_xform * cone_dirs[i], 0.0)).xyz); - -#if defined(GI_PROBE_HIGH_QUALITY) || defined(GI_PROBE_LOW_QUALITY) - -#ifdef GI_PROBE_USE_ANISOTROPY - vec4 cone_light = voxel_cone_trace_anisotropic(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#else - - vec4 cone_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); - -#endif // GI_PROBE_USE_ANISOTROPY - -#else - -#ifdef GI_PROBE_USE_ANISOTROPY - vec4 cone_light = voxel_cone_trace_anisotropic_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], gi_probe_textures[gi_probes.data[index].texture_slot + 1], gi_probe_textures[gi_probes.data[index].texture_slot + 2], normalize(mix(dir, normal, gi_probes.data[index].anisotropy_strength)), cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#else - vec4 cone_light = voxel_cone_trace_45_degrees(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, dir, cone_angle_tan, max_distance, gi_probes.data[index].bias); -#endif // GI_PROBE_USE_ANISOTROPY - -#endif - if (gi_probes.data[index].blend_ambient) { - cone_light.rgb = mix(ambient, cone_light.rgb, min(1.0, cone_light.a / 0.95)); - } - - light += cone_weights[i] * cone_light.rgb; - } - - light *= gi_probes.data[index].dynamic_range; - - if (gi_probes.data[index].ambient_occlusion > 0.001) { - - float size = 1.0 + gi_probes.data[index].ambient_occlusion_size * 7.0; - - float taps, blend; - blend = modf(size, taps); - float ao = 0.0; - for (float i = 1.0; i <= taps; i++) { - vec3 ofs = (position + normal * (i * 0.5 + 1.0)) * cell_size; - ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, i - 1.0).a * i; - } - - if (blend > 0.001) { - vec3 ofs = (position + normal * ((taps + 1.0) * 0.5 + 1.0)) * cell_size; - ao += textureLod(sampler3D(gi_probe_textures[gi_probes.data[index].texture_slot], material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ofs, taps).a * (taps + 1.0) * blend; - } - - ao = 1.0 - min(1.0, ao); - - light = mix(scene_data.ao_color.rgb, light, mix(1.0, ao, gi_probes.data[index].ambient_occlusion)); - } - - out_diff += vec4(light * blend, blend); - - //irradiance -#ifndef GI_PROBE_LOW_QUALITY - vec4 irr_light = voxel_cone_trace(gi_probe_textures[gi_probes.data[index].texture_slot], cell_size, position, ref_vec, tan(roughness * 0.5 * M_PI * 0.99), max_distance, gi_probes.data[index].bias); - if (gi_probes.data[index].blend_ambient) { - irr_light.rgb = mix(environment, irr_light.rgb, min(1.0, irr_light.a / 0.95)); - } - irr_light.rgb *= gi_probes.data[index].dynamic_range; - //irr_light=vec3(0.0); - - out_spec += vec4(irr_light.rgb * blend, blend); -#endif -} - -#endif //USE_VOXEL_CONE_TRACING - -#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - -void main() { - -#ifdef MODE_DUAL_PARABOLOID - - if (dp_clip > 0.0) - discard; -#endif - - //lay out everything, whathever is unused is optimized away anyway - vec3 vertex = vertex_interp; - vec3 view = -normalize(vertex_interp); - vec3 albedo = vec3(1.0); - vec3 transmission = vec3(0.0); - float metallic = 0.0; - float specular = 0.5; - vec3 emission = vec3(0.0); - float roughness = 1.0; - float rim = 0.0; - float rim_tint = 0.0; - float clearcoat = 0.0; - float clearcoat_gloss = 0.0; - float anisotropy = 0.0; - vec2 anisotropy_flow = vec2(1.0, 0.0); - -#if defined(AO_USED) - float ao = 1.0; - float ao_light_affect = 0.0; -#endif - - float alpha = 1.0; - -#if defined(ALPHA_SCISSOR_USED) - float alpha_scissor = 0.5; -#endif - -#if defined(TANGENT_USED) || defined(NORMALMAP_USED) || defined(LIGHT_ANISOTROPY_USED) - vec3 binormal = normalize(binormal_interp); - vec3 tangent = normalize(tangent_interp); -#else - vec3 binormal = vec3(0.0); - vec3 tangent = vec3(0.0); -#endif - vec3 normal = normalize(normal_interp); - -#if defined(DO_SIDE_CHECK) - if (!gl_FrontFacing) { - normal = -normal; - } -#endif - -#if defined(UV_USED) - vec2 uv = uv_interp; -#endif - -#if defined(UV2_USED) || defined(USE_LIGHTMAP) - vec2 uv2 = uv2_interp; -#endif - -#if defined(COLOR_USED) - vec4 color = color_interp; -#endif - -#if defined(NORMALMAP_USED) - - vec3 normalmap = vec3(0.5); -#endif - - float normaldepth = 1.0; - - vec2 screen_uv = gl_FragCoord.xy * scene_data.screen_pixel_size + scene_data.screen_pixel_size * 0.5; //account for center - - float sss_strength = 0.0; - - { - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ - } - -#if !defined(USE_SHADOW_TO_OPACITY) - -#if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { - discard; - } -#endif // ALPHA_SCISSOR_USED - -#ifdef USE_OPAQUE_PREPASS - - if (alpha < opaque_prepass_threshold) { - discard; - } - -#endif // USE_OPAQUE_PREPASS - -#endif // !USE_SHADOW_TO_OPACITY - -#if defined(NORMALMAP_USED) - - normalmap.xy = normalmap.xy * 2.0 - 1.0; - normalmap.z = sqrt(max(0.0, 1.0 - dot(normalmap.xy, normalmap.xy))); //always ignore Z, as it can be RG packed, Z may be pos/neg, etc. - - normal = normalize(mix(normal, tangent * normalmap.x + binormal * normalmap.y + normal * normalmap.z, normaldepth)); - -#endif - -#if defined(LIGHT_ANISOTROPY_USED) - - if (anisotropy > 0.01) { - //rotation matrix - mat3 rot = mat3(tangent, binormal, normal); - //make local to space - tangent = normalize(rot * vec3(anisotropy_flow.x, anisotropy_flow.y, 0.0)); - binormal = normalize(rot * vec3(-anisotropy_flow.y, anisotropy_flow.x, 0.0)); - } - -#endif - -#ifdef ENABLE_CLIP_ALPHA - if (albedo.a < 0.99) { - //used for doublepass and shadowmapping - discard; - } -#endif - - /////////////////////// LIGHTING ////////////////////////////// - - //apply energy conservation - - vec3 specular_light = vec3(0.0, 0.0, 0.0); - vec3 diffuse_light = vec3(0.0, 0.0, 0.0); - vec3 ambient_light = vec3(0.0, 0.0, 0.0); - -#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - - if (scene_data.roughness_limiter_enabled) { - float limit = texelFetch(sampler2D(roughness_buffer, material_samplers[SAMPLER_NEAREST_CLAMP]), ivec2(gl_FragCoord.xy), 0).r; - roughness = max(roughness, limit); - } - - if (scene_data.use_reflection_cubemap) { - - vec3 ref_vec = reflect(-view, normal); - ref_vec = scene_data.radiance_inverse_xform * ref_vec; -#ifdef USE_RADIANCE_CUBEMAP_ARRAY - - float lod, blend; - blend = modf(roughness * MAX_ROUGHNESS_LOD, lod); - specular_light = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod)).rgb; - specular_light = mix(specular_light, texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ref_vec, lod + 1)).rgb, blend); - -#else - specular_light = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ref_vec, roughness * MAX_ROUGHNESS_LOD).rgb; - -#endif //USE_RADIANCE_CUBEMAP_ARRAY - specular_light *= scene_data.ambient_light_color_energy.a; - } - -#ifndef USE_LIGHTMAP - //lightmap overrides everything - if (scene_data.use_ambient_light) { - - ambient_light = scene_data.ambient_light_color_energy.rgb; - - if (scene_data.use_ambient_cubemap) { - vec3 ambient_dir = scene_data.radiance_inverse_xform * normal; -#ifdef USE_RADIANCE_CUBEMAP_ARRAY - vec3 cubemap_ambient = texture(samplerCubeArray(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), vec4(ambient_dir, MAX_ROUGHNESS_LOD)).rgb; -#else - vec3 cubemap_ambient = textureLod(samplerCube(radiance_cubemap, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), ambient_dir, MAX_ROUGHNESS_LOD).rgb; -#endif //USE_RADIANCE_CUBEMAP_ARRAY - - ambient_light = mix(ambient_light, cubemap_ambient * scene_data.ambient_light_color_energy.a, scene_data.ambient_color_sky_mix); - } - } -#endif // USE_LIGHTMAP - -#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - - //radiance - - float specular_blob_intensity = 1.0; - -#if defined(SPECULAR_TOON) - specular_blob_intensity *= specular * 2.0; -#endif - -#if !defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - //gi probes - - //lightmap - - //lightmap capture - -#ifdef USE_VOXEL_CONE_TRACING - { // process giprobes - uint index1 = instances.data[instance_index].gi_offset & 0xFFFF; - if (index1 != 0xFFFF) { - vec3 ref_vec = normalize(reflect(normalize(vertex), normal)); - //find arbitrary tangent and bitangent, then build a matrix - vec3 v0 = abs(normal.z) < 0.999 ? vec3(0.0, 0.0, 1.0) : vec3(0.0, 1.0, 0.0); - vec3 tangent = normalize(cross(v0, normal)); - vec3 bitangent = normalize(cross(tangent, normal)); - mat3 normal_mat = mat3(tangent, bitangent, normal); - - vec4 amb_accum = vec4(0.0); - vec4 spec_accum = vec4(0.0); - gi_probe_compute(index1, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); - - uint index2 = instances.data[instance_index].gi_offset >> 16; - - if (index2 != 0xFFFF) { - gi_probe_compute(index2, vertex, normal, ref_vec, normal_mat, roughness * roughness, ambient_light, specular_light, spec_accum, amb_accum); - } - - if (amb_accum.a > 0.0) { - amb_accum.rgb /= amb_accum.a; - } - - if (spec_accum.a > 0.0) { - spec_accum.rgb /= spec_accum.a; - } - - specular_light = spec_accum.rgb; - ambient_light = amb_accum.rgb; - } - } -#endif - - uvec4 cluster_cell = texture(usampler3D(cluster_texture, material_samplers[SAMPLER_NEAREST_CLAMP]), vec3(screen_uv, (abs(vertex.z) - scene_data.z_near) / (scene_data.z_far - scene_data.z_near))); - - { // process reflections - - vec4 reflection_accum = vec4(0.0, 0.0, 0.0, 0.0); - vec4 ambient_accum = vec4(0.0, 0.0, 0.0, 0.0); - - uint reflection_probe_count = cluster_cell.z >> CLUSTER_COUNTER_SHIFT; - uint reflection_probe_pointer = cluster_cell.z & CLUSTER_POINTER_MASK; - - for (uint i = 0; i < reflection_probe_count; i++) { - - uint ref_index = cluster_data.indices[reflection_probe_pointer + i]; - reflection_process(ref_index, vertex, normal, roughness, ambient_light, specular_light, ambient_accum, reflection_accum); - } - - if (reflection_accum.a > 0.0) { - specular_light = reflection_accum.rgb / reflection_accum.a; - } - -#if !defined(USE_LIGHTMAP) - if (ambient_accum.a > 0.0) { - ambient_light = ambient_accum.rgb / ambient_accum.a; - } -#endif - } - - { - -#if defined(DIFFUSE_TOON) - //simplify for toon, as - specular_light *= specular * metallic * albedo * 2.0; -#else - - // scales the specular reflections, needs to be be computed before lighting happens, - // but after environment, GI, and reflection probes are added - // Environment brdf approximation (Lazarov 2013) - // see https://www.unrealengine.com/en-US/blog/physically-based-shading-on-mobile - const vec4 c0 = vec4(-1.0, -0.0275, -0.572, 0.022); - const vec4 c1 = vec4(1.0, 0.0425, 1.04, -0.04); - vec4 r = roughness * c0 + c1; - float ndotv = clamp(dot(normal, view), 0.0, 1.0); - float a004 = min(r.x * r.x, exp2(-9.28 * ndotv)) * r.x + r.y; - vec2 env = vec2(-1.04, 1.04) * a004 + r.zw; - - vec3 f0 = F0(metallic, specular, albedo); - specular_light *= env.x * f0 + env.y; -#endif - } - - { //directional light - - for (uint i = 0; i < scene_data.directional_light_count; i++) { - - if (!bool(directional_lights.data[i].mask & instances.data[instance_index].layer_mask)) { - continue; //not masked - } - - vec3 light_attenuation = vec3(1.0); - - if (directional_lights.data[i].shadow_enabled) { - float depth_z = -vertex.z; - - vec4 pssm_coord; - - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { - pssm_coord = (directional_lights.data[i].shadow_matrix1 * vec4(vertex, 1.0)); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { - pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0)); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { - pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0)); - } else { - pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0)); - } - - pssm_coord /= pssm_coord.w; - - float shadow = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); - - if (directional_lights.data[i].blend_splits) { - - float pssm_blend; - - if (depth_z < directional_lights.data[i].shadow_split_offsets.x) { - pssm_coord = (directional_lights.data[i].shadow_matrix2 * vec4(vertex, 1.0)); - pssm_blend = smoothstep(0.0, directional_lights.data[i].shadow_split_offsets.x, depth_z); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.y) { - pssm_coord = (directional_lights.data[i].shadow_matrix3 * vec4(vertex, 1.0)); - pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.x, directional_lights.data[i].shadow_split_offsets.y, depth_z); - } else if (depth_z < directional_lights.data[i].shadow_split_offsets.z) { - pssm_coord = (directional_lights.data[i].shadow_matrix4 * vec4(vertex, 1.0)); - pssm_blend = smoothstep(directional_lights.data[i].shadow_split_offsets.y, directional_lights.data[i].shadow_split_offsets.z, depth_z); - } else { - pssm_blend = 0.0; //if no blend, same coord will be used (divide by z will result in same value, and already cached) - } - - pssm_coord /= pssm_coord.w; - - float shadow2 = sample_shadow(directional_shadow_atlas, scene_data.directional_shadow_pixel_size, pssm_coord); - shadow = mix(shadow, shadow2, pssm_blend); - } - - shadow = mix(shadow, 1.0, smoothstep(directional_lights.data[i].fade_from, directional_lights.data[i].fade_to, vertex.z)); //done with negative values for performance - - light_attenuation = mix(directional_lights.data[i].shadow_color, vec3(1.0), shadow); - } - - light_compute(normal, directional_lights.data[i].direction, normalize(view), directional_lights.data[i].color * directional_lights.data[i].energy, light_attenuation, albedo, roughness, metallic, specular, directional_lights.data[i].specular * specular_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - transmission, -#endif -#ifdef LIGHT_RIM_USED - rim, rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - binormal, tangent, anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif - diffuse_light, - specular_light); - } - } - - { //omni lights - - uint omni_light_count = cluster_cell.x >> CLUSTER_COUNTER_SHIFT; - uint omni_light_pointer = cluster_cell.x & CLUSTER_POINTER_MASK; - - for (uint i = 0; i < omni_light_count; i++) { - - uint light_index = cluster_data.indices[omni_light_pointer + i]; - - if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { - continue; //not masked - } - - light_process_omni(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - transmission, -#endif -#ifdef LIGHT_RIM_USED - rim, - rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - tangent, binormal, anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif - diffuse_light, specular_light); - } - } - - { //spot lights - uint spot_light_count = cluster_cell.y >> CLUSTER_COUNTER_SHIFT; - uint spot_light_pointer = cluster_cell.y & CLUSTER_POINTER_MASK; - - for (uint i = 0; i < spot_light_count; i++) { - - uint light_index = cluster_data.indices[spot_light_pointer + i]; - - if (!bool(lights.data[light_index].mask & instances.data[instance_index].layer_mask)) { - continue; //not masked - } - - light_process_spot(light_index, vertex, view, normal, albedo, roughness, metallic, specular, specular_blob_intensity, -#ifdef LIGHT_TRANSMISSION_USED - transmission, -#endif -#ifdef LIGHT_RIM_USED - rim, - rim_tint, -#endif -#ifdef LIGHT_CLEARCOAT_USED - clearcoat, clearcoat_gloss, -#endif -#ifdef LIGHT_ANISOTROPY_USED - tangent, binormal, anisotropy, -#endif -#ifdef USE_SHADOW_TO_OPACITY - alpha, -#endif - diffuse_light, specular_light); - } - } - -#ifdef USE_SHADOW_TO_OPACITY - alpha = min(alpha, clamp(length(ambient_light), 0.0, 1.0)); - -#if defined(ALPHA_SCISSOR_USED) - if (alpha < alpha_scissor) { - discard; - } -#endif // ALPHA_SCISSOR_USED - -#ifdef USE_OPAQUE_PREPASS - - if (alpha < opaque_prepass_threshold) { - discard; - } - -#endif // USE_OPAQUE_PREPASS - -#endif // USE_SHADOW_TO_OPACITY - -#endif //!defined(MODE_RENDER_DEPTH) && !defined(MODE_UNSHADED) - -#ifdef MODE_RENDER_DEPTH - -#ifdef MODE_RENDER_MATERIAL - - albedo_output_buffer.rgb = albedo; - albedo_output_buffer.a = alpha; - - normal_output_buffer.rgb = normal * 0.5 + 0.5; - normal_output_buffer.a = 0.0; - depth_output_buffer.r = -vertex.z; - -#if defined(AO_USED) - orm_output_buffer.r = ao; -#else - orm_output_buffer.r = 0.0; -#endif - orm_output_buffer.g = roughness; - orm_output_buffer.b = metallic; - orm_output_buffer.a = sss_strength; - - emission_output_buffer.rgb = emission; - emission_output_buffer.a = 0.0; -#endif - -#ifdef MODE_RENDER_NORMAL - normal_output_buffer = vec4(normal * 0.5 + 0.5, 0.0); -#ifdef MODE_RENDER_ROUGHNESS - roughness_output_buffer = roughness; -#endif //MODE_RENDER_ROUGHNESS -#endif //MODE_RENDER_NORMAL - -//nothing happens, so a tree-ssa optimizer will result in no fragment shader :) -#else - - specular_light *= scene_data.reflection_multiplier; - ambient_light *= albedo; //ambient must be multiplied by albedo at the end - -//ambient occlusion -#if defined(AO_USED) - - if (scene_data.ssao_enabled && scene_data.ssao_ao_affect > 0.0) { - float ssao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; - ao = mix(ao, min(ao, ssao), scene_data.ssao_ao_affect); - ao_light_affect = mix(ao_light_affect, max(ao_light_affect, scene_data.ssao_light_affect), scene_data.ssao_ao_affect); - } - - ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); - ao_light_affect = mix(1.0, ao, ao_light_affect); - specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect); - diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); - -#else - - if (scene_data.ssao_enabled) { - float ao = texture(sampler2D(ao_buffer, material_samplers[SAMPLER_LINEAR_CLAMP]), screen_uv).r; - ambient_light = mix(scene_data.ao_color.rgb, ambient_light, ao); - float ao_light_affect = mix(1.0, ao, scene_data.ssao_light_affect); - specular_light = mix(scene_data.ao_color.rgb, specular_light, ao_light_affect); - diffuse_light = mix(scene_data.ao_color.rgb, diffuse_light, ao_light_affect); - } - -#endif // AO_USED - - // base color remapping - diffuse_light *= 1.0 - metallic; // TODO: avoid all diffuse and ambient light calculations when metallic == 1 up to this point - ambient_light *= 1.0 - metallic; - - //fog - -#ifdef MODE_MULTIPLE_RENDER_TARGETS - -#ifdef MODE_UNSHADED - diffuse_buffer = vec4(albedo.rgb, 0.0); - specular_buffer = vec4(0.0); - -#else - - diffuse_buffer = vec4(emission + diffuse_light + ambient_light, sss_strength); - specular_buffer = vec4(specular_light, metallic); - -#endif - -#else //MODE_MULTIPLE_RENDER_TARGETS - -#ifdef MODE_UNSHADED - frag_color = vec4(albedo, alpha); -#else - frag_color = vec4(emission + ambient_light + diffuse_light + specular_light, alpha); - //frag_color = vec4(1.0); - -#endif //USE_NO_SHADING - -#endif //MODE_MULTIPLE_RENDER_TARGETS - -#endif //MODE_RENDER_DEPTH -} diff --git a/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl b/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl deleted file mode 100644 index baef1e060f..0000000000 --- a/servers/visual/rasterizer_rd/shaders/scene_high_end_inc.glsl +++ /dev/null @@ -1,266 +0,0 @@ -#define M_PI 3.14159265359 -#define ROUGHNESS_MAX_LOD 5 - -layout(push_constant, binding = 0, std430) uniform DrawCall { - uint instance_index; - uint pad[3]; //16 bits minimum size -} -draw_call; - -/* Set 0 Scene data that never changes, ever */ - -#define SAMPLER_NEAREST_CLAMP 0 -#define SAMPLER_LINEAR_CLAMP 1 -#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 -#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3 -#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4 -#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5 -#define SAMPLER_NEAREST_REPEAT 6 -#define SAMPLER_LINEAR_REPEAT 7 -#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8 -#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9 -#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10 -#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 - -layout(set = 0, binding = 1) uniform sampler material_samplers[12]; - -layout(set = 0, binding = 2) uniform sampler shadow_sampler; - -layout(set = 0, binding = 3, std140) uniform SceneData { - - mat4 projection_matrix; - mat4 inv_projection_matrix; - - mat4 camera_matrix; - mat4 inv_camera_matrix; - - vec2 viewport_size; - vec2 screen_pixel_size; - - //used for shadow mapping only - float z_offset; - float z_slope_scale; - - float time; - float reflection_multiplier; // one normally, zero when rendering reflections - - vec4 ambient_light_color_energy; - - float ambient_color_sky_mix; - bool use_ambient_light; - bool use_ambient_cubemap; - bool use_reflection_cubemap; - - mat3 radiance_inverse_xform; - - vec2 shadow_atlas_pixel_size; - vec2 directional_shadow_pixel_size; - - uint directional_light_count; - float dual_paraboloid_side; - float z_far; - float z_near; - - bool ssao_enabled; - float ssao_light_affect; - float ssao_ao_affect; - bool roughness_limiter_enabled; - - vec4 ao_color; - -#if 0 - vec4 ambient_light_color; - vec4 bg_color; - - vec4 fog_color_enabled; - vec4 fog_sun_color_amount; - - float ambient_energy; - float bg_energy; -#endif - -#if 0 - vec2 shadow_atlas_pixel_size; - vec2 directional_shadow_pixel_size; - - float z_far; - - float subsurface_scatter_width; - float ambient_occlusion_affect_light; - float ambient_occlusion_affect_ao_channel; - float opaque_prepass_threshold; - - bool fog_depth_enabled; - float fog_depth_begin; - float fog_depth_end; - float fog_density; - float fog_depth_curve; - bool fog_transmit_enabled; - float fog_transmit_curve; - bool fog_height_enabled; - float fog_height_min; - float fog_height_max; - float fog_height_curve; -#endif -} -scene_data; - -#define INSTANCE_FLAGS_FORWARD_MASK 0x7 -#define INSTANCE_FLAGS_FORWARD_OMNI_LIGHT_SHIFT 3 -#define INSTANCE_FLAGS_FORWARD_SPOT_LIGHT_SHIFT 6 -#define INSTANCE_FLAGS_FORWARD_DECAL_SHIFT 9 - -#define INSTANCE_FLAGS_MULTIMESH (1 << 12) -#define INSTANCE_FLAGS_MULTIMESH_FORMAT_2D (1 << 13) -#define INSTANCE_FLAGS_MULTIMESH_HAS_COLOR (1 << 14) -#define INSTANCE_FLAGS_MULTIMESH_HAS_CUSTOM_DATA (1 << 15) -#define INSTANCE_FLAGS_MULTIMESH_STRIDE_SHIFT 16 -//3 bits of stride -#define INSTANCE_FLAGS_MULTIMESH_STRIDE_MASK 0x7 - -#define INSTANCE_FLAGS_SKELETON (1 << 19) - -struct InstanceData { - mat4 transform; - mat4 normal_transform; - uint flags; - uint instance_ofs; //instance_offset in instancing/skeleton buffer - uint gi_offset; //GI information when using lightmapping (VCT or lightmap) - uint layer_mask; -}; - -layout(set = 0, binding = 4, std430) buffer Instances { - InstanceData data[]; -} -instances; - -struct LightData { //this structure needs to be 128 bits - vec3 position; - float inv_radius; - vec3 direction; - uint attenuation_energy; //attenuation - uint color_specular; //rgb color, a specular (8 bit unorm) - uint cone_attenuation_angle; // attenuation and angle, (16bit float) - uint mask; - uint shadow_color_enabled; //shadow rgb color, a>0.5 enabled (8bit unorm) - vec4 atlas_rect; //used for shadow atlas uv on omni, and for projection atlas on spot - mat4 shadow_matrix; -}; - -layout(set = 0, binding = 5, std140) uniform Lights { - LightData data[MAX_LIGHT_DATA_STRUCTS]; -} -lights; - -struct ReflectionData { - - vec3 box_extents; - float index; - vec3 box_offset; - uint mask; - vec4 params; // intensity, 0, interior , boxproject - vec4 ambient; // ambient color, energy - mat4 local_matrix; // up to here for spot and omni, rest is for directional - // notes: for ambientblend, use distance to edge to blend between already existing global environment -}; - -layout(set = 0, binding = 6, std140) uniform ReflectionProbeData { - ReflectionData data[MAX_REFLECTION_DATA_STRUCTS]; -} -reflections; - -struct DirectionalLightData { - vec3 direction; - float energy; - vec3 color; - float specular; - vec3 shadow_color; - uint mask; - bool blend_splits; - bool shadow_enabled; - float fade_from; - float fade_to; - vec4 shadow_split_offsets; - mat4 shadow_matrix1; - mat4 shadow_matrix2; - mat4 shadow_matrix3; - mat4 shadow_matrix4; -}; - -layout(set = 0, binding = 7, std140) uniform DirectionalLights { - DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; -} -directional_lights; - -struct GIProbeData { - mat4 xform; - vec3 bounds; - float dynamic_range; - - float bias; - float normal_bias; - bool blend_ambient; - uint texture_slot; - - float anisotropy_strength; - float ambient_occlusion; - float ambient_occlusion_size; - uint pad2; -}; - -layout(set = 0, binding = 8, std140) uniform GIProbes { - GIProbeData data[MAX_GI_PROBES]; -} -gi_probes; - -layout(set = 0, binding = 9) uniform texture3D gi_probe_textures[MAX_GI_PROBE_TEXTURES]; - -#define CLUSTER_COUNTER_SHIFT 20 -#define CLUSTER_POINTER_MASK ((1 << CLUSTER_COUNTER_SHIFT) - 1) -#define CLUSTER_COUNTER_MASK 0xfff - -layout(set = 0, binding = 10) uniform utexture3D cluster_texture; - -layout(set = 0, binding = 11, std430) buffer ClusterData { - uint indices[]; -} -cluster_data; - -layout(set = 0, binding = 12) uniform texture2D directional_shadow_atlas; - -// decal atlas - -/* Set 1, Radiance */ - -#ifdef USE_RADIANCE_CUBEMAP_ARRAY - -layout(set = 1, binding = 0) uniform textureCubeArray radiance_cubemap; - -#else - -layout(set = 1, binding = 0) uniform textureCube radiance_cubemap; - -#endif - -/* Set 2, Reflection and Shadow Atlases (view dependant) */ - -layout(set = 2, binding = 0) uniform textureCubeArray reflection_atlas; - -layout(set = 2, binding = 1) uniform texture2D shadow_atlas; - -/* Set 1, Render Buffers */ - -layout(set = 3, binding = 0) uniform texture2D depth_buffer; -layout(set = 3, binding = 1) uniform texture2D color_buffer; -layout(set = 3, binding = 2) uniform texture2D normal_buffer; -layout(set = 3, binding = 3) uniform texture2D roughness_buffer; -layout(set = 3, binding = 4) uniform texture2D ao_buffer; - -/* Set 4 Skeleton & Instancing (Multimesh) */ - -layout(set = 4, binding = 0, std430) buffer Transforms { - vec4 data[]; -} -transforms; - -/* Set 5 User Material */ diff --git a/servers/visual/rasterizer_rd/shaders/sky.glsl b/servers/visual/rasterizer_rd/shaders/sky.glsl deleted file mode 100644 index 3f433eb2ee..0000000000 --- a/servers/visual/rasterizer_rd/shaders/sky.glsl +++ /dev/null @@ -1,181 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -layout(location = 0) out vec2 uv_interp; -/* clang-format on */ - -layout(push_constant, binding = 1, std430) uniform Params { - mat3 orientation; - vec4 proj; - vec4 position_multiplier; - float time; -} -params; - -void main() { - - vec2 base_arr[4] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 1.0), vec2(1.0, 1.0), vec2(1.0, -1.0)); - uv_interp = base_arr[gl_VertexIndex]; - gl_Position = vec4(uv_interp, 1.0, 1.0); -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -#define M_PI 3.14159265359 - -layout(location = 0) in vec2 uv_interp; -/* clang-format on */ - -layout(push_constant, binding = 1, std430) uniform Params { - mat3 orientation; - vec4 proj; - vec4 position_multiplier; - float time; //TODO consider adding vec2 screen res, and float radiance size -} -params; - -#define SAMPLER_NEAREST_CLAMP 0 -#define SAMPLER_LINEAR_CLAMP 1 -#define SAMPLER_NEAREST_WITH_MIPMAPS_CLAMP 2 -#define SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP 3 -#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_CLAMP 4 -#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_CLAMP 5 -#define SAMPLER_NEAREST_REPEAT 6 -#define SAMPLER_LINEAR_REPEAT 7 -#define SAMPLER_NEAREST_WITH_MIPMAPS_REPEAT 8 -#define SAMPLER_LINEAR_WITH_MIPMAPS_REPEAT 9 -#define SAMPLER_NEAREST_WITH_MIPMAPS_ANISOTROPIC_REPEAT 10 -#define SAMPLER_LINEAR_WITH_MIPMAPS_ANISOTROPIC_REPEAT 11 - -layout(set = 0, binding = 0) uniform sampler material_samplers[12]; - -#ifdef USE_MATERIAL_UNIFORMS -layout(set = 1, binding = 0, std140) uniform MaterialUniforms{ - /* clang-format off */ - -MATERIAL_UNIFORMS - - /* clang-format on */ -} material; -#endif - -layout(set = 2, binding = 0) uniform textureCube radiance; -#ifdef USE_CUBEMAP_PASS -layout(set = 2, binding = 1) uniform textureCube half_res; -layout(set = 2, binding = 2) uniform textureCube quarter_res; -#else -layout(set = 2, binding = 1) uniform texture2D half_res; -layout(set = 2, binding = 2) uniform texture2D quarter_res; -#endif - -#ifdef USE_CUBEMAP_PASS -#define AT_CUBEMAP_PASS true -#else -#define AT_CUBEMAP_PASS false -#endif - -#ifdef USE_HALF_RES_PASS -#define AT_HALF_RES_PASS true -#else -#define AT_HALF_RES_PASS false -#endif - -#ifdef USE_QUARTER_RES_PASS -#define AT_QUARTER_RES_PASS true -#else -#define AT_QUARTER_RES_PASS false -#endif - -struct DirectionalLightData { - vec3 direction; - float energy; - vec3 color; - bool enabled; -}; - -layout(set = 3, binding = 0, std140) uniform DirectionalLights { - DirectionalLightData data[MAX_DIRECTIONAL_LIGHT_DATA_STRUCTS]; -} -directional_lights; - -/* clang-format off */ - -FRAGMENT_SHADER_GLOBALS - -/* clang-format on */ - -layout(location = 0) out vec4 frag_color; - -void main() { - - vec3 cube_normal; - cube_normal.z = -1.0; - cube_normal.x = (cube_normal.z * (-uv_interp.x - params.proj.x)) / params.proj.y; - cube_normal.y = -(cube_normal.z * (-uv_interp.y - params.proj.z)) / params.proj.w; - cube_normal = mat3(params.orientation) * cube_normal; - cube_normal.z = -cube_normal.z; - cube_normal = normalize(cube_normal); - - vec2 uv = uv_interp * 0.5 + 0.5; - - vec2 panorama_coords = vec2(atan(cube_normal.x, cube_normal.z), acos(cube_normal.y)); - - if (panorama_coords.x < 0.0) { - panorama_coords.x += M_PI * 2.0; - } - - panorama_coords /= vec2(M_PI * 2.0, M_PI); - - vec3 color = vec3(0.0, 0.0, 0.0); - float alpha = 1.0; // Only available to subpasses - vec4 half_res_color = vec4(1.0); - vec4 quarter_res_color = vec4(1.0); - -#ifdef USE_CUBEMAP_PASS - float using_cubemap = 1.0; -#ifdef USES_HALF_RES_COLOR - half_res_color = texture(samplerCube(half_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal); -#endif -#ifdef USES_QUARTER_RES_COLOR - quarter_res_color = texture(samplerCube(quarter_res, material_samplers[SAMPLER_LINEAR_WITH_MIPMAPS_CLAMP]), cube_normal); -#endif -#else - float using_cubemap = 0.0; -#ifdef USES_HALF_RES_COLOR - half_res_color = textureLod(sampler2D(half_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); -#endif -#ifdef USES_QUARTER_RES_COLOR - quarter_res_color = textureLod(sampler2D(quarter_res, material_samplers[SAMPLER_LINEAR_CLAMP]), uv, 0.0); -#endif -#endif - -// unused, just here to make our compiler happy, make sure we don't execute any light code the user adds in.. -#ifndef REALLYINCLUDETHIS - { - /* clang-format off */ - -LIGHT_SHADER_CODE - - /* clang-format on */ - } -#endif - { - /* clang-format off */ - -FRAGMENT_SHADER_CODE - - /* clang-format on */ - } - - frag_color.rgb = color * params.position_multiplier.w; - frag_color.a = alpha; -} diff --git a/servers/visual/rasterizer_rd/shaders/ssao.glsl b/servers/visual/rasterizer_rd/shaders/ssao.glsl deleted file mode 100644 index c9d7134610..0000000000 --- a/servers/visual/rasterizer_rd/shaders/ssao.glsl +++ /dev/null @@ -1,252 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -/* clang-format on */ - -#define TWO_PI 6.283185307179586476925286766559 - -#ifdef SSAO_QUALITY_HIGH -#define NUM_SAMPLES (20) -#endif - -#ifdef SSAO_QUALITY_ULTRA -#define NUM_SAMPLES (48) -#endif - -#ifdef SSAO_QUALITY_LOW -#define NUM_SAMPLES (8) -#endif - -#if !defined(SSAO_QUALITY_LOW) && !defined(SSAO_QUALITY_HIGH) && !defined(SSAO_QUALITY_ULTRA) -#define NUM_SAMPLES (12) -#endif - -// If using depth mip levels, the log of the maximum pixel offset before we need to switch to a lower -// miplevel to maintain reasonable spatial locality in the cache -// If this number is too small (< 3), too many taps will land in the same pixel, and we'll get bad variance that manifests as flashing. -// If it is too high (> 5), we'll get bad performance because we're not using the MIP levels effectively -#define LOG_MAX_OFFSET (3) - -// This must be less than or equal to the MAX_MIP_LEVEL defined in SSAO.cpp -#define MAX_MIP_LEVEL (4) - -// This is the number of turns around the circle that the spiral pattern makes. This should be prime to prevent -// taps from lining up. This particular choice was tuned for NUM_SAMPLES == 9 - -const int ROTATIONS[] = int[]( - 1, 1, 2, 3, 2, 5, 2, 3, 2, - 3, 3, 5, 5, 3, 4, 7, 5, 5, 7, - 9, 8, 5, 5, 7, 7, 7, 8, 5, 8, - 11, 12, 7, 10, 13, 8, 11, 8, 7, 14, - 11, 11, 13, 12, 13, 19, 17, 13, 11, 18, - 19, 11, 11, 14, 17, 21, 15, 16, 17, 18, - 13, 17, 11, 17, 19, 18, 25, 18, 19, 19, - 29, 21, 19, 27, 31, 29, 21, 18, 17, 29, - 31, 31, 23, 18, 25, 26, 25, 23, 19, 34, - 19, 27, 21, 25, 39, 29, 17, 21, 27); -/* clang-format on */ - -//#define NUM_SPIRAL_TURNS (7) -const int NUM_SPIRAL_TURNS = ROTATIONS[NUM_SAMPLES - 1]; - -layout(set = 0, binding = 0) uniform sampler2D source_depth_mipmaps; -layout(r8, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; - -#ifndef USE_HALF_SIZE -layout(set = 2, binding = 0) uniform sampler2D source_depth; -#endif - -layout(set = 3, binding = 0) uniform sampler2D source_normal; - -layout(push_constant, binding = 1, std430) uniform Params { - ivec2 screen_size; - float z_far; - float z_near; - - bool orthogonal; - float intensity_div_r6; - float radius; - float bias; - - vec4 proj_info; - vec2 pixel_size; - float proj_scale; - uint pad; -} -params; - -vec3 reconstructCSPosition(vec2 S, float z) { - if (params.orthogonal) { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw), z); - } else { - return vec3((S.xy * params.proj_info.xy + params.proj_info.zw) * z, z); - } -} - -vec3 getPosition(ivec2 ssP) { - vec3 P; -#ifdef USE_HALF_SIZE - P.z = texelFetch(source_depth_mipmaps, ssP, 0).r; - P.z = -P.z; -#else - P.z = texelFetch(source_depth, ssP, 0).r; - - P.z = P.z * 2.0 - 1.0; - if (params.orthogonal) { - P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); - } - P.z = -P.z; -#endif - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - return P; -} - -/** Returns a unit vector and a screen-space radius for the tap on a unit disk (the caller should scale by the actual disk radius) */ -vec2 tapLocation(int sampleNumber, float spinAngle, out float ssR) { - // Radius relative to ssR - float alpha = (float(sampleNumber) + 0.5) * (1.0 / float(NUM_SAMPLES)); - float angle = alpha * (float(NUM_SPIRAL_TURNS) * 6.28) + spinAngle; - - ssR = alpha; - return vec2(cos(angle), sin(angle)); -} - -/** Read the camera-space position of the point at screen-space pixel ssP + unitOffset * ssR. Assumes length(unitOffset) == 1 */ -vec3 getOffsetPosition(ivec2 ssP, float ssR) { - // Derivation: - // mipLevel = floor(log(ssR / MAX_OFFSET)); - - int mipLevel = clamp(int(floor(log2(ssR))) - LOG_MAX_OFFSET, 0, MAX_MIP_LEVEL); - - vec3 P; - - // We need to divide by 2^mipLevel to read the appropriately scaled coordinate from a MIP-map. - // Manually clamp to the texture size because texelFetch bypasses the texture unit - ivec2 mipP = clamp(ssP >> mipLevel, ivec2(0), (params.screen_size >> mipLevel) - ivec2(1)); - -#ifdef USE_HALF_SIZE - P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel).r; - P.z = -P.z; -#else - if (mipLevel < 1) { - //read from depth buffer - P.z = texelFetch(source_depth, mipP, 0).r; - P.z = P.z * 2.0 - 1.0; - if (params.orthogonal) { - P.z = ((P.z + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - P.z = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - P.z * (params.z_far - params.z_near)); - } - P.z = -P.z; - - } else { - //read from mipmaps - P.z = texelFetch(source_depth_mipmaps, mipP, mipLevel - 1).r; - P.z = -P.z; - } -#endif - - // Offset to pixel center - P = reconstructCSPosition(vec2(ssP) + vec2(0.5), P.z); - - return P; -} - -/** Compute the occlusion due to sample with index \a i about the pixel at \a ssC that corresponds - to camera-space point \a C with unit normal \a n_C, using maximum screen-space sampling radius \a ssDiskRadius - - Note that units of H() in the HPG12 paper are meters, not - unitless. The whole falloff/sampling function is therefore - unitless. In this implementation, we factor out (9 / radius). - - Four versions of the falloff function are implemented below -*/ -float sampleAO(in ivec2 ssC, in vec3 C, in vec3 n_C, in float ssDiskRadius, in float p_radius, in int tapIndex, in float randomPatternRotationAngle) { - // Offset on the unit disk, spun for this pixel - float ssR; - vec2 unitOffset = tapLocation(tapIndex, randomPatternRotationAngle, ssR); - ssR *= ssDiskRadius; - - ivec2 ssP = ivec2(ssR * unitOffset) + ssC; - - if (any(lessThan(ssP, ivec2(0))) || any(greaterThanEqual(ssP, params.screen_size))) { - return 0.0; - } - - // The occluding point in camera space - vec3 Q = getOffsetPosition(ssP, ssR); - - vec3 v = Q - C; - - float vv = dot(v, v); - float vn = dot(v, n_C); - - const float epsilon = 0.01; - float radius2 = p_radius * p_radius; - - // A: From the HPG12 paper - // Note large epsilon to avoid overdarkening within cracks - //return float(vv < radius2) * max((vn - bias) / (epsilon + vv), 0.0) * radius2 * 0.6; - - // B: Smoother transition to zero (lowers contrast, smoothing out corners). [Recommended] - float f = max(radius2 - vv, 0.0); - return f * f * f * max((vn - params.bias) / (epsilon + vv), 0.0); - - // C: Medium contrast (which looks better at high radii), no division. Note that the - // contribution still falls off with radius^2, but we've adjusted the rate in a way that is - // more computationally efficient and happens to be aesthetically pleasing. - // return 4.0 * max(1.0 - vv * invRadius2, 0.0) * max(vn - bias, 0.0); - - // D: Low contrast, no division operation - // return 2.0 * float(vv < radius * radius) * max(vn - bias, 0.0); -} - -void main() { - // Pixel being shaded - ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing - return; - } - - // World space point being shaded - vec3 C = getPosition(ssC); - -#ifdef USE_HALF_SIZE - vec3 n_C = texelFetch(source_normal, ssC << 1, 0).xyz * 2.0 - 1.0; -#else - vec3 n_C = texelFetch(source_normal, ssC, 0).xyz * 2.0 - 1.0; -#endif - n_C = normalize(n_C); - n_C.y = -n_C.y; //because this code reads flipped - - // Hash function used in the HPG12 AlchemyAO paper - float randomPatternRotationAngle = mod(float((3 * ssC.x ^ ssC.y + ssC.x * ssC.y) * 10), TWO_PI); - - // Reconstruct normals from positions. These will lead to 1-pixel black lines - // at depth discontinuities, however the blur will wipe those out so they are not visible - // in the final image. - - // Choose the screen-space sample radius - // proportional to the projected area of the sphere - - float ssDiskRadius = -params.proj_scale * params.radius; - if (!params.orthogonal) { - ssDiskRadius = -params.proj_scale * params.radius / C.z; - } - float sum = 0.0; - for (int i = 0; i < NUM_SAMPLES; ++i) { - sum += sampleAO(ssC, C, n_C, ssDiskRadius, params.radius, i, randomPatternRotationAngle); - } - - float A = max(0.0, 1.0 - sum * params.intensity_div_r6 * (5.0 / float(NUM_SAMPLES))); - - imageStore(dest_image, ssC, vec4(A)); -} diff --git a/servers/visual/rasterizer_rd/shaders/ssao_blur.glsl b/servers/visual/rasterizer_rd/shaders/ssao_blur.glsl deleted file mode 100644 index e90c788e08..0000000000 --- a/servers/visual/rasterizer_rd/shaders/ssao_blur.glsl +++ /dev/null @@ -1,157 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform sampler2D source_ssao; -layout(set = 1, binding = 0) uniform sampler2D source_depth; -#ifdef MODE_UPSCALE -layout(set = 2, binding = 0) uniform sampler2D source_depth_mipmaps; -#endif - -layout(r8, set = 3, binding = 0) uniform restrict writeonly image2D dest_image; - -////////////////////////////////////////////////////////////////////////////////////////////// -// Tunable Parameters: - -layout(push_constant, binding = 1, std430) uniform Params { - float edge_sharpness; /** Increase to make depth edges crisper. Decrease to reduce flicker. */ - int filter_scale; - float z_far; - float z_near; - bool orthogonal; - uint pad0; - uint pad1; - uint pad2; - ivec2 axis; /** (1, 0) or (0, 1) */ - ivec2 screen_size; -} -params; - -/** Filter radius in pixels. This will be multiplied by SCALE. */ -#define R (4) - -////////////////////////////////////////////////////////////////////////////////////////////// - -// Gaussian coefficients -const float gaussian[R + 1] = - //float[](0.356642, 0.239400, 0.072410, 0.009869); - //float[](0.398943, 0.241971, 0.053991, 0.004432, 0.000134); // stddev = 1.0 - float[](0.153170, 0.144893, 0.122649, 0.092902, 0.062970); // stddev = 2.0 -//float[](0.111220, 0.107798, 0.098151, 0.083953, 0.067458, 0.050920, 0.036108); // stddev = 3.0 - -void main() { - - // Pixel being shaded - ivec2 ssC = ivec2(gl_GlobalInvocationID.xy); - if (any(greaterThan(ssC, params.screen_size))) { //too large, do nothing - return; - } - -#ifdef MODE_UPSCALE - - //closest one should be the same pixel, but check nearby just in case - float depth = texelFetch(source_depth, ssC, 0).r; - - depth = depth * 2.0 - 1.0; - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } - - vec2 pixel_size = 1.0 / vec2(params.screen_size); - vec2 closest_uv = vec2(ssC) * pixel_size + pixel_size * 0.5; - vec2 from_uv = closest_uv; - vec2 ps2 = pixel_size; // * 2.0; - - float closest_depth = abs(textureLod(source_depth_mipmaps, closest_uv, 0.0).r - depth); - - vec2 offsets[4] = vec2[](vec2(ps2.x, 0), vec2(-ps2.x, 0), vec2(0, ps2.y), vec2(0, -ps2.y)); - for (int i = 0; i < 4; i++) { - vec2 neighbour = from_uv + offsets[i]; - float neighbour_depth = abs(textureLod(source_depth_mipmaps, neighbour, 0.0).r - depth); - if (neighbour_depth < closest_depth) { - closest_uv = neighbour; - closest_depth = neighbour_depth; - } - } - - float visibility = textureLod(source_ssao, closest_uv, 0.0).r; - imageStore(dest_image, ssC, vec4(visibility)); -#else - - float depth = texelFetch(source_depth, ssC, 0).r; - -#ifdef MODE_FULL_SIZE - depth = depth * 2.0 - 1.0; - - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } - -#endif - float depth_divide = 1.0 / params.z_far; - - //depth *= depth_divide; - - /* - if (depth > params.z_far * 0.999) { - discard; //skybox - } - */ - - float sum = texelFetch(source_ssao, ssC, 0).r; - - // Base weight for depth falloff. Increase this for more blurriness, - // decrease it for better edge discrimination - float BASE = gaussian[0]; - float totalWeight = BASE; - sum *= totalWeight; - - ivec2 clamp_limit = params.screen_size - ivec2(1); - - for (int r = -R; r <= R; ++r) { - // We already handled the zero case above. This loop should be unrolled and the static branch optimized out, - // so the IF statement has no runtime cost - if (r != 0) { - - ivec2 ppos = ssC + params.axis * (r * params.filter_scale); - float value = texelFetch(source_ssao, clamp(ppos, ivec2(0), clamp_limit), 0).r; - ivec2 rpos = clamp(ppos, ivec2(0), clamp_limit); - - float temp_depth = texelFetch(source_depth, rpos, 0).r; -#ifdef MODE_FULL_SIZE - temp_depth = temp_depth * 2.0 - 1.0; - if (params.orthogonal) { - temp_depth = ((temp_depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - temp_depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - temp_depth * (params.z_far - params.z_near)); - } - //temp_depth *= depth_divide; -#endif - // spatial domain: offset gaussian tap - float weight = 0.3 + gaussian[abs(r)]; - //weight *= max(0.0, dot(temp_normal, normal)); - - // range domain (the "bilateral" weight). As depth difference increases, decrease weight. - weight *= max(0.0, 1.0 - params.edge_sharpness * abs(temp_depth - depth)); - - sum += value * weight; - totalWeight += weight; - } - } - - const float epsilon = 0.0001; - float visibility = sum / (totalWeight + epsilon); - - imageStore(dest_image, ssC, vec4(visibility)); -#endif -} diff --git a/servers/visual/rasterizer_rd/shaders/ssao_minify.glsl b/servers/visual/rasterizer_rd/shaders/ssao_minify.glsl deleted file mode 100644 index 8728154347..0000000000 --- a/servers/visual/rasterizer_rd/shaders/ssao_minify.glsl +++ /dev/null @@ -1,48 +0,0 @@ -/* clang-format off */ -[compute] - -#version 450 - -VERSION_DEFINES - -layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in; -/* clang-format on */ - -layout(push_constant, binding = 1, std430) uniform Params { - vec2 pixel_size; - float z_far; - float z_near; - ivec2 source_size; - bool orthogonal; - uint pad; -} -params; - -#ifdef MINIFY_START -layout(set = 0, binding = 0) uniform sampler2D source_texture; -#else -layout(r32f, set = 0, binding = 0) uniform restrict readonly image2D source_image; -#endif -layout(r32f, set = 1, binding = 0) uniform restrict writeonly image2D dest_image; - -void main() { - - ivec2 pos = ivec2(gl_GlobalInvocationID.xy); - - if (any(greaterThan(pos, params.source_size >> 1))) { //too large, do nothing - return; - } - -#ifdef MINIFY_START - float depth = texelFetch(source_texture, pos << 1, 0).r * 2.0 - 1.0; - if (params.orthogonal) { - depth = ((depth + (params.z_far + params.z_near) / (params.z_far - params.z_near)) * (params.z_far - params.z_near)) / 2.0; - } else { - depth = 2.0 * params.z_near * params.z_far / (params.z_far + params.z_near - depth * (params.z_far - params.z_near)); - } -#else - float depth = imageLoad(source_image, pos << 1).r; -#endif - - imageStore(dest_image, pos, vec4(depth)); -} diff --git a/servers/visual/rasterizer_rd/shaders/tonemap.glsl b/servers/visual/rasterizer_rd/shaders/tonemap.glsl deleted file mode 100644 index 524ca5e2ea..0000000000 --- a/servers/visual/rasterizer_rd/shaders/tonemap.glsl +++ /dev/null @@ -1,305 +0,0 @@ -/* clang-format off */ -[vertex] - -#version 450 - -VERSION_DEFINES - -layout(location = 0) out vec2 uv_interp; -/* clang-format on */ - -void main() { - - vec2 base_arr[4] = vec2[](vec2(0.0, 0.0), vec2(0.0, 1.0), vec2(1.0, 1.0), vec2(1.0, 0.0)); - uv_interp = base_arr[gl_VertexIndex]; - gl_Position = vec4(uv_interp * 2.0 - 1.0, 0.0, 1.0); -} - -/* clang-format off */ -[fragment] - -#version 450 - -VERSION_DEFINES - -layout(location = 0) in vec2 uv_interp; -/* clang-format on */ - -layout(set = 0, binding = 0) uniform sampler2D source_color; -layout(set = 1, binding = 0) uniform sampler2D source_auto_exposure; -layout(set = 2, binding = 0) uniform sampler2D source_glow; -layout(set = 3, binding = 0) uniform sampler3D color_correction; - -layout(push_constant, binding = 1, std430) uniform Params { - vec3 bcs; - bool use_bcs; - - bool use_glow; - bool use_auto_exposure; - bool use_color_correction; - uint tonemapper; - - uvec2 glow_texture_size; - - float glow_intensity; - uint glow_level_flags; - uint glow_mode; - - float exposure; - float white; - float auto_exposure_grey; -} -params; - -layout(location = 0) out vec4 frag_color; - -#ifdef USE_GLOW_FILTER_BICUBIC -// w0, w1, w2, and w3 are the four cubic B-spline basis functions -float w0(float a) { - return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); -} - -float w1(float a) { - return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f); -} - -float w2(float a) { - return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f); -} - -float w3(float a) { - return (1.0f / 6.0f) * (a * a * a); -} - -// g0 and g1 are the two amplitude functions -float g0(float a) { - return w0(a) + w1(a); -} - -float g1(float a) { - return w2(a) + w3(a); -} - -// h0 and h1 are the two offset functions -float h0(float a) { - return -1.0f + w1(a) / (w0(a) + w1(a)); -} - -float h1(float a) { - return 1.0f + w3(a) / (w2(a) + w3(a)); -} - -vec4 texture2D_bicubic(sampler2D tex, vec2 uv, int p_lod) { - float lod = float(p_lod); - vec2 tex_size = vec2(params.glow_texture_size >> p_lod); - vec2 pixel_size = vec2(1.0f) / tex_size; - - uv = uv * tex_size + vec2(0.5f); - - vec2 iuv = floor(uv); - vec2 fuv = fract(uv); - - float g0x = g0(fuv.x); - float g1x = g1(fuv.x); - float h0x = h0(fuv.x); - float h1x = h1(fuv.x); - float h0y = h0(fuv.y); - float h1y = h1(fuv.y); - - vec2 p0 = (vec2(iuv.x + h0x, iuv.y + h0y) - vec2(0.5f)) * pixel_size; - vec2 p1 = (vec2(iuv.x + h1x, iuv.y + h0y) - vec2(0.5f)) * pixel_size; - vec2 p2 = (vec2(iuv.x + h0x, iuv.y + h1y) - vec2(0.5f)) * pixel_size; - vec2 p3 = (vec2(iuv.x + h1x, iuv.y + h1y) - vec2(0.5f)) * pixel_size; - - return (g0(fuv.y) * (g0x * textureLod(tex, p0, lod) + g1x * textureLod(tex, p1, lod))) + - (g1(fuv.y) * (g0x * textureLod(tex, p2, lod) + g1x * textureLod(tex, p3, lod))); -} - -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) texture2D_bicubic(m_tex, m_uv, m_lod) - -#else - -#define GLOW_TEXTURE_SAMPLE(m_tex, m_uv, m_lod) textureLod(m_tex, m_uv, float(m_lod)) - -#endif - -vec3 tonemap_filmic(vec3 color, float white) { - // exposure bias: input scale (color *= bias, white *= bias) to make the brightness consistent with other tonemappers - // also useful to scale the input to the range that the tonemapper is designed for (some require very high input values) - // has no effect on the curve's general shape or visual properties - const float exposure_bias = 2.0f; - const float A = 0.22f * exposure_bias * exposure_bias; // bias baked into constants for performance - const float B = 0.30f * exposure_bias; - const float C = 0.10f; - const float D = 0.20f; - const float E = 0.01f; - const float F = 0.30f; - - vec3 color_tonemapped = ((color * (A * color + C * B) + D * E) / (color * (A * color + B) + D * F)) - E / F; - float white_tonemapped = ((white * (A * white + C * B) + D * E) / (white * (A * white + B) + D * F)) - E / F; - - return color_tonemapped / white_tonemapped; -} - -vec3 tonemap_aces(vec3 color, float white) { - const float exposure_bias = 0.85f; - const float A = 2.51f * exposure_bias * exposure_bias; - const float B = 0.03f * exposure_bias; - const float C = 2.43f * exposure_bias * exposure_bias; - const float D = 0.59f * exposure_bias; - const float E = 0.14f; - - vec3 color_tonemapped = (color * (A * color + B)) / (color * (C * color + D) + E); - float white_tonemapped = (white * (A * white + B)) / (white * (C * white + D) + E); - - return color_tonemapped / white_tonemapped; -} - -vec3 tonemap_reinhard(vec3 color, float white) { - return (white * color + color) / (color * white + white); -} - -vec3 linear_to_srgb(vec3 color) { - //if going to srgb, clamp from 0 to 1. - color = clamp(color, vec3(0.0), vec3(1.0)); - const vec3 a = vec3(0.055f); - return mix((vec3(1.0f) + a) * pow(color.rgb, vec3(1.0f / 2.4f)) - a, 12.92f * color.rgb, lessThan(color.rgb, vec3(0.0031308f))); -} - -#define TONEMAPPER_LINEAR 0 -#define TONEMAPPER_REINHARD 1 -#define TONEMAPPER_FILMIC 2 -#define TONEMAPPER_ACES 3 - -vec3 apply_tonemapping(vec3 color, float white) { // inputs are LINEAR, always outputs clamped [0;1] color - - if (params.tonemapper == TONEMAPPER_LINEAR) { - return color; - } else if (params.tonemapper == TONEMAPPER_REINHARD) { - return tonemap_reinhard(color, white); - } else if (params.tonemapper == TONEMAPPER_FILMIC) { - return tonemap_filmic(color, white); - } else { //aces - return tonemap_aces(color, white); - } -} - -vec3 gather_glow(sampler2D tex, vec2 uv) { // sample all selected glow levels - vec3 glow = vec3(0.0f); - - if (bool(params.glow_level_flags & (1 << 0))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 0).rgb; - } - - if (bool(params.glow_level_flags & (1 << 1))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 1).rgb; - } - - if (bool(params.glow_level_flags & (1 << 2))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 2).rgb; - } - - if (bool(params.glow_level_flags & (1 << 3))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 3).rgb; - } - - if (bool(params.glow_level_flags & (1 << 4))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 4).rgb; - } - - if (bool(params.glow_level_flags & (1 << 5))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 5).rgb; - } - - if (bool(params.glow_level_flags & (1 << 6))) { - glow += GLOW_TEXTURE_SAMPLE(tex, uv, 6).rgb; - } - - return glow; -} - -#define GLOW_MODE_ADD 0 -#define GLOW_MODE_SCREEN 1 -#define GLOW_MODE_SOFTLIGHT 2 -#define GLOW_MODE_REPLACE 3 -#define GLOW_MODE_MIX 4 - -vec3 apply_glow(vec3 color, vec3 glow) { // apply glow using the selected blending mode - if (params.glow_mode == GLOW_MODE_ADD) { - return color + glow; - } else if (params.glow_mode == GLOW_MODE_SCREEN) { - //need color clamping - return max((color + glow) - (color * glow), vec3(0.0)); - } else if (params.glow_mode == GLOW_MODE_SOFTLIGHT) { - //need color clamping - glow = glow * vec3(0.5f) + vec3(0.5f); - - color.r = (glow.r <= 0.5f) ? (color.r - (1.0f - 2.0f * glow.r) * color.r * (1.0f - color.r)) : (((glow.r > 0.5f) && (color.r <= 0.25f)) ? (color.r + (2.0f * glow.r - 1.0f) * (4.0f * color.r * (4.0f * color.r + 1.0f) * (color.r - 1.0f) + 7.0f * color.r)) : (color.r + (2.0f * glow.r - 1.0f) * (sqrt(color.r) - color.r))); - color.g = (glow.g <= 0.5f) ? (color.g - (1.0f - 2.0f * glow.g) * color.g * (1.0f - color.g)) : (((glow.g > 0.5f) && (color.g <= 0.25f)) ? (color.g + (2.0f * glow.g - 1.0f) * (4.0f * color.g * (4.0f * color.g + 1.0f) * (color.g - 1.0f) + 7.0f * color.g)) : (color.g + (2.0f * glow.g - 1.0f) * (sqrt(color.g) - color.g))); - color.b = (glow.b <= 0.5f) ? (color.b - (1.0f - 2.0f * glow.b) * color.b * (1.0f - color.b)) : (((glow.b > 0.5f) && (color.b <= 0.25f)) ? (color.b + (2.0f * glow.b - 1.0f) * (4.0f * color.b * (4.0f * color.b + 1.0f) * (color.b - 1.0f) + 7.0f * color.b)) : (color.b + (2.0f * glow.b - 1.0f) * (sqrt(color.b) - color.b))); - return color; - } else { //replace - return glow; - } -} - -vec3 apply_bcs(vec3 color, vec3 bcs) { - color = mix(vec3(0.0f), color, bcs.x); - color = mix(vec3(0.5f), color, bcs.y); - color = mix(vec3(dot(vec3(1.0f), color) * 0.33333f), color, bcs.z); - - return color; -} - -vec3 apply_color_correction(vec3 color, sampler3D correction_tex) { - return texture(correction_tex, color).rgb; -} - -void main() { - vec3 color = textureLod(source_color, uv_interp, 0.0f).rgb; - - // Exposure - - if (params.use_auto_exposure) { - color /= texelFetch(source_auto_exposure, ivec2(0, 0), 0).r / params.auto_exposure_grey; - } - - color *= params.exposure; - - // Early Tonemap & SRGB Conversion - - if (params.use_glow && params.glow_mode == GLOW_MODE_MIX) { - - vec3 glow = gather_glow(source_glow, uv_interp); - color.rgb = mix(color.rgb, glow, params.glow_intensity); - } - - color = apply_tonemapping(color, params.white); - - color = linear_to_srgb(color); // regular linear -> SRGB conversion - - // Glow - - if (params.use_glow && params.glow_mode != GLOW_MODE_MIX) { - - vec3 glow = gather_glow(source_glow, uv_interp) * params.glow_intensity; - - // high dynamic range -> SRGB - glow = apply_tonemapping(glow, params.white); - glow = linear_to_srgb(glow); - - color = apply_glow(color, glow); - } - - // Additional effects - - if (params.use_bcs) { - color = apply_bcs(color, params.bcs); - } - - if (params.use_color_correction) { - color = apply_color_correction(color, color_correction); - } - - frag_color = vec4(color, 1.0f); -} diff --git a/servers/visual/rendering_device.cpp b/servers/visual/rendering_device.cpp deleted file mode 100644 index 3c1795161d..0000000000 --- a/servers/visual/rendering_device.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************/ -/* rendering_device.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "rendering_device.h" - -RenderingDevice *RenderingDevice::singleton = NULL; - -RenderingDevice *RenderingDevice::get_singleton() { - return singleton; -} - -RenderingDevice::ShaderCompileFunction RenderingDevice::compile_function = NULL; -RenderingDevice::ShaderCacheFunction RenderingDevice::cache_function = NULL; - -void RenderingDevice::shader_set_compile_function(ShaderCompileFunction p_function) { - compile_function = p_function; -} -void RenderingDevice::shader_set_cache_function(ShaderCacheFunction p_function) { - cache_function = p_function; -} - -Vector RenderingDevice::shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error, bool p_allow_cache) { - if (p_allow_cache && cache_function) { - Vector cache = cache_function(p_stage, p_source_code, p_language); - if (cache.size()) { - return cache; - } - } - - ERR_FAIL_COND_V(!compile_function, Vector()); - - return compile_function(p_stage, p_source_code, p_language, r_error); -} - -RenderingDevice::RenderingDevice() { - singleton = this; -} diff --git a/servers/visual/rendering_device.h b/servers/visual/rendering_device.h deleted file mode 100644 index 4705bcaa75..0000000000 --- a/servers/visual/rendering_device.h +++ /dev/null @@ -1,1032 +0,0 @@ -/*************************************************************************/ -/* rendering_device.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef RENDERING_DEVICE_H -#define RENDERING_DEVICE_H - -#include "core/object.h" -#include "servers/display_server.h" - -class RenderingDevice : public Object { - GDCLASS(RenderingDevice, Object) -public: - enum ShaderStage { - SHADER_STAGE_VERTEX, - SHADER_STAGE_FRAGMENT, - SHADER_STAGE_TESSELATION_CONTROL, - SHADER_STAGE_TESSELATION_EVALUATION, - SHADER_STAGE_COMPUTE, - SHADER_STAGE_MAX, - SHADER_STAGE_VERTEX_BIT = (1 << SHADER_STAGE_VERTEX), - SHADER_STAGE_FRAGMENT_BIT = (1 << SHADER_STAGE_FRAGMENT), - SHADER_STAGE_TESSELATION_CONTROL_BIT = (1 << SHADER_STAGE_TESSELATION_CONTROL), - SHADER_STAGE_TESSELATION_EVALUATION_BIT = (1 << SHADER_STAGE_TESSELATION_EVALUATION), - SHADER_STAGE_COMPUTE_BIT = (1 << SHADER_STAGE_COMPUTE), - }; - - enum ShaderLanguage { - SHADER_LANGUAGE_GLSL, - SHADER_LANGUAGE_HLSL - }; - - typedef Vector (*ShaderCompileFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language, String *r_error); - typedef Vector (*ShaderCacheFunction)(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language); - -private: - static ShaderCompileFunction compile_function; - static ShaderCacheFunction cache_function; - - static RenderingDevice *singleton; - -public: - //base numeric ID for all types - enum { - INVALID_ID = -1 - }; - - /*****************/ - /**** GENERIC ****/ - /*****************/ - - enum CompareOperator { - COMPARE_OP_NEVER, - COMPARE_OP_LESS, - COMPARE_OP_EQUAL, - COMPARE_OP_LESS_OR_EQUAL, - COMPARE_OP_GREATER, - COMPARE_OP_NOT_EQUAL, - COMPARE_OP_GREATER_OR_EQUAL, - COMPARE_OP_ALWAYS, - COMPARE_OP_MAX //not an actual operator, just the amount of operators :D - }; - - enum DataFormat { - DATA_FORMAT_R4G4_UNORM_PACK8, - DATA_FORMAT_R4G4B4A4_UNORM_PACK16, - DATA_FORMAT_B4G4R4A4_UNORM_PACK16, - DATA_FORMAT_R5G6B5_UNORM_PACK16, - DATA_FORMAT_B5G6R5_UNORM_PACK16, - DATA_FORMAT_R5G5B5A1_UNORM_PACK16, - DATA_FORMAT_B5G5R5A1_UNORM_PACK16, - DATA_FORMAT_A1R5G5B5_UNORM_PACK16, - DATA_FORMAT_R8_UNORM, - DATA_FORMAT_R8_SNORM, - DATA_FORMAT_R8_USCALED, - DATA_FORMAT_R8_SSCALED, - DATA_FORMAT_R8_UINT, - DATA_FORMAT_R8_SINT, - DATA_FORMAT_R8_SRGB, - DATA_FORMAT_R8G8_UNORM, - DATA_FORMAT_R8G8_SNORM, - DATA_FORMAT_R8G8_USCALED, - DATA_FORMAT_R8G8_SSCALED, - DATA_FORMAT_R8G8_UINT, - DATA_FORMAT_R8G8_SINT, - DATA_FORMAT_R8G8_SRGB, - DATA_FORMAT_R8G8B8_UNORM, - DATA_FORMAT_R8G8B8_SNORM, - DATA_FORMAT_R8G8B8_USCALED, - DATA_FORMAT_R8G8B8_SSCALED, - DATA_FORMAT_R8G8B8_UINT, - DATA_FORMAT_R8G8B8_SINT, - DATA_FORMAT_R8G8B8_SRGB, - DATA_FORMAT_B8G8R8_UNORM, - DATA_FORMAT_B8G8R8_SNORM, - DATA_FORMAT_B8G8R8_USCALED, - DATA_FORMAT_B8G8R8_SSCALED, - DATA_FORMAT_B8G8R8_UINT, - DATA_FORMAT_B8G8R8_SINT, - DATA_FORMAT_B8G8R8_SRGB, - DATA_FORMAT_R8G8B8A8_UNORM, - DATA_FORMAT_R8G8B8A8_SNORM, - DATA_FORMAT_R8G8B8A8_USCALED, - DATA_FORMAT_R8G8B8A8_SSCALED, - DATA_FORMAT_R8G8B8A8_UINT, - DATA_FORMAT_R8G8B8A8_SINT, - DATA_FORMAT_R8G8B8A8_SRGB, - DATA_FORMAT_B8G8R8A8_UNORM, - DATA_FORMAT_B8G8R8A8_SNORM, - DATA_FORMAT_B8G8R8A8_USCALED, - DATA_FORMAT_B8G8R8A8_SSCALED, - DATA_FORMAT_B8G8R8A8_UINT, - DATA_FORMAT_B8G8R8A8_SINT, - DATA_FORMAT_B8G8R8A8_SRGB, - DATA_FORMAT_A8B8G8R8_UNORM_PACK32, - DATA_FORMAT_A8B8G8R8_SNORM_PACK32, - DATA_FORMAT_A8B8G8R8_USCALED_PACK32, - DATA_FORMAT_A8B8G8R8_SSCALED_PACK32, - DATA_FORMAT_A8B8G8R8_UINT_PACK32, - DATA_FORMAT_A8B8G8R8_SINT_PACK32, - DATA_FORMAT_A8B8G8R8_SRGB_PACK32, - DATA_FORMAT_A2R10G10B10_UNORM_PACK32, - DATA_FORMAT_A2R10G10B10_SNORM_PACK32, - DATA_FORMAT_A2R10G10B10_USCALED_PACK32, - DATA_FORMAT_A2R10G10B10_SSCALED_PACK32, - DATA_FORMAT_A2R10G10B10_UINT_PACK32, - DATA_FORMAT_A2R10G10B10_SINT_PACK32, - DATA_FORMAT_A2B10G10R10_UNORM_PACK32, - DATA_FORMAT_A2B10G10R10_SNORM_PACK32, - DATA_FORMAT_A2B10G10R10_USCALED_PACK32, - DATA_FORMAT_A2B10G10R10_SSCALED_PACK32, - DATA_FORMAT_A2B10G10R10_UINT_PACK32, - DATA_FORMAT_A2B10G10R10_SINT_PACK32, - DATA_FORMAT_R16_UNORM, - DATA_FORMAT_R16_SNORM, - DATA_FORMAT_R16_USCALED, - DATA_FORMAT_R16_SSCALED, - DATA_FORMAT_R16_UINT, - DATA_FORMAT_R16_SINT, - DATA_FORMAT_R16_SFLOAT, - DATA_FORMAT_R16G16_UNORM, - DATA_FORMAT_R16G16_SNORM, - DATA_FORMAT_R16G16_USCALED, - DATA_FORMAT_R16G16_SSCALED, - DATA_FORMAT_R16G16_UINT, - DATA_FORMAT_R16G16_SINT, - DATA_FORMAT_R16G16_SFLOAT, - DATA_FORMAT_R16G16B16_UNORM, - DATA_FORMAT_R16G16B16_SNORM, - DATA_FORMAT_R16G16B16_USCALED, - DATA_FORMAT_R16G16B16_SSCALED, - DATA_FORMAT_R16G16B16_UINT, - DATA_FORMAT_R16G16B16_SINT, - DATA_FORMAT_R16G16B16_SFLOAT, - DATA_FORMAT_R16G16B16A16_UNORM, - DATA_FORMAT_R16G16B16A16_SNORM, - DATA_FORMAT_R16G16B16A16_USCALED, - DATA_FORMAT_R16G16B16A16_SSCALED, - DATA_FORMAT_R16G16B16A16_UINT, - DATA_FORMAT_R16G16B16A16_SINT, - DATA_FORMAT_R16G16B16A16_SFLOAT, - DATA_FORMAT_R32_UINT, - DATA_FORMAT_R32_SINT, - DATA_FORMAT_R32_SFLOAT, - DATA_FORMAT_R32G32_UINT, - DATA_FORMAT_R32G32_SINT, - DATA_FORMAT_R32G32_SFLOAT, - DATA_FORMAT_R32G32B32_UINT, - DATA_FORMAT_R32G32B32_SINT, - DATA_FORMAT_R32G32B32_SFLOAT, - DATA_FORMAT_R32G32B32A32_UINT, - DATA_FORMAT_R32G32B32A32_SINT, - DATA_FORMAT_R32G32B32A32_SFLOAT, - DATA_FORMAT_R64_UINT, - DATA_FORMAT_R64_SINT, - DATA_FORMAT_R64_SFLOAT, - DATA_FORMAT_R64G64_UINT, - DATA_FORMAT_R64G64_SINT, - DATA_FORMAT_R64G64_SFLOAT, - DATA_FORMAT_R64G64B64_UINT, - DATA_FORMAT_R64G64B64_SINT, - DATA_FORMAT_R64G64B64_SFLOAT, - DATA_FORMAT_R64G64B64A64_UINT, - DATA_FORMAT_R64G64B64A64_SINT, - DATA_FORMAT_R64G64B64A64_SFLOAT, - DATA_FORMAT_B10G11R11_UFLOAT_PACK32, - DATA_FORMAT_E5B9G9R9_UFLOAT_PACK32, - DATA_FORMAT_D16_UNORM, - DATA_FORMAT_X8_D24_UNORM_PACK32, - DATA_FORMAT_D32_SFLOAT, - DATA_FORMAT_S8_UINT, - DATA_FORMAT_D16_UNORM_S8_UINT, - DATA_FORMAT_D24_UNORM_S8_UINT, - DATA_FORMAT_D32_SFLOAT_S8_UINT, - DATA_FORMAT_BC1_RGB_UNORM_BLOCK, - DATA_FORMAT_BC1_RGB_SRGB_BLOCK, - DATA_FORMAT_BC1_RGBA_UNORM_BLOCK, - DATA_FORMAT_BC1_RGBA_SRGB_BLOCK, - DATA_FORMAT_BC2_UNORM_BLOCK, - DATA_FORMAT_BC2_SRGB_BLOCK, - DATA_FORMAT_BC3_UNORM_BLOCK, - DATA_FORMAT_BC3_SRGB_BLOCK, - DATA_FORMAT_BC4_UNORM_BLOCK, - DATA_FORMAT_BC4_SNORM_BLOCK, - DATA_FORMAT_BC5_UNORM_BLOCK, - DATA_FORMAT_BC5_SNORM_BLOCK, - DATA_FORMAT_BC6H_UFLOAT_BLOCK, - DATA_FORMAT_BC6H_SFLOAT_BLOCK, - DATA_FORMAT_BC7_UNORM_BLOCK, - DATA_FORMAT_BC7_SRGB_BLOCK, - DATA_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, - DATA_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, - DATA_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, - DATA_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, - DATA_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, - DATA_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, - DATA_FORMAT_EAC_R11_UNORM_BLOCK, - DATA_FORMAT_EAC_R11_SNORM_BLOCK, - DATA_FORMAT_EAC_R11G11_UNORM_BLOCK, - DATA_FORMAT_EAC_R11G11_SNORM_BLOCK, - DATA_FORMAT_ASTC_4x4_UNORM_BLOCK, - DATA_FORMAT_ASTC_4x4_SRGB_BLOCK, - DATA_FORMAT_ASTC_5x4_UNORM_BLOCK, - DATA_FORMAT_ASTC_5x4_SRGB_BLOCK, - DATA_FORMAT_ASTC_5x5_UNORM_BLOCK, - DATA_FORMAT_ASTC_5x5_SRGB_BLOCK, - DATA_FORMAT_ASTC_6x5_UNORM_BLOCK, - DATA_FORMAT_ASTC_6x5_SRGB_BLOCK, - DATA_FORMAT_ASTC_6x6_UNORM_BLOCK, - DATA_FORMAT_ASTC_6x6_SRGB_BLOCK, - DATA_FORMAT_ASTC_8x5_UNORM_BLOCK, - DATA_FORMAT_ASTC_8x5_SRGB_BLOCK, - DATA_FORMAT_ASTC_8x6_UNORM_BLOCK, - DATA_FORMAT_ASTC_8x6_SRGB_BLOCK, - DATA_FORMAT_ASTC_8x8_UNORM_BLOCK, - DATA_FORMAT_ASTC_8x8_SRGB_BLOCK, - DATA_FORMAT_ASTC_10x5_UNORM_BLOCK, - DATA_FORMAT_ASTC_10x5_SRGB_BLOCK, - DATA_FORMAT_ASTC_10x6_UNORM_BLOCK, - DATA_FORMAT_ASTC_10x6_SRGB_BLOCK, - DATA_FORMAT_ASTC_10x8_UNORM_BLOCK, - DATA_FORMAT_ASTC_10x8_SRGB_BLOCK, - DATA_FORMAT_ASTC_10x10_UNORM_BLOCK, - DATA_FORMAT_ASTC_10x10_SRGB_BLOCK, - DATA_FORMAT_ASTC_12x10_UNORM_BLOCK, - DATA_FORMAT_ASTC_12x10_SRGB_BLOCK, - DATA_FORMAT_ASTC_12x12_UNORM_BLOCK, - DATA_FORMAT_ASTC_12x12_SRGB_BLOCK, - DATA_FORMAT_G8B8G8R8_422_UNORM, - DATA_FORMAT_B8G8R8G8_422_UNORM, - DATA_FORMAT_G8_B8_R8_3PLANE_420_UNORM, - DATA_FORMAT_G8_B8R8_2PLANE_420_UNORM, - DATA_FORMAT_G8_B8_R8_3PLANE_422_UNORM, - DATA_FORMAT_G8_B8R8_2PLANE_422_UNORM, - DATA_FORMAT_G8_B8_R8_3PLANE_444_UNORM, - DATA_FORMAT_R10X6_UNORM_PACK16, - DATA_FORMAT_R10X6G10X6_UNORM_2PACK16, - DATA_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, - DATA_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16, - DATA_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16, - DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_420_UNORM_3PACK16, - DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, - DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_422_UNORM_3PACK16, - DATA_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, - DATA_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, - DATA_FORMAT_R12X4_UNORM_PACK16, - DATA_FORMAT_R12X4G12X4_UNORM_2PACK16, - DATA_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16, - DATA_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16, - DATA_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16, - DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_420_UNORM_3PACK16, - DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, - DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_422_UNORM_3PACK16, - DATA_FORMAT_G12X4_B12X4R12X4_2PLANE_422_UNORM_3PACK16, - DATA_FORMAT_G12X4_B12X4_R12X4_3PLANE_444_UNORM_3PACK16, - DATA_FORMAT_G16B16G16R16_422_UNORM, - DATA_FORMAT_B16G16R16G16_422_UNORM, - DATA_FORMAT_G16_B16_R16_3PLANE_420_UNORM, - DATA_FORMAT_G16_B16R16_2PLANE_420_UNORM, - DATA_FORMAT_G16_B16_R16_3PLANE_422_UNORM, - DATA_FORMAT_G16_B16R16_2PLANE_422_UNORM, - DATA_FORMAT_G16_B16_R16_3PLANE_444_UNORM, - DATA_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG, - DATA_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG, - DATA_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG, - DATA_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG, - DATA_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG, - DATA_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG, - DATA_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG, - DATA_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG, - DATA_FORMAT_MAX - }; - - /*****************/ - /**** TEXTURE ****/ - /*****************/ - - enum TextureType { - TEXTURE_TYPE_1D, - TEXTURE_TYPE_2D, - TEXTURE_TYPE_3D, - TEXTURE_TYPE_CUBE, - TEXTURE_TYPE_1D_ARRAY, - TEXTURE_TYPE_2D_ARRAY, - TEXTURE_TYPE_CUBE_ARRAY, - TEXTURE_TYPE_MAX - }; - - enum TextureSamples { - TEXTURE_SAMPLES_1, - TEXTURE_SAMPLES_2, - TEXTURE_SAMPLES_4, - TEXTURE_SAMPLES_8, - TEXTURE_SAMPLES_16, - TEXTURE_SAMPLES_32, - TEXTURE_SAMPLES_64, - TEXTURE_SAMPLES_MAX - }; - - enum TextureUsageBits { - TEXTURE_USAGE_SAMPLING_BIT = (1 << 0), - TEXTURE_USAGE_COLOR_ATTACHMENT_BIT = (1 << 1), - TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT = (1 << 2), - TEXTURE_USAGE_STORAGE_BIT = (1 << 3), - TEXTURE_USAGE_STORAGE_ATOMIC_BIT = (1 << 4), - TEXTURE_USAGE_CPU_READ_BIT = (1 << 5), - TEXTURE_USAGE_CAN_UPDATE_BIT = (1 << 6), - TEXTURE_USAGE_CAN_COPY_FROM_BIT = (1 << 7), - TEXTURE_USAGE_CAN_COPY_TO_BIT = (1 << 8), - TEXTURE_USAGE_RESOLVE_ATTACHMENT_BIT = (1 << 9), - }; - - enum TextureSwizzle { - TEXTURE_SWIZZLE_IDENTITY, - TEXTURE_SWIZZLE_ZERO, - TEXTURE_SWIZZLE_ONE, - TEXTURE_SWIZZLE_R, - TEXTURE_SWIZZLE_G, - TEXTURE_SWIZZLE_B, - TEXTURE_SWIZZLE_A, - TEXTURE_SWIZZLE_MAX - }; - - struct TextureFormat { - DataFormat format; - uint32_t width; - uint32_t height; - uint32_t depth; - uint32_t array_layers; - uint32_t mipmaps; - TextureType type; - TextureSamples samples; - uint32_t usage_bits; - Vector shareable_formats; - - TextureFormat() { - format = DATA_FORMAT_R8_UNORM; - width = 1; - height = 1; - depth = 1; - array_layers = 1; - mipmaps = 1; - type = TEXTURE_TYPE_2D; - samples = TEXTURE_SAMPLES_1; - usage_bits = 0; - } - }; - - struct TextureView { - DataFormat format_override; - TextureSwizzle swizzle_r; - TextureSwizzle swizzle_g; - TextureSwizzle swizzle_b; - TextureSwizzle swizzle_a; - - TextureView() { - format_override = DATA_FORMAT_MAX; //means, use same as format - swizzle_r = TEXTURE_SWIZZLE_R; - swizzle_g = TEXTURE_SWIZZLE_G; - swizzle_b = TEXTURE_SWIZZLE_B; - swizzle_a = TEXTURE_SWIZZLE_A; - } - }; - - virtual RID texture_create(const TextureFormat &p_format, const TextureView &p_view, const Vector> &p_data = Vector>()) = 0; - virtual RID texture_create_shared(const TextureView &p_view, RID p_with_texture) = 0; - - enum TextureSliceType { - TEXTURE_SLICE_2D, - TEXTURE_SLICE_CUBEMAP, - TEXTURE_SLICE_3D, - }; - - virtual RID texture_create_shared_from_slice(const TextureView &p_view, RID p_with_texture, uint32_t p_layer, uint32_t p_mipmap, TextureSliceType p_slice_type = TEXTURE_SLICE_2D) = 0; - - virtual Error texture_update(RID p_texture, uint32_t p_layer, const Vector &p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the beginning of the frame, unless sync with draw is used, which is used to mix updates with draw calls - virtual Vector texture_get_data(RID p_texture, uint32_t p_layer) = 0; // CPU textures will return immediately, while GPU textures will most likely force a flush - - virtual bool texture_is_format_supported_for_usage(DataFormat p_format, uint32_t p_usage) const = 0; - virtual bool texture_is_shared(RID p_texture) = 0; - virtual bool texture_is_valid(RID p_texture) = 0; - - virtual Error texture_copy(RID p_from_texture, RID p_to_texture, const Vector3 &p_from, const Vector3 &p_to, const Vector3 &p_size, uint32_t p_src_mipmap, uint32_t p_dst_mipmap, uint32_t p_src_layer, uint32_t p_dst_layer, bool p_sync_with_draw = false) = 0; - virtual Error texture_clear(RID p_texture, const Color &p_color, uint32_t p_base_mipmap, uint32_t p_mipmaps, uint32_t p_base_layer, uint32_t p_layers, bool p_sync_with_draw = false) = 0; - - /*********************/ - /**** FRAMEBUFFER ****/ - /*********************/ - - struct AttachmentFormat { - DataFormat format; - TextureSamples samples; - uint32_t usage_flags; - AttachmentFormat() { - format = DATA_FORMAT_R8G8B8A8_UNORM; - samples = TEXTURE_SAMPLES_1; - usage_flags = 0; - } - }; - - typedef int64_t FramebufferFormatID; - - // This ID is warranted to be unique for the same formats, does not need to be freed - virtual FramebufferFormatID framebuffer_format_create(const Vector &p_format) = 0; - virtual TextureSamples framebuffer_format_get_texture_samples(FramebufferFormatID p_format) = 0; - - virtual RID framebuffer_create(const Vector &p_texture_attachments, FramebufferFormatID p_format_check = INVALID_ID) = 0; - - virtual FramebufferFormatID framebuffer_get_format(RID p_framebuffer) = 0; - - /*****************/ - /**** SAMPLER ****/ - /*****************/ - - enum SamplerFilter { - SAMPLER_FILTER_NEAREST, - SAMPLER_FILTER_LINEAR, - }; - - enum SamplerRepeatMode { - SAMPLER_REPEAT_MODE_REPEAT, - SAMPLER_REPEAT_MODE_MIRRORED_REPEAT, - SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE, - SAMPLER_REPEAT_MODE_CLAMP_TO_BORDER, - SAMPLER_REPEAT_MODE_MIRROR_CLAMP_TO_EDGE, - SAMPLER_REPEAT_MODE_MAX - }; - - enum SamplerBorderColor { - SAMPLER_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, - SAMPLER_BORDER_COLOR_INT_TRANSPARENT_BLACK, - SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK, - SAMPLER_BORDER_COLOR_INT_OPAQUE_BLACK, - SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_WHITE, - SAMPLER_BORDER_COLOR_INT_OPAQUE_WHITE, - SAMPLER_BORDER_COLOR_MAX - }; - - struct SamplerState { - SamplerFilter mag_filter; - SamplerFilter min_filter; - SamplerFilter mip_filter; - SamplerRepeatMode repeat_u; - SamplerRepeatMode repeat_v; - SamplerRepeatMode repeat_w; - float lod_bias; - bool use_anisotropy; - float anisotropy_max; - bool enable_compare; - CompareOperator compare_op; - float min_lod; - float max_lod; - SamplerBorderColor border_color; - bool unnormalized_uvw; - - SamplerState() { - mag_filter = SAMPLER_FILTER_NEAREST; - min_filter = SAMPLER_FILTER_NEAREST; - mip_filter = SAMPLER_FILTER_NEAREST; - repeat_u = SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - repeat_v = SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - repeat_w = SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - lod_bias = 0; - use_anisotropy = false; - anisotropy_max = 1.0; - enable_compare = false; - compare_op = COMPARE_OP_ALWAYS; - min_lod = 0; - max_lod = 1e20; //something very large should do - border_color = SAMPLER_BORDER_COLOR_FLOAT_OPAQUE_BLACK; - unnormalized_uvw = false; - } - }; - - virtual RID sampler_create(const SamplerState &p_state) = 0; - - /**********************/ - /**** VERTEX ARRAY ****/ - /**********************/ - - enum VertexFrequency { - VERTEX_FREQUENCY_VERTEX, - VERTEX_FREQUENCY_INSTANCE, - }; - - struct VertexDescription { - uint32_t location; //shader location - uint32_t offset; - DataFormat format; - uint32_t stride; - VertexFrequency frequency; - VertexDescription() { - location = 0; - offset = 0; - stride = 0; - format = DATA_FORMAT_MAX; - frequency = VERTEX_FREQUENCY_VERTEX; - } - }; - virtual RID vertex_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector()) = 0; - - typedef int64_t VertexFormatID; - - // This ID is warranted to be unique for the same formats, does not need to be freed - virtual VertexFormatID vertex_format_create(const Vector &p_vertex_formats) = 0; - virtual RID vertex_array_create(uint32_t p_vertex_count, VertexFormatID p_vertex_format, const Vector &p_src_buffers) = 0; - - enum IndexBufferFormat { - INDEX_BUFFER_FORMAT_UINT16, - INDEX_BUFFER_FORMAT_UINT32, - }; - - virtual RID index_buffer_create(uint32_t p_size_indices, IndexBufferFormat p_format, const Vector &p_data = Vector(), bool p_use_restart_indices = false) = 0; - virtual RID index_array_create(RID p_index_buffer, uint32_t p_index_offset, uint32_t p_index_count) = 0; - - /****************/ - /**** SHADER ****/ - /****************/ - - virtual Vector shader_compile_from_source(ShaderStage p_stage, const String &p_source_code, ShaderLanguage p_language = SHADER_LANGUAGE_GLSL, String *r_error = NULL, bool p_allow_cache = true); - - static void shader_set_compile_function(ShaderCompileFunction p_function); - static void shader_set_cache_function(ShaderCacheFunction p_function); - - struct ShaderStageData { - ShaderStage shader_stage; - Vector spir_v; - - ShaderStageData() { - shader_stage = SHADER_STAGE_VERTEX; - } - }; - - virtual RID shader_create(const Vector &p_stages) = 0; - virtual uint32_t shader_get_vertex_input_attribute_mask(RID p_shader) = 0; - - /******************/ - /**** UNIFORMS ****/ - /******************/ - - enum UniformType { - UNIFORM_TYPE_SAMPLER, //for sampling only (sampler GLSL type) - UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, // for sampling only, but includes a texture, (samplerXX GLSL type), first a sampler then a texture - UNIFORM_TYPE_TEXTURE, //only texture, (textureXX GLSL type) - UNIFORM_TYPE_IMAGE, // storage image (imageXX GLSL type), for compute mostly - UNIFORM_TYPE_TEXTURE_BUFFER, // buffer texture (or TBO, textureBuffer type) - UNIFORM_TYPE_SAMPLER_WITH_TEXTURE_BUFFER, // buffer texture with a sampler(or TBO, samplerBuffer type) - UNIFORM_TYPE_IMAGE_BUFFER, //texel buffer, (imageBuffer type), for compute mostly - UNIFORM_TYPE_UNIFORM_BUFFER, //regular uniform buffer (or UBO). - UNIFORM_TYPE_STORAGE_BUFFER, //storage buffer ("buffer" qualifier) like UBO, but supports storage, for compute mostly - UNIFORM_TYPE_INPUT_ATTACHMENT, //used for sub-pass read/write, for compute mostly - UNIFORM_TYPE_MAX - }; - - virtual RID uniform_buffer_create(uint32_t p_size_bytes, const Vector &p_data = Vector()) = 0; - virtual RID storage_buffer_create(uint32_t p_size, const Vector &p_data = Vector()) = 0; - virtual RID texture_buffer_create(uint32_t p_size_elements, DataFormat p_format, const Vector &p_data = Vector()) = 0; - - struct Uniform { - UniformType type; - int binding; //binding index as specified in shader - - //for single items, provide one ID, for - //multiple items (declared as arrays in shader), - //provide more - //for sampler with texture, supply two IDs for each. - //accepted IDs are: Sampler, Texture, Uniform Buffer and Texture Buffer - Vector ids; - - Uniform() { - type = UNIFORM_TYPE_IMAGE; - binding = 0; - } - }; - - virtual RID uniform_set_create(const Vector &p_uniforms, RID p_shader, uint32_t p_shader_set) = 0; - virtual bool uniform_set_is_valid(RID p_uniform_set) = 0; - - virtual Error buffer_update(RID p_buffer, uint32_t p_offset, uint32_t p_size, const void *p_data, bool p_sync_with_draw = false) = 0; //this function can be used from any thread and it takes effect at the beginning of the frame, unless sync with draw is used, which is used to mix updates with draw calls - virtual Vector buffer_get_data(RID p_buffer) = 0; //this causes stall, only use to retrieve large buffers for saving - - /*************************/ - /**** RENDER PIPELINE ****/ - /*************************/ - - enum RenderPrimitive { - RENDER_PRIMITIVE_POINTS, - RENDER_PRIMITIVE_LINES, - RENDER_PRIMITIVE_LINES_WITH_ADJACENCY, - RENDER_PRIMITIVE_LINESTRIPS, - RENDER_PRIMITIVE_LINESTRIPS_WITH_ADJACENCY, - RENDER_PRIMITIVE_TRIANGLES, - RENDER_PRIMITIVE_TRIANGLES_WITH_ADJACENCY, - RENDER_PRIMITIVE_TRIANGLE_STRIPS, - RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_AJACENCY, - RENDER_PRIMITIVE_TRIANGLE_STRIPS_WITH_RESTART_INDEX, - RENDER_PRIMITIVE_TESSELATION_PATCH, - RENDER_PRIMITIVE_MAX - }; - - //disable optimization, tessellate control points - - enum PolygonCullMode { - POLYGON_CULL_DISABLED, - POLYGON_CULL_FRONT, - POLYGON_CULL_BACK, - }; - - enum PolygonFrontFace { - POLYGON_FRONT_FACE_CLOCKWISE, - POLYGON_FRONT_FACE_COUNTER_CLOCKWISE, - }; - - enum StencilOperation { - STENCIL_OP_KEEP, - STENCIL_OP_ZERO, - STENCIL_OP_REPLACE, - STENCIL_OP_INCREMENT_AND_CLAMP, - STENCIL_OP_DECREMENT_AND_CLAMP, - STENCIL_OP_INVERT, - STENCIL_OP_INCREMENT_AND_WRAP, - STENCIL_OP_DECREMENT_AND_WRAP, - STENCIL_OP_MAX //not an actual operator, just the amount of operators :D - }; - - enum LogicOperation { - LOGIC_OP_CLEAR, - LOGIC_OP_AND, - LOGIC_OP_AND_REVERSE, - LOGIC_OP_COPY, - LOGIC_OP_AND_INVERTED, - LOGIC_OP_NO_OP, - LOGIC_OP_XOR, - LOGIC_OP_OR, - LOGIC_OP_NOR, - LOGIC_OP_EQUIVALENT, - LOGIC_OP_INVERT, - LOGIC_OP_OR_REVERSE, - LOGIC_OP_COPY_INVERTED, - LOGIC_OP_OR_INVERTED, - LOGIC_OP_NAND, - LOGIC_OP_SET, - LOGIC_OP_MAX //not an actual operator, just the amount of operators :D - }; - - enum BlendFactor { - BLEND_FACTOR_ZERO, - BLEND_FACTOR_ONE, - BLEND_FACTOR_SRC_COLOR, - BLEND_FACTOR_ONE_MINUS_SRC_COLOR, - BLEND_FACTOR_DST_COLOR, - BLEND_FACTOR_ONE_MINUS_DST_COLOR, - BLEND_FACTOR_SRC_ALPHA, - BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, - BLEND_FACTOR_DST_ALPHA, - BLEND_FACTOR_ONE_MINUS_DST_ALPHA, - BLEND_FACTOR_CONSTANT_COLOR, - BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, - BLEND_FACTOR_CONSTANT_ALPHA, - BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, - BLEND_FACTOR_SRC_ALPHA_SATURATE, - BLEND_FACTOR_SRC1_COLOR, - BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, - BLEND_FACTOR_SRC1_ALPHA, - BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, - BLEND_FACTOR_MAX - }; - - enum BlendOperation { - BLEND_OP_ADD, - BLEND_OP_SUBTRACT, - BLEND_OP_REVERSE_SUBTRACT, - BLEND_OP_MINIMUM, - BLEND_OP_MAXIMUM, //yes this one is an actual operator - BLEND_OP_MAX //not an actual operator, just the amount of operators :D - }; - - struct PipelineRasterizationState { - bool enable_depth_clamp; - bool discard_primitives; - bool wireframe; - PolygonCullMode cull_mode; - PolygonFrontFace front_face; - bool depth_bias_enable; - float depth_bias_constant_factor; - float depth_bias_clamp; - float depth_bias_slope_factor; - float line_width; - uint32_t patch_control_points; - PipelineRasterizationState() { - enable_depth_clamp = false; - discard_primitives = false; - wireframe = false; - cull_mode = POLYGON_CULL_DISABLED; - front_face = POLYGON_FRONT_FACE_CLOCKWISE; - depth_bias_enable = false; - depth_bias_constant_factor = 0; - depth_bias_clamp = 0; - depth_bias_slope_factor = 0; - line_width = 1.0; - patch_control_points = 1; - } - }; - - struct PipelineMultisampleState { - TextureSamples sample_count; - bool enable_sample_shading; - float min_sample_shading; - Vector sample_mask; - bool enable_alpha_to_coverage; - bool enable_alpha_to_one; - - PipelineMultisampleState() { - sample_count = TEXTURE_SAMPLES_1; - enable_sample_shading = false; - min_sample_shading = 0; - enable_alpha_to_coverage = false; - enable_alpha_to_one = false; - } - }; - - struct PipelineDepthStencilState { - - bool enable_depth_test; - bool enable_depth_write; - CompareOperator depth_compare_operator; - bool enable_depth_range; - float depth_range_min; - float depth_range_max; - bool enable_stencil; - - struct StencilOperationState { - StencilOperation fail; - StencilOperation pass; - StencilOperation depth_fail; - CompareOperator compare; - uint32_t compare_mask; - uint32_t write_mask; - uint32_t reference; - - StencilOperationState() { - fail = STENCIL_OP_ZERO; - pass = STENCIL_OP_ZERO; - depth_fail = STENCIL_OP_ZERO; - compare = COMPARE_OP_ALWAYS; - compare_mask = 0; - write_mask = 0; - reference = 0; - } - }; - - StencilOperationState stencil_operation_front; - StencilOperationState stencil_operation_back; - - PipelineDepthStencilState() { - enable_depth_test = false; - enable_depth_write = false; - depth_compare_operator = COMPARE_OP_ALWAYS; - enable_depth_range = false; - depth_range_min = 0; - depth_range_max = 0; - enable_stencil = false; - } - }; - - struct PipelineColorBlendState { - - bool enable_logic_op; - LogicOperation logic_op; - struct Attachment { - bool enable_blend; - BlendFactor src_color_blend_factor; - BlendFactor dst_color_blend_factor; - BlendOperation color_blend_op; - BlendFactor src_alpha_blend_factor; - BlendFactor dst_alpha_blend_factor; - BlendOperation alpha_blend_op; - bool write_r; - bool write_g; - bool write_b; - bool write_a; - Attachment() { - enable_blend = false; - src_color_blend_factor = BLEND_FACTOR_ZERO; - dst_color_blend_factor = BLEND_FACTOR_ZERO; - color_blend_op = BLEND_OP_ADD; - src_alpha_blend_factor = BLEND_FACTOR_ZERO; - dst_alpha_blend_factor = BLEND_FACTOR_ZERO; - alpha_blend_op = BLEND_OP_ADD; - write_r = true; - write_g = true; - write_b = true; - write_a = true; - } - }; - - static PipelineColorBlendState create_disabled(int p_attachments = 1) { - PipelineColorBlendState bs; - for (int i = 0; i < p_attachments; i++) { - bs.attachments.push_back(Attachment()); - } - return bs; - } - - static PipelineColorBlendState create_blend(int p_attachments = 1) { - PipelineColorBlendState bs; - for (int i = 0; i < p_attachments; i++) { - - Attachment ba; - ba.enable_blend = true; - ba.src_color_blend_factor = BLEND_FACTOR_SRC_ALPHA; - ba.dst_color_blend_factor = BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - ba.src_alpha_blend_factor = BLEND_FACTOR_SRC_ALPHA; - ba.dst_alpha_blend_factor = BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - - bs.attachments.push_back(ba); - } - return bs; - } - - Vector attachments; //one per render target texture - Color blend_constant; - - PipelineColorBlendState() { - enable_logic_op = false; - logic_op = LOGIC_OP_CLEAR; - } - }; - - enum PipelineDynamicStateFlags { - DYNAMIC_STATE_LINE_WIDTH = (1 << 0), - DYNAMIC_STATE_DEPTH_BIAS = (1 << 1), - DYNAMIC_STATE_BLEND_CONSTANTS = (1 << 2), - DYNAMIC_STATE_DEPTH_BOUNDS = (1 << 3), - DYNAMIC_STATE_STENCIL_COMPARE_MASK = (1 << 4), - DYNAMIC_STATE_STENCIL_WRITE_MASK = (1 << 5), - DYNAMIC_STATE_STENCIL_REFERENCE = (1 << 6), - }; - - virtual RID render_pipeline_create(RID p_shader, FramebufferFormatID p_framebuffer_format, VertexFormatID p_vertex_format, RenderPrimitive p_render_primitive, const PipelineRasterizationState &p_rasterization_state, const PipelineMultisampleState &p_multisample_state, const PipelineDepthStencilState &p_depth_stencil_state, const PipelineColorBlendState &p_blend_state, int p_dynamic_state_flags = 0) = 0; - virtual bool render_pipeline_is_valid(RID p_pipeline) = 0; - - /**************************/ - /**** COMPUTE PIPELINE ****/ - /**************************/ - - virtual RID compute_pipeline_create(RID p_shader) = 0; - virtual bool compute_pipeline_is_valid(RID p_pipeline) = 0; - - /****************/ - /**** SCREEN ****/ - /****************/ - - virtual int screen_get_width(DisplayServer::WindowID p_screen = 0) const = 0; - virtual int screen_get_height(DisplayServer::WindowID p_screen = 0) const = 0; - virtual FramebufferFormatID screen_get_framebuffer_format() const = 0; - - /********************/ - /**** DRAW LISTS ****/ - /********************/ - - enum InitialAction { - INITIAL_ACTION_CLEAR, //start rendering and clear the framebuffer (supply params) - INITIAL_ACTION_KEEP, //start rendering, but keep attached color texture contents (depth will be cleared) - INITIAL_ACTION_CONTINUE, //continue rendering (framebuffer must have been left in "continue" state as final action previously) - INITIAL_ACTION_MAX - }; - - enum FinalAction { - FINAL_ACTION_READ, //will no longer render to it, allows attached textures to be read again, but depth buffer contents will be dropped (Can't be read from) - FINAL_ACTION_DISCARD, // discard contents after rendering - FINAL_ACTION_CONTINUE, //will continue rendering later, attached textures can't be read until re-bound with "finish" - FINAL_ACTION_MAX - }; - - typedef int64_t DrawListID; - - virtual DrawListID draw_list_begin_for_screen(DisplayServer::WindowID p_screen = 0, const Color &p_clear_color = Color()) = 0; - virtual DrawListID draw_list_begin(RID p_framebuffer, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; - virtual Error draw_list_begin_split(RID p_framebuffer, uint32_t p_splits, DrawListID *r_split_ids, InitialAction p_initial_color_action, FinalAction p_final_color_action, InitialAction p_initial_depth_action, FinalAction p_final_depth_action, const Vector &p_clear_color_values = Vector(), float p_clear_depth = 1.0, uint32_t p_clear_stencil = 0, const Rect2 &p_region = Rect2()) = 0; - - virtual void draw_list_bind_render_pipeline(DrawListID p_list, RID p_render_pipeline) = 0; - virtual void draw_list_bind_uniform_set(DrawListID p_list, RID p_uniform_set, uint32_t p_index) = 0; - virtual void draw_list_bind_vertex_array(DrawListID p_list, RID p_vertex_array) = 0; - virtual void draw_list_bind_index_array(DrawListID p_list, RID p_index_array) = 0; - virtual void draw_list_set_line_width(DrawListID p_list, float p_width) = 0; - virtual void draw_list_set_push_constant(DrawListID p_list, void *p_data, uint32_t p_data_size) = 0; - - virtual void draw_list_draw(DrawListID p_list, bool p_use_indices, uint32_t p_instances = 1, uint32_t p_procedural_vertices = 0) = 0; - - virtual void draw_list_enable_scissor(DrawListID p_list, const Rect2 &p_rect) = 0; - virtual void draw_list_disable_scissor(DrawListID p_list) = 0; - - virtual void draw_list_end() = 0; - - /***********************/ - /**** COMPUTE LISTS ****/ - /***********************/ - - typedef int64_t ComputeListID; - - virtual ComputeListID compute_list_begin() = 0; - virtual void compute_list_bind_compute_pipeline(ComputeListID p_list, RID p_compute_pipeline) = 0; - virtual void compute_list_bind_uniform_set(ComputeListID p_list, RID p_uniform_set, uint32_t p_index) = 0; - virtual void compute_list_set_push_constant(ComputeListID p_list, void *p_data, uint32_t p_data_size) = 0; - virtual void compute_list_dispatch(ComputeListID p_list, uint32_t p_x_groups, uint32_t p_y_groups, uint32_t p_z_groups) = 0; - virtual void compute_list_add_barrier(ComputeListID p_list) = 0; - - virtual void compute_list_end() = 0; - - /***************/ - /**** FREE! ****/ - /***************/ - - virtual void free(RID p_id) = 0; - - /****************/ - /**** Timing ****/ - /****************/ - - virtual void capture_timestamp(const String &p_name, bool p_sync_to_draw) = 0; - virtual uint32_t get_captured_timestamps_count() const = 0; - virtual uint64_t get_captured_timestamps_frame() const = 0; - virtual uint64_t get_captured_timestamp_gpu_time(uint32_t p_index) const = 0; - virtual uint64_t get_captured_timestamp_cpu_time(uint32_t p_index) const = 0; - virtual String get_captured_timestamp_name(uint32_t p_index) const = 0; - - /****************/ - /**** LIMITS ****/ - /****************/ - - enum Limit { - LIMIT_MAX_BOUND_UNIFORM_SETS, - LIMIT_MAX_FRAMEBUFFER_COLOR_ATTACHMENTS, - LIMIT_MAX_TEXTURES_PER_UNIFORM_SET, - LIMIT_MAX_SAMPLERS_PER_UNIFORM_SET, - LIMIT_MAX_STORAGE_BUFFERS_PER_UNIFORM_SET, - LIMIT_MAX_STORAGE_IMAGES_PER_UNIFORM_SET, - LIMIT_MAX_UNIFORM_BUFFERS_PER_UNIFORM_SET, - LIMIT_MAX_DRAW_INDEXED_INDEX, - LIMIT_MAX_FRAMEBUFFER_HEIGHT, - LIMIT_MAX_FRAMEBUFFER_WIDTH, - LIMIT_MAX_TEXTURE_ARRAY_LAYERS, - LIMIT_MAX_TEXTURE_SIZE_1D, - LIMIT_MAX_TEXTURE_SIZE_2D, - LIMIT_MAX_TEXTURE_SIZE_3D, - LIMIT_MAX_TEXTURE_SIZE_CUBE, - LIMIT_MAX_TEXTURES_PER_SHADER_STAGE, - LIMIT_MAX_SAMPLERS_PER_SHADER_STAGE, - LIMIT_MAX_STORAGE_BUFFERS_PER_SHADER_STAGE, - LIMIT_MAX_STORAGE_IMAGES_PER_SHADER_STAGE, - LIMIT_MAX_UNIFORM_BUFFERS_PER_SHADER_STAGE, - LIMIT_MAX_PUSH_CONSTANT_SIZE, - LIMIT_MAX_UNIFORM_BUFFER_SIZE, - LIMIT_MAX_VERTEX_INPUT_ATTRIBUTE_OFFSET, - LIMIT_MAX_VERTEX_INPUT_ATTRIBUTES, - LIMIT_MAX_VERTEX_INPUT_BINDINGS, - LIMIT_MAX_VERTEX_INPUT_BINDING_STRIDE, - LIMIT_MIN_UNIFORM_BUFFER_OFFSET_ALIGNMENT, - LIMIT_MAX_COMPUTE_SHARED_MEMORY_SIZE, - LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_X, - LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Y, - LIMIT_MAX_COMPUTE_WORKGROUP_COUNT_Z, - LIMIT_MAX_COMPUTE_WORKGROUP_INVOCATIONS, - LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_X, - LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Y, - LIMIT_MAX_COMPUTE_WORKGROUP_SIZE_Z, - }; - - virtual int limit_get(Limit p_limit) = 0; - - //methods below not exposed, used by RenderingDeviceRD - virtual void prepare_screen_for_drawing() = 0; - - virtual void swap_buffers() = 0; - - virtual uint32_t get_frame_delay() const = 0; - - static RenderingDevice *get_singleton(); - - RenderingDevice(); -}; - -typedef RenderingDevice RD; - -#endif // RENDERING_DEVICE_H diff --git a/servers/visual/shader_language.cpp b/servers/visual/shader_language.cpp deleted file mode 100644 index 98786fad3b..0000000000 --- a/servers/visual/shader_language.cpp +++ /dev/null @@ -1,7006 +0,0 @@ -/*************************************************************************/ -/* shader_language.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shader_language.h" -#include "core/os/os.h" -#include "core/print_string.h" -#include "servers/visual_server.h" - -static bool _is_text_char(CharType c) { - - return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || c == '_'; -} - -static bool _is_number(CharType c) { - - return (c >= '0' && c <= '9'); -} - -static bool _is_hex(CharType c) { - - return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); -} - -String ShaderLanguage::get_operator_text(Operator p_op) { - - static const char *op_names[OP_MAX] = { "==", - "!=", - "<", - "<=", - ">", - ">=", - "&&", - "||", - "!", - "-", - "+", - "-", - "*", - "/", - "%", - "<<", - ">>", - "=", - "+=", - "-=", - "*=", - "/=", - "%=", - "<<=", - ">>=", - "&=", - "|=", - "^=", - "&", - "|", - "^", - "~", - "++", - "--", - "?", - ":", - "++", - "--", - "()", - "construct", - "index" }; - - return op_names[p_op]; -} - -const char *ShaderLanguage::token_names[TK_MAX] = { - "EMPTY", - "IDENTIFIER", - "TRUE", - "FALSE", - "REAL_CONSTANT", - "INT_CONSTANT", - "TYPE_VOID", - "TYPE_BOOL", - "TYPE_BVEC2", - "TYPE_BVEC3", - "TYPE_BVEC4", - "TYPE_INT", - "TYPE_IVEC2", - "TYPE_IVEC3", - "TYPE_IVEC4", - "TYPE_UINT", - "TYPE_UVEC2", - "TYPE_UVEC3", - "TYPE_UVEC4", - "TYPE_FLOAT", - "TYPE_VEC2", - "TYPE_VEC3", - "TYPE_VEC4", - "TYPE_MAT2", - "TYPE_MAT3", - "TYPE_MAT4", - "TYPE_SAMPLER2D", - "TYPE_ISAMPLER2D", - "TYPE_USAMPLER2D", - "TYPE_SAMPLER2DARRAY", - "TYPE_ISAMPLER2DARRAY", - "TYPE_USAMPLER2DARRAY", - "TYPE_SAMPLER3D", - "TYPE_ISAMPLER3D", - "TYPE_USAMPLER3D", - "TYPE_SAMPLERCUBE", - "INTERPOLATION_FLAT", - "INTERPOLATION_SMOOTH", - "CONST", - "PRECISION_LOW", - "PRECISION_MID", - "PRECISION_HIGH", - "OP_EQUAL", - "OP_NOT_EQUAL", - "OP_LESS", - "OP_LESS_EQUAL", - "OP_GREATER", - "OP_GREATER_EQUAL", - "OP_AND", - "OP_OR", - "OP_NOT", - "OP_ADD", - "OP_SUB", - "OP_MUL", - "OP_DIV", - "OP_MOD", - "OP_SHIFT_LEFT", - "OP_SHIFT_RIGHT", - "OP_ASSIGN", - "OP_ASSIGN_ADD", - "OP_ASSIGN_SUB", - "OP_ASSIGN_MUL", - "OP_ASSIGN_DIV", - "OP_ASSIGN_MOD", - "OP_ASSIGN_SHIFT_LEFT", - "OP_ASSIGN_SHIFT_RIGHT", - "OP_ASSIGN_BIT_AND", - "OP_ASSIGN_BIT_OR", - "OP_ASSIGN_BIT_XOR", - "OP_BIT_AND", - "OP_BIT_OR", - "OP_BIT_XOR", - "OP_BIT_INVERT", - "OP_INCREMENT", - "OP_DECREMENT", - "CF_IF", - "CF_ELSE", - "CF_FOR", - "CF_WHILE", - "CF_DO", - "CF_SWITCH", - "CF_CASE", - "CF_BREAK", - "CF_CONTINUE", - "CF_RETURN", - "CF_DISCARD", - "BRACKET_OPEN", - "BRACKET_CLOSE", - "CURLY_BRACKET_OPEN", - "CURLY_BRACKET_CLOSE", - "PARENTHESIS_OPEN", - "PARENTHESIS_CLOSE", - "QUESTION", - "COMMA", - "COLON", - "SEMICOLON", - "PERIOD", - "UNIFORM", - "VARYING", - "IN", - "OUT", - "INOUT", - "RENDER_MODE", - "HINT_WHITE_TEXTURE", - "HINT_BLACK_TEXTURE", - "HINT_NORMAL_TEXTURE", - "HINT_ANISO_TEXTURE", - "HINT_ALBEDO_TEXTURE", - "HINT_BLACK_ALBEDO_TEXTURE", - "HINT_COLOR", - "HINT_RANGE", - "FILTER_NEAREST", - "FILTER_LINEAR", - "FILTER_NEAREST_MIPMAP", - "FILTER_LINEAR_MIPMAP", - "FILTER_NEAREST_MIPMAP_ANISO", - "FILTER_LINEAR_MIPMAP_ANISO", - "REPEAT_ENABLE", - "REPEAT_DISABLE", - "SHADER_TYPE", - "CURSOR", - "ERROR", - "EOF", -}; - -String ShaderLanguage::get_token_text(Token p_token) { - - String name = token_names[p_token.type]; - if (p_token.type == TK_INT_CONSTANT || p_token.type == TK_REAL_CONSTANT) { - name += "(" + rtos(p_token.constant) + ")"; - } else if (p_token.type == TK_IDENTIFIER) { - name += "(" + String(p_token.text) + ")"; - } else if (p_token.type == TK_ERROR) { - name += "(" + String(p_token.text) + ")"; - } - - return name; -} - -ShaderLanguage::Token ShaderLanguage::_make_token(TokenType p_type, const StringName &p_text) { - - Token tk; - tk.type = p_type; - tk.text = p_text; - tk.line = tk_line; - if (tk.type == TK_ERROR) { - _set_error(p_text); - } - return tk; -} - -const ShaderLanguage::KeyWord ShaderLanguage::keyword_list[] = { - { TK_TRUE, "true" }, - { TK_FALSE, "false" }, - { TK_TYPE_VOID, "void" }, - { TK_TYPE_BOOL, "bool" }, - { TK_TYPE_BVEC2, "bvec2" }, - { TK_TYPE_BVEC3, "bvec3" }, - { TK_TYPE_BVEC4, "bvec4" }, - { TK_TYPE_INT, "int" }, - { TK_TYPE_IVEC2, "ivec2" }, - { TK_TYPE_IVEC3, "ivec3" }, - { TK_TYPE_IVEC4, "ivec4" }, - { TK_TYPE_UINT, "uint" }, - { TK_TYPE_UVEC2, "uvec2" }, - { TK_TYPE_UVEC3, "uvec3" }, - { TK_TYPE_UVEC4, "uvec4" }, - { TK_TYPE_FLOAT, "float" }, - { TK_TYPE_VEC2, "vec2" }, - { TK_TYPE_VEC3, "vec3" }, - { TK_TYPE_VEC4, "vec4" }, - { TK_TYPE_MAT2, "mat2" }, - { TK_TYPE_MAT3, "mat3" }, - { TK_TYPE_MAT4, "mat4" }, - { TK_TYPE_SAMPLER2D, "sampler2D" }, - { TK_TYPE_ISAMPLER2D, "isampler2D" }, - { TK_TYPE_USAMPLER2D, "usampler2D" }, - { TK_TYPE_SAMPLER2DARRAY, "sampler2DArray" }, - { TK_TYPE_ISAMPLER2DARRAY, "isampler2DArray" }, - { TK_TYPE_USAMPLER2DARRAY, "usampler2DArray" }, - { TK_TYPE_SAMPLER3D, "sampler3D" }, - { TK_TYPE_ISAMPLER3D, "isampler3D" }, - { TK_TYPE_USAMPLER3D, "usampler3D" }, - { TK_TYPE_SAMPLERCUBE, "samplerCube" }, - { TK_INTERPOLATION_FLAT, "flat" }, - { TK_INTERPOLATION_SMOOTH, "smooth" }, - { TK_CONST, "const" }, - { TK_STRUCT, "struct" }, - { TK_PRECISION_LOW, "lowp" }, - { TK_PRECISION_MID, "mediump" }, - { TK_PRECISION_HIGH, "highp" }, - { TK_CF_IF, "if" }, - { TK_CF_ELSE, "else" }, - { TK_CF_FOR, "for" }, - { TK_CF_WHILE, "while" }, - { TK_CF_DO, "do" }, - { TK_CF_SWITCH, "switch" }, - { TK_CF_CASE, "case" }, - { TK_CF_DEFAULT, "default" }, - { TK_CF_BREAK, "break" }, - { TK_CF_CONTINUE, "continue" }, - { TK_CF_RETURN, "return" }, - { TK_CF_DISCARD, "discard" }, - { TK_UNIFORM, "uniform" }, - { TK_VARYING, "varying" }, - { TK_ARG_IN, "in" }, - { TK_ARG_OUT, "out" }, - { TK_ARG_INOUT, "inout" }, - { TK_RENDER_MODE, "render_mode" }, - { TK_HINT_WHITE_TEXTURE, "hint_white" }, - { TK_HINT_BLACK_TEXTURE, "hint_black" }, - { TK_HINT_NORMAL_TEXTURE, "hint_normal" }, - { TK_HINT_ROUGHNESS_NORMAL_TEXTURE, "hint_roughness_normal" }, - { TK_HINT_ROUGHNESS_R, "hint_roughness_r" }, - { TK_HINT_ROUGHNESS_G, "hint_roughness_g" }, - { TK_HINT_ROUGHNESS_B, "hint_roughness_b" }, - { TK_HINT_ROUGHNESS_A, "hint_roughness_a" }, - { TK_HINT_ROUGHNESS_GRAY, "hint_roughness_gray" }, - { TK_HINT_ANISO_TEXTURE, "hint_aniso" }, - { TK_HINT_ALBEDO_TEXTURE, "hint_albedo" }, - { TK_HINT_BLACK_ALBEDO_TEXTURE, "hint_black_albedo" }, - { TK_HINT_COLOR, "hint_color" }, - { TK_HINT_RANGE, "hint_range" }, - { TK_FILTER_NEAREST, "filter_nearest" }, - { TK_FILTER_LINEAR, "filter_linear" }, - { TK_FILTER_NEAREST_MIPMAP, "filter_nearest_mipmap" }, - { TK_FILTER_LINEAR_MIPMAP, "filter_linear_mipmap" }, - { TK_FILTER_NEAREST_MIPMAP_ANISO, "filter_nearest_mipmap_aniso" }, - { TK_FILTER_LINEAR_MIPMAP_ANISO, "filter_linear_mipmap_aniso" }, - { TK_REPEAT_ENABLE, "repeat_enable" }, - { TK_REPEAT_DISABLE, "repeat_disable" }, - { TK_SHADER_TYPE, "shader_type" }, - { TK_ERROR, NULL } -}; - -ShaderLanguage::Token ShaderLanguage::_get_token() { - -#define GETCHAR(m_idx) (((char_idx + m_idx) < code.length()) ? code[char_idx + m_idx] : CharType(0)) - - while (true) { - char_idx++; - switch (GETCHAR(-1)) { - - case 0: - return _make_token(TK_EOF); - case 0xFFFF: - return _make_token(TK_CURSOR); //for completion - case '\t': - case '\r': - case ' ': - continue; - case '\n': - tk_line++; - continue; - case '/': { - - switch (GETCHAR(0)) { - case '*': { // block comment - - char_idx++; - while (true) { - if (GETCHAR(0) == 0) { - return _make_token(TK_EOF); - } - if (GETCHAR(0) == '*' && GETCHAR(1) == '/') { - char_idx += 2; - break; - } else if (GETCHAR(0) == '\n') { - tk_line++; - } - - char_idx++; - } - - } break; - case '/': { // line comment skip - - while (true) { - if (GETCHAR(0) == '\n') { - tk_line++; - char_idx++; - break; - } - if (GETCHAR(0) == 0) { - return _make_token(TK_EOF); - } - char_idx++; - } - - } break; - case '=': { // diveq - - char_idx++; - return _make_token(TK_OP_ASSIGN_DIV); - - } break; - default: - return _make_token(TK_OP_DIV); - } - - continue; //a comment, continue to next token - } break; - case '=': { - - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_EQUAL); - } - - return _make_token(TK_OP_ASSIGN); - - } break; - case '<': { - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_LESS_EQUAL); - } else if (GETCHAR(0) == '<') { - char_idx++; - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_SHIFT_LEFT); - } - - return _make_token(TK_OP_SHIFT_LEFT); - } - - return _make_token(TK_OP_LESS); - - } break; - case '>': { - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_GREATER_EQUAL); - } else if (GETCHAR(0) == '>') { - char_idx++; - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_SHIFT_RIGHT); - } - - return _make_token(TK_OP_SHIFT_RIGHT); - } - - return _make_token(TK_OP_GREATER); - - } break; - case '!': { - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_NOT_EQUAL); - } - - return _make_token(TK_OP_NOT); - - } break; - //case '"' //string - no strings in shader - //case '\'' //string - no strings in shader - case '{': - return _make_token(TK_CURLY_BRACKET_OPEN); - case '}': - return _make_token(TK_CURLY_BRACKET_CLOSE); - case '[': - return _make_token(TK_BRACKET_OPEN); - case ']': - return _make_token(TK_BRACKET_CLOSE); - case '(': - return _make_token(TK_PARENTHESIS_OPEN); - case ')': - return _make_token(TK_PARENTHESIS_CLOSE); - case ',': - return _make_token(TK_COMMA); - case ';': - return _make_token(TK_SEMICOLON); - case '?': - return _make_token(TK_QUESTION); - case ':': - return _make_token(TK_COLON); - case '^': - return _make_token(TK_OP_BIT_XOR); - case '~': - return _make_token(TK_OP_BIT_INVERT); - case '&': { - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_BIT_AND); - } else if (GETCHAR(0) == '&') { - char_idx++; - return _make_token(TK_OP_AND); - } - return _make_token(TK_OP_BIT_AND); - } break; - case '|': { - - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_BIT_OR); - } else if (GETCHAR(0) == '|') { - char_idx++; - return _make_token(TK_OP_OR); - } - return _make_token(TK_OP_BIT_OR); - - } break; - case '*': { - - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_MUL); - } - return _make_token(TK_OP_MUL); - } break; - case '+': { - - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_ADD); - } else if (GETCHAR(0) == '+') { - - char_idx++; - return _make_token(TK_OP_INCREMENT); - } - - return _make_token(TK_OP_ADD); - } break; - case '-': { - - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_SUB); - } else if (GETCHAR(0) == '-') { - - char_idx++; - return _make_token(TK_OP_DECREMENT); - } - - return _make_token(TK_OP_SUB); - } break; - case '%': { - - if (GETCHAR(0) == '=') { - char_idx++; - return _make_token(TK_OP_ASSIGN_MOD); - } - - return _make_token(TK_OP_MOD); - } break; - default: { - - char_idx--; //go back one, since we have no idea what this is - - if (_is_number(GETCHAR(0)) || (GETCHAR(0) == '.' && _is_number(GETCHAR(1)))) { - // parse number - bool period_found = false; - bool exponent_found = false; - bool hexa_found = false; - bool sign_found = false; - bool float_suffix_found = false; - - String str; - int i = 0; - - while (true) { - if (GETCHAR(i) == '.') { - if (period_found || exponent_found || hexa_found || float_suffix_found) - return _make_token(TK_ERROR, "Invalid numeric constant"); - period_found = true; - } else if (GETCHAR(i) == 'x') { - if (hexa_found || str.length() != 1 || str[0] != '0') - return _make_token(TK_ERROR, "Invalid numeric constant"); - hexa_found = true; - } else if (GETCHAR(i) == 'e') { - if (hexa_found || exponent_found || float_suffix_found) - return _make_token(TK_ERROR, "Invalid numeric constant"); - exponent_found = true; - } else if (GETCHAR(i) == 'f') { - if (hexa_found || exponent_found) - return _make_token(TK_ERROR, "Invalid numeric constant"); - float_suffix_found = true; - } else if (_is_number(GETCHAR(i))) { - if (float_suffix_found) - return _make_token(TK_ERROR, "Invalid numeric constant"); - } else if (hexa_found && _is_hex(GETCHAR(i))) { - - } else if ((GETCHAR(i) == '-' || GETCHAR(i) == '+') && exponent_found) { - if (sign_found) - return _make_token(TK_ERROR, "Invalid numeric constant"); - sign_found = true; - } else - break; - - str += CharType(GETCHAR(i)); - i++; - } - - CharType last_char = str[str.length() - 1]; - - if (hexa_found) { - //integer(hex) - if (str.size() > 11 || !str.is_valid_hex_number(true)) { // > 0xFFFFFFFF - return _make_token(TK_ERROR, "Invalid (hexadecimal) numeric constant"); - } - } else if (period_found || exponent_found || float_suffix_found) { - //floats - if (period_found) { - if (float_suffix_found) { - //checks for eg "1.f" or "1.99f" notations - if (last_char != 'f') { - return _make_token(TK_ERROR, "Invalid (float) numeric constant"); - } - } else { - //checks for eg. "1." or "1.99" notations - if (last_char != '.' && !_is_number(last_char)) { - return _make_token(TK_ERROR, "Invalid (float) numeric constant"); - } - } - } else if (float_suffix_found) { - // if no period found the float suffix must be the last character, like in "2f" for "2.0" - if (last_char != 'f') { - return _make_token(TK_ERROR, "Invalid (float) numeric constant"); - } - } - - if (float_suffix_found) { - //strip the suffix - str = str.left(str.length() - 1); - //compensate reading cursor position - char_idx += 1; - } - - if (!str.is_valid_float()) { - return _make_token(TK_ERROR, "Invalid (float) numeric constant"); - } - } else { - //integers - if (!_is_number(last_char)) { - return _make_token(TK_ERROR, "Invalid (integer) numeric constant"); - } - if (!str.is_valid_integer()) { - return _make_token(TK_ERROR, "Invalid numeric constant"); - } - } - - char_idx += str.length(); - Token tk; - if (period_found || exponent_found || float_suffix_found) - tk.type = TK_REAL_CONSTANT; - else - tk.type = TK_INT_CONSTANT; - - if (hexa_found) { - tk.constant = (double)str.hex_to_int64(true); - } else { - tk.constant = str.to_double(); - } - tk.line = tk_line; - - return tk; - } - - if (GETCHAR(0) == '.') { - //parse period - char_idx++; - return _make_token(TK_PERIOD); - } - - if (_is_text_char(GETCHAR(0))) { - // parse identifier - String str; - - while (_is_text_char(GETCHAR(0))) { - - str += CharType(GETCHAR(0)); - char_idx++; - } - - //see if keyword - //should be converted to a static map - int idx = 0; - - while (keyword_list[idx].text) { - - if (str == keyword_list[idx].text) { - - return _make_token(keyword_list[idx].token); - } - idx++; - } - - str = str.replace("dus_", "_"); - - return _make_token(TK_IDENTIFIER, str); - } - - if (GETCHAR(0) > 32) - return _make_token(TK_ERROR, "Tokenizer: Unknown character #" + itos(GETCHAR(0)) + ": '" + String::chr(GETCHAR(0)) + "'"); - else - return _make_token(TK_ERROR, "Tokenizer: Unknown character #" + itos(GETCHAR(0))); - - } break; - } - } - ERR_PRINT("BUG"); - return Token(); - -#undef GETCHAR -} - -String ShaderLanguage::token_debug(const String &p_code) { - - clear(); - - code = p_code; - - String output; - - Token tk = _get_token(); - while (tk.type != TK_EOF && tk.type != TK_ERROR) { - - output += itos(tk_line) + ": " + get_token_text(tk) + "\n"; - tk = _get_token(); - } - - return output; -} - -bool ShaderLanguage::is_token_variable_datatype(TokenType p_type) { - return ( - p_type == TK_TYPE_VOID || - p_type == TK_TYPE_BOOL || - p_type == TK_TYPE_BVEC2 || - p_type == TK_TYPE_BVEC3 || - p_type == TK_TYPE_BVEC4 || - p_type == TK_TYPE_INT || - p_type == TK_TYPE_IVEC2 || - p_type == TK_TYPE_IVEC3 || - p_type == TK_TYPE_IVEC4 || - p_type == TK_TYPE_UINT || - p_type == TK_TYPE_UVEC2 || - p_type == TK_TYPE_UVEC3 || - p_type == TK_TYPE_UVEC4 || - p_type == TK_TYPE_FLOAT || - p_type == TK_TYPE_VEC2 || - p_type == TK_TYPE_VEC3 || - p_type == TK_TYPE_VEC4 || - p_type == TK_TYPE_MAT2 || - p_type == TK_TYPE_MAT3 || - p_type == TK_TYPE_MAT4); -} - -bool ShaderLanguage::is_token_datatype(TokenType p_type) { - - return ( - p_type == TK_TYPE_VOID || - p_type == TK_TYPE_BOOL || - p_type == TK_TYPE_BVEC2 || - p_type == TK_TYPE_BVEC3 || - p_type == TK_TYPE_BVEC4 || - p_type == TK_TYPE_INT || - p_type == TK_TYPE_IVEC2 || - p_type == TK_TYPE_IVEC3 || - p_type == TK_TYPE_IVEC4 || - p_type == TK_TYPE_UINT || - p_type == TK_TYPE_UVEC2 || - p_type == TK_TYPE_UVEC3 || - p_type == TK_TYPE_UVEC4 || - p_type == TK_TYPE_FLOAT || - p_type == TK_TYPE_VEC2 || - p_type == TK_TYPE_VEC3 || - p_type == TK_TYPE_VEC4 || - p_type == TK_TYPE_MAT2 || - p_type == TK_TYPE_MAT3 || - p_type == TK_TYPE_MAT4 || - p_type == TK_TYPE_SAMPLER2D || - p_type == TK_TYPE_ISAMPLER2D || - p_type == TK_TYPE_USAMPLER2D || - p_type == TK_TYPE_SAMPLER2DARRAY || - p_type == TK_TYPE_ISAMPLER2DARRAY || - p_type == TK_TYPE_USAMPLER2DARRAY || - p_type == TK_TYPE_SAMPLER3D || - p_type == TK_TYPE_ISAMPLER3D || - p_type == TK_TYPE_USAMPLER3D || - p_type == TK_TYPE_SAMPLERCUBE); -} - -ShaderLanguage::DataType ShaderLanguage::get_token_datatype(TokenType p_type) { - - return DataType(p_type - TK_TYPE_VOID); -} - -bool ShaderLanguage::is_token_interpolation(TokenType p_type) { - - return ( - p_type == TK_INTERPOLATION_FLAT || - p_type == TK_INTERPOLATION_SMOOTH); -} - -ShaderLanguage::DataInterpolation ShaderLanguage::get_token_interpolation(TokenType p_type) { - - if (p_type == TK_INTERPOLATION_FLAT) - return INTERPOLATION_FLAT; - else - return INTERPOLATION_SMOOTH; -} - -bool ShaderLanguage::is_token_precision(TokenType p_type) { - - return ( - p_type == TK_PRECISION_LOW || - p_type == TK_PRECISION_MID || - p_type == TK_PRECISION_HIGH); -} - -ShaderLanguage::DataPrecision ShaderLanguage::get_token_precision(TokenType p_type) { - - if (p_type == TK_PRECISION_LOW) - return PRECISION_LOWP; - else if (p_type == TK_PRECISION_HIGH) - return PRECISION_HIGHP; - else - return PRECISION_MEDIUMP; -} - -String ShaderLanguage::get_precision_name(DataPrecision p_type) { - switch (p_type) { - case PRECISION_LOWP: return "lowp"; - case PRECISION_MEDIUMP: return "mediump"; - case PRECISION_HIGHP: return "highp"; - default: - break; - } - return ""; -} - -String ShaderLanguage::get_datatype_name(DataType p_type) { - - switch (p_type) { - - case TYPE_VOID: return "void"; - case TYPE_BOOL: return "bool"; - case TYPE_BVEC2: return "bvec2"; - case TYPE_BVEC3: return "bvec3"; - case TYPE_BVEC4: return "bvec4"; - case TYPE_INT: return "int"; - case TYPE_IVEC2: return "ivec2"; - case TYPE_IVEC3: return "ivec3"; - case TYPE_IVEC4: return "ivec4"; - case TYPE_UINT: return "uint"; - case TYPE_UVEC2: return "uvec2"; - case TYPE_UVEC3: return "uvec3"; - case TYPE_UVEC4: return "uvec4"; - case TYPE_FLOAT: return "float"; - case TYPE_VEC2: return "vec2"; - case TYPE_VEC3: return "vec3"; - case TYPE_VEC4: return "vec4"; - case TYPE_MAT2: return "mat2"; - case TYPE_MAT3: return "mat3"; - case TYPE_MAT4: return "mat4"; - case TYPE_SAMPLER2D: return "sampler2D"; - case TYPE_ISAMPLER2D: return "isampler2D"; - case TYPE_USAMPLER2D: return "usampler2D"; - case TYPE_SAMPLER2DARRAY: return "sampler2DArray"; - case TYPE_ISAMPLER2DARRAY: return "isampler2DArray"; - case TYPE_USAMPLER2DARRAY: return "usampler2DArray"; - case TYPE_SAMPLER3D: return "sampler3D"; - case TYPE_ISAMPLER3D: return "isampler3D"; - case TYPE_USAMPLER3D: return "usampler3D"; - case TYPE_SAMPLERCUBE: return "samplerCube"; - case TYPE_STRUCT: return "struct"; - } - - return ""; -} - -bool ShaderLanguage::is_token_nonvoid_datatype(TokenType p_type) { - - return is_token_datatype(p_type) && p_type != TK_TYPE_VOID; -} - -void ShaderLanguage::clear() { - - current_function = StringName(); - - completion_type = COMPLETION_NONE; - completion_block = NULL; - completion_function = StringName(); - completion_class = SubClassTag::TAG_GLOBAL; - completion_struct = StringName(); - - error_line = 0; - tk_line = 1; - char_idx = 0; - error_set = false; - error_str = ""; - while (nodes) { - Node *n = nodes; - nodes = nodes->next; - memdelete(n); - } -} - -bool ShaderLanguage::_find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map &p_builtin_types, const StringName &p_identifier, DataType *r_data_type, IdentifierType *r_type, bool *r_is_const, int *r_array_size, StringName *r_struct_name) { - - if (p_builtin_types.has(p_identifier)) { - - if (r_data_type) { - *r_data_type = p_builtin_types[p_identifier].type; - } - if (r_is_const) { - *r_is_const = p_builtin_types[p_identifier].constant; - } - if (r_type) { - *r_type = IDENTIFIER_BUILTIN_VAR; - } - - return true; - } - - FunctionNode *function = NULL; - - while (p_block) { - - if (p_block->variables.has(p_identifier)) { - if (r_data_type) { - *r_data_type = p_block->variables[p_identifier].type; - } - if (r_is_const) { - *r_is_const = p_block->variables[p_identifier].is_const; - } - if (r_array_size) { - *r_array_size = p_block->variables[p_identifier].array_size; - } - if (r_type) { - *r_type = IDENTIFIER_LOCAL_VAR; - } - if (r_struct_name) { - *r_struct_name = p_block->variables[p_identifier].struct_name; - } - - return true; - } - - if (p_block->parent_function) { - function = p_block->parent_function; - break; - } else { - if (p_allow_reassign) { - break; - } - ERR_FAIL_COND_V(!p_block->parent_block, false); - p_block = p_block->parent_block; - } - } - - if (function) { - for (int i = 0; i < function->arguments.size(); i++) { - if (function->arguments[i].name == p_identifier) { - if (r_data_type) { - *r_data_type = function->arguments[i].type; - } - if (r_type) { - *r_type = IDENTIFIER_FUNCTION_ARGUMENT; - } - if (r_struct_name) { - *r_struct_name = function->arguments[i].type_str; - } - return true; - } - } - } - - if (shader->varyings.has(p_identifier)) { - if (r_data_type) { - *r_data_type = shader->varyings[p_identifier].type; - } - if (r_array_size) { - *r_array_size = shader->varyings[p_identifier].array_size; - } - if (r_type) { - *r_type = IDENTIFIER_VARYING; - } - return true; - } - - if (shader->uniforms.has(p_identifier)) { - if (r_data_type) { - *r_data_type = shader->uniforms[p_identifier].type; - } - if (r_type) { - *r_type = IDENTIFIER_UNIFORM; - } - return true; - } - - if (shader->constants.has(p_identifier)) { - if (r_data_type) { - *r_data_type = shader->constants[p_identifier].type; - } - if (r_type) { - *r_type = IDENTIFIER_CONSTANT; - } - if (r_struct_name) { - *r_struct_name = shader->constants[p_identifier].type_str; - } - return true; - } - - for (int i = 0; i < shader->functions.size(); i++) { - - if (!shader->functions[i].callable) - continue; - - if (shader->functions[i].name == p_identifier) { - if (r_data_type) { - *r_data_type = shader->functions[i].function->return_type; - } - if (r_type) { - *r_type = IDENTIFIER_FUNCTION; - } - return true; - } - } - - return false; -} - -bool ShaderLanguage::_validate_operator(OperatorNode *p_op, DataType *r_ret_type) { - - bool valid = false; - DataType ret_type = TYPE_VOID; - - switch (p_op->op) { - case OP_EQUAL: - case OP_NOT_EQUAL: { - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - valid = na == nb; - ret_type = TYPE_BOOL; - } break; - case OP_LESS: - case OP_LESS_EQUAL: - case OP_GREATER: - case OP_GREATER_EQUAL: { - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - valid = na == nb && (na == TYPE_UINT || na == TYPE_INT || na == TYPE_FLOAT); - ret_type = TYPE_BOOL; - - } break; - case OP_AND: - case OP_OR: { - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - valid = na == nb && na == TYPE_BOOL; - ret_type = TYPE_BOOL; - - } break; - case OP_NOT: { - - DataType na = p_op->arguments[0]->get_datatype(); - valid = na == TYPE_BOOL; - ret_type = TYPE_BOOL; - - } break; - case OP_INCREMENT: - case OP_DECREMENT: - case OP_POST_INCREMENT: - case OP_POST_DECREMENT: - case OP_NEGATE: { - DataType na = p_op->arguments[0]->get_datatype(); - valid = na > TYPE_BOOL && na < TYPE_MAT2; - ret_type = na; - } break; - case OP_ADD: - case OP_SUB: - case OP_MUL: - case OP_DIV: { - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - if (na > nb) { - //make things easier; - SWAP(na, nb); - } - - if (na == nb) { - valid = (na > TYPE_BOOL && na <= TYPE_MAT4); - ret_type = na; - } else if (na == TYPE_INT && nb == TYPE_IVEC2) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_INT && nb == TYPE_IVEC3) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_INT && nb == TYPE_IVEC4) { - valid = true; - ret_type = TYPE_IVEC4; - } else if (na == TYPE_UINT && nb == TYPE_UVEC2) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UINT && nb == TYPE_UVEC3) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UINT && nb == TYPE_UVEC4) { - valid = true; - ret_type = TYPE_UVEC4; - } else if (na == TYPE_FLOAT && nb == TYPE_VEC2) { - valid = true; - ret_type = TYPE_VEC2; - } else if (na == TYPE_FLOAT && nb == TYPE_VEC3) { - valid = true; - ret_type = TYPE_VEC3; - } else if (na == TYPE_FLOAT && nb == TYPE_VEC4) { - valid = true; - ret_type = TYPE_VEC4; - } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT2) { - valid = true; - ret_type = TYPE_MAT2; - } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT3) { - valid = true; - ret_type = TYPE_MAT3; - } else if (p_op->op == OP_MUL && na == TYPE_FLOAT && nb == TYPE_MAT4) { - valid = true; - ret_type = TYPE_MAT4; - } else if (p_op->op == OP_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) { - valid = true; - ret_type = TYPE_VEC2; - } else if (p_op->op == OP_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) { - valid = true; - ret_type = TYPE_VEC3; - } else if (p_op->op == OP_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) { - valid = true; - ret_type = TYPE_VEC4; - } - } break; - case OP_ASSIGN_MOD: - case OP_MOD: { - /* - * The operator modulus (%) operates on signed or unsigned integers or integer vectors. The operand - * types must both be signed or both be unsigned. The operands cannot be vectors of differing size. If - * one operand is a scalar and the other vector, then the scalar is applied component-wise to the vector, - * resulting in the same type as the vector. If both are vectors of the same size, the result is computed - * component-wise. - */ - - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - if (na == TYPE_INT && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_INT; - } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC4; - } else if (na == TYPE_IVEC2 && nb == TYPE_IVEC2) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_IVEC3) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { - valid = true; - ret_type = TYPE_IVEC4; - ///// - } else if (na == TYPE_UINT && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UINT; - } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC4; - } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { - valid = true; - ret_type = TYPE_UVEC4; - } - } break; - case OP_ASSIGN_SHIFT_LEFT: - case OP_ASSIGN_SHIFT_RIGHT: - case OP_SHIFT_LEFT: - case OP_SHIFT_RIGHT: { - - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - if (na == TYPE_INT && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_INT; - } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC4; - } else if (na == TYPE_IVEC2 && nb == TYPE_IVEC2) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_IVEC3) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { - valid = true; - ret_type = TYPE_IVEC4; - } else if (na == TYPE_UINT && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UINT; - } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC4; - } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { - valid = true; - ret_type = TYPE_UVEC4; - } - } break; - case OP_ASSIGN: { - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - if (na == TYPE_STRUCT || nb == TYPE_STRUCT) { - valid = p_op->arguments[0]->get_datatype_name() == p_op->arguments[1]->get_datatype_name(); - } else { - valid = na == nb; - } - ret_type = na; - } break; - case OP_ASSIGN_ADD: - case OP_ASSIGN_SUB: - case OP_ASSIGN_MUL: - case OP_ASSIGN_DIV: { - - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - if (na == nb) { - valid = (na > TYPE_BOOL && na < TYPE_MAT2) || (p_op->op == OP_ASSIGN_MUL && na >= TYPE_MAT2 && na <= TYPE_MAT4); - ret_type = na; - } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC4; - } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC4; - } else if (na == TYPE_VEC2 && nb == TYPE_FLOAT) { - valid = true; - ret_type = TYPE_VEC2; - } else if (na == TYPE_VEC3 && nb == TYPE_FLOAT) { - valid = true; - ret_type = TYPE_VEC3; - } else if (na == TYPE_VEC4 && nb == TYPE_FLOAT) { - valid = true; - ret_type = TYPE_VEC4; - } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT2 && nb == TYPE_VEC2) { - valid = true; - ret_type = TYPE_MAT2; - } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT3 && nb == TYPE_VEC3) { - valid = true; - ret_type = TYPE_MAT3; - } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_MAT4 && nb == TYPE_VEC4) { - valid = true; - ret_type = TYPE_MAT4; - } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC2 && nb == TYPE_MAT2) { - valid = true; - ret_type = TYPE_VEC2; - } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC3 && nb == TYPE_MAT3) { - valid = true; - ret_type = TYPE_VEC3; - } else if (p_op->op == OP_ASSIGN_MUL && na == TYPE_VEC4 && nb == TYPE_MAT4) { - valid = true; - ret_type = TYPE_VEC4; - } - } break; - case OP_ASSIGN_BIT_AND: - case OP_ASSIGN_BIT_OR: - case OP_ASSIGN_BIT_XOR: - case OP_BIT_AND: - case OP_BIT_OR: - case OP_BIT_XOR: { - - /* - * The bitwise operators and (&), exclusive-or (^), and inclusive-or (|). The operands must be of type - * signed or unsigned integers or integer vectors. The operands cannot be vectors of differing size. If - * one operand is a scalar and the other a vector, the scalar is applied component-wise to the vector, - * resulting in the same type as the vector. The fundamental types of the operands (signed or unsigned) - * must match. - */ - - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - - if (na > nb && p_op->op >= OP_BIT_AND) { - //can swap for non assign - SWAP(na, nb); - } - - if (na == TYPE_INT && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_INT; - } else if (na == TYPE_IVEC2 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_INT) { - valid = true; - ret_type = TYPE_IVEC4; - } else if (na == TYPE_IVEC2 && nb == TYPE_IVEC2) { - valid = true; - ret_type = TYPE_IVEC2; - } else if (na == TYPE_IVEC3 && nb == TYPE_IVEC3) { - valid = true; - ret_type = TYPE_IVEC3; - } else if (na == TYPE_IVEC4 && nb == TYPE_IVEC4) { - valid = true; - ret_type = TYPE_IVEC4; - ///// - } else if (na == TYPE_UINT && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UINT; - } else if (na == TYPE_UVEC2 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UINT) { - valid = true; - ret_type = TYPE_UVEC4; - } else if (na == TYPE_UVEC2 && nb == TYPE_UVEC2) { - valid = true; - ret_type = TYPE_UVEC2; - } else if (na == TYPE_UVEC3 && nb == TYPE_UVEC3) { - valid = true; - ret_type = TYPE_UVEC3; - } else if (na == TYPE_UVEC4 && nb == TYPE_UVEC4) { - valid = true; - ret_type = TYPE_UVEC4; - } - } break; - case OP_BIT_INVERT: { //unaries - DataType na = p_op->arguments[0]->get_datatype(); - valid = na >= TYPE_INT && na < TYPE_FLOAT; - ret_type = na; - } break; - case OP_SELECT_IF: { - DataType na = p_op->arguments[0]->get_datatype(); - DataType nb = p_op->arguments[1]->get_datatype(); - DataType nc = p_op->arguments[2]->get_datatype(); - - valid = na == TYPE_BOOL && (nb == nc); - ret_type = nb; - } break; - default: { - ERR_FAIL_V(false); - } - } - - if (r_ret_type) - *r_ret_type = ret_type; - return valid; -} - -const ShaderLanguage::BuiltinFuncDef ShaderLanguage::builtin_func_defs[] = { - //constructors - { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec2", TYPE_BVEC2, { TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec3", TYPE_BVEC3, { TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec3", TYPE_BVEC3, { TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC2, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BOOL, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BOOL, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BOOL, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BVEC3, TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - - { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec2", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec3", TYPE_VEC3, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec3", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - - { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec2", TYPE_IVEC2, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec3", TYPE_IVEC3, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec3", TYPE_IVEC3, { TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_INT, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_INT, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - - { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec2", TYPE_UVEC2, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UINT, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UINT, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - - { "mat2", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat3", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat4", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "mat2", TYPE_MAT2, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat3", TYPE_MAT3, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat4", TYPE_MAT4, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - //conversion scalars - - { "int", TYPE_INT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "int", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "int", TYPE_INT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "int", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "float", TYPE_FLOAT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "float", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "float", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "float", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "uint", TYPE_UINT, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, true }, - { "uint", TYPE_UINT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uint", TYPE_UINT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "bool", TYPE_BOOL, { TYPE_BOOL, TYPE_VOID }, TAG_GLOBAL, false }, - { "bool", TYPE_BOOL, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "bool", TYPE_BOOL, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "bool", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - //conversion vectors - - { "ivec2", TYPE_IVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec2", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec2", TYPE_IVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec2", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - - { "vec2", TYPE_VEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec2", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec2", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "vec2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - - { "uvec2", TYPE_UVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec2", TYPE_UVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec2", TYPE_UVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec2", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - - { "bvec2", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec2", TYPE_BVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec2", TYPE_BVEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "bvec2", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - - { "ivec3", TYPE_IVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec3", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec3", TYPE_IVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "ivec3", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - - { "vec3", TYPE_VEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec3", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec3", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "vec3", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - - { "uvec3", TYPE_UVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec3", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - - { "bvec3", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec3", TYPE_BVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec3", TYPE_BVEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "bvec3", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - - { "ivec4", TYPE_IVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "ivec4", TYPE_IVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "ivec4", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "vec4", TYPE_VEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "vec4", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "vec4", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "uvec4", TYPE_UVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "uvec4", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "bvec4", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "bvec4", TYPE_BVEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "bvec4", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - //conversion between matrixes - - { "mat2", TYPE_MAT2, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat2", TYPE_MAT2, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat3", TYPE_MAT3, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat3", TYPE_MAT3, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat4", TYPE_MAT4, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, - { "mat4", TYPE_MAT4, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, - - //builtins - trigonometry - - { "radians", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "radians", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "radians", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "radians", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "degrees", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "degrees", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "degrees", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "degrees", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "sin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "sin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "sin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "sin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "cos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "cos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "cos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "cos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "tan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "tan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "tan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "tan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "asin", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "asin", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "asin", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "asin", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "acos", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "acos", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "acos", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "acos", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "atan", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "sinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "sinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "sinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "sinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "cosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "cosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "cosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "cosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "tanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "tanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "tanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "tanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "asinh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "asinh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "asinh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "asinh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "acosh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "acosh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "acosh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "acosh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "atanh", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "atanh", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "atanh", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "atanh", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - //builtins - exponential - { "pow", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "pow", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "pow", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "pow", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "log", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "log", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "log", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "log", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "exp2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "log2", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "log2", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "log2", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "log2", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "sqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "sqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "sqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "sqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "inversesqrt", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "inversesqrt", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "inversesqrt", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "inversesqrt", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - //builtins - common - { "abs", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "abs", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "abs", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "abs", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "abs", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "abs", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "abs", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "abs", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "sign", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "sign", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "sign", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "sign", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "sign", TYPE_INT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "sign", TYPE_IVEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "sign", TYPE_IVEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "sign", TYPE_IVEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "floor", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "floor", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "floor", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "floor", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "trunc", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "trunc", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "trunc", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "trunc", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "round", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "round", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "round", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "round", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "roundEven", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "roundEven", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "roundEven", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "roundEven", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "ceil", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "ceil", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "ceil", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "ceil", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "fract", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "fract", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "fract", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "fract", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "mod", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "mod", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "mod", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "mod", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "modf", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "modf", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "modf", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "modf", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "min", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "min", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "min", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "min", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "min", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "min", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "min", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "max", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "max", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "max", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "max", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "max", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "max", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "max", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "clamp", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_VEC2, { TYPE_VEC2, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_VEC3, { TYPE_VEC3, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_VEC4, { TYPE_VEC4, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "clamp", TYPE_INT, { TYPE_INT, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_IVEC2, { TYPE_IVEC2, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_IVEC3, { TYPE_IVEC3, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - { "clamp", TYPE_IVEC4, { TYPE_IVEC4, TYPE_INT, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "clamp", TYPE_UINT, { TYPE_UINT, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "clamp", TYPE_UVEC2, { TYPE_UVEC2, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "clamp", TYPE_UVEC3, { TYPE_UVEC3, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "clamp", TYPE_UVEC4, { TYPE_UVEC4, TYPE_UINT, TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "mix", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "mix", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "step", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "step", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "step", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "step", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "step", TYPE_VEC2, { TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "step", TYPE_VEC3, { TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "step", TYPE_VEC4, { TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_FLOAT, { TYPE_FLOAT, TYPE_FLOAT, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_VEC2, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_VEC3, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "smoothstep", TYPE_VEC4, { TYPE_FLOAT, TYPE_FLOAT, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "isnan", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "isnan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "isnan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "isnan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "isinf", TYPE_BOOL, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "isinf", TYPE_BVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "isinf", TYPE_BVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "isinf", TYPE_BVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "floatBitsToInt", TYPE_INT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "floatBitsToInt", TYPE_IVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "floatBitsToInt", TYPE_IVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "floatBitsToInt", TYPE_IVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "floatBitsToUint", TYPE_UINT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "floatBitsToUint", TYPE_UVEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "floatBitsToUint", TYPE_UVEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "floatBitsToUint", TYPE_UVEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "intBitsToFloat", TYPE_FLOAT, { TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "intBitsToFloat", TYPE_VEC2, { TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "intBitsToFloat", TYPE_VEC3, { TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "intBitsToFloat", TYPE_VEC4, { TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "uintBitsToFloat", TYPE_FLOAT, { TYPE_UINT, TYPE_VOID }, TAG_GLOBAL, true }, - { "uintBitsToFloat", TYPE_VEC2, { TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "uintBitsToFloat", TYPE_VEC3, { TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "uintBitsToFloat", TYPE_VEC4, { TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - //builtins - geometric - { "length", TYPE_FLOAT, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "length", TYPE_FLOAT, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "length", TYPE_FLOAT, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "distance", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "distance", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "distance", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "dot", TYPE_FLOAT, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "dot", TYPE_FLOAT, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "dot", TYPE_FLOAT, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "cross", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "normalize", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "normalize", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "normalize", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - { "reflect", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "refract", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "faceforward", TYPE_VEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "faceforward", TYPE_VEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "faceforward", TYPE_VEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "matrixCompMult", TYPE_MAT2, { TYPE_MAT2, TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, - { "matrixCompMult", TYPE_MAT3, { TYPE_MAT3, TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, - { "matrixCompMult", TYPE_MAT4, { TYPE_MAT4, TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "outerProduct", TYPE_MAT2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "outerProduct", TYPE_MAT3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "outerProduct", TYPE_MAT4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "transpose", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, - { "transpose", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, - { "transpose", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "determinant", TYPE_FLOAT, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, - { "determinant", TYPE_FLOAT, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, - { "determinant", TYPE_FLOAT, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "inverse", TYPE_MAT2, { TYPE_MAT2, TYPE_VOID }, TAG_GLOBAL, false }, - { "inverse", TYPE_MAT3, { TYPE_MAT3, TYPE_VOID }, TAG_GLOBAL, false }, - { "inverse", TYPE_MAT4, { TYPE_MAT4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "lessThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "lessThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "lessThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "lessThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "lessThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "greaterThan", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThan", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThan", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "greaterThan", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThan", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThan", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "greaterThan", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "greaterThan", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "greaterThan", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "lessThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "lessThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "lessThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "lessThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "lessThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "lessThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "greaterThanEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThanEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThanEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "greaterThanEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThanEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "greaterThanEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "greaterThanEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "greaterThanEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "greaterThanEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "equal", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "equal", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "equal", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "equal", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "equal", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "equal", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "equal", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "equal", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "equal", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "equal", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "equal", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "equal", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "notEqual", TYPE_BVEC2, { TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "notEqual", TYPE_BVEC3, { TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "notEqual", TYPE_BVEC4, { TYPE_VEC4, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "notEqual", TYPE_BVEC2, { TYPE_IVEC2, TYPE_IVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "notEqual", TYPE_BVEC3, { TYPE_IVEC3, TYPE_IVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "notEqual", TYPE_BVEC4, { TYPE_IVEC4, TYPE_IVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "notEqual", TYPE_BVEC2, { TYPE_UVEC2, TYPE_UVEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "notEqual", TYPE_BVEC3, { TYPE_UVEC3, TYPE_UVEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "notEqual", TYPE_BVEC4, { TYPE_UVEC4, TYPE_UVEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "notEqual", TYPE_BVEC2, { TYPE_BVEC2, TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "notEqual", TYPE_BVEC3, { TYPE_BVEC3, TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "notEqual", TYPE_BVEC4, { TYPE_BVEC4, TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "any", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "any", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "any", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "all", TYPE_BOOL, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "all", TYPE_BOOL, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "all", TYPE_BOOL, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - { "not", TYPE_BVEC2, { TYPE_BVEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "not", TYPE_BVEC3, { TYPE_BVEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "not", TYPE_BVEC4, { TYPE_BVEC4, TYPE_VOID }, TAG_GLOBAL, false }, - - //builtins - texture - { "textureSize", TYPE_IVEC2, { TYPE_SAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC2, { TYPE_ISAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC2, { TYPE_USAMPLER2D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER2DARRAY, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC3, { TYPE_SAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC3, { TYPE_ISAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC3, { TYPE_USAMPLER3D, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureSize", TYPE_IVEC2, { TYPE_SAMPLERCUBE, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, false }, - { "texture", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProj", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - { "textureLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureLod", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, false }, - - { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_IVEC2, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - { "texelFetch", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_IVEC3, TYPE_INT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC3, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureProjLod", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC4, TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - - { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2D, TYPE_VEC2, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER2DARRAY, TYPE_VEC3, TYPE_VEC2, TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_VEC4, { TYPE_SAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_IVEC4, { TYPE_ISAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_UVEC4, { TYPE_USAMPLER3D, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "textureGrad", TYPE_VEC4, { TYPE_SAMPLERCUBE, TYPE_VEC3, TYPE_VEC3, TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - - { "dFdx", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "dFdx", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "dFdx", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "dFdx", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "dFdy", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "dFdy", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "dFdy", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "dFdy", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - { "fwidth", TYPE_FLOAT, { TYPE_FLOAT, TYPE_VOID }, TAG_GLOBAL, true }, - { "fwidth", TYPE_VEC2, { TYPE_VEC2, TYPE_VOID }, TAG_GLOBAL, true }, - { "fwidth", TYPE_VEC3, { TYPE_VEC3, TYPE_VOID }, TAG_GLOBAL, true }, - { "fwidth", TYPE_VEC4, { TYPE_VEC4, TYPE_VOID }, TAG_GLOBAL, true }, - - //sub-functions - - //array - { "length", TYPE_INT, { TYPE_VOID }, TAG_ARRAY, true }, - - { NULL, TYPE_VOID, { TYPE_VOID }, TAG_GLOBAL, false } - -}; - -const ShaderLanguage::BuiltinFuncOutArgs ShaderLanguage::builtin_func_out_args[] = { - //constructors - { "modf", 1 }, - { NULL, 0 } -}; - -bool ShaderLanguage::_validate_function_call(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str) { - - ERR_FAIL_COND_V(p_func->op != OP_CALL && p_func->op != OP_CONSTRUCT, false); - - Vector args; - Vector args2; - - ERR_FAIL_COND_V(p_func->arguments[0]->type != Node::TYPE_VARIABLE, false); - - StringName name = static_cast(p_func->arguments[0])->name.operator String(); - - for (int i = 1; i < p_func->arguments.size(); i++) { - args.push_back(p_func->arguments[i]->get_datatype()); - args2.push_back(p_func->arguments[i]->get_datatype_name()); - } - - int argcount = args.size(); - - bool failed_builtin = false; - bool unsupported_builtin = false; - int builtin_idx = 0; - - if (argcount <= 4) { - // test builtins - int idx = 0; - - while (builtin_func_defs[idx].name) { - - if (completion_class != builtin_func_defs[idx].tag) { - idx++; - continue; - } - - if (name == builtin_func_defs[idx].name) { - - failed_builtin = true; - bool fail = false; - for (int i = 0; i < argcount; i++) { - - if (get_scalar_type(args[i]) == args[i] && p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast(p_func->arguments[i + 1]), builtin_func_defs[idx].args[i])) { - //all good, but needs implicit conversion later - } else if (args[i] != builtin_func_defs[idx].args[i]) { - fail = true; - break; - } - } - - if (!fail) { - if (VisualServer::get_singleton()->is_low_end()) { - if (builtin_func_defs[idx].high_end) { - fail = true; - unsupported_builtin = true; - builtin_idx = idx; - } - } - } - - if (!fail && argcount < 4 && builtin_func_defs[idx].args[argcount] != TYPE_VOID) - fail = true; //make sure the number of arguments matches - - if (!fail) { - - //make sure its not an out argument used in the wrong way - int outarg_idx = 0; - while (builtin_func_out_args[outarg_idx].name) { - - if (String(name) == builtin_func_out_args[outarg_idx].name) { - int arg_idx = builtin_func_out_args[outarg_idx].argument; - - if (arg_idx < argcount) { - - if (p_func->arguments[arg_idx + 1]->type != Node::TYPE_VARIABLE && p_func->arguments[arg_idx + 1]->type != Node::TYPE_MEMBER && p_func->arguments[arg_idx + 1]->type != Node::TYPE_ARRAY) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); - return false; - } - - if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { - ArrayNode *mn = static_cast(p_func->arguments[arg_idx + 1]); - if (mn->is_const) { - fail = true; - } - } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { - MemberNode *mn = static_cast(p_func->arguments[arg_idx + 1]); - if (mn->basetype_const) { - fail = true; - } - } else { // TYPE_VARIABLE - VariableNode *vn = static_cast(p_func->arguments[arg_idx + 1]); - if (vn->is_const) { - fail = true; - } else { - StringName varname = vn->name; - if (shader->uniforms.has(varname)) { - fail = true; - } else { - if (p_builtin_types.has(varname)) { - BuiltInInfo info = p_builtin_types[varname]; - if (info.constant) { - fail = true; - } - } - } - } - } - if (fail) { - _set_error(vformat("Constant value cannot be passed for '%s' parameter!", "out")); - return false; - } - - StringName var_name; - if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_ARRAY) { - var_name = static_cast(p_func->arguments[arg_idx + 1])->name; - } else if (p_func->arguments[arg_idx + 1]->type == Node::TYPE_MEMBER) { - Node *n = static_cast(p_func->arguments[arg_idx + 1])->owner; - while (n->type == Node::TYPE_MEMBER) { - n = static_cast(n)->owner; - } - if (n->type != Node::TYPE_VARIABLE && n->type != Node::TYPE_ARRAY) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' is not a variable, array or member."); - return false; - } - if (n->type == Node::TYPE_VARIABLE) { - var_name = static_cast(n)->name; - } else { // TYPE_ARRAY - var_name = static_cast(n)->name; - } - } else { // TYPE_VARIABLE - var_name = static_cast(p_func->arguments[arg_idx + 1])->name; - } - const BlockNode *b = p_block; - bool valid = false; - while (b) { - if (b->variables.has(var_name) || p_builtin_types.has(var_name)) { - valid = true; - break; - } - if (b->parent_function) { - for (int i = 0; i < b->parent_function->arguments.size(); i++) { - if (b->parent_function->arguments[i].name == var_name) { - valid = true; - break; - } - } - } - b = b->parent_block; - } - - if (!valid) { - _set_error("Argument " + itos(arg_idx + 1) + " of function '" + String(name) + "' can only take a local variable, array or member."); - return false; - } - } - } - - outarg_idx++; - } - //implicitly convert values if possible - for (int i = 0; i < argcount; i++) { - - if (get_scalar_type(args[i]) != args[i] || args[i] == builtin_func_defs[idx].args[i] || p_func->arguments[i + 1]->type != Node::TYPE_CONSTANT) { - //can't do implicit conversion here - continue; - } - - //this is an implicit conversion - ConstantNode *constant = static_cast(p_func->arguments[i + 1]); - ConstantNode *conversion = alloc_node(); - - conversion->datatype = builtin_func_defs[idx].args[i]; - conversion->values.resize(1); - - convert_constant(constant, builtin_func_defs[idx].args[i], conversion->values.ptrw()); - p_func->arguments.write[i + 1] = conversion; - } - - if (r_ret_type) - *r_ret_type = builtin_func_defs[idx].rettype; - - return true; - } - } - - idx++; - } - } - - if (unsupported_builtin) { - - String arglist = ""; - for (int i = 0; i < argcount; i++) { - if (i > 0) { - arglist += ", "; - } - arglist += get_datatype_name(builtin_func_defs[builtin_idx].args[i]); - } - - String err = "Built-in function \"" + String(name) + "(" + arglist + ")\" is supported only on high-end platform!"; - _set_error(err); - return false; - } - - if (failed_builtin) { - String err = "Invalid arguments for built-in function: " + String(name) + "("; - for (int i = 0; i < argcount; i++) { - if (i > 0) - err += ","; - - if (p_func->arguments[i + 1]->type == Node::TYPE_CONSTANT && p_func->arguments[i + 1]->get_datatype() == TYPE_INT && static_cast(p_func->arguments[i + 1])->values[0].sint < 0) { - err += "-"; - } - err += get_datatype_name(args[i]); - } - err += ")"; - _set_error(err); - return false; - } - - // try existing functions.. - - StringName exclude_function; - BlockNode *block = p_block; - - while (block) { - - if (block->parent_function) { - exclude_function = block->parent_function->name; - } - block = block->parent_block; - } - - if (name == exclude_function) { - _set_error("Recursion is not allowed"); - return false; - } - - for (int i = 0; i < shader->functions.size(); i++) { - - if (name != shader->functions[i].name) - continue; - - if (!shader->functions[i].callable) { - _set_error("Function '" + String(name) + " can't be called from source code."); - return false; - } - - FunctionNode *pfunc = shader->functions[i].function; - - if (pfunc->arguments.size() != args.size()) - continue; - - bool fail = false; - - for (int j = 0; j < args.size(); j++) { - if (args[j] == TYPE_STRUCT && args2[j] != pfunc->arguments[j].type_str) { - fail = true; - break; - } - if (get_scalar_type(args[j]) == args[j] && p_func->arguments[j + 1]->type == Node::TYPE_CONSTANT && convert_constant(static_cast(p_func->arguments[j + 1]), pfunc->arguments[j].type)) { - //all good, but it needs implicit conversion later - } else if (args[j] != pfunc->arguments[j].type) { - fail = true; - break; - } - } - - if (!fail) { - - //implicitly convert values if possible - for (int k = 0; k < args.size(); k++) { - - if (get_scalar_type(args[k]) != args[k] || args[k] == pfunc->arguments[k].type || p_func->arguments[k + 1]->type != Node::TYPE_CONSTANT) { - //can't do implicit conversion here - continue; - } - - //this is an implicit conversion - ConstantNode *constant = static_cast(p_func->arguments[k + 1]); - ConstantNode *conversion = alloc_node(); - - conversion->datatype = pfunc->arguments[k].type; - conversion->values.resize(1); - - convert_constant(constant, pfunc->arguments[k].type, conversion->values.ptrw()); - p_func->arguments.write[k + 1] = conversion; - } - - if (r_ret_type) { - *r_ret_type = pfunc->return_type; - if (pfunc->return_type == TYPE_STRUCT) { - *r_ret_type_str = pfunc->return_struct_name; - } - } - - return true; - } - } - - return false; -} - -bool ShaderLanguage::_compare_datatypes_in_nodes(Node *a, Node *b) const { - if (a->get_datatype() != b->get_datatype()) { - return false; - } - if (a->get_datatype() == TYPE_STRUCT || b->get_datatype() == TYPE_STRUCT) { - if (a->get_datatype_name() != b->get_datatype_name()) { - return false; - } - } - return true; -} - -bool ShaderLanguage::_parse_function_arguments(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, int *r_complete_arg) { - - TkPos pos = _get_tkpos(); - Token tk = _get_token(); - - if (tk.type == TK_PARENTHESIS_CLOSE) { - return true; - } - - _set_tkpos(pos); - - while (true) { - - if (r_complete_arg) { - pos = _get_tkpos(); - tk = _get_token(); - - if (tk.type == TK_CURSOR) { - - *r_complete_arg = p_func->arguments.size() - 1; - } else { - - _set_tkpos(pos); - } - } - - Node *arg = _parse_and_reduce_expression(p_block, p_builtin_types); - - if (!arg) { - - return false; - } - - p_func->arguments.push_back(arg); - - tk = _get_token(); - - if (tk.type == TK_PARENTHESIS_CLOSE) { - - return true; - } else if (tk.type != TK_COMMA) { - // something is broken - _set_error("Expected ',' or ')' after argument"); - return false; - } - } - - return true; -} - -bool ShaderLanguage::is_token_operator(TokenType p_type) { - - return (p_type == TK_OP_EQUAL || - p_type == TK_OP_NOT_EQUAL || - p_type == TK_OP_LESS || - p_type == TK_OP_LESS_EQUAL || - p_type == TK_OP_GREATER || - p_type == TK_OP_GREATER_EQUAL || - p_type == TK_OP_AND || - p_type == TK_OP_OR || - p_type == TK_OP_NOT || - p_type == TK_OP_ADD || - p_type == TK_OP_SUB || - p_type == TK_OP_MUL || - p_type == TK_OP_DIV || - p_type == TK_OP_MOD || - p_type == TK_OP_SHIFT_LEFT || - p_type == TK_OP_SHIFT_RIGHT || - p_type == TK_OP_ASSIGN || - p_type == TK_OP_ASSIGN_ADD || - p_type == TK_OP_ASSIGN_SUB || - p_type == TK_OP_ASSIGN_MUL || - p_type == TK_OP_ASSIGN_DIV || - p_type == TK_OP_ASSIGN_MOD || - p_type == TK_OP_ASSIGN_SHIFT_LEFT || - p_type == TK_OP_ASSIGN_SHIFT_RIGHT || - p_type == TK_OP_ASSIGN_BIT_AND || - p_type == TK_OP_ASSIGN_BIT_OR || - p_type == TK_OP_ASSIGN_BIT_XOR || - p_type == TK_OP_BIT_AND || - p_type == TK_OP_BIT_OR || - p_type == TK_OP_BIT_XOR || - p_type == TK_OP_BIT_INVERT || - p_type == TK_OP_INCREMENT || - p_type == TK_OP_DECREMENT || - p_type == TK_QUESTION || - p_type == TK_COLON); -} - -bool ShaderLanguage::convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value) { - - if (p_constant->datatype == p_to_type) { - if (p_value) { - for (int i = 0; i < p_constant->values.size(); i++) { - p_value[i] = p_constant->values[i]; - } - } - return true; - } else if (p_constant->datatype == TYPE_INT && p_to_type == TYPE_FLOAT) { - - if (p_value) { - p_value->real = p_constant->values[0].sint; - } - return true; - } else if (p_constant->datatype == TYPE_UINT && p_to_type == TYPE_FLOAT) { - - if (p_value) { - p_value->real = p_constant->values[0].uint; - } - return true; - } else if (p_constant->datatype == TYPE_INT && p_to_type == TYPE_UINT) { - if (p_constant->values[0].sint < 0) { - return false; - } - if (p_value) { - p_value->uint = p_constant->values[0].sint; - } - return true; - } else if (p_constant->datatype == TYPE_UINT && p_to_type == TYPE_INT) { - - if (p_constant->values[0].uint > 0x7FFFFFFF) { - return false; - } - if (p_value) { - p_value->sint = p_constant->values[0].uint; - } - return true; - } else - return false; -} - -bool ShaderLanguage::is_scalar_type(DataType p_type) { - - return p_type == TYPE_BOOL || p_type == TYPE_INT || p_type == TYPE_UINT || p_type == TYPE_FLOAT; -} - -bool ShaderLanguage::is_sampler_type(DataType p_type) { - - return p_type == TYPE_SAMPLER2D || - p_type == TYPE_ISAMPLER2D || - p_type == TYPE_USAMPLER2D || - p_type == TYPE_SAMPLER2DARRAY || - p_type == TYPE_ISAMPLER2DARRAY || - p_type == TYPE_USAMPLER2DARRAY || - p_type == TYPE_SAMPLER3D || - p_type == TYPE_ISAMPLER3D || - p_type == TYPE_USAMPLER3D || - p_type == TYPE_SAMPLERCUBE; -} - -Variant ShaderLanguage::constant_value_to_variant(const Vector &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint) { - if (p_value.size() > 0) { - Variant value; - switch (p_type) { - case ShaderLanguage::TYPE_BOOL: - value = Variant(p_value[0].boolean); - break; - case ShaderLanguage::TYPE_BVEC2: - case ShaderLanguage::TYPE_BVEC3: - case ShaderLanguage::TYPE_BVEC4: - case ShaderLanguage::TYPE_INT: - value = Variant(p_value[0].sint); - break; - case ShaderLanguage::TYPE_IVEC2: - value = Variant(Vector2(p_value[0].sint, p_value[1].sint)); - break; - case ShaderLanguage::TYPE_IVEC3: - value = Variant(Vector3(p_value[0].sint, p_value[1].sint, p_value[2].sint)); - break; - case ShaderLanguage::TYPE_IVEC4: - value = Variant(Plane(p_value[0].sint, p_value[1].sint, p_value[2].sint, p_value[3].sint)); - break; - case ShaderLanguage::TYPE_UINT: - value = Variant(p_value[0].uint); - break; - case ShaderLanguage::TYPE_UVEC2: - value = Variant(Vector2(p_value[0].uint, p_value[1].uint)); - break; - case ShaderLanguage::TYPE_UVEC3: - value = Variant(Vector3(p_value[0].uint, p_value[1].uint, p_value[2].uint)); - break; - case ShaderLanguage::TYPE_UVEC4: - value = Variant(Plane(p_value[0].uint, p_value[1].uint, p_value[2].uint, p_value[3].uint)); - break; - case ShaderLanguage::TYPE_FLOAT: - value = Variant(p_value[0].real); - break; - case ShaderLanguage::TYPE_VEC2: - value = Variant(Vector2(p_value[0].real, p_value[1].real)); - break; - case ShaderLanguage::TYPE_VEC3: - value = Variant(Vector3(p_value[0].real, p_value[1].real, p_value[2].real)); - break; - case ShaderLanguage::TYPE_VEC4: - if (p_hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - value = Variant(Color(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); - } else { - value = Variant(Plane(p_value[0].real, p_value[1].real, p_value[2].real, p_value[3].real)); - } - break; - case ShaderLanguage::TYPE_MAT2: - value = Variant(Transform2D(p_value[0].real, p_value[2].real, p_value[1].real, p_value[3].real, 0.0, 0.0)); - break; - case ShaderLanguage::TYPE_MAT3: { - Basis p; - p[0][0] = p_value[0].real; - p[0][1] = p_value[1].real; - p[0][2] = p_value[2].real; - p[1][0] = p_value[3].real; - p[1][1] = p_value[4].real; - p[1][2] = p_value[5].real; - p[2][0] = p_value[6].real; - p[2][1] = p_value[7].real; - p[2][2] = p_value[8].real; - value = Variant(p); - break; - } - case ShaderLanguage::TYPE_MAT4: { - Basis p; - p[0][0] = p_value[0].real; - p[0][1] = p_value[1].real; - p[0][2] = p_value[2].real; - p[1][0] = p_value[4].real; - p[1][1] = p_value[5].real; - p[1][2] = p_value[6].real; - p[2][0] = p_value[8].real; - p[2][1] = p_value[9].real; - p[2][2] = p_value[10].real; - Transform t = Transform(p, Vector3(p_value[3].real, p_value[7].real, p_value[11].real)); - value = Variant(t); - break; - } - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_SAMPLER2DARRAY: - case ShaderLanguage::TYPE_SAMPLER2D: - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER3D: - case ShaderLanguage::TYPE_SAMPLERCUBE: { - // Texture types, likely not relevant here. - break; - } - case ShaderLanguage::TYPE_STRUCT: - break; - case ShaderLanguage::TYPE_VOID: - break; - } - return value; - } - return Variant(); -} - -PropertyInfo ShaderLanguage::uniform_to_property_info(const ShaderNode::Uniform &p_uniform) { - PropertyInfo pi; - switch (p_uniform.type) { - case ShaderLanguage::TYPE_VOID: pi.type = Variant::NIL; break; - case ShaderLanguage::TYPE_BOOL: pi.type = Variant::BOOL; break; - case ShaderLanguage::TYPE_BVEC2: - pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_FLAGS; - pi.hint_string = "x,y"; - break; - case ShaderLanguage::TYPE_BVEC3: - pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_FLAGS; - pi.hint_string = "x,y,z"; - break; - case ShaderLanguage::TYPE_BVEC4: - pi.type = Variant::INT; - pi.hint = PROPERTY_HINT_FLAGS; - pi.hint_string = "x,y,z,w"; - break; - case ShaderLanguage::TYPE_UINT: - case ShaderLanguage::TYPE_INT: { - pi.type = Variant::INT; - if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { - pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]); - } - - } break; - case ShaderLanguage::TYPE_IVEC2: - case ShaderLanguage::TYPE_IVEC3: - case ShaderLanguage::TYPE_IVEC4: - case ShaderLanguage::TYPE_UVEC2: - case ShaderLanguage::TYPE_UVEC3: - case ShaderLanguage::TYPE_UVEC4: { - - pi.type = Variant::PACKED_INT32_ARRAY; - } break; - case ShaderLanguage::TYPE_FLOAT: { - pi.type = Variant::FLOAT; - if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_RANGE) { - pi.hint = PROPERTY_HINT_RANGE; - pi.hint_string = rtos(p_uniform.hint_range[0]) + "," + rtos(p_uniform.hint_range[1]) + "," + rtos(p_uniform.hint_range[2]); - } - - } break; - case ShaderLanguage::TYPE_VEC2: pi.type = Variant::VECTOR2; break; - case ShaderLanguage::TYPE_VEC3: pi.type = Variant::VECTOR3; break; - case ShaderLanguage::TYPE_VEC4: { - if (p_uniform.hint == ShaderLanguage::ShaderNode::Uniform::HINT_COLOR) { - pi.type = Variant::COLOR; - } else { - pi.type = Variant::PLANE; - } - } break; - case ShaderLanguage::TYPE_MAT2: pi.type = Variant::TRANSFORM2D; break; - case ShaderLanguage::TYPE_MAT3: pi.type = Variant::BASIS; break; - case ShaderLanguage::TYPE_MAT4: pi.type = Variant::TRANSFORM; break; - case ShaderLanguage::TYPE_SAMPLER2D: - case ShaderLanguage::TYPE_ISAMPLER2D: - case ShaderLanguage::TYPE_USAMPLER2D: { - - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture2D"; - } break; - case ShaderLanguage::TYPE_SAMPLER2DARRAY: - case ShaderLanguage::TYPE_ISAMPLER2DARRAY: - case ShaderLanguage::TYPE_USAMPLER2DARRAY: { - - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "TextureArray"; - } break; - case ShaderLanguage::TYPE_SAMPLER3D: - case ShaderLanguage::TYPE_ISAMPLER3D: - case ShaderLanguage::TYPE_USAMPLER3D: { - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "Texture3D"; - } break; - case ShaderLanguage::TYPE_SAMPLERCUBE: { - - pi.type = Variant::OBJECT; - pi.hint = PROPERTY_HINT_RESOURCE_TYPE; - pi.hint_string = "CubeMap"; - } break; - case ShaderLanguage::TYPE_STRUCT: { - // FIXME: Implement this. - } break; - } - return pi; -} - -uint32_t ShaderLanguage::get_type_size(DataType p_type) { - switch (p_type) { - case TYPE_VOID: - return 0; - case TYPE_BOOL: - case TYPE_INT: - case TYPE_UINT: - case TYPE_FLOAT: - return 4; - case TYPE_BVEC2: - case TYPE_IVEC2: - case TYPE_UVEC2: - case TYPE_VEC2: - return 8; - case TYPE_BVEC3: - case TYPE_IVEC3: - case TYPE_UVEC3: - case TYPE_VEC3: - return 12; - case TYPE_BVEC4: - case TYPE_IVEC4: - case TYPE_UVEC4: - case TYPE_VEC4: - return 16; - case TYPE_MAT2: - return 8; - case TYPE_MAT3: - return 12; - case TYPE_MAT4: - return 16; - case TYPE_SAMPLER2D: - case TYPE_ISAMPLER2D: - case TYPE_USAMPLER2D: - case TYPE_SAMPLER2DARRAY: - case TYPE_ISAMPLER2DARRAY: - case TYPE_USAMPLER2DARRAY: - case TYPE_SAMPLER3D: - case TYPE_ISAMPLER3D: - case TYPE_USAMPLER3D: - case TYPE_SAMPLERCUBE: - return 4; //not really, but useful for indices - case TYPE_STRUCT: - // FIXME: Implement. - return 0; - } - return 0; -} - -void ShaderLanguage::get_keyword_list(List *r_keywords) { - - Set kws; - - int idx = 0; - - while (keyword_list[idx].text) { - - kws.insert(keyword_list[idx].text); - idx++; - } - - idx = 0; - - while (builtin_func_defs[idx].name) { - - kws.insert(builtin_func_defs[idx].name); - - idx++; - } - - for (Set::Element *E = kws.front(); E; E = E->next()) { - r_keywords->push_back(E->get()); - } -} - -void ShaderLanguage::get_builtin_funcs(List *r_keywords) { - - Set kws; - - int idx = 0; - - while (builtin_func_defs[idx].name) { - - kws.insert(builtin_func_defs[idx].name); - - idx++; - } - - for (Set::Element *E = kws.front(); E; E = E->next()) { - r_keywords->push_back(E->get()); - } -} - -ShaderLanguage::DataType ShaderLanguage::get_scalar_type(DataType p_type) { - - static const DataType scalar_types[] = { - TYPE_VOID, - TYPE_BOOL, - TYPE_BOOL, - TYPE_BOOL, - TYPE_BOOL, - TYPE_INT, - TYPE_INT, - TYPE_INT, - TYPE_INT, - TYPE_UINT, - TYPE_UINT, - TYPE_UINT, - TYPE_UINT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_FLOAT, - TYPE_INT, - TYPE_UINT, - TYPE_FLOAT, - }; - - return scalar_types[p_type]; -} - -int ShaderLanguage::get_cardinality(DataType p_type) { - static const int cardinality_table[] = { - 0, - 1, - 2, - 3, - 4, - 1, - 2, - 3, - 4, - 1, - 2, - 3, - 4, - 1, - 2, - 3, - 4, - 4, - 9, - 16, - 1, - 1, - 1, - 1, - }; - - return cardinality_table[p_type]; -} - -bool ShaderLanguage::_get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier) { - - identifier = StringName(); - - TkPos pos = { 0, 0 }; - - Token tk = _get_token(); - - if (tk.type == TK_IDENTIFIER) { - identifier = tk.text; - pos = _get_tkpos(); - tk = _get_token(); - } - - if (tk.type == TK_CURSOR) { - - completion_type = p_type; - completion_line = tk_line; - completion_block = p_block; - - pos = _get_tkpos(); - tk = _get_token(); - - if (tk.type == TK_IDENTIFIER) { - identifier = identifier.operator String() + tk.text.operator String(); - } else { - _set_tkpos(pos); - } - return true; - } else if (identifier != StringName()) { - _set_tkpos(pos); - } - - return false; -} - -bool ShaderLanguage::_is_operator_assign(Operator p_op) const { - switch (p_op) { - case OP_ASSIGN: - case OP_ASSIGN_ADD: - case OP_ASSIGN_SUB: - case OP_ASSIGN_MUL: - case OP_ASSIGN_DIV: - case OP_ASSIGN_MOD: - case OP_ASSIGN_SHIFT_LEFT: - case OP_ASSIGN_SHIFT_RIGHT: - case OP_ASSIGN_BIT_AND: - case OP_ASSIGN_BIT_OR: - case OP_ASSIGN_BIT_XOR: - return true; - default: - return false; - } - - return false; -} - -bool ShaderLanguage::_validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message) { - - if (p_node->type == Node::TYPE_OPERATOR) { - - OperatorNode *op = static_cast(p_node); - - if (op->op == OP_INDEX) { - return _validate_assign(op->arguments[0], p_builtin_types, r_message); - - } else if (_is_operator_assign(op->op)) { - //chained assignment - return _validate_assign(op->arguments[1], p_builtin_types, r_message); - - } else if (op->op == OP_CALL) { - if (r_message) - *r_message = RTR("Assignment to function."); - return false; - } - - } else if (p_node->type == Node::TYPE_MEMBER) { - - MemberNode *member = static_cast(p_node); - - if (member->has_swizzling_duplicates) { - if (r_message) - *r_message = RTR("Swizzling assignment contains duplicates."); - return false; - } - - return _validate_assign(member->owner, p_builtin_types, r_message); - - } else if (p_node->type == Node::TYPE_VARIABLE) { - - VariableNode *var = static_cast(p_node); - - if (shader->uniforms.has(var->name)) { - if (r_message) - *r_message = RTR("Assignment to uniform."); - return false; - } - - if (shader->varyings.has(var->name) && current_function != String("vertex")) { - if (r_message) - *r_message = RTR("Varyings can only be assigned in vertex function."); - return false; - } - - if (shader->constants.has(var->name) || var->is_const) { - if (r_message) - *r_message = RTR("Constants cannot be modified."); - return false; - } - - if (!(p_builtin_types.has(var->name) && p_builtin_types[var->name].constant)) { - return true; - } - } else if (p_node->type == Node::TYPE_ARRAY) { - - ArrayNode *arr = static_cast(p_node); - - if (arr->is_const) { - if (r_message) - *r_message = RTR("Constants cannot be modified."); - return false; - } - - if (shader->varyings.has(arr->name) && current_function != String("vertex")) { - if (r_message) - *r_message = RTR("Varyings can only be assigned in vertex function."); - return false; - } - - return true; - } - - if (r_message) - *r_message = "Assignment to constant expression."; - return false; -} - -bool ShaderLanguage::_propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat) { - for (int i = 0; shader->functions.size(); i++) { - if (shader->functions[i].name == p_name) { - - ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); - FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; - if (arg->tex_builtin_check) { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."); - return false; - } else if (arg->tex_argument_check) { - //was checked, verify that filter and repeat are the same - if (arg->tex_argument_filter == p_filter && arg->tex_argument_repeat == p_repeat) { - return true; - } else { - - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using textures that differ in either filter or repeat setting."); - return false; - } - } else { - - arg->tex_argument_check = true; - arg->tex_argument_filter = p_filter; - arg->tex_argument_repeat = p_repeat; - for (Map>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) { - for (Set::Element *F = E->get().front(); F; F = F->next()) { - if (!_propagate_function_call_sampler_uniform_settings(E->key(), F->get(), p_filter, p_repeat)) { - return false; - } - } - } - return true; - } - } - } - ERR_FAIL_V(false); //bug? function not found -} -bool ShaderLanguage::_propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin) { - for (int i = 0; shader->functions.size(); i++) { - if (shader->functions[i].name == p_name) { - - ERR_FAIL_INDEX_V(p_argument, shader->functions[i].function->arguments.size(), false); - FunctionNode::Argument *arg = &shader->functions[i].function->arguments.write[p_argument]; - if (arg->tex_argument_check) { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using both built-ins and uniform textures, this is not supported (use either one or the other)."); - return false; - } else if (arg->tex_builtin_check) { - //was checked, verify that the built-in is the same - if (arg->tex_builtin == p_builtin) { - return true; - } else { - _set_error("Sampler argument #" + itos(p_argument) + " of function '" + String(p_name) + "' called more than once using different built-ins. Only calling with the same built-in is supported."); - return false; - } - } else { - - arg->tex_builtin_check = true; - arg->tex_builtin = p_builtin; - - for (Map>::Element *E = arg->tex_argument_connect.front(); E; E = E->next()) { - for (Set::Element *F = E->get().front(); F; F = F->next()) { - if (!_propagate_function_call_sampler_builtin_reference(E->key(), F->get(), p_builtin)) { - return false; - } - } - } - return true; - } - } - } - ERR_FAIL_V(false); //bug? function not found -} - -ShaderLanguage::Node *ShaderLanguage::_parse_expression(BlockNode *p_block, const Map &p_builtin_types) { - - Vector expression; - - //Vector operators; - - while (true) { - - Node *expr = NULL; - TkPos prepos = _get_tkpos(); - Token tk = _get_token(); - TkPos pos = _get_tkpos(); - - bool is_const = false; - - if (tk.type == TK_PARENTHESIS_OPEN) { - //handle subexpression - - expr = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!expr) - return NULL; - - tk = _get_token(); - - if (tk.type != TK_PARENTHESIS_CLOSE) { - - _set_error("Expected ')' in expression"); - return NULL; - } - - } else if (tk.type == TK_REAL_CONSTANT) { - - ConstantNode *constant = alloc_node(); - ConstantNode::Value v; - v.real = tk.constant; - constant->values.push_back(v); - constant->datatype = TYPE_FLOAT; - expr = constant; - - } else if (tk.type == TK_INT_CONSTANT) { - - ConstantNode *constant = alloc_node(); - ConstantNode::Value v; - v.sint = tk.constant; - constant->values.push_back(v); - constant->datatype = TYPE_INT; - expr = constant; - - } else if (tk.type == TK_TRUE) { - - //handle true constant - ConstantNode *constant = alloc_node(); - ConstantNode::Value v; - v.boolean = true; - constant->values.push_back(v); - constant->datatype = TYPE_BOOL; - expr = constant; - - } else if (tk.type == TK_FALSE) { - - //handle false constant - ConstantNode *constant = alloc_node(); - ConstantNode::Value v; - v.boolean = false; - constant->values.push_back(v); - constant->datatype = TYPE_BOOL; - expr = constant; - - } else if (tk.type == TK_TYPE_VOID) { - - //make sure void is not used in expression - _set_error("Void value not allowed in Expression"); - return NULL; - } else if (is_token_nonvoid_datatype(tk.type)) { - //basic type constructor - - OperatorNode *func = alloc_node(); - func->op = OP_CONSTRUCT; - - if (is_token_precision(tk.type)) { - - func->return_precision_cache = get_token_precision(tk.type); - tk = _get_token(); - } - - VariableNode *funcname = alloc_node(); - funcname->name = get_datatype_name(get_token_datatype(tk.type)); - func->arguments.push_back(funcname); - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after type name"); - return NULL; - } - - int carg = -1; - - bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); - - if (carg >= 0) { - completion_type = COMPLETION_CALL_ARGUMENTS; - completion_line = tk_line; - completion_block = p_block; - completion_function = funcname->name; - completion_argument = carg; - } - - if (!ok) - return NULL; - - if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) { - _set_error("No matching constructor found for: '" + String(funcname->name) + "'"); - return NULL; - } - - expr = _reduce_expression(p_block, func); - - } else if (tk.type == TK_IDENTIFIER) { - - _set_tkpos(prepos); - - StringName identifier; - - StructNode *pstruct = NULL; - bool struct_init = false; - - _get_completable_identifier(p_block, COMPLETION_IDENTIFIER, identifier); - - if (shader->structs.has(identifier)) { - pstruct = shader->structs[identifier].shader_struct; - struct_init = true; - } - - tk = _get_token(); - if (tk.type == TK_PARENTHESIS_OPEN) { - - if (struct_init) { //a struct constructor - - const StringName &name = identifier; - - OperatorNode *func = alloc_node(); - func->op = OP_STRUCT; - func->struct_name = name; - func->return_cache = TYPE_STRUCT; - VariableNode *funcname = alloc_node(); - funcname->name = name; - func->arguments.push_back(funcname); - - for (int i = 0; i < pstruct->members.size(); i++) { - Node *nexpr; - - if (pstruct->members[i]->array_size != 0) { - - DataType type = pstruct->members[i]->get_datatype(); - String struct_name = pstruct->members[i]->struct_name; - int array_size = pstruct->members[i]->array_size; - - DataType type2; - String struct_name2 = ""; - int array_size2 = 0; - - bool auto_size = false; - - tk = _get_token(); - - if (tk.type == TK_CURLY_BRACKET_OPEN) { - auto_size = true; - } else { - - if (shader->structs.has(tk.text)) { - type2 = TYPE_STRUCT; - struct_name2 = tk.text; - } else { - if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for array"); - return NULL; - } - type2 = get_token_datatype(tk.type); - } - - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - TkPos pos2 = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - array_size2 = array_size; - tk = _get_token(); - } else { - _set_tkpos(pos2); - - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { - _set_error("Expected single integer constant > 0"); - return NULL; - } - - ConstantNode *cnode = (ConstantNode *)n; - if (cnode->values.size() == 1) { - array_size2 = cnode->values[0].sint; - if (array_size2 <= 0) { - _set_error("Expected single integer constant > 0"); - return NULL; - } - } else { - _set_error("Expected single integer constant > 0"); - return NULL; - } - - tk = _get_token(); - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return NULL; - } else { - tk = _get_token(); - } - } - } else { - _set_error("Expected '['"); - return NULL; - } - - if (type != type2 || struct_name != struct_name2 || array_size != array_size2) { - String error_str = "Cannot convert from '"; - if (type2 == TYPE_STRUCT) { - error_str += struct_name2; - } else { - error_str += get_datatype_name(type2); - } - error_str += "["; - error_str += itos(array_size2); - error_str += "]'"; - error_str += " to '"; - if (type == TYPE_STRUCT) { - error_str += struct_name; - } else { - error_str += get_datatype_name(type); - } - error_str += "["; - error_str += itos(array_size); - error_str += "]'"; - _set_error(error_str); - return NULL; - } - } - - ArrayConstructNode *an = alloc_node(); - an->datatype = type; - an->struct_name = struct_name; - - if (tk.type == TK_PARENTHESIS_OPEN || auto_size) { // initialization - while (true) { - - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n) { - return NULL; - } - - if (type != n->get_datatype() || struct_name != n->get_datatype_name()) { - _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (type == TYPE_STRUCT ? struct_name : get_datatype_name(type)) + "'"); - return NULL; - } - - tk = _get_token(); - if (tk.type == TK_COMMA) { - an->initializer.push_back(n); - continue; - } else if (!auto_size && tk.type == TK_PARENTHESIS_CLOSE) { - an->initializer.push_back(n); - break; - } else if (auto_size && tk.type == TK_CURLY_BRACKET_CLOSE) { - an->initializer.push_back(n); - break; - } else { - if (auto_size) - _set_error("Expected '}' or ','"); - else - _set_error("Expected ')' or ','"); - return NULL; - } - } - if (an->initializer.size() != array_size) { - _set_error("Array size mismatch"); - return NULL; - } - } else { - _set_error("Expected array initialization!"); - return NULL; - } - - nexpr = an; - } else { - nexpr = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!nexpr) { - return NULL; - } - Node *node = pstruct->members[i]; - if (!_compare_datatypes_in_nodes(pstruct->members[i], nexpr)) { - String type_name = nexpr->get_datatype() == TYPE_STRUCT ? nexpr->get_datatype_name() : get_datatype_name(nexpr->get_datatype()); - String type_name2 = node->get_datatype() == TYPE_STRUCT ? node->get_datatype_name() : get_datatype_name(node->get_datatype()); - _set_error("Invalid assignment of '" + type_name + "' to '" + type_name2 + "'"); - return NULL; - } - } - - if (i + 1 < pstruct->members.size()) { - tk = _get_token(); - if (tk.type != TK_COMMA) { - _set_error("Expected ','"); - return NULL; - } - } - func->arguments.push_back(nexpr); - } - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')'"); - return NULL; - } - - expr = func; - - } else { //a function - - const StringName &name = identifier; - - OperatorNode *func = alloc_node(); - func->op = OP_CALL; - VariableNode *funcname = alloc_node(); - funcname->name = name; - func->arguments.push_back(funcname); - - int carg = -1; - - bool ok = _parse_function_arguments(p_block, p_builtin_types, func, &carg); - - // Check if block has a variable with the same name as function to prevent shader crash. - ShaderLanguage::BlockNode *bnode = p_block; - while (bnode) { - if (bnode->variables.has(name)) { - _set_error("Expected function name"); - return NULL; - } - bnode = bnode->parent_block; - } - - //test if function was parsed first - int function_index = -1; - for (int i = 0; i < shader->functions.size(); i++) { - if (shader->functions[i].name == name) { - //add to current function as dependency - for (int j = 0; j < shader->functions.size(); j++) { - if (shader->functions[j].name == current_function) { - shader->functions.write[j].uses_function.insert(name); - break; - } - } - - //see if texture arguments must connect - function_index = i; - break; - } - } - - if (carg >= 0) { - completion_type = COMPLETION_CALL_ARGUMENTS; - completion_line = tk_line; - completion_block = p_block; - completion_function = funcname->name; - completion_argument = carg; - } - - if (!ok) - return NULL; - - if (!_validate_function_call(p_block, p_builtin_types, func, &func->return_cache, &func->struct_name)) { - _set_error("No matching function found for: '" + String(funcname->name) + "'"); - return NULL; - } - completion_class = TAG_GLOBAL; // reset sub-class - if (function_index >= 0) { - //connect texture arguments, so we can cache in the - //argument what type of filter and repeat to use - - FunctionNode *call_function = shader->functions[function_index].function; - if (call_function) { - - //get current base function - FunctionNode *base_function = NULL; - { - BlockNode *b = p_block; - - while (b) { - - if (b->parent_function) { - base_function = b->parent_function; - break; - } else { - b = b->parent_block; - } - } - } - - ERR_FAIL_COND_V(!base_function, NULL); //bug, wtf - - for (int i = 0; i < call_function->arguments.size(); i++) { - int argidx = i + 1; - if (argidx < func->arguments.size()) { - if (call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT || call_function->arguments[i].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT) { - bool error = false; - Node *n = func->arguments[argidx]; - if (n->type == Node::TYPE_CONSTANT || n->type == Node::TYPE_OPERATOR) { - error = true; - } else if (n->type == Node::TYPE_ARRAY) { - ArrayNode *an = static_cast(n); - if (an->call_expression != NULL) { - error = true; - } - } else if (n->type == Node::TYPE_VARIABLE) { - VariableNode *vn = static_cast(n); - if (vn->is_const) { - error = true; - } else { - StringName varname = vn->name; - if (shader->uniforms.has(varname)) { - error = true; - } else { - if (p_builtin_types.has(varname)) { - BuiltInInfo info = p_builtin_types[varname]; - if (info.constant) { - error = true; - } - } - } - } - } else if (n->type == Node::TYPE_MEMBER) { - MemberNode *mn = static_cast(n); - if (mn->basetype_const) { - error = true; - } - } - if (error) { - _set_error(vformat("Constant value cannot be passed for '%s' parameter!", _get_qualifier_str(call_function->arguments[i].qualifier))); - return NULL; - } - } - if (is_sampler_type(call_function->arguments[i].type)) { - //let's see where our argument comes from - Node *n = func->arguments[argidx]; - ERR_CONTINUE(n->type != Node::TYPE_VARIABLE); //bug? this should always be a variable - VariableNode *vn = static_cast(n); - StringName varname = vn->name; - if (shader->uniforms.has(varname)) { - //being sampler, this either comes from a uniform - ShaderNode::Uniform *u = &shader->uniforms[varname]; - ERR_CONTINUE(u->type != call_function->arguments[i].type); //this should have been validated previously - //propagate - if (!_propagate_function_call_sampler_uniform_settings(name, i, u->filter, u->repeat)) { - return NULL; - } - } else if (p_builtin_types.has(varname)) { - //a built-in - if (!_propagate_function_call_sampler_builtin_reference(name, i, varname)) { - return NULL; - } - } else { - //or this comes from an argument, but nothing else can be a sampler - bool found = false; - for (int j = 0; j < base_function->arguments.size(); j++) { - if (base_function->arguments[j].name == varname) { - if (!base_function->arguments[j].tex_argument_connect.has(call_function->name)) { - base_function->arguments.write[j].tex_argument_connect[call_function->name] = Set(); - } - base_function->arguments.write[j].tex_argument_connect[call_function->name].insert(i); - found = true; - break; - } - } - ERR_CONTINUE(!found); - } - } - } else { - break; - } - } - } - } - expr = func; - } - } else { - //an identifier - - _set_tkpos(pos); - - DataType data_type; - IdentifierType ident_type; - int array_size = 0; - StringName struct_name; - - if (p_block && p_block->block_tag != SubClassTag::TAG_GLOBAL) { - int idx = 0; - bool found = false; - - while (builtin_func_defs[idx].name) { - if (builtin_func_defs[idx].tag == p_block->block_tag && builtin_func_defs[idx].name == identifier) { - found = true; - break; - } - idx++; - } - if (!found) { - _set_error("Unknown identifier in expression: " + String(identifier)); - return NULL; - } - } else { - - if (!_find_identifier(p_block, false, p_builtin_types, identifier, &data_type, &ident_type, &is_const, &array_size, &struct_name)) { - _set_error("Unknown identifier in expression: " + String(identifier)); - return NULL; - } - - if (ident_type == IDENTIFIER_FUNCTION) { - _set_error("Can't use function as identifier: " + String(identifier)); - return NULL; - } - } - - Node *index_expression = NULL; - Node *call_expression = NULL; - - if (array_size > 0) { - tk = _get_token(); - - if (tk.type != TK_BRACKET_OPEN && tk.type != TK_PERIOD) { - _set_error("Expected '[' or '.'"); - return NULL; - } - - if (tk.type == TK_PERIOD) { - completion_class = TAG_ARRAY; - p_block->block_tag = SubClassTag::TAG_ARRAY; - call_expression = _parse_and_reduce_expression(p_block, p_builtin_types); - p_block->block_tag = SubClassTag::TAG_GLOBAL; - if (!call_expression) - return NULL; - data_type = call_expression->get_datatype(); - } else { // indexing - - index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!index_expression) - return NULL; - - if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) { - _set_error("Only integer expressions are allowed for indexing"); - return NULL; - } - - if (index_expression->type == Node::TYPE_CONSTANT) { - ConstantNode *cnode = (ConstantNode *)index_expression; - if (cnode) { - if (!cnode->values.empty()) { - int value = cnode->values[0].sint; - if (value < 0 || value >= array_size) { - _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); - return NULL; - } - } - } - } - - tk = _get_token(); - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return NULL; - } - } - - ArrayNode *arrname = alloc_node(); - arrname->name = identifier; - arrname->datatype_cache = data_type; - arrname->struct_name = struct_name; - arrname->index_expression = index_expression; - arrname->call_expression = call_expression; - arrname->is_const = is_const; - expr = arrname; - - } else { - - VariableNode *varname = alloc_node(); - varname->name = identifier; - varname->datatype_cache = data_type; - varname->is_const = is_const; - varname->struct_name = struct_name; - expr = varname; - } - } - } else if (tk.type == TK_OP_ADD) { - continue; //this one does nothing - } else if (tk.type == TK_OP_SUB || tk.type == TK_OP_NOT || tk.type == TK_OP_BIT_INVERT || tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) { - - Expression e; - e.is_op = true; - - switch (tk.type) { - case TK_OP_SUB: e.op = OP_NEGATE; break; - case TK_OP_NOT: e.op = OP_NOT; break; - case TK_OP_BIT_INVERT: e.op = OP_BIT_INVERT; break; - case TK_OP_INCREMENT: e.op = OP_INCREMENT; break; - case TK_OP_DECREMENT: e.op = OP_DECREMENT; break; - default: ERR_FAIL_V(NULL); - } - - expression.push_back(e); - continue; - } else { - _set_error("Expected expression, found: " + get_token_text(tk)); - return NULL; - //nothing - } - - ERR_FAIL_COND_V(!expr, NULL); - - /* OK now see what's NEXT to the operator.. */ - /* OK now see what's NEXT to the operator.. */ - /* OK now see what's NEXT to the operator.. */ - - while (true) { - TkPos pos2 = _get_tkpos(); - tk = _get_token(); - - if (tk.type == TK_CURSOR) { - //do nothing - } else if (tk.type == TK_IDENTIFIER) { - - } else if (tk.type == TK_PERIOD) { - - DataType dt = expr->get_datatype(); - String st = expr->get_datatype_name(); - - StringName identifier; - if (_get_completable_identifier(p_block, dt == TYPE_STRUCT ? COMPLETION_STRUCT : COMPLETION_INDEX, identifier)) { - if (dt == TYPE_STRUCT) { - completion_struct = st; - } else { - completion_base = dt; - } - } - - if (identifier == StringName()) { - _set_error("Expected identifier as member"); - return NULL; - } - String ident = identifier; - - bool ok = true; - bool repeated = false; - DataType member_type = TYPE_VOID; - StringName member_struct_name = ""; - int array_size = 0; - - Set position_symbols; - Set color_symbols; - Set texture_symbols; - - bool mix_error = false; - - switch (dt) { - case TYPE_STRUCT: { - ok = false; - String member_name = String(ident.ptr()); - if (shader->structs.has(st)) { - StructNode *n = shader->structs[st].shader_struct; - for (List::Element *E = n->members.front(); E; E = E->next()) { - if (String(E->get()->name) == member_name) { - member_type = E->get()->datatype; - array_size = E->get()->array_size; - if (member_type == TYPE_STRUCT) { - member_struct_name = E->get()->struct_name; - } - ok = true; - break; - } - } - } - - } break; - case TYPE_BVEC2: - case TYPE_IVEC2: - case TYPE_UVEC2: - case TYPE_VEC2: { - - int l = ident.length(); - if (l == 1) { - member_type = DataType(dt - 1); - } else if (l == 2) { - member_type = dt; - } else if (l == 3) { - member_type = DataType(dt + 1); - } else if (l == 4) { - member_type = DataType(dt + 2); - } else { - ok = false; - break; - } - - const CharType *c = ident.ptr(); - for (int i = 0; i < l; i++) { - - switch (c[i]) { - case 'r': - case 'g': - if (position_symbols.size() > 0 || texture_symbols.size() > 0) { - mix_error = true; - break; - } - if (!color_symbols.has(c[i])) { - color_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - case 'x': - case 'y': - if (color_symbols.size() > 0 || texture_symbols.size() > 0) { - mix_error = true; - break; - } - if (!position_symbols.has(c[i])) { - position_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - case 's': - case 't': - if (color_symbols.size() > 0 || position_symbols.size() > 0) { - mix_error = true; - break; - } - if (!texture_symbols.has(c[i])) { - texture_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - default: - ok = false; - break; - } - } - - } break; - case TYPE_BVEC3: - case TYPE_IVEC3: - case TYPE_UVEC3: - case TYPE_VEC3: { - - int l = ident.length(); - if (l == 1) { - member_type = DataType(dt - 2); - } else if (l == 2) { - member_type = DataType(dt - 1); - } else if (l == 3) { - member_type = dt; - } else if (l == 4) { - member_type = DataType(dt + 1); - } else { - ok = false; - break; - } - - const CharType *c = ident.ptr(); - for (int i = 0; i < l; i++) { - - switch (c[i]) { - case 'r': - case 'g': - case 'b': - if (position_symbols.size() > 0 || texture_symbols.size() > 0) { - mix_error = true; - break; - } - if (!color_symbols.has(c[i])) { - color_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - case 'x': - case 'y': - case 'z': - if (color_symbols.size() > 0 || texture_symbols.size() > 0) { - mix_error = true; - break; - } - if (!position_symbols.has(c[i])) { - position_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - case 's': - case 't': - case 'p': - if (color_symbols.size() > 0 || position_symbols.size() > 0) { - mix_error = true; - break; - } - if (!texture_symbols.has(c[i])) { - texture_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - default: - ok = false; - break; - } - } - - } break; - case TYPE_BVEC4: - case TYPE_IVEC4: - case TYPE_UVEC4: - case TYPE_VEC4: { - - int l = ident.length(); - if (l == 1) { - member_type = DataType(dt - 3); - } else if (l == 2) { - member_type = DataType(dt - 2); - } else if (l == 3) { - member_type = DataType(dt - 1); - } else if (l == 4) { - member_type = dt; - } else { - ok = false; - break; - } - - const CharType *c = ident.ptr(); - for (int i = 0; i < l; i++) { - - switch (c[i]) { - case 'r': - case 'g': - case 'b': - case 'a': - if (position_symbols.size() > 0 || texture_symbols.size() > 0) { - mix_error = true; - break; - } - if (!color_symbols.has(c[i])) { - color_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - case 'x': - case 'y': - case 'z': - case 'w': - if (color_symbols.size() > 0 || texture_symbols.size() > 0) { - mix_error = true; - break; - } - if (!position_symbols.has(c[i])) { - position_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - case 's': - case 't': - case 'p': - case 'q': - if (color_symbols.size() > 0 || position_symbols.size() > 0) { - mix_error = true; - break; - } - if (!texture_symbols.has(c[i])) { - texture_symbols.insert(c[i]); - } else { - repeated = true; - } - break; - default: - ok = false; - break; - } - } - - } break; - - default: { - ok = false; - } - } - - if (mix_error) { - _set_error("Cannot combine symbols from different sets in expression ." + ident); - return NULL; - } - - if (!ok) { - _set_error("Invalid member for " + (dt == TYPE_STRUCT ? st : get_datatype_name(dt)) + " expression: ." + ident); - return NULL; - } - - MemberNode *mn = alloc_node(); - mn->basetype = dt; - mn->basetype_const = is_const; - mn->datatype = member_type; - mn->base_struct_name = st; - mn->struct_name = member_struct_name; - mn->array_size = array_size; - mn->name = ident; - mn->owner = expr; - mn->has_swizzling_duplicates = repeated; - - if (array_size > 0) { - - tk = _get_token(); - if (tk.type == TK_PERIOD) { - _set_error("Nested array length() is not yet implemented"); - return NULL; - } else if (tk.type == TK_BRACKET_OPEN) { - - Node *index_expression = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!index_expression) - return NULL; - - if (index_expression->get_datatype() != TYPE_INT && index_expression->get_datatype() != TYPE_UINT) { - _set_error("Only integer expressions are allowed for indexing"); - return NULL; - } - - if (index_expression->type == Node::TYPE_CONSTANT) { - ConstantNode *cnode = (ConstantNode *)index_expression; - if (cnode) { - if (!cnode->values.empty()) { - int value = cnode->values[0].sint; - if (value < 0 || value >= array_size) { - _set_error(vformat("Index [%s] out of range [%s..%s]", value, 0, array_size - 1)); - return NULL; - } - } - } - } - - tk = _get_token(); - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return NULL; - } - mn->index_expression = index_expression; - - } else { - _set_error("Expected '[' or '.'"); - return NULL; - } - } - - expr = mn; - - //todo - //member (period) has priority over any operator - //creates a subindexing expression in place - - /*} else if (tk.type==TK_BRACKET_OPEN) { - //todo - //subindexing has priority over any operator - //creates a subindexing expression in place - - */ - } else if (tk.type == TK_BRACKET_OPEN) { - - Node *index = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!index) - return NULL; - - if (index->get_datatype() != TYPE_INT && index->get_datatype() != TYPE_UINT) { - _set_error("Only integer datatypes are allowed for indexing"); - return NULL; - } - - DataType member_type = TYPE_VOID; - - switch (expr->get_datatype()) { - case TYPE_BVEC2: - case TYPE_VEC2: - case TYPE_IVEC2: - case TYPE_UVEC2: - case TYPE_MAT2: - if (index->type == Node::TYPE_CONSTANT) { - uint32_t index_constant = static_cast(index)->values[0].uint; - if (index_constant >= 2) { - _set_error("Index out of range (0-1)"); - return NULL; - } - } - - switch (expr->get_datatype()) { - case TYPE_BVEC2: member_type = TYPE_BOOL; break; - case TYPE_VEC2: member_type = TYPE_FLOAT; break; - case TYPE_IVEC2: member_type = TYPE_INT; break; - case TYPE_UVEC2: member_type = TYPE_UINT; break; - case TYPE_MAT2: member_type = TYPE_VEC2; break; - default: break; - } - - break; - case TYPE_BVEC3: - case TYPE_VEC3: - case TYPE_IVEC3: - case TYPE_UVEC3: - case TYPE_MAT3: - if (index->type == Node::TYPE_CONSTANT) { - uint32_t index_constant = static_cast(index)->values[0].uint; - if (index_constant >= 3) { - _set_error("Index out of range (0-2)"); - return NULL; - } - } - - switch (expr->get_datatype()) { - case TYPE_BVEC3: member_type = TYPE_BOOL; break; - case TYPE_VEC3: member_type = TYPE_FLOAT; break; - case TYPE_IVEC3: member_type = TYPE_INT; break; - case TYPE_UVEC3: member_type = TYPE_UINT; break; - case TYPE_MAT3: member_type = TYPE_VEC3; break; - default: break; - } - break; - case TYPE_BVEC4: - case TYPE_VEC4: - case TYPE_IVEC4: - case TYPE_UVEC4: - case TYPE_MAT4: - if (index->type == Node::TYPE_CONSTANT) { - uint32_t index_constant = static_cast(index)->values[0].uint; - if (index_constant >= 4) { - _set_error("Index out of range (0-3)"); - return NULL; - } - } - - switch (expr->get_datatype()) { - case TYPE_BVEC4: member_type = TYPE_BOOL; break; - case TYPE_VEC4: member_type = TYPE_FLOAT; break; - case TYPE_IVEC4: member_type = TYPE_INT; break; - case TYPE_UVEC4: member_type = TYPE_UINT; break; - case TYPE_MAT4: member_type = TYPE_VEC4; break; - default: break; - } - break; - default: { - _set_error("Object of type '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' can't be indexed"); - return NULL; - } - } - - OperatorNode *op = alloc_node(); - op->op = OP_INDEX; - op->return_cache = member_type; - op->arguments.push_back(expr); - op->arguments.push_back(index); - expr = op; - - tk = _get_token(); - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']' after indexing expression"); - return NULL; - } - - } else if (tk.type == TK_OP_INCREMENT || tk.type == TK_OP_DECREMENT) { - - OperatorNode *op = alloc_node(); - op->op = tk.type == TK_OP_DECREMENT ? OP_POST_DECREMENT : OP_POST_INCREMENT; - op->arguments.push_back(expr); - - if (!_validate_operator(op, &op->return_cache)) { - _set_error("Invalid base type for increment/decrement operator"); - return NULL; - } - - if (!_validate_assign(expr, p_builtin_types)) { - _set_error("Invalid use of increment/decrement operator in constant expression."); - return NULL; - } - expr = op; - } else { - - _set_tkpos(pos2); - break; - } - } - - Expression e; - e.is_op = false; - e.node = expr; - expression.push_back(e); - - pos = _get_tkpos(); - tk = _get_token(); - - if (is_token_operator(tk.type)) { - - Expression o; - o.is_op = true; - - switch (tk.type) { - - case TK_OP_EQUAL: o.op = OP_EQUAL; break; - case TK_OP_NOT_EQUAL: o.op = OP_NOT_EQUAL; break; - case TK_OP_LESS: o.op = OP_LESS; break; - case TK_OP_LESS_EQUAL: o.op = OP_LESS_EQUAL; break; - case TK_OP_GREATER: o.op = OP_GREATER; break; - case TK_OP_GREATER_EQUAL: o.op = OP_GREATER_EQUAL; break; - case TK_OP_AND: o.op = OP_AND; break; - case TK_OP_OR: o.op = OP_OR; break; - case TK_OP_ADD: o.op = OP_ADD; break; - case TK_OP_SUB: o.op = OP_SUB; break; - case TK_OP_MUL: o.op = OP_MUL; break; - case TK_OP_DIV: o.op = OP_DIV; break; - case TK_OP_MOD: o.op = OP_MOD; break; - case TK_OP_SHIFT_LEFT: o.op = OP_SHIFT_LEFT; break; - case TK_OP_SHIFT_RIGHT: o.op = OP_SHIFT_RIGHT; break; - case TK_OP_ASSIGN: o.op = OP_ASSIGN; break; - case TK_OP_ASSIGN_ADD: o.op = OP_ASSIGN_ADD; break; - case TK_OP_ASSIGN_SUB: o.op = OP_ASSIGN_SUB; break; - case TK_OP_ASSIGN_MUL: o.op = OP_ASSIGN_MUL; break; - case TK_OP_ASSIGN_DIV: o.op = OP_ASSIGN_DIV; break; - case TK_OP_ASSIGN_MOD: o.op = OP_ASSIGN_MOD; break; - case TK_OP_ASSIGN_SHIFT_LEFT: o.op = OP_ASSIGN_SHIFT_LEFT; break; - case TK_OP_ASSIGN_SHIFT_RIGHT: o.op = OP_ASSIGN_SHIFT_RIGHT; break; - case TK_OP_ASSIGN_BIT_AND: o.op = OP_ASSIGN_BIT_AND; break; - case TK_OP_ASSIGN_BIT_OR: o.op = OP_ASSIGN_BIT_OR; break; - case TK_OP_ASSIGN_BIT_XOR: o.op = OP_ASSIGN_BIT_XOR; break; - case TK_OP_BIT_AND: o.op = OP_BIT_AND; break; - case TK_OP_BIT_OR: o.op = OP_BIT_OR; break; - case TK_OP_BIT_XOR: o.op = OP_BIT_XOR; break; - case TK_QUESTION: o.op = OP_SELECT_IF; break; - case TK_COLON: o.op = OP_SELECT_ELSE; break; - default: { - _set_error("Invalid token for operator: " + get_token_text(tk)); - return NULL; - } - } - - expression.push_back(o); - - } else { - _set_tkpos(pos); //something else, so rollback and end - break; - } - } - - /* Reduce the set set of expressions and place them in an operator tree, respecting precedence */ - - while (expression.size() > 1) { - - int next_op = -1; - int min_priority = 0xFFFFF; - bool is_unary = false; - bool is_ternary = false; - - for (int i = 0; i < expression.size(); i++) { - - if (!expression[i].is_op) { - - continue; - } - - bool unary = false; - bool ternary = false; - - int priority; - switch (expression[i].op) { - case OP_EQUAL: priority = 8; break; - case OP_NOT_EQUAL: priority = 8; break; - case OP_LESS: priority = 7; break; - case OP_LESS_EQUAL: priority = 7; break; - case OP_GREATER: priority = 7; break; - case OP_GREATER_EQUAL: priority = 7; break; - case OP_AND: priority = 12; break; - case OP_OR: priority = 14; break; - case OP_NOT: - priority = 3; - unary = true; - break; - case OP_NEGATE: - priority = 3; - unary = true; - break; - case OP_ADD: priority = 5; break; - case OP_SUB: priority = 5; break; - case OP_MUL: priority = 4; break; - case OP_DIV: priority = 4; break; - case OP_MOD: priority = 4; break; - case OP_SHIFT_LEFT: priority = 6; break; - case OP_SHIFT_RIGHT: priority = 6; break; - case OP_ASSIGN: priority = 16; break; - case OP_ASSIGN_ADD: priority = 16; break; - case OP_ASSIGN_SUB: priority = 16; break; - case OP_ASSIGN_MUL: priority = 16; break; - case OP_ASSIGN_DIV: priority = 16; break; - case OP_ASSIGN_MOD: priority = 16; break; - case OP_ASSIGN_SHIFT_LEFT: priority = 16; break; - case OP_ASSIGN_SHIFT_RIGHT: priority = 16; break; - case OP_ASSIGN_BIT_AND: priority = 16; break; - case OP_ASSIGN_BIT_OR: priority = 16; break; - case OP_ASSIGN_BIT_XOR: priority = 16; break; - case OP_BIT_AND: priority = 9; break; - case OP_BIT_OR: priority = 11; break; - case OP_BIT_XOR: priority = 10; break; - case OP_BIT_INVERT: - priority = 3; - unary = true; - break; - case OP_INCREMENT: - priority = 3; - unary = true; - break; - case OP_DECREMENT: - priority = 3; - unary = true; - break; - case OP_SELECT_IF: - priority = 15; - ternary = true; - break; - case OP_SELECT_ELSE: - priority = 15; - ternary = true; - break; - - default: - ERR_FAIL_V(NULL); //unexpected operator - } - - if (priority < min_priority) { - // < is used for left to right (default) - // <= is used for right to left - next_op = i; - min_priority = priority; - is_unary = unary; - is_ternary = ternary; - } - } - - ERR_FAIL_COND_V(next_op == -1, NULL); - - // OK! create operator.. - // OK! create operator.. - if (is_unary) { - - int expr_pos = next_op; - while (expression[expr_pos].is_op) { - - expr_pos++; - if (expr_pos == expression.size()) { - //can happen.. - _set_error("Unexpected end of expression..."); - return NULL; - } - } - - //consecutively do unary operators - for (int i = expr_pos - 1; i >= next_op; i--) { - - OperatorNode *op = alloc_node(); - op->op = expression[i].op; - if ((op->op == OP_INCREMENT || op->op == OP_DECREMENT) && !_validate_assign(expression[i + 1].node, p_builtin_types)) { - - _set_error("Can't use increment/decrement operator in constant expression."); - return NULL; - } - op->arguments.push_back(expression[i + 1].node); - - expression.write[i].is_op = false; - expression.write[i].node = op; - - if (!_validate_operator(op, &op->return_cache)) { - - String at; - for (int j = 0; j < op->arguments.size(); j++) { - if (j > 0) - at += " and "; - at += get_datatype_name(op->arguments[j]->get_datatype()); - } - _set_error("Invalid arguments to unary operator '" + get_operator_text(op->op) + "' :" + at); - return NULL; - } - expression.remove(i + 1); - } - - } else if (is_ternary) { - - if (next_op < 1 || next_op >= (expression.size() - 1)) { - _set_error("Parser bug..."); - ERR_FAIL_V(NULL); - } - - if (next_op + 2 >= expression.size() || !expression[next_op + 2].is_op || expression[next_op + 2].op != OP_SELECT_ELSE) { - _set_error("Missing matching ':' for select operator"); - return NULL; - } - - OperatorNode *op = alloc_node(); - op->op = expression[next_op].op; - op->arguments.push_back(expression[next_op - 1].node); - op->arguments.push_back(expression[next_op + 1].node); - op->arguments.push_back(expression[next_op + 3].node); - - expression.write[next_op - 1].is_op = false; - expression.write[next_op - 1].node = op; - if (!_validate_operator(op, &op->return_cache)) { - - String at; - for (int i = 0; i < op->arguments.size(); i++) { - if (i > 0) - at += " and "; - at += get_datatype_name(op->arguments[i]->get_datatype()); - } - _set_error("Invalid argument to ternary ?: operator: " + at); - return NULL; - } - - for (int i = 0; i < 4; i++) { - expression.remove(next_op); - } - - } else { - - if (next_op < 1 || next_op >= (expression.size() - 1)) { - _set_error("Parser bug..."); - ERR_FAIL_V(NULL); - } - - OperatorNode *op = alloc_node(); - op->op = expression[next_op].op; - - if (expression[next_op - 1].is_op) { - - _set_error("Parser bug..."); - ERR_FAIL_V(NULL); - } - - if (_is_operator_assign(op->op)) { - - String assign_message; - if (!_validate_assign(expression[next_op - 1].node, p_builtin_types, &assign_message)) { - - _set_error(assign_message); - return NULL; - } - } - - if (expression[next_op + 1].is_op) { - // this is not invalid and can really appear - // but it becomes invalid anyway because no binary op - // can be followed by a unary op in a valid combination, - // due to how precedence works, unaries will always disappear first - - _set_error("Parser bug..."); - } - - op->arguments.push_back(expression[next_op - 1].node); //expression goes as left - op->arguments.push_back(expression[next_op + 1].node); //next expression goes as right - expression.write[next_op - 1].node = op; - - //replace all 3 nodes by this operator and make it an expression - - if (!_validate_operator(op, &op->return_cache)) { - - String at; - for (int i = 0; i < op->arguments.size(); i++) { - if (i > 0) - at += " and "; - if (op->arguments[i]->get_datatype() == TYPE_STRUCT) { - at += op->arguments[i]->get_datatype_name(); - } else { - at += get_datatype_name(op->arguments[i]->get_datatype()); - } - } - _set_error("Invalid arguments to operator '" + get_operator_text(op->op) + "' :" + at); - return NULL; - } - - expression.remove(next_op); - expression.remove(next_op); - } - } - - return expression[0].node; -} - -ShaderLanguage::Node *ShaderLanguage::_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node) { - - if (p_node->type != Node::TYPE_OPERATOR) - return p_node; - - //for now only reduce simple constructors - OperatorNode *op = static_cast(p_node); - - if (op->op == OP_CONSTRUCT) { - - ERR_FAIL_COND_V(op->arguments[0]->type != Node::TYPE_VARIABLE, p_node); - - DataType type = op->get_datatype(); - DataType base = get_scalar_type(type); - int cardinality = get_cardinality(type); - - Vector values; - - for (int i = 1; i < op->arguments.size(); i++) { - - op->arguments.write[i] = _reduce_expression(p_block, op->arguments[i]); - if (op->arguments[i]->type == Node::TYPE_CONSTANT) { - ConstantNode *cn = static_cast(op->arguments[i]); - - if (get_scalar_type(cn->datatype) == base) { - for (int j = 0; j < cn->values.size(); j++) { - values.push_back(cn->values[j]); - } - } else if (get_scalar_type(cn->datatype) == cn->datatype) { - - ConstantNode::Value v; - if (!convert_constant(cn, base, &v)) { - return p_node; - } - values.push_back(v); - } else { - return p_node; - } - - } else { - return p_node; - } - } - - if (values.size() == 1) { - if (type >= TYPE_MAT2 && type <= TYPE_MAT4) { - ConstantNode::Value value = values[0]; - ConstantNode::Value zero; - zero.real = 0.0f; - int size = 2 + (type - TYPE_MAT2); - - values.clear(); - for (int i = 0; i < size; i++) { - for (int j = 0; j < size; j++) { - values.push_back(i == j ? value : zero); - } - } - } else { - ConstantNode::Value value = values[0]; - for (int i = 1; i < cardinality; i++) { - values.push_back(value); - } - } - } else if (values.size() != cardinality) { - ERR_PRINT("Failed to reduce expression, values and cardinality mismatch."); - return p_node; - } - - ConstantNode *cn = alloc_node(); - cn->datatype = op->get_datatype(); - cn->values = values; - return cn; - } else if (op->op == OP_NEGATE) { - - op->arguments.write[0] = _reduce_expression(p_block, op->arguments[0]); - if (op->arguments[0]->type == Node::TYPE_CONSTANT) { - - ConstantNode *cn = static_cast(op->arguments[0]); - - DataType base = get_scalar_type(cn->datatype); - - Vector values; - - for (int i = 0; i < cn->values.size(); i++) { - - ConstantNode::Value nv; - switch (base) { - case TYPE_BOOL: { - nv.boolean = !cn->values[i].boolean; - } break; - case TYPE_INT: { - nv.sint = -cn->values[i].sint; - } break; - case TYPE_UINT: { - // Intentionally wrap the unsigned int value, because GLSL does. - nv.uint = 0 - cn->values[i].uint; - } break; - case TYPE_FLOAT: { - nv.real = -cn->values[i].real; - } break; - default: { - } - } - - values.push_back(nv); - } - - cn->values = values; - return cn; - } - } - - return p_node; -} - -ShaderLanguage::Node *ShaderLanguage::_parse_and_reduce_expression(BlockNode *p_block, const Map &p_builtin_types) { - - ShaderLanguage::Node *expr = _parse_expression(p_block, p_builtin_types); - if (!expr) //errored - return NULL; - - expr = _reduce_expression(p_block, expr); - - return expr; -} - -Error ShaderLanguage::_parse_block(BlockNode *p_block, const Map &p_builtin_types, bool p_just_one, bool p_can_break, bool p_can_continue) { - - while (true) { - - TkPos pos = _get_tkpos(); - - Token tk = _get_token(); - - if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_SWITCH) { - if (tk.type != TK_CF_CASE && tk.type != TK_CF_DEFAULT && tk.type != TK_CURLY_BRACKET_CLOSE) { - _set_error("Switch may contains only case and default blocks"); - return ERR_PARSE_ERROR; - } - } - - bool is_struct = shader->structs.has(tk.text); - - if (tk.type == TK_CURLY_BRACKET_CLOSE) { //end of block - if (p_just_one) { - _set_error("Unexpected '}'"); - return ERR_PARSE_ERROR; - } - - return OK; - - } else if (tk.type == TK_CONST || is_token_precision(tk.type) || is_token_nonvoid_datatype(tk.type) || is_struct) { - String struct_name = ""; - if (is_struct) { - struct_name = tk.text; - } - - bool is_const = false; - - if (tk.type == TK_CONST) { - is_const = true; - tk = _get_token(); - - if (!is_struct) { - is_struct = shader->structs.has(tk.text); // check again. - struct_name = tk.text; - } - } - - DataPrecision precision = PRECISION_DEFAULT; - if (is_token_precision(tk.type)) { - precision = get_token_precision(tk.type); - tk = _get_token(); - - if (!is_struct) { - is_struct = shader->structs.has(tk.text); // check again. - } - if (is_struct && precision != PRECISION_DEFAULT) { - _set_error("Precision modifier cannot be used on structs."); - return ERR_PARSE_ERROR; - } - if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precision"); - return ERR_PARSE_ERROR; - } - } - - if (!is_struct) { - if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for variable (samplers not allowed)"); - return ERR_PARSE_ERROR; - } - } - - DataType type = is_struct ? TYPE_STRUCT : get_token_datatype(tk.type); - - if (_validate_datatype(type) != OK) { - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - Node *vardecl = NULL; - - while (true) { - - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier after type"); - return ERR_PARSE_ERROR; - } - - StringName name = tk.text; - ShaderLanguage::IdentifierType itype; - if (_find_identifier(p_block, true, p_builtin_types, name, (ShaderLanguage::DataType *)0, &itype)) { - if (itype != IDENTIFIER_FUNCTION) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - } - - BlockNode::Variable var; - var.type = type; - var.precision = precision; - var.line = tk_line; - var.array_size = 0; - var.is_const = is_const; - var.struct_name = struct_name; - - tk = _get_token(); - - if (tk.type == TK_BRACKET_OPEN) { - bool unknown_size = false; - - if (VisualServer::get_singleton()->is_low_end() && is_const) { - _set_error("Local const arrays are supported only on high-end platform!"); - return ERR_PARSE_ERROR; - } - - ArrayDeclarationNode *node = alloc_node(); - if (is_struct) { - node->struct_name = struct_name; - node->datatype = TYPE_STRUCT; - } else { - node->datatype = type; - } - node->precision = precision; - node->is_const = is_const; - vardecl = (Node *)node; - - ArrayDeclarationNode::Declaration decl; - decl.name = name; - decl.size = 0U; - - tk = _get_token(); - - if (tk.type == TK_BRACKET_CLOSE) { - unknown_size = true; - } else { - - if (tk.type != TK_INT_CONSTANT || ((int)tk.constant) <= 0) { - _set_error("Expected integer constant > 0 or ']'"); - return ERR_PARSE_ERROR; - } - - decl.size = ((uint32_t)tk.constant); - tk = _get_token(); - - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - var.array_size = decl.size; - } - - bool full_def = false; - - tk = _get_token(); - if (tk.type == TK_OP_ASSIGN) { - - if (VisualServer::get_singleton()->is_low_end()) { - _set_error("Array initialization is supported only on high-end platform!"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - if (tk.type != TK_CURLY_BRACKET_OPEN) { - - if (unknown_size) { - _set_error("Expected '{'"); - return ERR_PARSE_ERROR; - } - - full_def = true; - - DataPrecision precision2 = PRECISION_DEFAULT; - if (is_token_precision(tk.type)) { - precision2 = get_token_precision(tk.type); - tk = _get_token(); - if (shader->structs.has(tk.text)) { - _set_error("Precision modifier cannot be used on structs."); - return ERR_PARSE_ERROR; - } - if (!is_token_nonvoid_datatype(tk.type)) { - _set_error("Expected datatype after precision"); - return ERR_PARSE_ERROR; - } - } - - DataType type2; - String struct_name2 = ""; - - if (shader->structs.has(tk.text)) { - type2 = TYPE_STRUCT; - struct_name2 = tk.text; - } else { - if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for array"); - return ERR_PARSE_ERROR; - } - type2 = get_token_datatype(tk.type); - } - - int array_size2 = 0; - - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - TkPos pos2 = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - array_size2 = var.array_size; - tk = _get_token(); - } else { - _set_tkpos(pos2); - - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n || n->type != Node::TYPE_CONSTANT || n->get_datatype() != TYPE_INT) { - _set_error("Expected single integer constant > 0"); - return ERR_PARSE_ERROR; - } - - ConstantNode *cnode = (ConstantNode *)n; - if (cnode->values.size() == 1) { - array_size2 = cnode->values[0].sint; - if (array_size2 <= 0) { - _set_error("Expected single integer constant > 0"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected single integer constant > 0"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_BRACKET_CLOSE) { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } else { - tk = _get_token(); - } - } - } else { - _set_error("Expected '['"); - return ERR_PARSE_ERROR; - } - - if (precision != precision2 || type != type2 || struct_name != struct_name2 || var.array_size != array_size2) { - String error_str = "Cannot convert from '"; - if (precision2 != PRECISION_DEFAULT) { - error_str += get_precision_name(precision2); - error_str += " "; - } - if (type2 == TYPE_STRUCT) { - error_str += struct_name2; - } else { - error_str += get_datatype_name(type2); - } - error_str += "["; - error_str += itos(array_size2); - error_str += "]'"; - error_str += " to '"; - if (precision != PRECISION_DEFAULT) { - error_str += get_precision_name(precision); - error_str += " "; - } - if (type == TYPE_STRUCT) { - error_str += struct_name; - } else { - error_str += get_datatype_name(type); - } - error_str += "["; - error_str += itos(var.array_size); - error_str += "]'"; - _set_error(error_str); - return ERR_PARSE_ERROR; - } - } - - bool curly = tk.type == TK_CURLY_BRACKET_OPEN; - - if (unknown_size) { - if (!curly) { - _set_error("Expected '{'"); - return ERR_PARSE_ERROR; - } - } else { - if (full_def) { - if (curly) { - _set_error("Expected '('"); - return ERR_PARSE_ERROR; - } - } - } - - if (tk.type == TK_PARENTHESIS_OPEN || curly) { // initialization - while (true) { - - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n) { - return ERR_PARSE_ERROR; - } - - if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - _set_error("Expected constant expression"); - return ERR_PARSE_ERROR; - } - - if (var.type != n->get_datatype() || struct_name != n->get_datatype_name()) { - _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? struct_name : get_datatype_name(var.type)) + "'"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type == TK_COMMA) { - decl.initializer.push_back(n); - continue; - } else if (!curly && tk.type == TK_PARENTHESIS_CLOSE) { - decl.initializer.push_back(n); - break; - } else if (curly && tk.type == TK_CURLY_BRACKET_CLOSE) { - decl.initializer.push_back(n); - break; - } else { - if (curly) - _set_error("Expected '}' or ','"); - else - _set_error("Expected ')' or ','"); - return ERR_PARSE_ERROR; - } - } - if (unknown_size) { - decl.size = decl.initializer.size(); - var.array_size = decl.initializer.size(); - } else if (decl.initializer.size() != var.array_size) { - _set_error("Array size mismatch"); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - } - } else { - if (unknown_size) { - _set_error("Expected array initialization"); - return ERR_PARSE_ERROR; - } - if (is_const) { - _set_error("Expected initialization of constant"); - return ERR_PARSE_ERROR; - } - } - - node->declarations.push_back(decl); - } else if (tk.type == TK_OP_ASSIGN) { - - VariableDeclarationNode *node = alloc_node(); - if (is_struct) { - node->struct_name = struct_name; - node->datatype = TYPE_STRUCT; - } else { - node->datatype = type; - } - node->precision = precision; - node->is_const = is_const; - vardecl = (Node *)node; - - VariableDeclarationNode::Declaration decl; - decl.name = name; - decl.initializer = NULL; - - //variable created with assignment! must parse an expression - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n) - return ERR_PARSE_ERROR; - if (node->is_const && n->type == Node::TYPE_OPERATOR && ((OperatorNode *)n)->op == OP_CALL) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; - } - decl.initializer = n; - - if (var.type == TYPE_STRUCT ? (var.struct_name != n->get_datatype_name()) : (var.type != n->get_datatype())) { - _set_error("Invalid assignment of '" + (n->get_datatype() == TYPE_STRUCT ? n->get_datatype_name() : get_datatype_name(n->get_datatype())) + "' to '" + (var.type == TYPE_STRUCT ? String(var.struct_name) : get_datatype_name(var.type)) + "'"); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - node->declarations.push_back(decl); - } else { - if (is_const) { - _set_error("Expected initialization of constant"); - return ERR_PARSE_ERROR; - } - - VariableDeclarationNode *node = alloc_node(); - if (is_struct) { - node->struct_name = struct_name; - node->datatype = TYPE_STRUCT; - } else { - node->datatype = type; - } - node->precision = precision; - vardecl = (Node *)node; - - VariableDeclarationNode::Declaration decl; - decl.name = name; - decl.initializer = NULL; - node->declarations.push_back(decl); - } - - p_block->statements.push_back(vardecl); - - p_block->variables[name] = var; - - if (tk.type == TK_COMMA) { - tk = _get_token(); - //another variable - } else if (tk.type == TK_SEMICOLON) { - break; - } else { - _set_error("Expected ',' or ';' after variable"); - return ERR_PARSE_ERROR; - } - } - } else if (tk.type == TK_CURLY_BRACKET_OPEN) { - //a sub block, just because.. - BlockNode *block = alloc_node(); - block->parent_block = p_block; - if (_parse_block(block, p_builtin_types, false, p_can_break, p_can_continue) != OK) { - return ERR_PARSE_ERROR; - } - p_block->statements.push_back(block); - } else if (tk.type == TK_CF_IF) { - //if () {} - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after if"); - return ERR_PARSE_ERROR; - } - - ControlFlowNode *cf = alloc_node(); - cf->flow_op = FLOW_OP_IF; - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n) - return ERR_PARSE_ERROR; - - if (n->get_datatype() != TYPE_BOOL) { - _set_error("Expected boolean expression"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after expression"); - return ERR_PARSE_ERROR; - } - - BlockNode *block = alloc_node(); - block->parent_block = p_block; - cf->expressions.push_back(n); - cf->blocks.push_back(block); - p_block->statements.push_back(cf); - - Error err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); - if (err) - return err; - - pos = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_CF_ELSE) { - - block = alloc_node(); - block->parent_block = p_block; - cf->blocks.push_back(block); - err = _parse_block(block, p_builtin_types, true, p_can_break, p_can_continue); - - } else { - _set_tkpos(pos); //rollback - } - } else if (tk.type == TK_CF_SWITCH) { - - if (VisualServer::get_singleton()->is_low_end()) { - _set_error("\"switch\" operator is supported only on high-end platform!"); - return ERR_PARSE_ERROR; - } - - // switch() {} - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after switch"); - return ERR_PARSE_ERROR; - } - ControlFlowNode *cf = alloc_node(); - cf->flow_op = FLOW_OP_SWITCH; - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n) - return ERR_PARSE_ERROR; - if (n->get_datatype() != TYPE_INT) { - _set_error("Expected integer expression"); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after expression"); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - if (tk.type != TK_CURLY_BRACKET_OPEN) { - _set_error("Expected '{' after switch statement"); - return ERR_PARSE_ERROR; - } - BlockNode *switch_block = alloc_node(); - switch_block->block_type = BlockNode::BLOCK_TYPE_SWITCH; - switch_block->parent_block = p_block; - cf->expressions.push_back(n); - cf->blocks.push_back(switch_block); - p_block->statements.push_back(cf); - - int prev_type = TK_CF_CASE; - while (true) { // Go-through multiple cases. - - if (_parse_block(switch_block, p_builtin_types, true, true, false) != OK) { - return ERR_PARSE_ERROR; - } - pos = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_CF_CASE || tk.type == TK_CF_DEFAULT) { - if (prev_type == TK_CF_DEFAULT) { - if (tk.type == TK_CF_CASE) { - _set_error("Cases must be defined before default case."); - return ERR_PARSE_ERROR; - } else if (prev_type == TK_CF_DEFAULT) { - _set_error("Default case must be defined only once."); - return ERR_PARSE_ERROR; - } - } - prev_type = tk.type; - _set_tkpos(pos); - continue; - } else { - Set constants; - for (int i = 0; i < switch_block->statements.size(); i++) { // Checks for duplicates. - ControlFlowNode *flow = (ControlFlowNode *)switch_block->statements[i]; - if (flow) { - if (flow->flow_op == FLOW_OP_CASE) { - ConstantNode *n2 = static_cast(flow->expressions[0]); - if (!n2) { - return ERR_PARSE_ERROR; - } - if (n2->values.empty()) { - return ERR_PARSE_ERROR; - } - if (constants.has(n2->values[0].sint)) { - _set_error("Duplicated case label: '" + itos(n2->values[0].sint) + "'"); - return ERR_PARSE_ERROR; - } - constants.insert(n2->values[0].sint); - } else if (flow->flow_op == FLOW_OP_DEFAULT) { - continue; - } else { - return ERR_PARSE_ERROR; - } - } else { - return ERR_PARSE_ERROR; - } - } - break; - } - } - - } else if (tk.type == TK_CF_CASE) { - // case x : break; | return; - - if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { - _set_tkpos(pos); - return OK; - } - - if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { - _set_error("case must be placed within switch block"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - int sign = 1; - - if (tk.type == TK_OP_SUB) { - sign = -1; - tk = _get_token(); - } - - if (tk.type != TK_INT_CONSTANT) { - _set_error("Expected integer constant"); - return ERR_PARSE_ERROR; - } - - int constant = (int)tk.constant * sign; - - tk = _get_token(); - - if (tk.type != TK_COLON) { - _set_error("Expected ':'"); - return ERR_PARSE_ERROR; - } - - ControlFlowNode *cf = alloc_node(); - cf->flow_op = FLOW_OP_CASE; - - ConstantNode *n = alloc_node(); - ConstantNode::Value v; - v.sint = constant; - n->values.push_back(v); - n->datatype = TYPE_INT; - - BlockNode *case_block = alloc_node(); - case_block->block_type = BlockNode::BLOCK_TYPE_CASE; - case_block->parent_block = p_block; - cf->expressions.push_back(n); - cf->blocks.push_back(case_block); - p_block->statements.push_back(cf); - - Error err = _parse_block(case_block, p_builtin_types, false, true, false); - if (err) - return err; - - return OK; - - } else if (tk.type == TK_CF_DEFAULT) { - - if (p_block && p_block->block_type == BlockNode::BLOCK_TYPE_CASE) { - _set_tkpos(pos); - return OK; - } - - if (!p_block || (p_block->block_type != BlockNode::BLOCK_TYPE_SWITCH)) { - _set_error("default must be placed within switch block"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - if (tk.type != TK_COLON) { - _set_error("Expected ':'"); - return ERR_PARSE_ERROR; - } - - ControlFlowNode *cf = alloc_node(); - cf->flow_op = FLOW_OP_DEFAULT; - - BlockNode *default_block = alloc_node(); - default_block->block_type = BlockNode::BLOCK_TYPE_DEFAULT; - default_block->parent_block = p_block; - cf->blocks.push_back(default_block); - p_block->statements.push_back(cf); - - Error err = _parse_block(default_block, p_builtin_types, false, true, false); - if (err) - return err; - - return OK; - - } else if (tk.type == TK_CF_DO || tk.type == TK_CF_WHILE) { - // do {} while() - // while() {} - bool is_do = tk.type == TK_CF_DO; - - BlockNode *do_block = NULL; - if (is_do) { - - do_block = alloc_node(); - do_block->parent_block = p_block; - - Error err = _parse_block(do_block, p_builtin_types, true, true, true); - if (err) - return err; - - tk = _get_token(); - if (tk.type != TK_CF_WHILE) { - _set_error("Expected while after do"); - return ERR_PARSE_ERROR; - } - } - tk = _get_token(); - - if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after while"); - return ERR_PARSE_ERROR; - } - - ControlFlowNode *cf = alloc_node(); - if (is_do) { - cf->flow_op = FLOW_OP_DO; - } else { - cf->flow_op = FLOW_OP_WHILE; - } - Node *n = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!n) - return ERR_PARSE_ERROR; - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after expression"); - return ERR_PARSE_ERROR; - } - if (!is_do) { - BlockNode *block = alloc_node(); - block->parent_block = p_block; - cf->expressions.push_back(n); - cf->blocks.push_back(block); - p_block->statements.push_back(cf); - - Error err = _parse_block(block, p_builtin_types, true, true, true); - if (err) - return err; - } else { - - cf->expressions.push_back(n); - cf->blocks.push_back(do_block); - p_block->statements.push_back(cf); - - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } - } - } else if (tk.type == TK_CF_FOR) { - // for() {} - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after for"); - return ERR_PARSE_ERROR; - } - - ControlFlowNode *cf = alloc_node(); - cf->flow_op = FLOW_OP_FOR; - - BlockNode *init_block = alloc_node(); - init_block->parent_block = p_block; - init_block->single_statement = true; - cf->blocks.push_back(init_block); - if (_parse_block(init_block, p_builtin_types, true, false, false) != OK) { - return ERR_PARSE_ERROR; - } - - Node *n = _parse_and_reduce_expression(init_block, p_builtin_types); - if (!n) - return ERR_PARSE_ERROR; - - if (n->get_datatype() != TYPE_BOOL) { - _set_error("Middle expression is expected to be boolean."); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after middle expression"); - return ERR_PARSE_ERROR; - } - - cf->expressions.push_back(n); - - n = _parse_and_reduce_expression(init_block, p_builtin_types); - if (!n) - return ERR_PARSE_ERROR; - - cf->expressions.push_back(n); - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ')' after third expression"); - return ERR_PARSE_ERROR; - } - - BlockNode *block = alloc_node(); - block->parent_block = init_block; - cf->blocks.push_back(block); - p_block->statements.push_back(cf); - - Error err = _parse_block(block, p_builtin_types, true, true, true); - if (err) - return err; - - } else if (tk.type == TK_CF_RETURN) { - - //check return type - BlockNode *b = p_block; - while (b && !b->parent_function) { - b = b->parent_block; - } - - if (!b) { - _set_error("Bug"); - return ERR_BUG; - } - - ControlFlowNode *flow = alloc_node(); - flow->flow_op = FLOW_OP_RETURN; - - pos = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_SEMICOLON) { - //all is good - if (b->parent_function->return_type != TYPE_VOID) { - _set_error("Expected return with expression of type '" + get_datatype_name(b->parent_function->return_type) + "'"); - return ERR_PARSE_ERROR; - } - } else { - _set_tkpos(pos); //rollback, wants expression - Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!expr) - return ERR_PARSE_ERROR; - - if (b->parent_function->return_type != expr->get_datatype()) { - _set_error("Expected return expression of type '" + get_datatype_name(b->parent_function->return_type) + "'"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after return expression"); - return ERR_PARSE_ERROR; - } - - flow->expressions.push_back(expr); - } - - p_block->statements.push_back(flow); - - BlockNode *block = p_block; - while (block) { - if (block->block_type == BlockNode::BLOCK_TYPE_CASE || block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { - return OK; - } - block = block->parent_block; - } - } else if (tk.type == TK_CF_DISCARD) { - - //check return type - BlockNode *b = p_block; - while (b && !b->parent_function) { - b = b->parent_block; - } - if (!b) { - _set_error("Bug"); - return ERR_BUG; - } - - if (!b->parent_function->can_discard) { - _set_error("Use of 'discard' is not allowed here."); - return ERR_PARSE_ERROR; - } - - ControlFlowNode *flow = alloc_node(); - flow->flow_op = FLOW_OP_DISCARD; - - pos = _get_tkpos(); - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - //all is good - _set_error("Expected ';' after discard"); - } - - p_block->statements.push_back(flow); - } else if (tk.type == TK_CF_BREAK) { - - if (!p_can_break) { - //all is good - _set_error("Breaking is not allowed here"); - } - - ControlFlowNode *flow = alloc_node(); - flow->flow_op = FLOW_OP_BREAK; - - pos = _get_tkpos(); - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - //all is good - _set_error("Expected ';' after break"); - } - - p_block->statements.push_back(flow); - - BlockNode *block = p_block; - while (block) { - if (block->block_type == BlockNode::BLOCK_TYPE_CASE || block->block_type == BlockNode::BLOCK_TYPE_DEFAULT) { - return OK; - } - block = block->parent_block; - } - - } else if (tk.type == TK_CF_CONTINUE) { - - if (!p_can_continue) { - //all is good - _set_error("Continuing is not allowed here"); - } - - ControlFlowNode *flow = alloc_node(); - flow->flow_op = FLOW_OP_CONTINUE; - - pos = _get_tkpos(); - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - //all is good - _set_error("Expected ';' after continue"); - } - - p_block->statements.push_back(flow); - - } else { - - //nothing else, so expression - _set_tkpos(pos); //rollback - Node *expr = _parse_and_reduce_expression(p_block, p_builtin_types); - if (!expr) - return ERR_PARSE_ERROR; - p_block->statements.push_back(expr); - tk = _get_token(); - - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after statement"); - return ERR_PARSE_ERROR; - } - } - - if (p_just_one) - break; - } - - return OK; -} - -String ShaderLanguage::_get_shader_type_list(const Set &p_shader_types) const { - - // Return a list of shader types as an human-readable string - String valid_types; - for (const Set::Element *E = p_shader_types.front(); E; E = E->next()) { - if (valid_types != String()) { - valid_types += ", "; - } - - valid_types += "'" + E->get() + "'"; - } - - return valid_types; -} - -String ShaderLanguage::_get_qualifier_str(ArgumentQualifier p_qualifier) const { - switch (p_qualifier) { - case ArgumentQualifier::ARGUMENT_QUALIFIER_IN: - return "in"; - case ArgumentQualifier::ARGUMENT_QUALIFIER_OUT: - return "out"; - case ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT: - return "inout"; - } - return ""; -} - -Error ShaderLanguage::_validate_datatype(DataType p_type) { - if (VisualServer::get_singleton()->is_low_end()) { - bool invalid_type = false; - - switch (p_type) { - case TYPE_UINT: - case TYPE_UVEC2: - case TYPE_UVEC3: - case TYPE_UVEC4: - case TYPE_ISAMPLER2D: - case TYPE_USAMPLER2D: - case TYPE_ISAMPLER3D: - case TYPE_USAMPLER3D: - case TYPE_USAMPLER2DARRAY: - case TYPE_ISAMPLER2DARRAY: - invalid_type = true; - break; - default: - break; - } - - if (invalid_type) { - _set_error(vformat("\"%s\" type is supported only on high-end platform!", get_datatype_name(p_type))); - return ERR_UNAVAILABLE; - } - } - return OK; -} - -Error ShaderLanguage::_parse_shader(const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types) { - - Token tk = _get_token(); - - if (tk.type != TK_SHADER_TYPE) { - _set_error("Expected 'shader_type' at the beginning of shader. Valid types are: " + _get_shader_type_list(p_shader_types)); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier after 'shader_type', indicating type of shader. Valid types are: " + _get_shader_type_list(p_shader_types)); - return ERR_PARSE_ERROR; - } - - String shader_type_identifier; - - shader_type_identifier = tk.text; - - if (!p_shader_types.has(shader_type_identifier)) { - _set_error("Invalid shader type. Valid types are: " + _get_shader_type_list(p_shader_types)); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';' after 'shader_type '."); - } - - tk = _get_token(); - - int texture_uniforms = 0; - int uniforms = 0; - - while (tk.type != TK_EOF) { - - switch (tk.type) { - case TK_RENDER_MODE: { - - while (true) { - - StringName mode; - _get_completable_identifier(NULL, COMPLETION_RENDER_MODE, mode); - - if (mode == StringName()) { - _set_error("Expected identifier for render mode"); - return ERR_PARSE_ERROR; - } - - if (p_render_modes.find(mode) == -1) { - _set_error("Invalid render mode: '" + String(mode) + "'"); - return ERR_PARSE_ERROR; - } - - if (shader->render_modes.find(mode) != -1) { - _set_error("Duplicate render mode: '" + String(mode) + "'"); - return ERR_PARSE_ERROR; - } - - shader->render_modes.push_back(mode); - - tk = _get_token(); - if (tk.type == TK_COMMA) { - //all good, do nothing - } else if (tk.type == TK_SEMICOLON) { - break; //done - } else { - _set_error("Unexpected token: " + get_token_text(tk)); - return ERR_PARSE_ERROR; - } - } - } break; - case TK_STRUCT: { - ShaderNode::Struct st; - DataType type; - - tk = _get_token(); - if (tk.type == TK_IDENTIFIER) { - st.name = tk.text; - tk = _get_token(); - if (tk.type != TK_CURLY_BRACKET_OPEN) { - _set_error("Expected '{'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected struct identifier!"); - return ERR_PARSE_ERROR; - } - - StructNode *st_node = alloc_node(); - st.shader_struct = st_node; - - int member_count = 0; - Set member_names; - while (true) { // variables list - tk = _get_token(); - if (tk.type == TK_CURLY_BRACKET_CLOSE) { - break; - } - StringName struct_name = ""; - bool struct_dt = false; - bool use_precision = false; - DataPrecision precision = DataPrecision::PRECISION_DEFAULT; - - if (tk.type == TK_STRUCT) { - _set_error("nested structs are not allowed!"); - return ERR_PARSE_ERROR; - } - - if (is_token_precision(tk.type)) { - precision = get_token_precision(tk.type); - use_precision = true; - tk = _get_token(); - } - - if (shader->structs.has(tk.text)) { - struct_name = tk.text; - struct_dt = true; - if (use_precision) { - _set_error("Precision modifier cannot be used on structs."); - return ERR_PARSE_ERROR; - } - } - - if (!is_token_datatype(tk.type) && !struct_dt) { - _set_error("Expected datatype."); - return ERR_PARSE_ERROR; - } else { - type = struct_dt ? TYPE_STRUCT : get_token_datatype(tk.type); - - if (is_sampler_type(type)) { - _set_error("sampler datatype not allowed here"); - return ERR_PARSE_ERROR; - } else if (type == TYPE_VOID) { - _set_error("void datatype not allowed here"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier!"); - return ERR_PARSE_ERROR; - } - - MemberNode *member = alloc_node(); - member->precision = precision; - member->datatype = type; - member->struct_name = struct_name; - member->name = tk.text; - - if (member_names.has(member->name)) { - _set_error("Redefinition of '" + String(member->name) + "'"); - return ERR_PARSE_ERROR; - } - member_names.insert(member->name); - - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - tk = _get_token(); - if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { - member->array_size = (int)tk.constant; - - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected single integer constant > 0"); - return ERR_PARSE_ERROR; - } - } - st_node->members.push_back(member); - - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ']' or ';'"); - return ERR_PARSE_ERROR; - } - member_count++; - } - } - if (member_count == 0) { - _set_error("Empty structs are not allowed!"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } - shader->structs[st.name] = st; - shader->vstructs.push_back(st); // struct's order is important! - - } break; - case TK_UNIFORM: - case TK_VARYING: { - - bool uniform = tk.type == TK_UNIFORM; - DataPrecision precision = PRECISION_DEFAULT; - DataInterpolation interpolation = INTERPOLATION_SMOOTH; - DataType type; - StringName name; - - tk = _get_token(); - if (is_token_interpolation(tk.type)) { - interpolation = get_token_interpolation(tk.type); - tk = _get_token(); - } - - if (is_token_precision(tk.type)) { - precision = get_token_precision(tk.type); - tk = _get_token(); - } - - if (!is_token_datatype(tk.type)) { - _set_error("Expected datatype. "); - return ERR_PARSE_ERROR; - } - - type = get_token_datatype(tk.type); - - if (type == TYPE_VOID) { - _set_error("void datatype not allowed here"); - return ERR_PARSE_ERROR; - } - - if (!uniform && (type < TYPE_FLOAT || type > TYPE_MAT4)) { - _set_error("Invalid type for varying, only float,vec2,vec3,vec4,mat2,mat3,mat4 or array of these types allowed."); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier!"); - return ERR_PARSE_ERROR; - } - - name = tk.text; - - if (_find_identifier(NULL, false, Map(), name)) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - - if (has_builtin(p_functions, name)) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - - if (uniform) { - - ShaderNode::Uniform uniform2; - - if (is_sampler_type(type)) { - uniform2.texture_order = texture_uniforms++; - uniform2.order = -1; - if (_validate_datatype(type) != OK) { - return ERR_PARSE_ERROR; - } - } else { - uniform2.texture_order = -1; - uniform2.order = uniforms++; - } - uniform2.type = type; - uniform2.precision = precision; - - //todo parse default value - - tk = _get_token(); - - if (tk.type == TK_COLON) { - //hint - do { - tk = _get_token(); - if (tk.type == TK_HINT_WHITE_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_WHITE; - } else if (tk.type == TK_HINT_BLACK_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_BLACK; - } else if (tk.type == TK_HINT_NORMAL_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_NORMAL; - } else if (tk.type == TK_HINT_ROUGHNESS_NORMAL_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_NORMAL; - } else if (tk.type == TK_HINT_ROUGHNESS_R) { - uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_R; - } else if (tk.type == TK_HINT_ROUGHNESS_G) { - uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_G; - } else if (tk.type == TK_HINT_ROUGHNESS_B) { - uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_B; - } else if (tk.type == TK_HINT_ROUGHNESS_A) { - uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_A; - } else if (tk.type == TK_HINT_ROUGHNESS_GRAY) { - uniform2.hint = ShaderNode::Uniform::HINT_ROUGHNESS_GRAY; - } else if (tk.type == TK_HINT_ANISO_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_ANISO; - } else if (tk.type == TK_HINT_ALBEDO_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_ALBEDO; - } else if (tk.type == TK_HINT_BLACK_ALBEDO_TEXTURE) { - uniform2.hint = ShaderNode::Uniform::HINT_BLACK_ALBEDO; - } else if (tk.type == TK_HINT_COLOR) { - if (type != TYPE_VEC4) { - _set_error("Color hint is for vec4 only"); - return ERR_PARSE_ERROR; - } - uniform2.hint = ShaderNode::Uniform::HINT_COLOR; - } else if (tk.type == TK_HINT_RANGE) { - - uniform2.hint = ShaderNode::Uniform::HINT_RANGE; - if (type != TYPE_FLOAT && type != TYPE_INT) { - _set_error("Range hint is for float and int only"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_OPEN) { - _set_error("Expected '(' after hint_range"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - float sign = 1.0; - - if (tk.type == TK_OP_SUB) { - sign = -1.0; - tk = _get_token(); - } - - if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { - _set_error("Expected integer constant"); - return ERR_PARSE_ERROR; - } - - uniform2.hint_range[0] = tk.constant; - uniform2.hint_range[0] *= sign; - - tk = _get_token(); - - if (tk.type != TK_COMMA) { - _set_error("Expected ',' after integer constant"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - sign = 1.0; - - if (tk.type == TK_OP_SUB) { - sign = -1.0; - tk = _get_token(); - } - - if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { - _set_error("Expected integer constant after ','"); - return ERR_PARSE_ERROR; - } - - uniform2.hint_range[1] = tk.constant; - uniform2.hint_range[1] *= sign; - - tk = _get_token(); - - if (tk.type == TK_COMMA) { - tk = _get_token(); - - if (tk.type != TK_REAL_CONSTANT && tk.type != TK_INT_CONSTANT) { - _set_error("Expected integer constant after ','"); - return ERR_PARSE_ERROR; - } - - uniform2.hint_range[2] = tk.constant; - tk = _get_token(); - } else { - if (type == TYPE_INT) { - uniform2.hint_range[2] = 1; - } else { - uniform2.hint_range[2] = 0.001; - } - } - - if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ','"); - return ERR_PARSE_ERROR; - } - } else if (tk.type == TK_FILTER_LINEAR) { - uniform2.filter = FILTER_LINEAR; - } else if (tk.type == TK_FILTER_NEAREST) { - uniform2.filter = FILTER_NEAREST; - } else if (tk.type == TK_FILTER_NEAREST_MIPMAP) { - uniform2.filter = FILTER_NEAREST_MIPMAP; - } else if (tk.type == TK_FILTER_LINEAR_MIPMAP) { - uniform2.filter = FILTER_LINEAR_MIPMAP; - } else if (tk.type == TK_FILTER_NEAREST_MIPMAP_ANISO) { - uniform2.filter = FILTER_NEAREST_MIPMAP_ANISO; - } else if (tk.type == TK_FILTER_LINEAR_MIPMAP_ANISO) { - uniform2.filter = FILTER_LINEAR_MIPMAP_ANISO; - } else if (tk.type == TK_REPEAT_DISABLE) { - uniform2.repeat = REPEAT_DISABLE; - } else if (tk.type == TK_REPEAT_ENABLE) { - uniform2.repeat = REPEAT_ENABLE; - } else { - _set_error("Expected valid type hint after ':'."); - } - - if (uniform2.hint != ShaderNode::Uniform::HINT_RANGE && uniform2.hint != ShaderNode::Uniform::HINT_NONE && uniform2.hint != ShaderNode::Uniform::HINT_COLOR && type <= TYPE_MAT4) { - _set_error("This hint is only for sampler types"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - } while (tk.type == TK_COMMA); - } - - if (tk.type == TK_OP_ASSIGN) { - - Node *expr = _parse_and_reduce_expression(NULL, Map()); - if (!expr) - return ERR_PARSE_ERROR; - if (expr->type != Node::TYPE_CONSTANT) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; - } - - ConstantNode *cn = static_cast(expr); - - uniform2.default_value.resize(cn->values.size()); - - if (!convert_constant(cn, uniform2.type, uniform2.default_value.ptrw())) { - _set_error("Can't convert constant to " + get_datatype_name(uniform2.type)); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - } - - shader->uniforms[name] = uniform2; - - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } - } else { - - ShaderNode::Varying varying; - varying.type = type; - varying.precision = precision; - varying.interpolation = interpolation; - - tk = _get_token(); - if (tk.type != TK_SEMICOLON && tk.type != TK_BRACKET_OPEN) { - _set_error("Expected ';' or '['"); - return ERR_PARSE_ERROR; - } - - if (tk.type == TK_BRACKET_OPEN) { - tk = _get_token(); - if (tk.type == TK_INT_CONSTANT && tk.constant > 0) { - varying.array_size = (int)tk.constant; - - tk = _get_token(); - if (tk.type == TK_BRACKET_CLOSE) { - tk = _get_token(); - if (tk.type != TK_SEMICOLON) { - _set_error("Expected ';'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected ']'"); - return ERR_PARSE_ERROR; - } - } else { - _set_error("Expected single integer constant > 0"); - return ERR_PARSE_ERROR; - } - } - - shader->varyings[name] = varying; - } - - } break; - default: { - //function or constant variable - - bool is_constant = false; - bool is_struct = false; - StringName struct_name; - DataPrecision precision = PRECISION_DEFAULT; - DataType type; - StringName name; - - if (tk.type == TK_CONST) { - is_constant = true; - tk = _get_token(); - } - - if (is_token_precision(tk.type)) { - precision = get_token_precision(tk.type); - tk = _get_token(); - } - - if (shader->structs.has(tk.text)) { - if (precision != PRECISION_DEFAULT) { - _set_error("Precision modifier cannot be used on structs."); - return ERR_PARSE_ERROR; - } - is_struct = true; - struct_name = tk.text; - } else { - - if (!is_token_datatype(tk.type)) { - _set_error("Expected constant, function, uniform or varying"); - return ERR_PARSE_ERROR; - } - - if (!is_token_variable_datatype(tk.type)) { - _set_error("Invalid data type for constants or function return (samplers not allowed)"); - return ERR_PARSE_ERROR; - } - } - - if (is_struct) { - type = TYPE_STRUCT; - } else { - type = get_token_datatype(tk.type); - } - TkPos prev_pos = _get_tkpos(); - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - _set_error("Cannot use arrays as return types"); - return ERR_PARSE_ERROR; - } - _set_tkpos(prev_pos); - - _get_completable_identifier(NULL, COMPLETION_MAIN_FUNCTION, name); - - if (name == StringName()) { - _set_error("Expected function name after datatype"); - return ERR_PARSE_ERROR; - } - - if (_find_identifier(NULL, false, Map(), name)) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - - if (has_builtin(p_functions, name)) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - if (tk.type != TK_PARENTHESIS_OPEN) { - if (type == TYPE_VOID) { - _set_error("Expected '(' after function identifier"); - return ERR_PARSE_ERROR; - } - - //variable - - while (true) { - ShaderNode::Constant constant; - constant.type = is_struct ? TYPE_STRUCT : type; - constant.type_str = struct_name; - constant.precision = precision; - constant.initializer = NULL; - - if (tk.type == TK_OP_ASSIGN) { - - if (!is_constant) { - _set_error("Expected 'const' keyword before constant definition"); - return ERR_PARSE_ERROR; - } - - //variable created with assignment! must parse an expression - Node *expr = _parse_and_reduce_expression(NULL, Map()); - if (!expr) - return ERR_PARSE_ERROR; - if (expr->type == Node::TYPE_OPERATOR && ((OperatorNode *)expr)->op == OP_CALL) { - _set_error("Expected constant expression after '='"); - return ERR_PARSE_ERROR; - } - - constant.initializer = static_cast(expr); - - if (is_struct) { - if (expr->get_datatype_name() != struct_name) { - _set_error("Invalid assignment of '" + (expr->get_datatype() == TYPE_STRUCT ? expr->get_datatype_name() : get_datatype_name(expr->get_datatype())) + "' to '" + struct_name + "'"); - return ERR_PARSE_ERROR; - } - } else if (type != expr->get_datatype()) { - _set_error("Invalid assignment of '" + get_datatype_name(expr->get_datatype()) + "' to '" + get_datatype_name(type) + "'"); - return ERR_PARSE_ERROR; - } - tk = _get_token(); - } else { - _set_error("Expected initialization of constant"); - return ERR_PARSE_ERROR; - } - - shader->constants[name] = constant; - if (tk.type == TK_COMMA) { - tk = _get_token(); - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier after type"); - return ERR_PARSE_ERROR; - } - - name = tk.text; - if (_find_identifier(NULL, false, Map(), name)) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - - if (has_builtin(p_functions, name)) { - _set_error("Redefinition of '" + String(name) + "'"); - return ERR_PARSE_ERROR; - } - - tk = _get_token(); - - } else if (tk.type == TK_SEMICOLON) { - break; - } else { - _set_error("Expected ',' or ';' after constant"); - return ERR_PARSE_ERROR; - } - } - - break; - } - - Map builtin_types; - if (p_functions.has(name)) { - builtin_types = p_functions[name].built_ins; - } - - if (p_functions.has("global")) { // Adds global variables: 'TIME' - for (Map::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) { - builtin_types.insert(E->key(), E->value()); - } - } - - ShaderNode::Function function; - - function.callable = !p_functions.has(name); - function.name = name; - - FunctionNode *func_node = alloc_node(); - - function.function = func_node; - - shader->functions.push_back(function); - - func_node->name = name; - func_node->return_type = type; - func_node->return_struct_name = struct_name; - func_node->return_precision = precision; - - if (p_functions.has(name)) { - func_node->can_discard = p_functions[name].can_discard; - } - - func_node->body = alloc_node(); - func_node->body->parent_function = func_node; - - tk = _get_token(); - - while (true) { - if (tk.type == TK_PARENTHESIS_CLOSE) { - break; - } - - ArgumentQualifier qualifier = ARGUMENT_QUALIFIER_IN; - - if (tk.type == TK_ARG_IN) { - qualifier = ARGUMENT_QUALIFIER_IN; - tk = _get_token(); - } else if (tk.type == TK_ARG_OUT) { - qualifier = ARGUMENT_QUALIFIER_OUT; - tk = _get_token(); - } else if (tk.type == TK_ARG_INOUT) { - qualifier = ARGUMENT_QUALIFIER_INOUT; - tk = _get_token(); - } - - DataType ptype; - StringName pname; - StringName param_struct_name; - DataPrecision pprecision = PRECISION_DEFAULT; - bool use_precision = false; - - if (is_token_precision(tk.type)) { - pprecision = get_token_precision(tk.type); - tk = _get_token(); - use_precision = true; - } - - is_struct = false; - - if (shader->structs.has(tk.text)) { - is_struct = true; - param_struct_name = tk.text; - if (use_precision) { - _set_error("Precision modifier cannot be used on structs."); - return ERR_PARSE_ERROR; - } - } - - if (!is_struct && !is_token_datatype(tk.type)) { - _set_error("Expected a valid datatype for argument"); - return ERR_PARSE_ERROR; - } - - if (qualifier == ARGUMENT_QUALIFIER_OUT || qualifier == ARGUMENT_QUALIFIER_INOUT) { - if (is_sampler_type(get_token_datatype(tk.type))) { - _set_error("Opaque types cannot be output parameters."); - return ERR_PARSE_ERROR; - } - } - - if (is_struct) { - ptype = TYPE_STRUCT; - } else { - ptype = get_token_datatype(tk.type); - if (_validate_datatype(ptype) != OK) { - return ERR_PARSE_ERROR; - } - if (ptype == TYPE_VOID) { - _set_error("void not allowed in argument"); - return ERR_PARSE_ERROR; - } - } - - tk = _get_token(); - - if (tk.type == TK_BRACKET_OPEN) { - _set_error("Arrays as parameters are not implemented yet"); - return ERR_PARSE_ERROR; - } - if (tk.type != TK_IDENTIFIER) { - _set_error("Expected identifier for argument name"); - return ERR_PARSE_ERROR; - } - - pname = tk.text; - - ShaderLanguage::IdentifierType itype; - if (_find_identifier(func_node->body, false, builtin_types, pname, (ShaderLanguage::DataType *)0, &itype)) { - if (itype != IDENTIFIER_FUNCTION) { - _set_error("Redefinition of '" + String(pname) + "'"); - return ERR_PARSE_ERROR; - } - } - - if (has_builtin(p_functions, pname)) { - _set_error("Redefinition of '" + String(pname) + "'"); - return ERR_PARSE_ERROR; - } - - FunctionNode::Argument arg; - arg.type = ptype; - arg.name = pname; - arg.type_str = param_struct_name; - arg.precision = pprecision; - arg.qualifier = qualifier; - arg.tex_argument_check = false; - arg.tex_builtin_check = false; - arg.tex_argument_filter = FILTER_DEFAULT; - arg.tex_argument_repeat = REPEAT_DEFAULT; - - func_node->arguments.push_back(arg); - - tk = _get_token(); - if (tk.type == TK_BRACKET_OPEN) { - _set_error("Arrays as parameters are not implemented yet"); - return ERR_PARSE_ERROR; - } - - if (tk.type == TK_COMMA) { - tk = _get_token(); - //do none and go on - } else if (tk.type != TK_PARENTHESIS_CLOSE) { - _set_error("Expected ',' or ')' after identifier"); - return ERR_PARSE_ERROR; - } - } - - if (p_functions.has(name)) { - //if one of the core functions, make sure they are of the correct form - if (func_node->arguments.size() > 0) { - _set_error("Function '" + String(name) + "' expects no arguments."); - return ERR_PARSE_ERROR; - } - if (func_node->return_type != TYPE_VOID) { - _set_error("Function '" + String(name) + "' must be of void return type."); - return ERR_PARSE_ERROR; - } - } - - //all good let's parse inside the function! - tk = _get_token(); - if (tk.type != TK_CURLY_BRACKET_OPEN) { - _set_error("Expected '{' to begin function"); - return ERR_PARSE_ERROR; - } - - current_function = name; - - Error err = _parse_block(func_node->body, builtin_types); - if (err) - return err; - - if (func_node->return_type != DataType::TYPE_VOID) { - - BlockNode *block = func_node->body; - if (_find_last_flow_op_in_block(block, FlowOperation::FLOW_OP_RETURN) != OK) { - _set_error("Expected at least one return statement in a non-void function."); - return ERR_PARSE_ERROR; - } - } - current_function = StringName(); - } - } - - tk = _get_token(); - } - - return OK; -} - -bool ShaderLanguage::has_builtin(const Map &p_functions, const StringName &p_name) { - - if (p_functions.has("vertex")) { - if (p_functions["vertex"].built_ins.has(p_name)) { - return true; - } - } - if (p_functions.has("fragment")) { - if (p_functions["fragment"].built_ins.has(p_name)) { - return true; - } - } - if (p_functions.has("light")) { - if (p_functions["light"].built_ins.has(p_name)) { - return true; - } - } - return false; -} - -Error ShaderLanguage::_find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op) { - - bool found = false; - - for (int i = p_flow->blocks.size() - 1; i >= 0; i--) { - if (p_flow->blocks[i]->type == Node::TYPE_BLOCK) { - BlockNode *last_block = (BlockNode *)p_flow->blocks[i]; - if (_find_last_flow_op_in_block(last_block, p_op) == OK) { - found = true; - break; - } - } - } - if (found) { - return OK; - } - return FAILED; -} - -Error ShaderLanguage::_find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op) { - - bool found = false; - - for (int i = p_block->statements.size() - 1; i >= 0; i--) { - - if (p_block->statements[i]->type == Node::TYPE_CONTROL_FLOW) { - ControlFlowNode *flow = (ControlFlowNode *)p_block->statements[i]; - if (flow->flow_op == p_op) { - found = true; - break; - } else { - if (_find_last_flow_op_in_op(flow, p_op) == OK) { - found = true; - break; - } - } - } else if (p_block->statements[i]->type == Node::TYPE_BLOCK) { - BlockNode *block = (BlockNode *)p_block->statements[i]; - if (_find_last_flow_op_in_block(block, p_op) == OK) { - found = true; - break; - } - } - } - - if (found) { - return OK; - } - return FAILED; -} - -// skips over whitespace and /* */ and // comments -static int _get_first_ident_pos(const String &p_code) { - - int idx = 0; - -#define GETCHAR(m_idx) (((idx + m_idx) < p_code.length()) ? p_code[idx + m_idx] : CharType(0)) - - while (true) { - if (GETCHAR(0) == '/' && GETCHAR(1) == '/') { - idx += 2; - while (true) { - if (GETCHAR(0) == 0) return 0; - if (GETCHAR(0) == '\n') { - idx++; - break; // loop - } - idx++; - } - } else if (GETCHAR(0) == '/' && GETCHAR(1) == '*') { - idx += 2; - while (true) { - if (GETCHAR(0) == 0) return 0; - if (GETCHAR(0) == '*' && GETCHAR(1) == '/') { - idx += 2; - break; // loop - } - idx++; - } - } else { - switch (GETCHAR(0)) { - case ' ': - case '\t': - case '\r': - case '\n': { - idx++; - } break; // switch - default: - return idx; - } - } - } - -#undef GETCHAR -} - -String ShaderLanguage::get_shader_type(const String &p_code) { - - bool reading_type = false; - - String cur_identifier; - - for (int i = _get_first_ident_pos(p_code); i < p_code.length(); i++) { - - if (p_code[i] == ';') { - break; - - } else if (p_code[i] <= 32) { - if (cur_identifier != String()) { - if (!reading_type) { - if (cur_identifier != "shader_type") { - return String(); - } - - reading_type = true; - cur_identifier = String(); - } else { - return cur_identifier; - } - } - } else { - cur_identifier += String::chr(p_code[i]); - } - } - - if (reading_type) - return cur_identifier; - - return String(); -} - -Error ShaderLanguage::compile(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types) { - - clear(); - - code = p_code; - - nodes = NULL; - - shader = alloc_node(); - Error err = _parse_shader(p_functions, p_render_modes, p_shader_types); - - if (err != OK) { - return err; - } - return OK; -} - -Error ShaderLanguage::complete(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types, List *r_options, String &r_call_hint) { - - clear(); - - code = p_code; - - nodes = NULL; - - shader = alloc_node(); - _parse_shader(p_functions, p_render_modes, p_shader_types); - - switch (completion_type) { - - case COMPLETION_NONE: { - //do nothing - return OK; - } break; - case COMPLETION_RENDER_MODE: { - for (int i = 0; i < p_render_modes.size(); i++) { - ScriptCodeCompletionOption option(p_render_modes[i], ScriptCodeCompletionOption::KIND_ENUM); - r_options->push_back(option); - } - - return OK; - } break; - case COMPLETION_STRUCT: { - - if (shader->structs.has(completion_struct)) { - StructNode *node = shader->structs[completion_struct].shader_struct; - for (int i = 0; i < node->members.size(); i++) { - ScriptCodeCompletionOption option(node->members[i]->name, ScriptCodeCompletionOption::KIND_MEMBER); - r_options->push_back(option); - } - } - - return OK; - } break; - case COMPLETION_MAIN_FUNCTION: { - - for (const Map::Element *E = p_functions.front(); E; E = E->next()) { - ScriptCodeCompletionOption option(E->key(), ScriptCodeCompletionOption::KIND_FUNCTION); - r_options->push_back(option); - } - - return OK; - } break; - case COMPLETION_IDENTIFIER: - case COMPLETION_FUNCTION_CALL: { - - bool comp_ident = completion_type == COMPLETION_IDENTIFIER; - Map matches; - StringName skip_function; - BlockNode *block = completion_block; - - if (completion_class == TAG_GLOBAL) { - while (block) { - if (comp_ident) { - for (const Map::Element *E = block->variables.front(); E; E = E->next()) { - - if (E->get().line < completion_line) { - matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE); - } - } - } - - if (block->parent_function) { - if (comp_ident) { - for (int i = 0; i < block->parent_function->arguments.size(); i++) { - matches.insert(block->parent_function->arguments[i].name, ScriptCodeCompletionOption::KIND_VARIABLE); - } - } - skip_function = block->parent_function->name; - } - block = block->parent_block; - } - - if (comp_ident) { - if (p_functions.has("global")) { - for (Map::Element *E = p_functions["global"].built_ins.front(); E; E = E->next()) { - ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; - if (E->get().constant) { - kind = ScriptCodeCompletionOption::KIND_CONSTANT; - } - matches.insert(E->key(), kind); - } - } - - if (skip_function != StringName() && p_functions.has(skip_function)) { - for (Map::Element *E = p_functions[skip_function].built_ins.front(); E; E = E->next()) { - ScriptCodeCompletionOption::Kind kind = ScriptCodeCompletionOption::KIND_MEMBER; - if (E->get().constant) { - kind = ScriptCodeCompletionOption::KIND_CONSTANT; - } - matches.insert(E->key(), kind); - } - } - - for (const Map::Element *E = shader->varyings.front(); E; E = E->next()) { - matches.insert(E->key(), ScriptCodeCompletionOption::KIND_VARIABLE); - } - for (const Map::Element *E = shader->uniforms.front(); E; E = E->next()) { - matches.insert(E->key(), ScriptCodeCompletionOption::KIND_MEMBER); - } - } - - for (int i = 0; i < shader->functions.size(); i++) { - if (!shader->functions[i].callable || shader->functions[i].name == skip_function) - continue; - matches.insert(String(shader->functions[i].name), ScriptCodeCompletionOption::KIND_FUNCTION); - } - - int idx = 0; - bool low_end = VisualServer::get_singleton()->is_low_end(); - - while (builtin_func_defs[idx].name) { - if (low_end && builtin_func_defs[idx].high_end) { - idx++; - continue; - } - matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION); - idx++; - } - - } else { // sub-class - int idx = 0; - bool low_end = VisualServer::get_singleton()->is_low_end(); - - while (builtin_func_defs[idx].name) { - if (low_end && builtin_func_defs[idx].high_end) { - idx++; - continue; - } - if (builtin_func_defs[idx].tag == completion_class) { - matches.insert(String(builtin_func_defs[idx].name), ScriptCodeCompletionOption::KIND_FUNCTION); - } - idx++; - } - } - - for (Map::Element *E = matches.front(); E; E = E->next()) { - ScriptCodeCompletionOption option(E->key(), E->value()); - if (E->value() == ScriptCodeCompletionOption::KIND_FUNCTION) { - option.insert_text += "("; - } - r_options->push_back(option); - } - - return OK; - } break; - case COMPLETION_CALL_ARGUMENTS: { - - for (int i = 0; i < shader->functions.size(); i++) { - if (!shader->functions[i].callable) - continue; - if (shader->functions[i].name == completion_function) { - - String calltip; - - calltip += get_datatype_name(shader->functions[i].function->return_type); - calltip += " "; - calltip += shader->functions[i].name; - calltip += "("; - - for (int j = 0; j < shader->functions[i].function->arguments.size(); j++) { - - if (j > 0) - calltip += ", "; - else - calltip += " "; - - if (j == completion_argument) { - calltip += CharType(0xFFFF); - } - - if (shader->functions[i].function->arguments[j].qualifier != ArgumentQualifier::ARGUMENT_QUALIFIER_IN) { - if (shader->functions[i].function->arguments[j].qualifier == ArgumentQualifier::ARGUMENT_QUALIFIER_OUT) { - calltip += "out "; - } else { // ArgumentQualifier::ARGUMENT_QUALIFIER_INOUT - calltip += "inout "; - } - } - - calltip += get_datatype_name(shader->functions[i].function->arguments[j].type); - calltip += " "; - calltip += shader->functions[i].function->arguments[j].name; - - if (j == completion_argument) { - calltip += CharType(0xFFFF); - } - } - - if (shader->functions[i].function->arguments.size()) - calltip += " "; - calltip += ")"; - - r_call_hint = calltip; - return OK; - } - } - - int idx = 0; - - String calltip; - bool low_end = VisualServer::get_singleton()->is_low_end(); - - while (builtin_func_defs[idx].name) { - - if (low_end && builtin_func_defs[idx].high_end) { - idx++; - continue; - } - - int idx2 = 0; - int out_arg = -1; - while (builtin_func_out_args[idx2].name != nullptr) { - if (builtin_func_out_args[idx2].name == builtin_func_defs[idx].name) { - out_arg = builtin_func_out_args[idx2].argument; - break; - } - idx2++; - } - - if (completion_function == builtin_func_defs[idx].name) { - - if (builtin_func_defs[idx].tag != completion_class) { - idx++; - continue; - } - - if (calltip.length()) - calltip += "\n"; - - calltip += get_datatype_name(builtin_func_defs[idx].rettype); - calltip += " "; - calltip += builtin_func_defs[idx].name; - calltip += "("; - - bool found_arg = false; - for (int i = 0; i < 4; i++) { - - if (builtin_func_defs[idx].args[i] == TYPE_VOID) - break; - - if (i > 0) - calltip += ", "; - else - calltip += " "; - - if (i == completion_argument) { - calltip += CharType(0xFFFF); - } - - if (out_arg >= 0 && i == out_arg) { - calltip += "out "; - } - - calltip += get_datatype_name(builtin_func_defs[idx].args[i]); - - if (i == completion_argument) { - calltip += CharType(0xFFFF); - } - - found_arg = true; - } - - if (found_arg) - calltip += " "; - calltip += ")"; - } - idx++; - } - - r_call_hint = calltip; - - return OK; - - } break; - case COMPLETION_INDEX: { - - const char colv[4] = { 'r', 'g', 'b', 'a' }; - const char coordv[4] = { 'x', 'y', 'z', 'w' }; - const char coordt[4] = { 's', 't', 'p', 'q' }; - - int limit = 0; - - switch (completion_base) { - case TYPE_BVEC2: - case TYPE_IVEC2: - case TYPE_UVEC2: - case TYPE_VEC2: { - limit = 2; - - } break; - case TYPE_BVEC3: - case TYPE_IVEC3: - case TYPE_UVEC3: - case TYPE_VEC3: { - - limit = 3; - - } break; - case TYPE_BVEC4: - case TYPE_IVEC4: - case TYPE_UVEC4: - case TYPE_VEC4: { - - limit = 4; - - } break; - case TYPE_MAT2: limit = 2; break; - case TYPE_MAT3: limit = 3; break; - case TYPE_MAT4: limit = 4; break; - default: { - } - } - - for (int i = 0; i < limit; i++) { - r_options->push_back(ScriptCodeCompletionOption(String::chr(colv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); - r_options->push_back(ScriptCodeCompletionOption(String::chr(coordv[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); - r_options->push_back(ScriptCodeCompletionOption(String::chr(coordt[i]), ScriptCodeCompletionOption::KIND_PLAIN_TEXT)); - } - - } break; - } - - return ERR_PARSE_ERROR; -} - -String ShaderLanguage::get_error_text() { - - return error_str; -} - -int ShaderLanguage::get_error_line() { - - return error_line; -} - -ShaderLanguage::ShaderNode *ShaderLanguage::get_shader() { - - return shader; -} - -ShaderLanguage::ShaderLanguage() { - - nodes = NULL; - completion_class = TAG_GLOBAL; -} - -ShaderLanguage::~ShaderLanguage() { - - clear(); -} diff --git a/servers/visual/shader_language.h b/servers/visual/shader_language.h deleted file mode 100644 index bdc15cc4aa..0000000000 --- a/servers/visual/shader_language.h +++ /dev/null @@ -1,900 +0,0 @@ -/*************************************************************************/ -/* shader_language.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHADER_LANGUAGE_H -#define SHADER_LANGUAGE_H - -#include "core/list.h" -#include "core/map.h" -#include "core/script_language.h" -#include "core/string_name.h" -#include "core/typedefs.h" -#include "core/ustring.h" -#include "core/variant.h" - -class ShaderLanguage { - -public: - enum TokenType { - TK_EMPTY, - TK_IDENTIFIER, - TK_TRUE, - TK_FALSE, - TK_REAL_CONSTANT, - TK_INT_CONSTANT, - TK_TYPE_VOID, - TK_TYPE_BOOL, - TK_TYPE_BVEC2, - TK_TYPE_BVEC3, - TK_TYPE_BVEC4, - TK_TYPE_INT, - TK_TYPE_IVEC2, - TK_TYPE_IVEC3, - TK_TYPE_IVEC4, - TK_TYPE_UINT, - TK_TYPE_UVEC2, - TK_TYPE_UVEC3, - TK_TYPE_UVEC4, - TK_TYPE_FLOAT, - TK_TYPE_VEC2, - TK_TYPE_VEC3, - TK_TYPE_VEC4, - TK_TYPE_MAT2, - TK_TYPE_MAT3, - TK_TYPE_MAT4, - TK_TYPE_SAMPLER2D, - TK_TYPE_ISAMPLER2D, - TK_TYPE_USAMPLER2D, - TK_TYPE_SAMPLER2DARRAY, - TK_TYPE_ISAMPLER2DARRAY, - TK_TYPE_USAMPLER2DARRAY, - TK_TYPE_SAMPLER3D, - TK_TYPE_ISAMPLER3D, - TK_TYPE_USAMPLER3D, - TK_TYPE_SAMPLERCUBE, - TK_INTERPOLATION_FLAT, - TK_INTERPOLATION_SMOOTH, - TK_CONST, - TK_STRUCT, - TK_PRECISION_LOW, - TK_PRECISION_MID, - TK_PRECISION_HIGH, - TK_OP_EQUAL, - TK_OP_NOT_EQUAL, - TK_OP_LESS, - TK_OP_LESS_EQUAL, - TK_OP_GREATER, - TK_OP_GREATER_EQUAL, - TK_OP_AND, - TK_OP_OR, - TK_OP_NOT, - TK_OP_ADD, - TK_OP_SUB, - TK_OP_MUL, - TK_OP_DIV, - TK_OP_MOD, - TK_OP_SHIFT_LEFT, - TK_OP_SHIFT_RIGHT, - TK_OP_ASSIGN, - TK_OP_ASSIGN_ADD, - TK_OP_ASSIGN_SUB, - TK_OP_ASSIGN_MUL, - TK_OP_ASSIGN_DIV, - TK_OP_ASSIGN_MOD, - TK_OP_ASSIGN_SHIFT_LEFT, - TK_OP_ASSIGN_SHIFT_RIGHT, - TK_OP_ASSIGN_BIT_AND, - TK_OP_ASSIGN_BIT_OR, - TK_OP_ASSIGN_BIT_XOR, - TK_OP_BIT_AND, - TK_OP_BIT_OR, - TK_OP_BIT_XOR, - TK_OP_BIT_INVERT, - TK_OP_INCREMENT, - TK_OP_DECREMENT, - TK_CF_IF, - TK_CF_ELSE, - TK_CF_FOR, - TK_CF_WHILE, - TK_CF_DO, - TK_CF_SWITCH, - TK_CF_CASE, - TK_CF_DEFAULT, - TK_CF_BREAK, - TK_CF_CONTINUE, - TK_CF_RETURN, - TK_CF_DISCARD, - TK_BRACKET_OPEN, - TK_BRACKET_CLOSE, - TK_CURLY_BRACKET_OPEN, - TK_CURLY_BRACKET_CLOSE, - TK_PARENTHESIS_OPEN, - TK_PARENTHESIS_CLOSE, - TK_QUESTION, - TK_COMMA, - TK_COLON, - TK_SEMICOLON, - TK_PERIOD, - TK_UNIFORM, - TK_VARYING, - TK_ARG_IN, - TK_ARG_OUT, - TK_ARG_INOUT, - TK_RENDER_MODE, - TK_HINT_WHITE_TEXTURE, - TK_HINT_BLACK_TEXTURE, - TK_HINT_NORMAL_TEXTURE, - TK_HINT_ROUGHNESS_NORMAL_TEXTURE, - TK_HINT_ROUGHNESS_R, - TK_HINT_ROUGHNESS_G, - TK_HINT_ROUGHNESS_B, - TK_HINT_ROUGHNESS_A, - TK_HINT_ROUGHNESS_GRAY, - TK_HINT_ANISO_TEXTURE, - TK_HINT_ALBEDO_TEXTURE, - TK_HINT_BLACK_ALBEDO_TEXTURE, - TK_HINT_COLOR, - TK_HINT_RANGE, - TK_FILTER_NEAREST, - TK_FILTER_LINEAR, - TK_FILTER_NEAREST_MIPMAP, - TK_FILTER_LINEAR_MIPMAP, - TK_FILTER_NEAREST_MIPMAP_ANISO, - TK_FILTER_LINEAR_MIPMAP_ANISO, - TK_REPEAT_ENABLE, - TK_REPEAT_DISABLE, - TK_SHADER_TYPE, - TK_CURSOR, - TK_ERROR, - TK_EOF, - TK_MAX - }; - -/* COMPILER */ - -// lame work around to Apple defining this as a macro in 10.12 SDK -#ifdef TYPE_BOOL -#undef TYPE_BOOL -#endif - - enum DataType { - TYPE_VOID, - TYPE_BOOL, - TYPE_BVEC2, - TYPE_BVEC3, - TYPE_BVEC4, - TYPE_INT, - TYPE_IVEC2, - TYPE_IVEC3, - TYPE_IVEC4, - TYPE_UINT, - TYPE_UVEC2, - TYPE_UVEC3, - TYPE_UVEC4, - TYPE_FLOAT, - TYPE_VEC2, - TYPE_VEC3, - TYPE_VEC4, - TYPE_MAT2, - TYPE_MAT3, - TYPE_MAT4, - TYPE_SAMPLER2D, - TYPE_ISAMPLER2D, - TYPE_USAMPLER2D, - TYPE_SAMPLER2DARRAY, - TYPE_ISAMPLER2DARRAY, - TYPE_USAMPLER2DARRAY, - TYPE_SAMPLER3D, - TYPE_ISAMPLER3D, - TYPE_USAMPLER3D, - TYPE_SAMPLERCUBE, - TYPE_STRUCT, - }; - - enum DataPrecision { - PRECISION_LOWP, - PRECISION_MEDIUMP, - PRECISION_HIGHP, - PRECISION_DEFAULT, - }; - - enum DataInterpolation { - INTERPOLATION_FLAT, - INTERPOLATION_SMOOTH, - }; - - enum Operator { - OP_EQUAL, - OP_NOT_EQUAL, - OP_LESS, - OP_LESS_EQUAL, - OP_GREATER, - OP_GREATER_EQUAL, - OP_AND, - OP_OR, - OP_NOT, - OP_NEGATE, - OP_ADD, - OP_SUB, - OP_MUL, - OP_DIV, - OP_MOD, - OP_SHIFT_LEFT, - OP_SHIFT_RIGHT, - OP_ASSIGN, - OP_ASSIGN_ADD, - OP_ASSIGN_SUB, - OP_ASSIGN_MUL, - OP_ASSIGN_DIV, - OP_ASSIGN_MOD, - OP_ASSIGN_SHIFT_LEFT, - OP_ASSIGN_SHIFT_RIGHT, - OP_ASSIGN_BIT_AND, - OP_ASSIGN_BIT_OR, - OP_ASSIGN_BIT_XOR, - OP_BIT_AND, - OP_BIT_OR, - OP_BIT_XOR, - OP_BIT_INVERT, - OP_INCREMENT, - OP_DECREMENT, - OP_SELECT_IF, - OP_SELECT_ELSE, //used only internally, then only IF appears with 3 arguments - OP_POST_INCREMENT, - OP_POST_DECREMENT, - OP_CALL, - OP_CONSTRUCT, - OP_STRUCT, - OP_INDEX, - OP_MAX - }; - - enum FlowOperation { - FLOW_OP_IF, - FLOW_OP_RETURN, - FLOW_OP_FOR, - FLOW_OP_WHILE, - FLOW_OP_DO, - FLOW_OP_BREAK, - FLOW_OP_SWITCH, - FLOW_OP_CASE, - FLOW_OP_DEFAULT, - FLOW_OP_CONTINUE, - FLOW_OP_DISCARD - }; - - enum ArgumentQualifier { - ARGUMENT_QUALIFIER_IN, - ARGUMENT_QUALIFIER_OUT, - ARGUMENT_QUALIFIER_INOUT, - }; - - enum SubClassTag { - TAG_GLOBAL, - TAG_ARRAY, - }; - - enum TextureFilter { - FILTER_NEAREST, - FILTER_LINEAR, - FILTER_NEAREST_MIPMAP, - FILTER_LINEAR_MIPMAP, - FILTER_NEAREST_MIPMAP_ANISO, - FILTER_LINEAR_MIPMAP_ANISO, - FILTER_DEFAULT, - }; - - enum TextureRepeat { - REPEAT_DISABLE, - REPEAT_ENABLE, - REPEAT_DEFAULT, - }; - - struct Node { - Node *next; - - enum Type { - TYPE_SHADER, - TYPE_FUNCTION, - TYPE_BLOCK, - TYPE_VARIABLE, - TYPE_VARIABLE_DECLARATION, - TYPE_CONSTANT, - TYPE_OPERATOR, - TYPE_CONTROL_FLOW, - TYPE_MEMBER, - TYPE_ARRAY, - TYPE_ARRAY_DECLARATION, - TYPE_ARRAY_CONSTRUCT, - TYPE_STRUCT, - }; - - Type type; - - virtual DataType get_datatype() const { return TYPE_VOID; } - virtual String get_datatype_name() const { return ""; } - - Node(Type t) : - next(NULL), - type(t) {} - virtual ~Node() {} - }; - - template - T *alloc_node() { - T *node = memnew(T); - node->next = nodes; - nodes = node; - return node; - } - - Node *nodes; - - struct OperatorNode : public Node { - DataType return_cache; - DataPrecision return_precision_cache; - Operator op; - StringName struct_name; - Vector arguments; - virtual DataType get_datatype() const { return return_cache; } - virtual String get_datatype_name() const { return String(struct_name); } - - OperatorNode() : - Node(TYPE_OPERATOR), - return_cache(TYPE_VOID), - return_precision_cache(PRECISION_DEFAULT), - op(OP_EQUAL), - struct_name("") {} - }; - - struct VariableNode : public Node { - DataType datatype_cache; - StringName name; - StringName struct_name; - virtual DataType get_datatype() const { return datatype_cache; } - virtual String get_datatype_name() const { return String(struct_name); } - bool is_const; - - VariableNode() : - Node(TYPE_VARIABLE), - datatype_cache(TYPE_VOID), - is_const(false) {} - }; - - struct VariableDeclarationNode : public Node { - DataPrecision precision; - DataType datatype; - String struct_name; - bool is_const; - - struct Declaration { - StringName name; - Node *initializer; - }; - - Vector declarations; - virtual DataType get_datatype() const { return datatype; } - - VariableDeclarationNode() : - Node(TYPE_VARIABLE_DECLARATION), - precision(PRECISION_DEFAULT), - datatype(TYPE_VOID), - is_const(false) {} - }; - - struct ArrayNode : public Node { - DataType datatype_cache; - StringName struct_name; - StringName name; - Node *index_expression; - Node *call_expression; - bool is_const; - - virtual DataType get_datatype() const { return datatype_cache; } - virtual String get_datatype_name() const { return String(struct_name); } - - ArrayNode() : - Node(TYPE_ARRAY), - datatype_cache(TYPE_VOID), - index_expression(NULL), - call_expression(NULL), - is_const(false) {} - }; - - struct ArrayConstructNode : public Node { - DataType datatype; - String struct_name; - Vector initializer; - - ArrayConstructNode() : - Node(TYPE_ARRAY_CONSTRUCT), - datatype(TYPE_VOID) { - } - }; - - struct ArrayDeclarationNode : public Node { - DataPrecision precision; - DataType datatype; - String struct_name; - bool is_const; - - struct Declaration { - StringName name; - uint32_t size; - Vector initializer; - }; - - Vector declarations; - virtual DataType get_datatype() const { return datatype; } - - ArrayDeclarationNode() : - Node(TYPE_ARRAY_DECLARATION), - precision(PRECISION_DEFAULT), - datatype(TYPE_VOID), - is_const(false) {} - }; - - struct ConstantNode : public Node { - DataType datatype; - - union Value { - bool boolean; - float real; - int32_t sint; - uint32_t uint; - }; - - Vector values; - virtual DataType get_datatype() const { return datatype; } - - ConstantNode() : - Node(TYPE_CONSTANT), - datatype(TYPE_VOID) {} - }; - - struct FunctionNode; - - struct BlockNode : public Node { - FunctionNode *parent_function; - BlockNode *parent_block; - - enum BlockType { - BLOCK_TYPE_STANDART, - BLOCK_TYPE_SWITCH, - BLOCK_TYPE_CASE, - BLOCK_TYPE_DEFAULT, - }; - - int block_type; - SubClassTag block_tag; - - struct Variable { - DataType type; - StringName struct_name; - DataPrecision precision; - int line; //for completion - int array_size; - bool is_const; - }; - - Map variables; - List statements; - bool single_statement; - - BlockNode() : - Node(TYPE_BLOCK), - parent_function(NULL), - parent_block(NULL), - block_type(BLOCK_TYPE_STANDART), - block_tag(SubClassTag::TAG_GLOBAL), - single_statement(false) {} - }; - - struct ControlFlowNode : public Node { - FlowOperation flow_op; - Vector expressions; - Vector blocks; - - ControlFlowNode() : - Node(TYPE_CONTROL_FLOW), - flow_op(FLOW_OP_IF) {} - }; - - struct MemberNode : public Node { - DataType basetype; - bool basetype_const; - StringName base_struct_name; - DataPrecision precision; - DataType datatype; - int array_size; - StringName struct_name; - StringName name; - Node *owner; - Node *index_expression; - bool has_swizzling_duplicates; - - virtual DataType get_datatype() const { return datatype; } - virtual String get_datatype_name() const { return String(struct_name); } - - MemberNode() : - Node(TYPE_MEMBER), - basetype(TYPE_VOID), - basetype_const(false), - datatype(TYPE_VOID), - array_size(0), - owner(NULL), - index_expression(NULL), - has_swizzling_duplicates(false) {} - }; - - struct StructNode : public Node { - - List members; - StructNode() : - Node(TYPE_STRUCT) {} - }; - - struct FunctionNode : public Node { - - struct Argument { - ArgumentQualifier qualifier; - StringName name; - DataType type; - StringName type_str; - DataPrecision precision; - //for passing textures as arguments - bool tex_argument_check; - TextureFilter tex_argument_filter; - TextureRepeat tex_argument_repeat; - bool tex_builtin_check; - StringName tex_builtin; - - Map> tex_argument_connect; - }; - - StringName name; - DataType return_type; - StringName return_struct_name; - DataPrecision return_precision; - Vector arguments; - BlockNode *body; - bool can_discard; - - FunctionNode() : - Node(TYPE_FUNCTION), - return_type(TYPE_VOID), - return_precision(PRECISION_DEFAULT), - body(NULL), - can_discard(false) {} - }; - - struct ShaderNode : public Node { - - struct Constant { - DataType type; - StringName type_str; - DataPrecision precision; - ConstantNode *initializer; - }; - - struct Function { - StringName name; - FunctionNode *function; - Set uses_function; - bool callable; - }; - - struct Struct { - StringName name; - StructNode *shader_struct; - }; - - struct Varying { - DataType type; - DataInterpolation interpolation; - DataPrecision precision; - int array_size; - - Varying() : - type(TYPE_VOID), - interpolation(INTERPOLATION_FLAT), - precision(PRECISION_DEFAULT), - array_size(0) {} - }; - - struct Uniform { - enum Hint { - HINT_NONE, - HINT_COLOR, - HINT_RANGE, - HINT_ALBEDO, - HINT_BLACK_ALBEDO, - HINT_NORMAL, - HINT_ROUGHNESS_NORMAL, - HINT_ROUGHNESS_R, - HINT_ROUGHNESS_G, - HINT_ROUGHNESS_B, - HINT_ROUGHNESS_A, - HINT_ROUGHNESS_GRAY, - HINT_BLACK, - HINT_WHITE, - HINT_ANISO, - HINT_MAX - }; - - int order; - int texture_order; - DataType type; - DataPrecision precision; - Vector default_value; - Hint hint; - TextureFilter filter; - TextureRepeat repeat; - float hint_range[3]; - - Uniform() : - order(0), - texture_order(0), - type(TYPE_VOID), - precision(PRECISION_DEFAULT), - hint(HINT_NONE), - filter(FILTER_DEFAULT), - repeat(REPEAT_DEFAULT) { - hint_range[0] = 0.0f; - hint_range[1] = 1.0f; - hint_range[2] = 0.001f; - } - }; - - Map constants; - Map varyings; - Map uniforms; - Map structs; - Vector render_modes; - - Vector functions; - Vector vstructs; - - ShaderNode() : - Node(TYPE_SHADER) {} - }; - - struct Expression { - bool is_op; - union { - Operator op; - Node *node; - }; - }; - - struct VarInfo { - StringName name; - DataType type; - }; - - enum CompletionType { - COMPLETION_NONE, - COMPLETION_RENDER_MODE, - COMPLETION_MAIN_FUNCTION, - COMPLETION_IDENTIFIER, - COMPLETION_FUNCTION_CALL, - COMPLETION_CALL_ARGUMENTS, - COMPLETION_INDEX, - COMPLETION_STRUCT, - }; - - struct Token { - TokenType type; - StringName text; - double constant; - uint16_t line; - }; - - static String get_operator_text(Operator p_op); - static String get_token_text(Token p_token); - - static bool is_token_datatype(TokenType p_type); - static bool is_token_variable_datatype(TokenType p_type); - static DataType get_token_datatype(TokenType p_type); - static bool is_token_interpolation(TokenType p_type); - static DataInterpolation get_token_interpolation(TokenType p_type); - static bool is_token_precision(TokenType p_type); - static DataPrecision get_token_precision(TokenType p_type); - static String get_precision_name(DataPrecision p_type); - static String get_datatype_name(DataType p_type); - static bool is_token_nonvoid_datatype(TokenType p_type); - static bool is_token_operator(TokenType p_type); - - static bool convert_constant(ConstantNode *p_constant, DataType p_to_type, ConstantNode::Value *p_value = NULL); - static DataType get_scalar_type(DataType p_type); - static int get_cardinality(DataType p_type); - static bool is_scalar_type(DataType p_type); - static bool is_sampler_type(DataType p_type); - static Variant constant_value_to_variant(const Vector &p_value, DataType p_type, ShaderLanguage::ShaderNode::Uniform::Hint p_hint = ShaderLanguage::ShaderNode::Uniform::HINT_NONE); - static PropertyInfo uniform_to_property_info(const ShaderNode::Uniform &p_uniform); - static uint32_t get_type_size(DataType p_type); - - static void get_keyword_list(List *r_keywords); - static void get_builtin_funcs(List *r_keywords); - - struct BuiltInInfo { - DataType type; - bool constant; - - BuiltInInfo() : - type(TYPE_VOID), - constant(false) {} - - BuiltInInfo(DataType p_type, bool p_constant = false) : - type(p_type), - constant(p_constant) {} - }; - - struct FunctionInfo { - Map built_ins; - bool can_discard; - }; - static bool has_builtin(const Map &p_functions, const StringName &p_name); - -private: - struct KeyWord { - TokenType token; - const char *text; - }; - - static const KeyWord keyword_list[]; - - bool error_set; - String error_str; - int error_line; - - String code; - int char_idx; - int tk_line; - - StringName current_function; - - struct TkPos { - int char_idx; - int tk_line; - }; - - TkPos _get_tkpos() { - TkPos tkp; - tkp.char_idx = char_idx; - tkp.tk_line = tk_line; - return tkp; - } - - void _set_tkpos(TkPos p_pos) { - char_idx = p_pos.char_idx; - tk_line = p_pos.tk_line; - } - - void _set_error(const String &p_str) { - if (error_set) - return; - - error_line = tk_line; - error_set = true; - error_str = p_str; - } - - static const char *token_names[TK_MAX]; - - Token _make_token(TokenType p_type, const StringName &p_text = StringName()); - Token _get_token(); - - ShaderNode *shader; - - enum IdentifierType { - IDENTIFIER_FUNCTION, - IDENTIFIER_UNIFORM, - IDENTIFIER_VARYING, - IDENTIFIER_FUNCTION_ARGUMENT, - IDENTIFIER_LOCAL_VAR, - IDENTIFIER_BUILTIN_VAR, - IDENTIFIER_CONSTANT, - }; - - bool _find_identifier(const BlockNode *p_block, bool p_allow_reassign, const Map &p_builtin_types, const StringName &p_identifier, DataType *r_data_type = NULL, IdentifierType *r_type = NULL, bool *r_is_const = NULL, int *r_array_size = NULL, StringName *r_struct_name = NULL); - bool _is_operator_assign(Operator p_op) const; - bool _validate_assign(Node *p_node, const Map &p_builtin_types, String *r_message = NULL); - bool _validate_operator(OperatorNode *p_op, DataType *r_ret_type = NULL); - - struct BuiltinFuncDef { - enum { MAX_ARGS = 5 }; - const char *name; - DataType rettype; - const DataType args[MAX_ARGS]; - SubClassTag tag; - bool high_end; - }; - - struct BuiltinFuncOutArgs { //arguments used as out in built in functions - const char *name; - int argument; - }; - - CompletionType completion_type; - int completion_line; - BlockNode *completion_block; - DataType completion_base; - SubClassTag completion_class; - StringName completion_function; - StringName completion_struct; - int completion_argument; - - bool _get_completable_identifier(BlockNode *p_block, CompletionType p_type, StringName &identifier); - static const BuiltinFuncDef builtin_func_defs[]; - static const BuiltinFuncOutArgs builtin_func_out_args[]; - - Error _validate_datatype(DataType p_type); - bool _compare_datatypes_in_nodes(Node *a, Node *b) const; - - bool _validate_function_call(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, DataType *r_ret_type, StringName *r_ret_type_str); - bool _parse_function_arguments(BlockNode *p_block, const Map &p_builtin_types, OperatorNode *p_func, int *r_complete_arg = NULL); - bool _propagate_function_call_sampler_uniform_settings(StringName p_name, int p_argument, TextureFilter p_filter, TextureRepeat p_repeat); - bool _propagate_function_call_sampler_builtin_reference(StringName p_name, int p_argument, const StringName &p_builtin); - - Node *_parse_expression(BlockNode *p_block, const Map &p_builtin_types); - ShaderLanguage::Node *_reduce_expression(BlockNode *p_block, ShaderLanguage::Node *p_node); - - Node *_parse_and_reduce_expression(BlockNode *p_block, const Map &p_builtin_types); - Error _parse_block(BlockNode *p_block, const Map &p_builtin_types, bool p_just_one = false, bool p_can_break = false, bool p_can_continue = false); - String _get_shader_type_list(const Set &p_shader_types) const; - String _get_qualifier_str(ArgumentQualifier p_qualifier) const; - - Error _parse_shader(const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types); - - Error _find_last_flow_op_in_block(BlockNode *p_block, FlowOperation p_op); - Error _find_last_flow_op_in_op(ControlFlowNode *p_flow, FlowOperation p_op); - -public: - //static void get_keyword_list(ShaderType p_type,List *p_keywords); - - void clear(); - - static String get_shader_type(const String &p_code); - Error compile(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types); - Error complete(const String &p_code, const Map &p_functions, const Vector &p_render_modes, const Set &p_shader_types, List *r_options, String &r_call_hint); - - String get_error_text(); - int get_error_line(); - - ShaderNode *get_shader(); - - String token_debug(const String &p_code); - - ShaderLanguage(); - ~ShaderLanguage(); -}; - -#endif // SHADER_LANGUAGE_H diff --git a/servers/visual/shader_types.cpp b/servers/visual/shader_types.cpp deleted file mode 100644 index 041ad799d0..0000000000 --- a/servers/visual/shader_types.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/*************************************************************************/ -/* shader_types.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "shader_types.h" - -const Map &ShaderTypes::get_functions(VS::ShaderMode p_mode) { - - return shader_modes[p_mode].functions; -} - -const Vector &ShaderTypes::get_modes(VS::ShaderMode p_mode) { - - return shader_modes[p_mode].modes; -} - -const Set &ShaderTypes::get_types() { - return shader_types; -} - -ShaderTypes *ShaderTypes::singleton = NULL; - -static ShaderLanguage::BuiltInInfo constt(ShaderLanguage::DataType p_type) { - - return ShaderLanguage::BuiltInInfo(p_type, true); -} - -ShaderTypes::ShaderTypes() { - singleton = this; - - /*************** SPATIAL ***********************/ - - shader_modes[VS::SHADER_SPATIAL].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POSITION"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["UV2"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_ID"] = constt(ShaderLanguage::TYPE_INT); - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].can_discard = false; - - //builtins - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["WORLD_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["PROJECTION_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_MATRIX"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["MODELVIEW_NORMAL_MATRIX"] = ShaderLanguage::TYPE_MAT3; - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SPATIAL].functions["vertex"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["FRONT_FACING"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TANGENT"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["BINORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALBEDO"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["METALLIC"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SPECULAR"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ROUGHNESS"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["RIM_TINT"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["CLEARCOAT_GLOSS"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["ANISOTROPY_FLOW"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SSS_STRENGTH"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["TRANSMISSION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["AO_LIGHT_AFFECT"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["EMISSION"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH_TEXTURE"] = ShaderLanguage::TYPE_SAMPLER2D; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["DEPTH"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["SCREEN_UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); - - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["WORLD_NORMAL_MATRIX"] = constt(ShaderLanguage::TYPE_MAT3); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SPATIAL].functions["fragment"].can_discard = true; - - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["CAMERA_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["INV_PROJECTION_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEWPORT_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["UV2"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["VIEW"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ATTENUATION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALBEDO"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["TRANSMISSION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ROUGHNESS"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["DIFFUSE_LIGHT"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["SPECULAR_LIGHT"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["OUTPUT_IS_SRGB"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SPATIAL].functions["light"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; - - shader_modes[VS::SHADER_SPATIAL].functions["light"].can_discard = true; - - //order used puts first enum mode (default) first - shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_mix"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_add"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_sub"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("blend_mul"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_opaque"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_always"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_draw_never"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_prepass_alpha"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("depth_test_disabled"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_back"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_front"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("cull_disabled"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("unshaded"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("wireframe"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_lambert_wrap"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_oren_nayar"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_burley"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("diffuse_toon"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_schlick_ggx"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_blinn"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_phong"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_toon"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("specular_disabled"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("skip_vertex_transform"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("world_vertex_coords"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("ensure_correct_normals"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadows_disabled"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("ambient_light_disabled"); - shader_modes[VS::SHADER_SPATIAL].modes.push_back("shadow_to_opacity"); - - shader_modes[VS::SHADER_SPATIAL].modes.push_back("vertex_lighting"); - - /************ CANVAS ITEM **************************/ - - shader_modes[VS::SHADER_CANVAS_ITEM].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["UV"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["POINT_SIZE"] = ShaderLanguage::TYPE_FLOAT; - - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["WORLD_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["CANVAS_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["SCREEN_MATRIX"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["INSTANCE_CUSTOM"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["vertex"].can_discard = false; - - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["VERTEX"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SHADOW_VERTEX"] = ShaderLanguage::TYPE_VEC2; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["LIGHT_VERTEX"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMALMAP_DEPTH"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["NORMAL_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["AT_LIGHT_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].built_ins["SCREEN_TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["fragment"].can_discard = true; - - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["FRAGCOORD"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["NORMAL"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SPECULAR_SHININESS"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_POSITION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT_VERTEX"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["LIGHT"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SHADOW_MODULATE"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE"] = constt(ShaderLanguage::TYPE_SAMPLER2D); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["TEXTURE_PIXEL_SIZE"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].built_ins["POINT_COORD"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_CANVAS_ITEM].functions["light"].can_discard = true; - - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("skip_vertex_transform"); - - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_mix"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_add"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_sub"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_mul"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_premul_alpha"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("blend_disabled"); - - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("unshaded"); - shader_modes[VS::SHADER_CANVAS_ITEM].modes.push_back("light_only"); - - /************ PARTICLES **************************/ - - shader_modes[VS::SHADER_PARTICLES].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["VELOCITY"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["MASS"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["ACTIVE"] = ShaderLanguage::TYPE_BOOL; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RESTART"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["CUSTOM"] = ShaderLanguage::TYPE_VEC4; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["TRANSFORM"] = ShaderLanguage::TYPE_MAT4; - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["LIFETIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["DELTA"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["NUMBER"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["INDEX"] = constt(ShaderLanguage::TYPE_INT); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["EMISSION_TRANSFORM"] = constt(ShaderLanguage::TYPE_MAT4); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].built_ins["RANDOM_SEED"] = constt(ShaderLanguage::TYPE_UINT); - shader_modes[VS::SHADER_PARTICLES].functions["vertex"].can_discard = false; - - shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_force"); - shader_modes[VS::SHADER_PARTICLES].modes.push_back("disable_velocity"); - shader_modes[VS::SHADER_PARTICLES].modes.push_back("keep_data"); - - /************ SKY **************************/ - - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["TIME"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["POSITION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["RADIANCE"] = constt(ShaderLanguage::TYPE_SAMPLERCUBE); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["AT_HALF_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["AT_QUARTER_RES_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["AT_CUBEMAP_PASS"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT0_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT0_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT0_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT1_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT1_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT1_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT2_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT2_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT2_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENABLED"] = constt(ShaderLanguage::TYPE_BOOL); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT3_DIRECTION"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT3_ENERGY"] = constt(ShaderLanguage::TYPE_FLOAT); - shader_modes[VS::SHADER_SKY].functions["global"].built_ins["LIGHT3_COLOR"] = constt(ShaderLanguage::TYPE_VEC3); - - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["COLOR"] = ShaderLanguage::TYPE_VEC3; - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["ALPHA"] = ShaderLanguage::TYPE_FLOAT; - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["EYEDIR"] = constt(ShaderLanguage::TYPE_VEC3); - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["SCREEN_UV"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["SKY_COORDS"] = constt(ShaderLanguage::TYPE_VEC2); - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["HALF_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - shader_modes[VS::SHADER_SKY].functions["fragment"].built_ins["QUARTER_RES_COLOR"] = constt(ShaderLanguage::TYPE_VEC4); - - shader_modes[VS::SHADER_SKY].modes.push_back("use_half_res_pass"); - shader_modes[VS::SHADER_SKY].modes.push_back("use_quarter_res_pass"); - - shader_types.insert("spatial"); - shader_types.insert("canvas_item"); - shader_types.insert("particles"); - shader_types.insert("sky"); -} diff --git a/servers/visual/shader_types.h b/servers/visual/shader_types.h deleted file mode 100644 index 7d674bfb5c..0000000000 --- a/servers/visual/shader_types.h +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************/ -/* shader_types.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef SHADERTYPES_H -#define SHADERTYPES_H - -#include "core/ordered_hash_map.h" -#include "servers/visual_server.h" -#include "shader_language.h" - -class ShaderTypes { - - struct Type { - - Map functions; - Vector modes; - }; - - Map shader_modes; - - static ShaderTypes *singleton; - - Set shader_types; - -public: - static ShaderTypes *get_singleton() { return singleton; } - - const Map &get_functions(VS::ShaderMode p_mode); - const Vector &get_modes(VS::ShaderMode p_mode); - const Set &get_types(); - - ShaderTypes(); -}; - -#endif // SHADERTYPES_H diff --git a/servers/visual/visual_server_canvas.cpp b/servers/visual/visual_server_canvas.cpp deleted file mode 100644 index c192b77988..0000000000 --- a/servers/visual/visual_server_canvas.cpp +++ /dev/null @@ -1,1479 +0,0 @@ -/*************************************************************************/ -/* visual_server_canvas.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server_canvas.h" -#include "visual_server_globals.h" -#include "visual_server_raster.h" -#include "visual_server_viewport.h" - -static const int z_range = VS::CANVAS_ITEM_Z_MAX - VS::CANVAS_ITEM_Z_MIN + 1; - -void VisualServerCanvas::_render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights) { - - RENDER_TIMESTAMP("Cull CanvasItem Tree"); - - memset(z_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); - memset(z_last_list, 0, z_range * sizeof(RasterizerCanvas::Item *)); - - for (int i = 0; i < p_child_item_count; i++) { - _cull_canvas_item(p_child_items[i].item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL); - } - if (p_canvas_item) { - _cull_canvas_item(p_canvas_item, p_transform, p_clip_rect, Color(1, 1, 1, 1), 0, z_list, z_last_list, NULL, NULL); - } - - RasterizerCanvas::Item *list = NULL; - RasterizerCanvas::Item *list_end = NULL; - - for (int i = 0; i < z_range; i++) { - if (!z_list[i]) - continue; - if (!list) { - list = z_list[i]; - list_end = z_last_list[i]; - } else { - list_end->next = z_list[i]; - list_end = z_last_list[i]; - } - } - - RENDER_TIMESTAMP("Render Canvas Items"); - - VSG::canvas_render->canvas_render_items(p_to_render_target, list, p_modulate, p_lights, p_transform); -} - -void _collect_ysort_children(VisualServerCanvas::Item *p_canvas_item, Transform2D p_transform, VisualServerCanvas::Item *p_material_owner, VisualServerCanvas::Item **r_items, int &r_index) { - int child_item_count = p_canvas_item->child_items.size(); - VisualServerCanvas::Item **child_items = p_canvas_item->child_items.ptrw(); - for (int i = 0; i < child_item_count; i++) { - if (child_items[i]->visible) { - if (r_items) { - r_items[r_index] = child_items[i]; - child_items[i]->ysort_xform = p_transform; - child_items[i]->ysort_pos = p_transform.xform(child_items[i]->xform.elements[2]); - child_items[i]->material_owner = child_items[i]->use_parent_material ? p_material_owner : NULL; - } - - r_index++; - - if (child_items[i]->sort_y) - _collect_ysort_children(child_items[i], p_transform * child_items[i]->xform, child_items[i]->use_parent_material ? p_material_owner : child_items[i], r_items, r_index); - } - } -} - -void _mark_ysort_dirty(VisualServerCanvas::Item *ysort_owner, RID_PtrOwner &canvas_item_owner) { - do { - ysort_owner->ysort_children_count = -1; - ysort_owner = canvas_item_owner.owns(ysort_owner->parent) ? canvas_item_owner.getornull(ysort_owner->parent) : NULL; - } while (ysort_owner && ysort_owner->sort_y); -} - -void VisualServerCanvas::_cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner) { - - Item *ci = p_canvas_item; - - if (!ci->visible) - return; - - if (ci->children_order_dirty) { - - ci->child_items.sort_custom(); - ci->children_order_dirty = false; - } - - Rect2 rect = ci->get_rect(); - Transform2D xform = p_transform * ci->xform; - Rect2 global_rect = xform.xform(rect); - global_rect.position += p_clip_rect.position; - - if (ci->use_parent_material && p_material_owner) - ci->material_owner = p_material_owner; - else { - p_material_owner = ci; - ci->material_owner = NULL; - } - - Color modulate(ci->modulate.r * p_modulate.r, ci->modulate.g * p_modulate.g, ci->modulate.b * p_modulate.b, ci->modulate.a * p_modulate.a); - - if (modulate.a < 0.007) - return; - - int child_item_count = ci->child_items.size(); - Item **child_items = ci->child_items.ptrw(); - - if (ci->clip) { - if (p_canvas_clip != NULL) { - ci->final_clip_rect = p_canvas_clip->final_clip_rect.clip(global_rect); - } else { - ci->final_clip_rect = global_rect; - } - ci->final_clip_owner = ci; - - } else { - ci->final_clip_owner = p_canvas_clip; - } - - if (ci->sort_y) { - - if (ci->ysort_children_count == -1) { - ci->ysort_children_count = 0; - _collect_ysort_children(ci, Transform2D(), p_material_owner, NULL, ci->ysort_children_count); - } - - child_item_count = ci->ysort_children_count; - child_items = (Item **)alloca(child_item_count * sizeof(Item *)); - - int i = 0; - _collect_ysort_children(ci, Transform2D(), p_material_owner, child_items, i); - - SortArray sorter; - sorter.sort(child_items, child_item_count); - } - - if (ci->z_relative) - p_z = CLAMP(p_z + ci->z_index, VS::CANVAS_ITEM_Z_MIN, VS::CANVAS_ITEM_Z_MAX); - else - p_z = ci->z_index; - - for (int i = 0; i < child_item_count; i++) { - - if (!child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) - continue; - if (ci->sort_y) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); - } else { - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); - } - } - - if (ci->copy_back_buffer) { - - ci->copy_back_buffer->screen_rect = xform.xform(ci->copy_back_buffer->rect).clip(p_clip_rect); - } - - if (ci->update_when_visible) { - VisualServerRaster::redraw_request(); - } - - if ((ci->commands != NULL && p_clip_rect.intersects(global_rect, true)) || ci->vp_render || ci->copy_back_buffer) { - //something to draw? - ci->final_transform = xform; - ci->final_modulate = Color(modulate.r * ci->self_modulate.r, modulate.g * ci->self_modulate.g, modulate.b * ci->self_modulate.b, modulate.a * ci->self_modulate.a); - ci->global_rect_cache = global_rect; - ci->global_rect_cache.position -= p_clip_rect.position; - ci->light_masked = false; - - int zidx = p_z - VS::CANVAS_ITEM_Z_MIN; - - if (z_last_list[zidx]) { - z_last_list[zidx]->next = ci; - z_last_list[zidx] = ci; - - } else { - z_list[zidx] = ci; - z_last_list[zidx] = ci; - } - - ci->z_final = p_z; - - ci->next = NULL; - } - - for (int i = 0; i < child_item_count; i++) { - - if (child_items[i]->behind || (ci->sort_y && child_items[i]->sort_y)) - continue; - if (ci->sort_y) { - _cull_canvas_item(child_items[i], xform * child_items[i]->ysort_xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, (Item *)child_items[i]->material_owner); - } else { - _cull_canvas_item(child_items[i], xform, p_clip_rect, modulate, p_z, z_list, z_last_list, (Item *)ci->final_clip_owner, p_material_owner); - } - } -} - -void VisualServerCanvas::_light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights) { - - if (!p_masked_lights) - return; - - RasterizerCanvas::Item *ci = p_canvas_item; - - while (ci) { - - RasterizerCanvas::Light *light = p_masked_lights; - while (light) { - - if (ci->light_mask & light->item_mask && p_z >= light->z_min && p_z <= light->z_max && ci->global_rect_cache.intersects_transformed(light->xform_cache, light->rect_cache)) { - ci->light_masked = true; - } - - light = light->mask_next_ptr; - } - - ci = ci->next; - } -} - -void VisualServerCanvas::render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect) { - - RENDER_TIMESTAMP(">Render Canvas"); - - if (p_canvas->children_order_dirty) { - - p_canvas->child_items.sort(); - p_canvas->children_order_dirty = false; - } - - int l = p_canvas->child_items.size(); - Canvas::ChildItem *ci = p_canvas->child_items.ptrw(); - - bool has_mirror = false; - for (int i = 0; i < l; i++) { - if (ci[i].mirror.x || ci[i].mirror.y) { - has_mirror = true; - break; - } - } - - if (!has_mirror) { - - _render_canvas_item_tree(p_render_target, ci, l, NULL, p_transform, p_clip_rect, p_canvas->modulate, p_lights); - - } else { - //used for parallaxlayer mirroring - for (int i = 0; i < l; i++) { - - const Canvas::ChildItem &ci2 = p_canvas->child_items[i]; - _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, p_transform, p_clip_rect, p_canvas->modulate, p_lights); - - //mirroring (useful for scrolling backgrounds) - if (ci2.mirror.x != 0) { - - Transform2D xform2 = p_transform * Transform2D(0, Vector2(ci2.mirror.x, 0)); - _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); - } - if (ci2.mirror.y != 0) { - - Transform2D xform2 = p_transform * Transform2D(0, Vector2(0, ci2.mirror.y)); - _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); - } - if (ci2.mirror.y != 0 && ci2.mirror.x != 0) { - - Transform2D xform2 = p_transform * Transform2D(0, ci2.mirror); - _render_canvas_item_tree(p_render_target, NULL, 0, ci2.item, xform2, p_clip_rect, p_canvas->modulate, p_lights); - } - } - } - - RENDER_TIMESTAMP("find_item(canvas_item); - ERR_FAIL_COND(idx == -1); - canvas->child_items.write[idx].mirror = p_mirroring; -} -void VisualServerCanvas::canvas_set_modulate(RID p_canvas, const Color &p_color) { - - Canvas *canvas = canvas_owner.getornull(p_canvas); - ERR_FAIL_COND(!canvas); - canvas->modulate = p_color; -} - -void VisualServerCanvas::canvas_set_disable_scale(bool p_disable) { - disable_scale = p_disable; -} - -void VisualServerCanvas::canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) { - - Canvas *canvas = canvas_owner.getornull(p_canvas); - ERR_FAIL_COND(!canvas); - - canvas->parent = p_parent; - canvas->parent_scale = p_scale; -} - -RID VisualServerCanvas::canvas_item_create() { - - Item *canvas_item = memnew(Item); - ERR_FAIL_COND_V(!canvas_item, RID()); - - return canvas_item_owner.make_rid(canvas_item); -} - -void VisualServerCanvas::canvas_item_set_parent(RID p_item, RID p_parent) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - if (canvas_item->parent.is_valid()) { - - if (canvas_owner.owns(canvas_item->parent)) { - - Canvas *canvas = canvas_owner.getornull(canvas_item->parent); - canvas->erase_item(canvas_item); - } else if (canvas_item_owner.owns(canvas_item->parent)) { - - Item *item_owner = canvas_item_owner.getornull(canvas_item->parent); - item_owner->child_items.erase(canvas_item); - - if (item_owner->sort_y) { - _mark_ysort_dirty(item_owner, canvas_item_owner); - } - } - - canvas_item->parent = RID(); - } - - if (p_parent.is_valid()) { - if (canvas_owner.owns(p_parent)) { - - Canvas *canvas = canvas_owner.getornull(p_parent); - Canvas::ChildItem ci; - ci.item = canvas_item; - canvas->child_items.push_back(ci); - canvas->children_order_dirty = true; - } else if (canvas_item_owner.owns(p_parent)) { - - Item *item_owner = canvas_item_owner.getornull(p_parent); - item_owner->child_items.push_back(canvas_item); - item_owner->children_order_dirty = true; - - if (item_owner->sort_y) { - _mark_ysort_dirty(item_owner, canvas_item_owner); - } - - } else { - - ERR_FAIL_MSG("Invalid parent."); - } - } - - canvas_item->parent = p_parent; -} -void VisualServerCanvas::canvas_item_set_visible(RID p_item, bool p_visible) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->visible = p_visible; - - _mark_ysort_dirty(canvas_item, canvas_item_owner); -} -void VisualServerCanvas::canvas_item_set_light_mask(RID p_item, int p_mask) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->light_mask = p_mask; -} - -void VisualServerCanvas::canvas_item_set_transform(RID p_item, const Transform2D &p_transform) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->xform = p_transform; -} -void VisualServerCanvas::canvas_item_set_clip(RID p_item, bool p_clip) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->clip = p_clip; -} -void VisualServerCanvas::canvas_item_set_distance_field_mode(RID p_item, bool p_enable) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->distance_field = p_enable; -} -void VisualServerCanvas::canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->custom_rect = p_custom_rect; - canvas_item->rect = p_rect; -} -void VisualServerCanvas::canvas_item_set_modulate(RID p_item, const Color &p_color) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->modulate = p_color; -} -void VisualServerCanvas::canvas_item_set_self_modulate(RID p_item, const Color &p_color) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->self_modulate = p_color; -} - -void VisualServerCanvas::canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->behind = p_enable; -} - -void VisualServerCanvas::canvas_item_set_update_when_visible(RID p_item, bool p_update) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->update_when_visible = p_update; -} - -void VisualServerCanvas::canvas_item_set_default_texture_filter(RID p_item, VS::CanvasItemTextureFilter p_filter) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - canvas_item->texture_filter = p_filter; -} - -void VisualServerCanvas::canvas_item_set_default_texture_repeat(RID p_item, VS::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - canvas_item->texture_repeat = p_repeat; -} - -void VisualServerCanvas::canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandPrimitive *line = canvas_item->alloc_command(); - ERR_FAIL_COND(!line); - if (p_width > 1.001) { - - Vector2 t = (p_from - p_to).tangent().normalized(); - line->points[0] = p_from + t * p_width; - line->points[1] = p_from - t * p_width; - line->points[2] = p_to - t * p_width; - line->points[3] = p_to + t * p_width; - line->point_count = 4; - } else { - line->point_count = 2; - line->points[0] = p_from; - line->points[1] = p_to; - } - for (uint32_t i = 0; i < line->point_count; i++) { - line->colors[i] = p_color; - } - line->specular_shininess = Color(1, 1, 1, 1); -} - -void VisualServerCanvas::canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width) { - - ERR_FAIL_COND(p_points.size() < 2); - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandPolygon *pline = canvas_item->alloc_command(); - ERR_FAIL_COND(!pline); - - pline->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); - - if (true || p_width <= 1) { -#define TODO make thick lines possible - Vector indices; - int pc = p_points.size(); - indices.resize((pc - 1) * 2); - { - int *iptr = indices.ptrw(); - for (int i = 0; i < (pc - 1); i++) { - iptr[i * 2 + 0] = i; - iptr[i * 2 + 1] = i + 1; - } - } - - pline->primitive = VS::PRIMITIVE_LINES; - pline->specular_shininess = Color(1, 1, 1, 1); - pline->polygon.create(indices, p_points, p_colors); - } else { -#if 0 - //make a trianglestrip for drawing the line... - Vector2 prev_t; - pline->triangles.resize(p_points.size() * 2); - if (p_antialiased) { - pline->lines.resize(p_points.size() * 2); - } - - if (p_colors.size() == 0) { - pline->triangle_colors.push_back(Color(1, 1, 1, 1)); - if (p_antialiased) { - pline->line_colors.push_back(Color(1, 1, 1, 1)); - } - } else if (p_colors.size() == 1) { - pline->triangle_colors = p_colors; - pline->line_colors = p_colors; - } else { - if (p_colors.size() != p_points.size()) { - pline->triangle_colors.push_back(p_colors[0]); - pline->line_colors.push_back(p_colors[0]); - } else { - pline->triangle_colors.resize(pline->triangles.size()); - pline->line_colors.resize(pline->lines.size()); - } - } - - for (int i = 0; i < p_points.size(); i++) { - - Vector2 t; - if (i == p_points.size() - 1) { - t = prev_t; - } else { - t = (p_points[i + 1] - p_points[i]).normalized().tangent(); - if (i == 0) { - prev_t = t; - } - } - - Vector2 tangent = ((t + prev_t).normalized()) * p_width * 0.5; - - if (p_antialiased) { - pline->lines.write[i] = p_points[i] + tangent; - pline->lines.write[p_points.size() * 2 - i - 1] = p_points[i] - tangent; - if (pline->line_colors.size() > 1) { - pline->line_colors.write[i] = p_colors[i]; - pline->line_colors.write[p_points.size() * 2 - i - 1] = p_colors[i]; - } - } - - pline->triangles.write[i * 2 + 0] = p_points[i] + tangent; - pline->triangles.write[i * 2 + 1] = p_points[i] - tangent; - - if (pline->triangle_colors.size() > 1) { - - pline->triangle_colors.write[i * 2 + 0] = p_colors[i]; - pline->triangle_colors.write[i * 2 + 1] = p_colors[i]; - } - - prev_t = t; - } -#endif - } -} - -void VisualServerCanvas::canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width) { - - ERR_FAIL_COND(p_points.size() < 2); - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandPolygon *pline = canvas_item->alloc_command(); - ERR_FAIL_COND(!pline); - - pline->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); - - if (true || p_width <= 1) { -#define TODO make thick lines possible - - pline->primitive = VS::PRIMITIVE_LINES; - pline->specular_shininess = Color(1, 1, 1, 1); - pline->polygon.create(Vector(), p_points, p_colors); - } else { - } -} - -void VisualServerCanvas::canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandRect *rect = canvas_item->alloc_command(); - ERR_FAIL_COND(!rect); - rect->modulate = p_color; - rect->rect = p_rect; -} - -void VisualServerCanvas::canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandPolygon *circle = canvas_item->alloc_command(); - ERR_FAIL_COND(!circle); - - circle->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, RID(), RID(), RID(), VS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, VS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, RID()); - - circle->primitive = VS::PRIMITIVE_TRIANGLES; - circle->specular_shininess = Color(1, 1, 1, 1); - - Vector indices; - Vector points; - - static const int circle_points = 64; - - points.resize(circle_points); - for (int i = 0; i < circle_points; i++) { - float angle = (i / float(circle_points)) * 2 * Math_PI; - points.write[i].x = Math::cos(angle) * p_radius; - points.write[i].y = Math::sin(angle) * p_radius; - points.write[i] += p_pos; - } - indices.resize((circle_points - 2) * 3); - - for (int i = 0; i < circle_points - 2; i++) { - indices.write[i * 3 + 0] = 0; - indices.write[i * 3 + 1] = i + 1; - indices.write[i * 3 + 2] = i + 2; - } - - Vector color; - color.push_back(p_color); - circle->polygon.create(indices, points, color); -} - -void VisualServerCanvas::canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandRect *rect = canvas_item->alloc_command(); - ERR_FAIL_COND(!rect); - rect->modulate = p_modulate; - rect->rect = p_rect; - rect->flags = 0; - if (p_tile) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_TILE; - rect->flags |= RasterizerCanvas::CANVAS_RECT_REGION; - rect->source = Rect2(0, 0, fabsf(p_rect.size.width), fabsf(p_rect.size.height)); - } - - if (p_rect.size.x < 0) { - - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; - rect->rect.size.x = -rect->rect.size.x; - } - if (p_rect.size.y < 0) { - - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; - rect->rect.size.y = -rect->rect.size.y; - } - if (p_transpose) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; - SWAP(rect->rect.size.x, rect->rect.size.y); - } - rect->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - rect->specular_shininess = p_specular_color_shininess; -} - -void VisualServerCanvas::canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate, bool p_transpose, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, bool p_clip_uv, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandRect *rect = canvas_item->alloc_command(); - ERR_FAIL_COND(!rect); - rect->modulate = p_modulate; - rect->rect = p_rect; - rect->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - rect->specular_shininess = p_specular_color_shininess; - rect->source = p_src_rect; - rect->flags = RasterizerCanvas::CANVAS_RECT_REGION; - - if (p_rect.size.x < 0) { - - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_H; - rect->rect.size.x = -rect->rect.size.x; - } - if (p_src_rect.size.x < 0) { - - rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_H; - rect->source.size.x = -rect->source.size.x; - } - if (p_rect.size.y < 0) { - - rect->flags |= RasterizerCanvas::CANVAS_RECT_FLIP_V; - rect->rect.size.y = -rect->rect.size.y; - } - if (p_src_rect.size.y < 0) { - - rect->flags ^= RasterizerCanvas::CANVAS_RECT_FLIP_V; - rect->source.size.y = -rect->source.size.y; - } - - if (p_transpose) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_TRANSPOSE; - SWAP(rect->rect.size.x, rect->rect.size.y); - } - - if (p_clip_uv) { - rect->flags |= RasterizerCanvas::CANVAS_RECT_CLIP_UV; - } -} - -void VisualServerCanvas::canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, VS::NinePatchAxisMode p_x_axis_mode, VS::NinePatchAxisMode p_y_axis_mode, bool p_draw_center, const Color &p_modulate, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandNinePatch *style = canvas_item->alloc_command(); - ERR_FAIL_COND(!style); - style->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - style->specular_shininess = p_specular_color_shininess; - style->rect = p_rect; - style->source = p_source; - style->draw_center = p_draw_center; - style->color = p_modulate; - style->margin[MARGIN_LEFT] = p_topleft.x; - style->margin[MARGIN_TOP] = p_topleft.y; - style->margin[MARGIN_RIGHT] = p_bottomright.x; - style->margin[MARGIN_BOTTOM] = p_bottomright.y; - style->axis_x = p_x_axis_mode; - style->axis_y = p_y_axis_mode; -} -void VisualServerCanvas::canvas_item_add_primitive(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, float p_width, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - uint32_t pc = p_points.size(); - ERR_FAIL_COND(pc == 0 || pc > 4); - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandPrimitive *prim = canvas_item->alloc_command(); - ERR_FAIL_COND(!prim); - - for (int i = 0; i < p_points.size(); i++) { - prim->points[i] = p_points[i]; - if (i < p_uvs.size()) { - prim->uvs[i] = p_uvs[i]; - } - if (i < p_colors.size()) { - prim->colors[i] = p_colors[i]; - } else if (p_colors.size()) { - prim->colors[i] = p_colors[0]; - } else { - prim->colors[i] = Color(1, 1, 1, 1); - } - } - - prim->point_count = p_points.size(); - - prim->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - prim->specular_shininess = p_specular_color_shininess; -} - -void VisualServerCanvas::canvas_item_add_polygon(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); -#ifdef DEBUG_ENABLED - int pointcount = p_points.size(); - ERR_FAIL_COND(pointcount < 3); - int color_size = p_colors.size(); - int uv_size = p_uvs.size(); - ERR_FAIL_COND(color_size != 0 && color_size != 1 && color_size != pointcount); - ERR_FAIL_COND(uv_size != 0 && (uv_size != pointcount)); -#endif - Vector indices = Geometry::triangulate_polygon(p_points); - ERR_FAIL_COND_MSG(indices.empty(), "Invalid polygon data, triangulation failed."); - - Item::CommandPolygon *polygon = canvas_item->alloc_command(); - ERR_FAIL_COND(!polygon); - polygon->primitive = VS::PRIMITIVE_TRIANGLES; - polygon->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - polygon->specular_shininess = p_specular_color_shininess; - polygon->polygon.create(indices, p_points, p_colors, p_uvs); -} - -void VisualServerCanvas::canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, const Vector &p_bones, const Vector &p_weights, RID p_texture, int p_count, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - int vertex_count = p_points.size(); - ERR_FAIL_COND(vertex_count == 0); - ERR_FAIL_COND(!p_colors.empty() && p_colors.size() != vertex_count && p_colors.size() != 1); - ERR_FAIL_COND(!p_uvs.empty() && p_uvs.size() != vertex_count); - ERR_FAIL_COND(!p_bones.empty() && p_bones.size() != vertex_count * 4); - ERR_FAIL_COND(!p_weights.empty() && p_weights.size() != vertex_count * 4); - - Vector indices = p_indices; - - Item::CommandPolygon *polygon = canvas_item->alloc_command(); - ERR_FAIL_COND(!polygon); - polygon->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - polygon->specular_shininess = p_specular_color_shininess; - polygon->polygon.create(indices, p_points, p_colors, p_uvs, p_bones, p_weights); - - polygon->primitive = VS::PRIMITIVE_TRIANGLES; -} - -void VisualServerCanvas::canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandTransform *tr = canvas_item->alloc_command(); - ERR_FAIL_COND(!tr); - tr->xform = p_transform; -} - -void VisualServerCanvas::canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform, const Color &p_modulate, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandMesh *m = canvas_item->alloc_command(); - ERR_FAIL_COND(!m); - m->mesh = p_mesh; - m->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - m->specular_shininess = p_specular_color_shininess; - m->transform = p_transform; - m->modulate = p_modulate; -} -void VisualServerCanvas::canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandParticles *part = canvas_item->alloc_command(); - ERR_FAIL_COND(!part); - part->particles = p_particles; - part->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, RID()); - part->specular_shininess = p_specular_color_shininess; - - //take the chance and request processing for them, at least once until they become visible again - VSG::storage->particles_request_process(p_particles); -} - -void VisualServerCanvas::canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture, RID p_normal_map, RID p_specular_map, const Color &p_specular_color_shininess, VisualServer::CanvasItemTextureFilter p_filter, VisualServer::CanvasItemTextureRepeat p_repeat) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandMultiMesh *mm = canvas_item->alloc_command(); - ERR_FAIL_COND(!mm); - mm->multimesh = p_mesh; - mm->texture_binding.create(canvas_item->texture_filter, canvas_item->texture_repeat, p_texture, p_normal_map, p_specular_map, p_filter, p_repeat, mm->multimesh); - mm->specular_shininess = p_specular_color_shininess; -} - -void VisualServerCanvas::canvas_item_add_clip_ignore(RID p_item, bool p_ignore) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - Item::CommandClipIgnore *ci = canvas_item->alloc_command(); - ERR_FAIL_COND(!ci); - ci->ignore = p_ignore; -} -void VisualServerCanvas::canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->sort_y = p_enable; - - _mark_ysort_dirty(canvas_item, canvas_item_owner); -} -void VisualServerCanvas::canvas_item_set_z_index(RID p_item, int p_z) { - - ERR_FAIL_COND(p_z < VS::CANVAS_ITEM_Z_MIN || p_z > VS::CANVAS_ITEM_Z_MAX); - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->z_index = p_z; -} -void VisualServerCanvas::canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->z_relative = p_enable; -} - -void VisualServerCanvas::canvas_item_attach_skeleton(RID p_item, RID p_skeleton) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->skeleton = p_skeleton; -} - -void VisualServerCanvas::canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - if (bool(canvas_item->copy_back_buffer != NULL) != p_enable) { - if (p_enable) { - canvas_item->copy_back_buffer = memnew(RasterizerCanvas::Item::CopyBackBuffer); - } else { - memdelete(canvas_item->copy_back_buffer); - canvas_item->copy_back_buffer = NULL; - } - } - - if (p_enable) { - canvas_item->copy_back_buffer->rect = p_rect; - canvas_item->copy_back_buffer->full = p_rect == Rect2(); - } -} - -void VisualServerCanvas::canvas_item_clear(RID p_item) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->clear(); -} -void VisualServerCanvas::canvas_item_set_draw_index(RID p_item, int p_index) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->index = p_index; - - if (canvas_item_owner.owns(canvas_item->parent)) { - Item *canvas_item_parent = canvas_item_owner.getornull(canvas_item->parent); - canvas_item_parent->children_order_dirty = true; - return; - } - - Canvas *canvas = canvas_owner.getornull(canvas_item->parent); - if (canvas) { - canvas->children_order_dirty = true; - return; - } -} - -void VisualServerCanvas::canvas_item_set_material(RID p_item, RID p_material) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->material = p_material; -} - -void VisualServerCanvas::canvas_item_set_use_parent_material(RID p_item, bool p_enable) { - - Item *canvas_item = canvas_item_owner.getornull(p_item); - ERR_FAIL_COND(!canvas_item); - - canvas_item->use_parent_material = p_enable; -} - -RID VisualServerCanvas::canvas_light_create() { - - RasterizerCanvas::Light *clight = memnew(RasterizerCanvas::Light); - clight->light_internal = VSG::canvas_render->light_create(); - return canvas_light_owner.make_rid(clight); -} -void VisualServerCanvas::canvas_light_attach_to_canvas(RID p_light, RID p_canvas) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - if (clight->canvas.is_valid()) { - - Canvas *canvas = canvas_owner.getornull(clight->canvas); - canvas->lights.erase(clight); - } - - if (!canvas_owner.owns(p_canvas)) - p_canvas = RID(); - - clight->canvas = p_canvas; - - if (clight->canvas.is_valid()) { - - Canvas *canvas = canvas_owner.getornull(clight->canvas); - canvas->lights.insert(clight); - } -} - -void VisualServerCanvas::canvas_light_set_enabled(RID p_light, bool p_enabled) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->enabled = p_enabled; -} -void VisualServerCanvas::canvas_light_set_scale(RID p_light, float p_scale) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->scale = p_scale; -} -void VisualServerCanvas::canvas_light_set_transform(RID p_light, const Transform2D &p_transform) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->xform = p_transform; -} -void VisualServerCanvas::canvas_light_set_texture(RID p_light, RID p_texture) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->texture = p_texture; - clight->version++; - VSG::canvas_render->light_set_texture(clight->light_internal, p_texture); -} -void VisualServerCanvas::canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->texture_offset = p_offset; -} -void VisualServerCanvas::canvas_light_set_color(RID p_light, const Color &p_color) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->color = p_color; -} -void VisualServerCanvas::canvas_light_set_height(RID p_light, float p_height) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->height = p_height; -} -void VisualServerCanvas::canvas_light_set_energy(RID p_light, float p_energy) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->energy = p_energy; -} -void VisualServerCanvas::canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->z_min = p_min_z; - clight->z_max = p_max_z; -} -void VisualServerCanvas::canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->layer_max = p_max_layer; - clight->layer_min = p_min_layer; -} -void VisualServerCanvas::canvas_light_set_item_cull_mask(RID p_light, int p_mask) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->item_mask = p_mask; -} -void VisualServerCanvas::canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->item_shadow_mask = p_mask; -} -void VisualServerCanvas::canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->mode = p_mode; -} - -void VisualServerCanvas::canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - if (clight->use_shadow == p_enabled) { - return; - } - clight->use_shadow = p_enabled; - clight->version++; - VSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); -} - -void VisualServerCanvas::canvas_light_set_shadow_buffer_size(RID p_light, int p_size) { - - ERR_FAIL_COND(p_size < 32 || p_size > 16384); - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - int new_size = next_power_of_2(p_size); - if (new_size == clight->shadow_buffer_size) - return; - - clight->shadow_buffer_size = next_power_of_2(p_size); - clight->version++; - - VSG::canvas_render->light_set_use_shadow(clight->light_internal, clight->use_shadow, clight->shadow_buffer_size); -} - -void VisualServerCanvas::canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->shadow_filter = p_filter; -} -void VisualServerCanvas::canvas_light_set_shadow_color(RID p_light, const Color &p_color) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - - clight->shadow_color = p_color; -} - -void VisualServerCanvas::canvas_light_set_shadow_smooth(RID p_light, float p_smooth) { - - RasterizerCanvas::Light *clight = canvas_light_owner.getornull(p_light); - ERR_FAIL_COND(!clight); - clight->shadow_smooth = p_smooth; -} - -RID VisualServerCanvas::canvas_light_occluder_create() { - - RasterizerCanvas::LightOccluderInstance *occluder = memnew(RasterizerCanvas::LightOccluderInstance); - - return canvas_light_occluder_owner.make_rid(occluder); -} -void VisualServerCanvas::canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) { - - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); - ERR_FAIL_COND(!occluder); - - if (occluder->canvas.is_valid()) { - - Canvas *canvas = canvas_owner.getornull(occluder->canvas); - canvas->occluders.erase(occluder); - } - - if (!canvas_owner.owns(p_canvas)) - p_canvas = RID(); - - occluder->canvas = p_canvas; - - if (occluder->canvas.is_valid()) { - - Canvas *canvas = canvas_owner.getornull(occluder->canvas); - canvas->occluders.insert(occluder); - } -} -void VisualServerCanvas::canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) { - - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); - ERR_FAIL_COND(!occluder); - - occluder->enabled = p_enabled; -} -void VisualServerCanvas::canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) { - - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); - ERR_FAIL_COND(!occluder); - - if (occluder->polygon.is_valid()) { - LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon); - if (occluder_poly) { - occluder_poly->owners.erase(occluder); - } - } - - occluder->polygon = p_polygon; - occluder->occluder = RID(); - - if (occluder->polygon.is_valid()) { - LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_polygon); - if (!occluder_poly) { - occluder->polygon = RID(); - ERR_FAIL_COND(!occluder_poly); - } else { - occluder_poly->owners.insert(occluder); - occluder->occluder = occluder_poly->occluder; - occluder->aabb_cache = occluder_poly->aabb; - occluder->cull_cache = occluder_poly->cull_mode; - } - } -} -void VisualServerCanvas::canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) { - - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); - ERR_FAIL_COND(!occluder); - - occluder->xform = p_xform; -} -void VisualServerCanvas::canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) { - - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_occluder); - ERR_FAIL_COND(!occluder); - - occluder->light_mask = p_mask; -} - -RID VisualServerCanvas::canvas_occluder_polygon_create() { - - LightOccluderPolygon *occluder_poly = memnew(LightOccluderPolygon); - occluder_poly->occluder = VSG::canvas_render->occluder_polygon_create(); - return canvas_light_occluder_polygon_owner.make_rid(occluder_poly); -} -void VisualServerCanvas::canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector &p_shape, bool p_closed) { - - if (p_shape.size() < 3) { - canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, p_shape); - return; - } - - Vector lines; - int lc = p_shape.size() * 2; - - lines.resize(lc - (p_closed ? 0 : 2)); - { - Vector2 *w = lines.ptrw(); - const Vector2 *r = p_shape.ptr(); - - int max = lc / 2; - if (!p_closed) { - max--; - } - for (int i = 0; i < max; i++) { - - Vector2 a = r[i]; - Vector2 b = r[(i + 1) % (lc / 2)]; - w[i * 2 + 0] = a; - w[i * 2 + 1] = b; - } - } - - canvas_occluder_polygon_set_shape_as_lines(p_occluder_polygon, lines); -} -void VisualServerCanvas::canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector &p_shape) { - - LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); - ERR_FAIL_COND(!occluder_poly); - ERR_FAIL_COND(p_shape.size() & 1); - - int lc = p_shape.size(); - occluder_poly->aabb = Rect2(); - { - const Vector2 *r = p_shape.ptr(); - for (int i = 0; i < lc; i++) { - if (i == 0) - occluder_poly->aabb.position = r[i]; - else - occluder_poly->aabb.expand_to(r[i]); - } - } - - VSG::canvas_render->occluder_polygon_set_shape_as_lines(occluder_poly->occluder, p_shape); - for (Set::Element *E = occluder_poly->owners.front(); E; E = E->next()) { - E->get()->aabb_cache = occluder_poly->aabb; - } -} - -void VisualServerCanvas::canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, VS::CanvasOccluderPolygonCullMode p_mode) { - - LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_occluder_polygon); - ERR_FAIL_COND(!occluder_poly); - occluder_poly->cull_mode = p_mode; - VSG::canvas_render->occluder_polygon_set_cull_mode(occluder_poly->occluder, p_mode); - for (Set::Element *E = occluder_poly->owners.front(); E; E = E->next()) { - E->get()->cull_cache = p_mode; - } -} - -bool VisualServerCanvas::free(RID p_rid) { - - if (canvas_owner.owns(p_rid)) { - - Canvas *canvas = canvas_owner.getornull(p_rid); - ERR_FAIL_COND_V(!canvas, false); - - while (canvas->viewports.size()) { - - VisualServerViewport::Viewport *vp = VSG::viewport->viewport_owner.getornull(canvas->viewports.front()->get()); - ERR_FAIL_COND_V(!vp, true); - - Map::Element *E = vp->canvas_map.find(p_rid); - ERR_FAIL_COND_V(!E, true); - vp->canvas_map.erase(p_rid); - - canvas->viewports.erase(canvas->viewports.front()); - } - - for (int i = 0; i < canvas->child_items.size(); i++) { - - canvas->child_items[i].item->parent = RID(); - } - - for (Set::Element *E = canvas->lights.front(); E; E = E->next()) { - - E->get()->canvas = RID(); - } - - for (Set::Element *E = canvas->occluders.front(); E; E = E->next()) { - - E->get()->canvas = RID(); - } - - canvas_owner.free(p_rid); - - memdelete(canvas); - - } else if (canvas_item_owner.owns(p_rid)) { - - Item *canvas_item = canvas_item_owner.getornull(p_rid); - ERR_FAIL_COND_V(!canvas_item, true); - - if (canvas_item->parent.is_valid()) { - - if (canvas_owner.owns(canvas_item->parent)) { - - Canvas *canvas = canvas_owner.getornull(canvas_item->parent); - canvas->erase_item(canvas_item); - } else if (canvas_item_owner.owns(canvas_item->parent)) { - - Item *item_owner = canvas_item_owner.getornull(canvas_item->parent); - item_owner->child_items.erase(canvas_item); - - if (item_owner->sort_y) { - _mark_ysort_dirty(item_owner, canvas_item_owner); - } - } - } - - for (int i = 0; i < canvas_item->child_items.size(); i++) { - - canvas_item->child_items[i]->parent = RID(); - } - - /* - if (canvas_item->material) { - canvas_item->material->owners.erase(canvas_item); - } - */ - - canvas_item_owner.free(p_rid); - - memdelete(canvas_item); - - } else if (canvas_light_owner.owns(p_rid)) { - - RasterizerCanvas::Light *canvas_light = canvas_light_owner.getornull(p_rid); - ERR_FAIL_COND_V(!canvas_light, true); - - if (canvas_light->canvas.is_valid()) { - Canvas *canvas = canvas_owner.getornull(canvas_light->canvas); - if (canvas) - canvas->lights.erase(canvas_light); - } - - VSG::canvas_render->free(canvas_light->light_internal); - - canvas_light_owner.free(p_rid); - memdelete(canvas_light); - - } else if (canvas_light_occluder_owner.owns(p_rid)) { - - RasterizerCanvas::LightOccluderInstance *occluder = canvas_light_occluder_owner.getornull(p_rid); - ERR_FAIL_COND_V(!occluder, true); - - if (occluder->polygon.is_valid()) { - - LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(occluder->polygon); - if (occluder_poly) { - occluder_poly->owners.erase(occluder); - } - } - - if (occluder->canvas.is_valid() && canvas_owner.owns(occluder->canvas)) { - - Canvas *canvas = canvas_owner.getornull(occluder->canvas); - canvas->occluders.erase(occluder); - } - - canvas_light_occluder_owner.free(p_rid); - memdelete(occluder); - - } else if (canvas_light_occluder_polygon_owner.owns(p_rid)) { - - LightOccluderPolygon *occluder_poly = canvas_light_occluder_polygon_owner.getornull(p_rid); - ERR_FAIL_COND_V(!occluder_poly, true); - VSG::canvas_render->free(occluder_poly->occluder); - - while (occluder_poly->owners.size()) { - - occluder_poly->owners.front()->get()->polygon = RID(); - occluder_poly->owners.erase(occluder_poly->owners.front()); - } - - canvas_light_occluder_polygon_owner.free(p_rid); - memdelete(occluder_poly); - } else { - return false; - } - - return true; -} - -VisualServerCanvas::VisualServerCanvas() { - - z_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); - z_last_list = (RasterizerCanvas::Item **)memalloc(z_range * sizeof(RasterizerCanvas::Item *)); - - disable_scale = false; -} - -VisualServerCanvas::~VisualServerCanvas() { - - memfree(z_list); - memfree(z_last_list); -} diff --git a/servers/visual/visual_server_canvas.h b/servers/visual/visual_server_canvas.h deleted file mode 100644 index dea4183752..0000000000 --- a/servers/visual/visual_server_canvas.h +++ /dev/null @@ -1,270 +0,0 @@ -/*************************************************************************/ -/* visual_server_canvas.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUALSERVERCANVAS_H -#define VISUALSERVERCANVAS_H - -#include "rasterizer.h" -#include "visual_server_viewport.h" - -class VisualServerCanvas { -public: - struct Item : public RasterizerCanvas::Item { - - RID parent; // canvas it belongs to - List::Element *E; - int z_index; - bool z_relative; - bool sort_y; - Color modulate; - Color self_modulate; - bool use_parent_material; - int index; - bool children_order_dirty; - int ysort_children_count; - Color ysort_modulate; - Transform2D ysort_xform; - Vector2 ysort_pos; - VS::CanvasItemTextureFilter texture_filter; - VS::CanvasItemTextureRepeat texture_repeat; - - Vector child_items; - - Item() { - children_order_dirty = true; - E = NULL; - z_index = 0; - modulate = Color(1, 1, 1, 1); - self_modulate = Color(1, 1, 1, 1); - sort_y = false; - use_parent_material = false; - z_relative = true; - index = 0; - ysort_children_count = -1; - ysort_xform = Transform2D(); - ysort_pos = Vector2(); - texture_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT; - texture_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT; - } - }; - - struct ItemIndexSort { - - _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { - - return p_left->index < p_right->index; - } - }; - - struct ItemPtrSort { - - _FORCE_INLINE_ bool operator()(const Item *p_left, const Item *p_right) const { - - if (Math::is_equal_approx(p_left->ysort_pos.y, p_right->ysort_pos.y)) - return p_left->ysort_pos.x < p_right->ysort_pos.x; - - return p_left->ysort_pos.y < p_right->ysort_pos.y; - } - }; - - struct LightOccluderPolygon { - - bool active; - Rect2 aabb; - VS::CanvasOccluderPolygonCullMode cull_mode; - RID occluder; - Set owners; - - LightOccluderPolygon() { - active = false; - cull_mode = VS::CANVAS_OCCLUDER_POLYGON_CULL_DISABLED; - } - }; - - RID_PtrOwner canvas_light_occluder_polygon_owner; - - RID_PtrOwner canvas_light_occluder_owner; - - struct Canvas : public VisualServerViewport::CanvasBase { - - Set viewports; - struct ChildItem { - - Point2 mirror; - Item *item; - bool operator<(const ChildItem &p_item) const { - return item->index < p_item.item->index; - } - }; - - Set lights; - - Set occluders; - - bool children_order_dirty; - Vector child_items; - Color modulate; - RID parent; - float parent_scale; - - int find_item(Item *p_item) { - for (int i = 0; i < child_items.size(); i++) { - if (child_items[i].item == p_item) - return i; - } - return -1; - } - void erase_item(Item *p_item) { - int idx = find_item(p_item); - if (idx >= 0) - child_items.remove(idx); - } - - Canvas() { - modulate = Color(1, 1, 1, 1); - children_order_dirty = true; - parent_scale = 1.0; - } - }; - - mutable RID_PtrOwner canvas_owner; - RID_PtrOwner canvas_item_owner; - RID_PtrOwner canvas_light_owner; - - bool disable_scale; - -private: - void _render_canvas_item_tree(RID p_to_render_target, Canvas::ChildItem *p_child_items, int p_child_item_count, Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, RasterizerCanvas::Light *p_lights); - void _cull_canvas_item(Item *p_canvas_item, const Transform2D &p_transform, const Rect2 &p_clip_rect, const Color &p_modulate, int p_z, RasterizerCanvas::Item **z_list, RasterizerCanvas::Item **z_last_list, Item *p_canvas_clip, Item *p_material_owner); - void _light_mask_canvas_items(int p_z, RasterizerCanvas::Item *p_canvas_item, RasterizerCanvas::Light *p_masked_lights); - - RasterizerCanvas::Item **z_list; - RasterizerCanvas::Item **z_last_list; - -public: - void render_canvas(RID p_render_target, Canvas *p_canvas, const Transform2D &p_transform, RasterizerCanvas::Light *p_lights, RasterizerCanvas::Light *p_masked_lights, const Rect2 &p_clip_rect); - - RID canvas_create(); - void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring); - void canvas_set_modulate(RID p_canvas, const Color &p_color); - void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale); - void canvas_set_disable_scale(bool p_disable); - - RID canvas_item_create(); - void canvas_item_set_parent(RID p_item, RID p_parent); - - void canvas_item_set_visible(RID p_item, bool p_visible); - void canvas_item_set_light_mask(RID p_item, int p_mask); - - void canvas_item_set_transform(RID p_item, const Transform2D &p_transform); - void canvas_item_set_clip(RID p_item, bool p_clip); - void canvas_item_set_distance_field_mode(RID p_item, bool p_enable); - void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()); - void canvas_item_set_modulate(RID p_item, const Color &p_color); - void canvas_item_set_self_modulate(RID p_item, const Color &p_color); - - void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable); - - void canvas_item_set_update_when_visible(RID p_item, bool p_update); - - void canvas_item_set_default_texture_filter(RID p_item, VS::CanvasItemTextureFilter p_filter); - void canvas_item_set_default_texture_repeat(RID p_item, VS::CanvasItemTextureRepeat p_repeat); - - void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0); - void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0); - void canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0); - void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color); - void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color); - void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, VS::NinePatchAxisMode p_x_axis_mode = VS::NINE_PATCH_STRETCH, VS::NinePatchAxisMode p_y_axis_mode = VS::NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_primitive(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_polygon(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), VS::CanvasItemTextureFilter p_filter = VS::CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, VS::CanvasItemTextureRepeat p_repeat = VS::CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform); - void canvas_item_add_clip_ignore(RID p_item, bool p_ignore); - void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable); - void canvas_item_set_z_index(RID p_item, int p_z); - void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable); - void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect); - void canvas_item_attach_skeleton(RID p_item, RID p_skeleton); - - void canvas_item_clear(RID p_item); - void canvas_item_set_draw_index(RID p_item, int p_index); - - void canvas_item_set_material(RID p_item, RID p_material); - - void canvas_item_set_use_parent_material(RID p_item, bool p_enable); - - RID canvas_light_create(); - void canvas_light_attach_to_canvas(RID p_light, RID p_canvas); - void canvas_light_set_enabled(RID p_light, bool p_enabled); - void canvas_light_set_scale(RID p_light, float p_scale); - void canvas_light_set_transform(RID p_light, const Transform2D &p_transform); - void canvas_light_set_texture(RID p_light, RID p_texture); - void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset); - void canvas_light_set_color(RID p_light, const Color &p_color); - void canvas_light_set_height(RID p_light, float p_height); - void canvas_light_set_energy(RID p_light, float p_energy); - void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z); - void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer); - void canvas_light_set_item_cull_mask(RID p_light, int p_mask); - void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask); - - void canvas_light_set_mode(RID p_light, VS::CanvasLightMode p_mode); - - void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled); - void canvas_light_set_shadow_buffer_size(RID p_light, int p_size); - void canvas_light_set_shadow_filter(RID p_light, VS::CanvasLightShadowFilter p_filter); - void canvas_light_set_shadow_color(RID p_light, const Color &p_color); - void canvas_light_set_shadow_smooth(RID p_light, float p_smooth); - - RID canvas_light_occluder_create(); - void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas); - void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled); - void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon); - void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform); - void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask); - - RID canvas_occluder_polygon_create(); - void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector &p_shape, bool p_closed); - void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector &p_shape); - - void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, VS::CanvasOccluderPolygonCullMode p_mode); - - bool free(RID p_rid); - VisualServerCanvas(); - ~VisualServerCanvas(); -}; - -#endif // VISUALSERVERCANVAS_H diff --git a/servers/visual/visual_server_globals.cpp b/servers/visual/visual_server_globals.cpp deleted file mode 100644 index 248d27e08a..0000000000 --- a/servers/visual/visual_server_globals.cpp +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************/ -/* visual_server_globals.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server_globals.h" - -RasterizerStorage *VisualServerGlobals::storage = NULL; -RasterizerCanvas *VisualServerGlobals::canvas_render = NULL; -RasterizerScene *VisualServerGlobals::scene_render = NULL; -Rasterizer *VisualServerGlobals::rasterizer = NULL; - -VisualServerCanvas *VisualServerGlobals::canvas = NULL; -VisualServerViewport *VisualServerGlobals::viewport = NULL; -VisualServerScene *VisualServerGlobals::scene = NULL; diff --git a/servers/visual/visual_server_globals.h b/servers/visual/visual_server_globals.h deleted file mode 100644 index 5a9d365eca..0000000000 --- a/servers/visual/visual_server_globals.h +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************/ -/* visual_server_globals.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUAL_SERVER_GLOBALS_H -#define VISUAL_SERVER_GLOBALS_H - -#include "rasterizer.h" - -class VisualServerCanvas; -class VisualServerViewport; -class VisualServerScene; - -class VisualServerGlobals { -public: - static RasterizerStorage *storage; - static RasterizerCanvas *canvas_render; - static RasterizerScene *scene_render; - static Rasterizer *rasterizer; - - static VisualServerCanvas *canvas; - static VisualServerViewport *viewport; - static VisualServerScene *scene; -}; - -#define VSG VisualServerGlobals - -#endif // VISUAL_SERVER_GLOBALS_H diff --git a/servers/visual/visual_server_raster.cpp b/servers/visual/visual_server_raster.cpp deleted file mode 100644 index 1026972a62..0000000000 --- a/servers/visual/visual_server_raster.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/*************************************************************************/ -/* visual_server_raster.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server_raster.h" - -#include "core/io/marshalls.h" -#include "core/os/os.h" -#include "core/project_settings.h" -#include "core/sort_array.h" -#include "visual_server_canvas.h" -#include "visual_server_globals.h" -#include "visual_server_scene.h" - -// careful, these may run in different threads than the visual server - -int VisualServerRaster::changes = 0; - -/* BLACK BARS */ - -void VisualServerRaster::black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) { - - black_margin[MARGIN_LEFT] = p_left; - black_margin[MARGIN_TOP] = p_top; - black_margin[MARGIN_RIGHT] = p_right; - black_margin[MARGIN_BOTTOM] = p_bottom; -} - -void VisualServerRaster::black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) { - - black_image[MARGIN_LEFT] = p_left; - black_image[MARGIN_TOP] = p_top; - black_image[MARGIN_RIGHT] = p_right; - black_image[MARGIN_BOTTOM] = p_bottom; -} - -void VisualServerRaster::_draw_margins() { - - VSG::canvas_render->draw_window_margins(black_margin, black_image); -}; - -/* FREE */ - -void VisualServerRaster::free(RID p_rid) { - - if (VSG::storage->free(p_rid)) - return; - if (VSG::canvas->free(p_rid)) - return; - if (VSG::viewport->free(p_rid)) - return; - if (VSG::scene->free(p_rid)) - return; - if (VSG::scene_render->free(p_rid)) - return; -} - -/* EVENT QUEUING */ - -void VisualServerRaster::request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) { - - ERR_FAIL_NULL(p_where); - FrameDrawnCallbacks fdc; - fdc.object = p_where->get_instance_id(); - fdc.method = p_method; - fdc.param = p_userdata; - - frame_drawn_callbacks.push_back(fdc); -} - -void VisualServerRaster::draw(bool p_swap_buffers, double frame_step) { - - //needs to be done before changes is reset to 0, to not force the editor to redraw - VS::get_singleton()->emit_signal("frame_pre_draw"); - - changes = 0; - - VSG::rasterizer->begin_frame(frame_step); - - TIMESTAMP_BEGIN() - - VSG::scene_render->update(); //update scenes stuff before updating instances - - VSG::scene->update_dirty_instances(); //update scene stuff - - VSG::scene->render_probes(); - VSG::viewport->draw_viewports(); - VSG::canvas_render->update(); - - _draw_margins(); - VSG::rasterizer->end_frame(p_swap_buffers); - - while (frame_drawn_callbacks.front()) { - - Object *obj = ObjectDB::get_instance(frame_drawn_callbacks.front()->get().object); - if (obj) { - Callable::CallError ce; - const Variant *v = &frame_drawn_callbacks.front()->get().param; - obj->call(frame_drawn_callbacks.front()->get().method, &v, 1, ce); - if (ce.error != Callable::CallError::CALL_OK) { - String err = Variant::get_call_error_text(obj, frame_drawn_callbacks.front()->get().method, &v, 1, ce); - ERR_PRINT("Error calling frame drawn function: " + err); - } - } - - frame_drawn_callbacks.pop_front(); - } - VS::get_singleton()->emit_signal("frame_post_draw"); - - if (VSG::storage->get_captured_timestamps_count()) { - Vector new_profile; - new_profile.resize(VSG::storage->get_captured_timestamps_count()); - - uint64_t base_cpu = VSG::storage->get_captured_timestamp_cpu_time(0); - uint64_t base_gpu = VSG::storage->get_captured_timestamp_gpu_time(0); - for (uint32_t i = 0; i < VSG::storage->get_captured_timestamps_count(); i++) { - uint64_t time_cpu = VSG::storage->get_captured_timestamp_cpu_time(i) - base_cpu; - uint64_t time_gpu = VSG::storage->get_captured_timestamp_gpu_time(i) - base_gpu; - new_profile.write[i].gpu_msec = float(time_gpu / 1000) / 1000.0; - new_profile.write[i].cpu_msec = float(time_cpu) / 1000.0; - new_profile.write[i].name = VSG::storage->get_captured_timestamp_name(i); - } - - frame_profile = new_profile; - } - - frame_profile_frame = VSG::storage->get_captured_timestamps_frame(); -} -void VisualServerRaster::sync() { -} -bool VisualServerRaster::has_changed() const { - - return changes > 0; -} -void VisualServerRaster::init() { - - VSG::rasterizer->initialize(); -} -void VisualServerRaster::finish() { - - if (test_cube.is_valid()) { - free(test_cube); - } - - VSG::rasterizer->finalize(); -} - -/* STATUS INFORMATION */ - -int VisualServerRaster::get_render_info(RenderInfo p_info) { - - return VSG::storage->get_render_info(p_info); -} - -String VisualServerRaster::get_video_adapter_name() const { - - return VSG::storage->get_video_adapter_name(); -} - -String VisualServerRaster::get_video_adapter_vendor() const { - - return VSG::storage->get_video_adapter_vendor(); -} - -void VisualServerRaster::set_frame_profiling_enabled(bool p_enable) { - VSG::storage->capturing_timestamps = p_enable; -} - -uint64_t VisualServerRaster::get_frame_profile_frame() { - return frame_profile_frame; -} - -Vector VisualServerRaster::get_frame_profile() { - return frame_profile; -} - -/* TESTING */ - -void VisualServerRaster::set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter) { - - redraw_request(); - VSG::rasterizer->set_boot_image(p_image, p_color, p_scale, p_use_filter); -} -void VisualServerRaster::set_default_clear_color(const Color &p_color) { - VSG::viewport->set_default_clear_color(p_color); -} - -bool VisualServerRaster::has_feature(Features p_feature) const { - - return false; -} - -RID VisualServerRaster::get_test_cube() { - if (!test_cube.is_valid()) { - test_cube = _make_test_cube(); - } - return test_cube; -} - -bool VisualServerRaster::has_os_feature(const String &p_feature) const { - - return VSG::storage->has_os_feature(p_feature); -} - -void VisualServerRaster::set_debug_generate_wireframes(bool p_generate) { - - VSG::storage->set_debug_generate_wireframes(p_generate); -} - -void VisualServerRaster::call_set_use_vsync(bool p_enable) { - DisplayServer::get_singleton()->_set_use_vsync(p_enable); -} - -bool VisualServerRaster::is_low_end() const { - // FIXME: Commented out when rebasing vulkan branch on master, - // causes a crash, it seems rasterizer is not initialized yet the - // first time it's called. - //return VSG::rasterizer->is_low_end(); - return false; -} -VisualServerRaster::VisualServerRaster() { - - VSG::canvas = memnew(VisualServerCanvas); - VSG::viewport = memnew(VisualServerViewport); - VSG::scene = memnew(VisualServerScene); - VSG::rasterizer = Rasterizer::create(); - VSG::storage = VSG::rasterizer->get_storage(); - VSG::canvas_render = VSG::rasterizer->get_canvas(); - VSG::scene_render = VSG::rasterizer->get_scene(); - - frame_profile_frame = 0; - - for (int i = 0; i < 4; i++) { - black_margin[i] = 0; - black_image[i] = RID(); - } -} - -VisualServerRaster::~VisualServerRaster() { - - memdelete(VSG::canvas); - memdelete(VSG::viewport); - memdelete(VSG::rasterizer); - memdelete(VSG::scene); -} diff --git a/servers/visual/visual_server_raster.h b/servers/visual/visual_server_raster.h deleted file mode 100644 index 1a40fc96a2..0000000000 --- a/servers/visual/visual_server_raster.h +++ /dev/null @@ -1,761 +0,0 @@ -/*************************************************************************/ -/* visual_server_raster.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUAL_SERVER_RASTER_H -#define VISUAL_SERVER_RASTER_H - -#include "core/math/octree.h" -#include "servers/visual/rasterizer.h" -#include "servers/visual_server.h" -#include "visual_server_canvas.h" -#include "visual_server_globals.h" -#include "visual_server_scene.h" -#include "visual_server_viewport.h" - -class VisualServerRaster : public VisualServer { - - enum { - - MAX_INSTANCE_CULL = 8192, - MAX_INSTANCE_LIGHTS = 4, - LIGHT_CACHE_DIRTY = -1, - MAX_LIGHTS_CULLED = 256, - MAX_ROOM_CULL = 32, - MAX_EXTERIOR_PORTALS = 128, - MAX_LIGHT_SAMPLERS = 256, - INSTANCE_ROOMLESS_MASK = (1 << 20) - - }; - - static int changes; - RID test_cube; - - int black_margin[4]; - RID black_image[4]; - - struct FrameDrawnCallbacks { - - ObjectID object; - StringName method; - Variant param; - }; - - List frame_drawn_callbacks; - - void _draw_margins(); - static void _changes_changed() {} - - uint64_t frame_profile_frame; - Vector frame_profile; - -public: - //if editor is redrawing when it shouldn't, enable this and put a breakpoint in _changes_changed() - //#define DEBUG_CHANGES - -#ifdef DEBUG_CHANGES - _FORCE_INLINE_ static void redraw_request() { - changes++; - _changes_changed(); - } - -#define DISPLAY_CHANGED \ - changes++; \ - _changes_changed(); - -#else - _FORCE_INLINE_ static void redraw_request() { changes++; } - -#define DISPLAY_CHANGED \ - changes++; -#endif - -#define BIND0R(m_r, m_name) \ - m_r m_name() { return BINDBASE->m_name(); } -#define BIND1R(m_r, m_name, m_type1) \ - m_r m_name(m_type1 arg1) { return BINDBASE->m_name(arg1); } -#define BIND1RC(m_r, m_name, m_type1) \ - m_r m_name(m_type1 arg1) const { return BINDBASE->m_name(arg1); } -#define BIND2R(m_r, m_name, m_type1, m_type2) \ - m_r m_name(m_type1 arg1, m_type2 arg2) { return BINDBASE->m_name(arg1, arg2); } -#define BIND2RC(m_r, m_name, m_type1, m_type2) \ - m_r m_name(m_type1 arg1, m_type2 arg2) const { return BINDBASE->m_name(arg1, arg2); } -#define BIND3RC(m_r, m_name, m_type1, m_type2, m_type3) \ - m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) const { return BINDBASE->m_name(arg1, arg2, arg3); } -#define BIND4RC(m_r, m_name, m_type1, m_type2, m_type3, m_type4) \ - m_r m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) const { return BINDBASE->m_name(arg1, arg2, arg3, arg4); } - -#define BIND1(m_name, m_type1) \ - void m_name(m_type1 arg1) { DISPLAY_CHANGED BINDBASE->m_name(arg1); } -#define BIND2(m_name, m_type1, m_type2) \ - void m_name(m_type1 arg1, m_type2 arg2) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2); } -#define BIND2C(m_name, m_type1, m_type2) \ - void m_name(m_type1 arg1, m_type2 arg2) const { BINDBASE->m_name(arg1, arg2); } -#define BIND3(m_name, m_type1, m_type2, m_type3) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3); } -#define BIND4(m_name, m_type1, m_type2, m_type3, m_type4) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4); } -#define BIND5(m_name, m_type1, m_type2, m_type3, m_type4, m_type5) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5); } -#define BIND6(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6); } -#define BIND7(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7); } -#define BIND8(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); } -#define BIND9(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); } -#define BIND10(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); } -#define BIND11(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); } -#define BIND12(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); } -#define BIND13(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); } -#define BIND14(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); } -#define BIND15(m_name, m_type1, m_type2, m_type3, m_type4, m_type5, m_type6, m_type7, m_type8, m_type9, m_type10, m_type11, m_type12, m_type13, m_type14, m_type15) \ - void m_name(m_type1 arg1, m_type2 arg2, m_type3 arg3, m_type4 arg4, m_type5 arg5, m_type6 arg6, m_type7 arg7, m_type8 arg8, m_type9 arg9, m_type10 arg10, m_type11 arg11, m_type12 arg12, m_type13 arg13, m_type14 arg14, m_type15 arg15) { DISPLAY_CHANGED BINDBASE->m_name(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); } - -//from now on, calls forwarded to this singleton -#define BINDBASE VSG::storage - - /* TEXTURE API */ - - //these go pass-through, as they can be called from any thread - BIND1R(RID, texture_2d_create, const Ref &) - BIND2R(RID, texture_2d_layered_create, const Vector> &, TextureLayeredType) - BIND1R(RID, texture_3d_create, const Vector> &) - BIND1R(RID, texture_proxy_create, RID) - - //goes pass-through - BIND3(texture_2d_update_immediate, RID, const Ref &, int) - //these go through command queue if they are in another thread - BIND3(texture_2d_update, RID, const Ref &, int) - BIND4(texture_3d_update, RID, const Ref &, int, int) - BIND2(texture_proxy_update, RID, RID) - - //these also go pass-through - BIND0R(RID, texture_2d_placeholder_create) - BIND0R(RID, texture_2d_layered_placeholder_create) - BIND0R(RID, texture_3d_placeholder_create) - - BIND1RC(Ref, texture_2d_get, RID) - BIND2RC(Ref, texture_2d_layer_get, RID, int) - BIND3RC(Ref, texture_3d_slice_get, RID, int, int) - - BIND2(texture_replace, RID, RID) - - BIND3(texture_set_size_override, RID, int, int) -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - BIND2(texture_bind, RID, uint32_t) -#endif - - BIND3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *) - BIND3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *) - BIND3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *) - - BIND2(texture_set_path, RID, const String &) - BIND1RC(String, texture_get_path, RID) - BIND1(texture_debug_usage, List *) - - BIND2(texture_set_force_redraw_if_visible, RID, bool) - - /* SHADER API */ - - BIND0R(RID, shader_create) - - BIND2(shader_set_code, RID, const String &) - BIND1RC(String, shader_get_code, RID) - - BIND2C(shader_get_param_list, RID, List *) - - BIND3(shader_set_default_texture_param, RID, const StringName &, RID) - BIND2RC(RID, shader_get_default_texture_param, RID, const StringName &) - BIND2RC(Variant, shader_get_param_default, RID, const StringName &) - - /* COMMON MATERIAL API */ - - BIND0R(RID, material_create) - - BIND2(material_set_shader, RID, RID) - - BIND3(material_set_param, RID, const StringName &, const Variant &) - BIND2RC(Variant, material_get_param, RID, const StringName &) - - BIND2(material_set_render_priority, RID, int) - BIND2(material_set_next_pass, RID, RID) - - /* MESH API */ - - virtual RID mesh_create_from_surfaces(const Vector &p_surfaces) { - RID mesh = mesh_create(); - for (int i = 0; i < p_surfaces.size(); i++) { - mesh_add_surface(mesh, p_surfaces[i]); - } - return mesh; - } - - BIND0R(RID, mesh_create) - - BIND2(mesh_add_surface, RID, const SurfaceData &) - - BIND1RC(int, mesh_get_blend_shape_count, RID) - - BIND2(mesh_set_blend_shape_mode, RID, BlendShapeMode) - BIND1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID) - - BIND4(mesh_surface_update_region, RID, int, int, const Vector &) - - BIND3(mesh_surface_set_material, RID, int, RID) - BIND2RC(RID, mesh_surface_get_material, RID, int) - - BIND2RC(SurfaceData, mesh_get_surface, RID, int) - - BIND1RC(int, mesh_get_surface_count, RID) - - BIND2(mesh_set_custom_aabb, RID, const AABB &) - BIND1RC(AABB, mesh_get_custom_aabb, RID) - - BIND1(mesh_clear, RID) - - /* MULTIMESH API */ - - BIND0R(RID, multimesh_create) - - BIND5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool) - BIND1RC(int, multimesh_get_instance_count, RID) - - BIND2(multimesh_set_mesh, RID, RID) - BIND3(multimesh_instance_set_transform, RID, int, const Transform &) - BIND3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &) - BIND3(multimesh_instance_set_color, RID, int, const Color &) - BIND3(multimesh_instance_set_custom_data, RID, int, const Color &) - - BIND1RC(RID, multimesh_get_mesh, RID) - BIND1RC(AABB, multimesh_get_aabb, RID) - - BIND2RC(Transform, multimesh_instance_get_transform, RID, int) - BIND2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int) - BIND2RC(Color, multimesh_instance_get_color, RID, int) - BIND2RC(Color, multimesh_instance_get_custom_data, RID, int) - - BIND2(multimesh_set_buffer, RID, const Vector &) - BIND1RC(Vector, multimesh_get_buffer, RID) - - BIND2(multimesh_set_visible_instances, RID, int) - BIND1RC(int, multimesh_get_visible_instances, RID) - - /* IMMEDIATE API */ - - BIND0R(RID, immediate_create) - BIND3(immediate_begin, RID, PrimitiveType, RID) - BIND2(immediate_vertex, RID, const Vector3 &) - BIND2(immediate_normal, RID, const Vector3 &) - BIND2(immediate_tangent, RID, const Plane &) - BIND2(immediate_color, RID, const Color &) - BIND2(immediate_uv, RID, const Vector2 &) - BIND2(immediate_uv2, RID, const Vector2 &) - BIND1(immediate_end, RID) - BIND1(immediate_clear, RID) - BIND2(immediate_set_material, RID, RID) - BIND1RC(RID, immediate_get_material, RID) - - /* SKELETON API */ - - BIND0R(RID, skeleton_create) - BIND3(skeleton_allocate, RID, int, bool) - BIND1RC(int, skeleton_get_bone_count, RID) - BIND3(skeleton_bone_set_transform, RID, int, const Transform &) - BIND2RC(Transform, skeleton_bone_get_transform, RID, int) - BIND3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) - BIND2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) - BIND2(skeleton_set_base_transform_2d, RID, const Transform2D &) - - /* Light API */ - - BIND0R(RID, directional_light_create) - BIND0R(RID, omni_light_create) - BIND0R(RID, spot_light_create) - - BIND2(light_set_color, RID, const Color &) - BIND3(light_set_param, RID, LightParam, float) - BIND2(light_set_shadow, RID, bool) - BIND2(light_set_shadow_color, RID, const Color &) - BIND2(light_set_projector, RID, RID) - BIND2(light_set_negative, RID, bool) - BIND2(light_set_cull_mask, RID, uint32_t) - BIND2(light_set_reverse_cull_face_mode, RID, bool) - BIND2(light_set_use_gi, RID, bool) - - BIND2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) - - BIND2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) - BIND2(light_directional_set_blend_splits, RID, bool) - BIND2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) - - /* PROBE API */ - - BIND0R(RID, reflection_probe_create) - - BIND2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode) - BIND2(reflection_probe_set_intensity, RID, float) - BIND2(reflection_probe_set_interior_ambient, RID, const Color &) - BIND2(reflection_probe_set_interior_ambient_energy, RID, float) - BIND2(reflection_probe_set_interior_ambient_probe_contribution, RID, float) - BIND2(reflection_probe_set_max_distance, RID, float) - BIND2(reflection_probe_set_extents, RID, const Vector3 &) - BIND2(reflection_probe_set_origin_offset, RID, const Vector3 &) - BIND2(reflection_probe_set_as_interior, RID, bool) - BIND2(reflection_probe_set_enable_box_projection, RID, bool) - BIND2(reflection_probe_set_enable_shadows, RID, bool) - BIND2(reflection_probe_set_cull_mask, RID, uint32_t) - BIND2(reflection_probe_set_resolution, RID, int) - - /* BAKED LIGHT API */ - - BIND0R(RID, gi_probe_create) - - BIND8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector &, const Vector &, const Vector &, const Vector &) - - BIND1RC(AABB, gi_probe_get_bounds, RID) - BIND1RC(Vector3i, gi_probe_get_octree_size, RID) - BIND1RC(Vector, gi_probe_get_octree_cells, RID) - BIND1RC(Vector, gi_probe_get_data_cells, RID) - BIND1RC(Vector, gi_probe_get_distance_field, RID) - BIND1RC(Vector, gi_probe_get_level_counts, RID) - BIND1RC(Transform, gi_probe_get_to_cell_xform, RID) - - BIND2(gi_probe_set_dynamic_range, RID, float) - BIND1RC(float, gi_probe_get_dynamic_range, RID) - - BIND2(gi_probe_set_propagation, RID, float) - BIND1RC(float, gi_probe_get_propagation, RID) - - BIND2(gi_probe_set_energy, RID, float) - BIND1RC(float, gi_probe_get_energy, RID) - - BIND2(gi_probe_set_ao, RID, float) - BIND1RC(float, gi_probe_get_ao, RID) - - BIND2(gi_probe_set_ao_size, RID, float) - BIND1RC(float, gi_probe_get_ao_size, RID) - - BIND2(gi_probe_set_bias, RID, float) - BIND1RC(float, gi_probe_get_bias, RID) - - BIND2(gi_probe_set_normal_bias, RID, float) - BIND1RC(float, gi_probe_get_normal_bias, RID) - - BIND2(gi_probe_set_interior, RID, bool) - BIND1RC(bool, gi_probe_is_interior, RID) - - BIND2(gi_probe_set_use_two_bounces, RID, bool) - BIND1RC(bool, gi_probe_is_using_two_bounces, RID) - - BIND2(gi_probe_set_anisotropy_strength, RID, float) - BIND1RC(float, gi_probe_get_anisotropy_strength, RID) - - /* LIGHTMAP CAPTURE */ - - BIND0R(RID, lightmap_capture_create) - - BIND2(lightmap_capture_set_bounds, RID, const AABB &) - BIND1RC(AABB, lightmap_capture_get_bounds, RID) - - BIND2(lightmap_capture_set_octree, RID, const Vector &) - BIND1RC(Vector, lightmap_capture_get_octree, RID) - - BIND2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) - BIND1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) - BIND2(lightmap_capture_set_octree_cell_subdiv, RID, int) - BIND1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) - - BIND2(lightmap_capture_set_energy, RID, float) - BIND1RC(float, lightmap_capture_get_energy, RID) - - /* PARTICLES */ - - BIND0R(RID, particles_create) - - BIND2(particles_set_emitting, RID, bool) - BIND1R(bool, particles_get_emitting, RID) - BIND2(particles_set_amount, RID, int) - BIND2(particles_set_lifetime, RID, float) - BIND2(particles_set_one_shot, RID, bool) - BIND2(particles_set_pre_process_time, RID, float) - BIND2(particles_set_explosiveness_ratio, RID, float) - BIND2(particles_set_randomness_ratio, RID, float) - BIND2(particles_set_custom_aabb, RID, const AABB &) - BIND2(particles_set_speed_scale, RID, float) - BIND2(particles_set_use_local_coordinates, RID, bool) - BIND2(particles_set_process_material, RID, RID) - BIND2(particles_set_fixed_fps, RID, int) - BIND2(particles_set_fractional_delta, RID, bool) - BIND1R(bool, particles_is_inactive, RID) - BIND1(particles_request_process, RID) - BIND1(particles_restart, RID) - - BIND2(particles_set_draw_order, RID, VS::ParticlesDrawOrder) - - BIND2(particles_set_draw_passes, RID, int) - BIND3(particles_set_draw_pass_mesh, RID, int, RID) - - BIND1R(AABB, particles_get_current_aabb, RID) - BIND2(particles_set_emission_transform, RID, const Transform &) - -#undef BINDBASE -//from now on, calls forwarded to this singleton -#define BINDBASE VSG::scene - - /* CAMERA API */ - - BIND0R(RID, camera_create) - BIND4(camera_set_perspective, RID, float, float, float) - BIND4(camera_set_orthogonal, RID, float, float, float) - BIND5(camera_set_frustum, RID, float, Vector2, float, float) - BIND2(camera_set_transform, RID, const Transform &) - BIND2(camera_set_cull_mask, RID, uint32_t) - BIND2(camera_set_environment, RID, RID) - BIND2(camera_set_camera_effects, RID, RID) - BIND2(camera_set_use_vertical_aspect, RID, bool) - -#undef BINDBASE -//from now on, calls forwarded to this singleton -#define BINDBASE VSG::viewport - - /* VIEWPORT TARGET API */ - - BIND0R(RID, viewport_create) - - BIND2(viewport_set_use_arvr, RID, bool) - BIND3(viewport_set_size, RID, int, int) - - BIND2(viewport_set_active, RID, bool) - BIND2(viewport_set_parent_viewport, RID, RID) - - BIND2(viewport_set_clear_mode, RID, ViewportClearMode) - - BIND3(viewport_attach_to_screen, RID, const Rect2 &, int) - BIND2(viewport_set_render_direct_to_screen, RID, bool) - - BIND2(viewport_set_update_mode, RID, ViewportUpdateMode) - BIND2(viewport_set_vflip, RID, bool) - - BIND1RC(RID, viewport_get_texture, RID) - - BIND2(viewport_set_hide_scenario, RID, bool) - BIND2(viewport_set_hide_canvas, RID, bool) - BIND2(viewport_set_disable_environment, RID, bool) - - BIND2(viewport_attach_camera, RID, RID) - BIND2(viewport_set_scenario, RID, RID) - BIND2(viewport_attach_canvas, RID, RID) - - BIND2(viewport_remove_canvas, RID, RID) - BIND3(viewport_set_canvas_transform, RID, RID, const Transform2D &) - BIND2(viewport_set_transparent_background, RID, bool) - - BIND2(viewport_set_global_canvas_transform, RID, const Transform2D &) - BIND4(viewport_set_canvas_stacking, RID, RID, int, int) - BIND2(viewport_set_shadow_atlas_size, RID, int) - BIND3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) - BIND2(viewport_set_msaa, RID, ViewportMSAA) - - BIND2R(int, viewport_get_render_info, RID, ViewportRenderInfo) - BIND2(viewport_set_debug_draw, RID, ViewportDebugDraw) - - /* ENVIRONMENT API */ - -#undef BINDBASE -//from now on, calls forwarded to this singleton -#define BINDBASE VSG::scene_render - - BIND1(directional_shadow_atlas_set_size, int) - - /* SKY API */ - - BIND0R(RID, sky_create) - BIND2(sky_set_radiance_size, RID, int) - BIND2(sky_set_mode, RID, SkyMode) - BIND2(sky_set_material, RID, RID) - - BIND0R(RID, environment_create) - - BIND2(environment_set_background, RID, EnvironmentBG) - BIND2(environment_set_sky, RID, RID) - BIND2(environment_set_sky_custom_fov, RID, float) - BIND2(environment_set_sky_orientation, RID, const Basis &) - BIND2(environment_set_bg_color, RID, const Color &) - BIND2(environment_set_bg_energy, RID, float) - BIND2(environment_set_canvas_max_layer, RID, int) - BIND7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &) - -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - BIND2(environment_set_camera_feed_id, RID, int) -#endif - BIND7(environment_set_ssr, RID, bool, int, float, float, float, bool) - BIND9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) - BIND2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) - - BIND12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) - - BIND9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) - - BIND6(environment_set_adjustment, RID, bool, float, float, float, RID) - - BIND5(environment_set_fog, RID, bool, const Color &, const Color &, float) - BIND7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) - BIND5(environment_set_fog_height, RID, bool, float, float, float) - - BIND2(screen_space_roughness_limiter_set_active, bool, float) - - /* CAMERA EFFECTS */ - - BIND0R(RID, camera_effects_create) - - BIND2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool) - BIND1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape) - - BIND8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) - BIND3(camera_effects_set_custom_exposure, RID, bool, float) - - /* SCENARIO API */ - -#undef BINDBASE -#define BINDBASE VSG::scene - - BIND0R(RID, scenario_create) - - BIND2(scenario_set_debug, RID, ScenarioDebugMode) - BIND2(scenario_set_environment, RID, RID) - BIND2(scenario_set_camera_effects, RID, RID) - BIND2(scenario_set_fallback_environment, RID, RID) - - /* INSTANCING API */ - BIND0R(RID, instance_create) - - BIND2(instance_set_base, RID, RID) - BIND2(instance_set_scenario, RID, RID) - BIND2(instance_set_layer_mask, RID, uint32_t) - BIND2(instance_set_transform, RID, const Transform &) - BIND2(instance_attach_object_instance_id, RID, ObjectID) - BIND3(instance_set_blend_shape_weight, RID, int, float) - BIND3(instance_set_surface_material, RID, int, RID) - BIND2(instance_set_visible, RID, bool) - BIND3(instance_set_use_lightmap, RID, RID, RID) - - BIND2(instance_set_custom_aabb, RID, AABB) - - BIND2(instance_attach_skeleton, RID, RID) - BIND2(instance_set_exterior, RID, bool) - - BIND2(instance_set_extra_visibility_margin, RID, real_t) - - // don't use these in a game! - BIND2RC(Vector, instances_cull_aabb, const AABB &, RID) - BIND3RC(Vector, instances_cull_ray, const Vector3 &, const Vector3 &, RID) - BIND2RC(Vector, instances_cull_convex, const Vector &, RID) - - BIND3(instance_geometry_set_flag, RID, InstanceFlags, bool) - BIND2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting) - BIND2(instance_geometry_set_material_override, RID, RID) - - BIND5(instance_geometry_set_draw_range, RID, float, float, float, float) - BIND2(instance_geometry_set_as_instance_lod, RID, RID) - -#undef BINDBASE -//from now on, calls forwarded to this singleton -#define BINDBASE VSG::canvas - - /* CANVAS (2D) */ - - BIND0R(RID, canvas_create) - BIND3(canvas_set_item_mirroring, RID, RID, const Point2 &) - BIND2(canvas_set_modulate, RID, const Color &) - BIND3(canvas_set_parent, RID, RID, float) - BIND1(canvas_set_disable_scale, bool) - - BIND0R(RID, canvas_item_create) - BIND2(canvas_item_set_parent, RID, RID) - - BIND2(canvas_item_set_visible, RID, bool) - BIND2(canvas_item_set_light_mask, RID, int) - - BIND2(canvas_item_set_update_when_visible, RID, bool) - - BIND2(canvas_item_set_transform, RID, const Transform2D &) - BIND2(canvas_item_set_clip, RID, bool) - BIND2(canvas_item_set_distance_field_mode, RID, bool) - BIND3(canvas_item_set_custom_rect, RID, bool, const Rect2 &) - BIND2(canvas_item_set_modulate, RID, const Color &) - BIND2(canvas_item_set_self_modulate, RID, const Color &) - - BIND2(canvas_item_set_draw_behind_parent, RID, bool) - - BIND2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) - BIND2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) - - BIND5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) - BIND4(canvas_item_add_polyline, RID, const Vector &, const Vector &, float) - BIND4(canvas_item_add_multiline, RID, const Vector &, const Vector &, float) - BIND3(canvas_item_add_rect, RID, const Rect2 &, const Color &) - BIND4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) - BIND11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND11(canvas_item_add_primitive, RID, const Vector &, const Vector &, const Vector &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND10(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND14(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - BIND2(canvas_item_add_set_transform, RID, const Transform2D &) - BIND2(canvas_item_add_clip_ignore, RID, bool) - BIND2(canvas_item_set_sort_children_by_y, RID, bool) - BIND2(canvas_item_set_z_index, RID, int) - BIND2(canvas_item_set_z_as_relative_to_parent, RID, bool) - BIND3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) - BIND2(canvas_item_attach_skeleton, RID, RID) - - BIND1(canvas_item_clear, RID) - BIND2(canvas_item_set_draw_index, RID, int) - - BIND2(canvas_item_set_material, RID, RID) - - BIND2(canvas_item_set_use_parent_material, RID, bool) - - BIND0R(RID, canvas_light_create) - BIND2(canvas_light_attach_to_canvas, RID, RID) - BIND2(canvas_light_set_enabled, RID, bool) - BIND2(canvas_light_set_scale, RID, float) - BIND2(canvas_light_set_transform, RID, const Transform2D &) - BIND2(canvas_light_set_texture, RID, RID) - BIND2(canvas_light_set_texture_offset, RID, const Vector2 &) - BIND2(canvas_light_set_color, RID, const Color &) - BIND2(canvas_light_set_height, RID, float) - BIND2(canvas_light_set_energy, RID, float) - BIND3(canvas_light_set_z_range, RID, int, int) - BIND3(canvas_light_set_layer_range, RID, int, int) - BIND2(canvas_light_set_item_cull_mask, RID, int) - BIND2(canvas_light_set_item_shadow_cull_mask, RID, int) - - BIND2(canvas_light_set_mode, RID, CanvasLightMode) - - BIND2(canvas_light_set_shadow_enabled, RID, bool) - BIND2(canvas_light_set_shadow_buffer_size, RID, int) - BIND2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) - BIND2(canvas_light_set_shadow_color, RID, const Color &) - BIND2(canvas_light_set_shadow_smooth, RID, float) - - BIND0R(RID, canvas_light_occluder_create) - BIND2(canvas_light_occluder_attach_to_canvas, RID, RID) - BIND2(canvas_light_occluder_set_enabled, RID, bool) - BIND2(canvas_light_occluder_set_polygon, RID, RID) - BIND2(canvas_light_occluder_set_transform, RID, const Transform2D &) - BIND2(canvas_light_occluder_set_light_mask, RID, int) - - BIND0R(RID, canvas_occluder_polygon_create) - BIND3(canvas_occluder_polygon_set_shape, RID, const Vector &, bool) - BIND2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector &) - - BIND2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) - - /* BLACK BARS */ - - virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom); - virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom); - - /* FREE */ - - virtual void free(RID p_rid); ///< free RIDs associated with the visual server - - /* EVENT QUEUING */ - - virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata); - - virtual void draw(bool p_swap_buffers, double frame_step); - virtual void sync(); - virtual bool has_changed() const; - virtual void init(); - virtual void finish(); - - /* STATUS INFORMATION */ - - virtual int get_render_info(RenderInfo p_info); - virtual String get_video_adapter_name() const; - virtual String get_video_adapter_vendor() const; - - virtual void set_frame_profiling_enabled(bool p_enable); - virtual Vector get_frame_profile(); - virtual uint64_t get_frame_profile_frame(); - - virtual RID get_test_cube(); - - /* TESTING */ - - virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true); - virtual void set_default_clear_color(const Color &p_color); - - virtual bool has_feature(Features p_feature) const; - - virtual bool has_os_feature(const String &p_feature) const; - virtual void set_debug_generate_wireframes(bool p_generate); - - virtual void call_set_use_vsync(bool p_enable); - - virtual bool is_low_end() const; - - VisualServerRaster(); - ~VisualServerRaster(); - -#undef DISPLAY_CHANGED - -#undef BIND0R -#undef BIND1RC -#undef BIND2RC -#undef BIND3RC -#undef BIND4RC - -#undef BIND1 -#undef BIND2 -#undef BIND3 -#undef BIND4 -#undef BIND5 -#undef BIND6 -#undef BIND7 -#undef BIND8 -#undef BIND9 -#undef BIND10 -}; - -#endif diff --git a/servers/visual/visual_server_scene.cpp b/servers/visual/visual_server_scene.cpp deleted file mode 100644 index 1a9ecae23a..0000000000 --- a/servers/visual/visual_server_scene.cpp +++ /dev/null @@ -1,2839 +0,0 @@ -/*************************************************************************/ -/* visual_server_scene.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server_scene.h" - -#include "core/os/os.h" -#include "visual_server_globals.h" -#include "visual_server_raster.h" - -#include - -/* CAMERA API */ - -RID VisualServerScene::camera_create() { - - Camera *camera = memnew(Camera); - return camera_owner.make_rid(camera); -} - -void VisualServerScene::camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->type = Camera::PERSPECTIVE; - camera->fov = p_fovy_degrees; - camera->znear = p_z_near; - camera->zfar = p_z_far; -} - -void VisualServerScene::camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->type = Camera::ORTHOGONAL; - camera->size = p_size; - camera->znear = p_z_near; - camera->zfar = p_z_far; -} - -void VisualServerScene::camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) { - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->type = Camera::FRUSTUM; - camera->size = p_size; - camera->offset = p_offset; - camera->znear = p_z_near; - camera->zfar = p_z_far; -} - -void VisualServerScene::camera_set_transform(RID p_camera, const Transform &p_transform) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->transform = p_transform.orthonormalized(); -} - -void VisualServerScene::camera_set_cull_mask(RID p_camera, uint32_t p_layers) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - - camera->visible_layers = p_layers; -} - -void VisualServerScene::camera_set_environment(RID p_camera, RID p_env) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->env = p_env; -} - -void VisualServerScene::camera_set_camera_effects(RID p_camera, RID p_fx) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->effects = p_fx; -} - -void VisualServerScene::camera_set_use_vertical_aspect(RID p_camera, bool p_enable) { - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - camera->vaspect = p_enable; -} - -/* SCENARIO API */ - -void *VisualServerScene::_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int) { - - //VisualServerScene *self = (VisualServerScene*)p_self; - Instance *A = p_A; - Instance *B = p_B; - - //instance indices are designed so greater always contains lesser - if (A->base_type > B->base_type) { - SWAP(A, B); //lesser always first - } - - if (B->base_type == VS::INSTANCE_LIGHT && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceLightData *light = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - InstanceLightData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->lighting.push_back(B); - - List::Element *E = light->geometries.push_back(pinfo); - - if (geom->can_cast_shadows) { - - light->shadow_dirty = true; - } - geom->lighting_dirty = true; - - return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceReflectionProbeData *reflection_probe = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - InstanceReflectionProbeData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->reflection_probes.push_back(B); - - List::Element *E = reflection_probe->geometries.push_back(pinfo); - - geom->reflection_dirty = true; - - return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceLightmapCaptureData *lightmap_capture = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - InstanceLightmapCaptureData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->lightmap_captures.push_back(B); - - List::Element *E = lightmap_capture->geometries.push_back(pinfo); - ((VisualServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture - - return E; //this element should make freeing faster - } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - InstanceGIProbeData::PairInfo pinfo; - pinfo.geometry = A; - pinfo.L = geom->gi_probes.push_back(B); - - List::Element *E; - if (A->dynamic_gi) { - E = gi_probe->dynamic_geometries.push_back(pinfo); - } else { - E = gi_probe->geometries.push_back(pinfo); - } - - geom->gi_probes_dirty = true; - - return E; //this element should make freeing faster - - } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { - - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - return gi_probe->lights.insert(A); - } - - return NULL; -} -void VisualServerScene::_instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *udata) { - - //VisualServerScene *self = (VisualServerScene*)p_self; - Instance *A = p_A; - Instance *B = p_B; - - //instance indices are designed so greater always contains lesser - if (A->base_type > B->base_type) { - SWAP(A, B); //lesser always first - } - - if (B->base_type == VS::INSTANCE_LIGHT && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceLightData *light = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - List::Element *E = reinterpret_cast::Element *>(udata); - - geom->lighting.erase(E->get().L); - light->geometries.erase(E); - - if (geom->can_cast_shadows) { - light->shadow_dirty = true; - } - geom->lighting_dirty = true; - - } else if (B->base_type == VS::INSTANCE_REFLECTION_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceReflectionProbeData *reflection_probe = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - List::Element *E = reinterpret_cast::Element *>(udata); - - geom->reflection_probes.erase(E->get().L); - reflection_probe->geometries.erase(E); - - geom->reflection_dirty = true; - } else if (B->base_type == VS::INSTANCE_LIGHTMAP_CAPTURE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceLightmapCaptureData *lightmap_capture = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - List::Element *E = reinterpret_cast::Element *>(udata); - - geom->lightmap_captures.erase(E->get().L); - lightmap_capture->geometries.erase(E); - ((VisualServerScene *)p_self)->_instance_queue_update(A, false, false); //need to update capture - - } else if (B->base_type == VS::INSTANCE_GI_PROBE && ((1 << A->base_type) & VS::INSTANCE_GEOMETRY_MASK)) { - - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - InstanceGeometryData *geom = static_cast(A->base_data); - - List::Element *E = reinterpret_cast::Element *>(udata); - - geom->gi_probes.erase(E->get().L); - if (A->dynamic_gi) { - gi_probe->dynamic_geometries.erase(E); - } else { - gi_probe->geometries.erase(E); - } - - geom->gi_probes_dirty = true; - - } else if (B->base_type == VS::INSTANCE_GI_PROBE && A->base_type == VS::INSTANCE_LIGHT) { - - InstanceGIProbeData *gi_probe = static_cast(B->base_data); - Set::Element *E = reinterpret_cast::Element *>(udata); - - gi_probe->lights.erase(E); - } -} - -RID VisualServerScene::scenario_create() { - - Scenario *scenario = memnew(Scenario); - ERR_FAIL_COND_V(!scenario, RID()); - RID scenario_rid = scenario_owner.make_rid(scenario); - scenario->self = scenario_rid; - - scenario->octree.set_pair_callback(_instance_pair, this); - scenario->octree.set_unpair_callback(_instance_unpair, this); - scenario->reflection_probe_shadow_atlas = VSG::scene_render->shadow_atlas_create(); - VSG::scene_render->shadow_atlas_set_size(scenario->reflection_probe_shadow_atlas, 1024); //make enough shadows for close distance, don't bother with rest - VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 0, 4); - VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 1, 4); - VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 2, 4); - VSG::scene_render->shadow_atlas_set_quadrant_subdivision(scenario->reflection_probe_shadow_atlas, 3, 8); - scenario->reflection_atlas = VSG::scene_render->reflection_atlas_create(); - return scenario_rid; -} - -void VisualServerScene::scenario_set_debug(RID p_scenario, VS::ScenarioDebugMode p_debug_mode) { - - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->debug = p_debug_mode; -} - -void VisualServerScene::scenario_set_environment(RID p_scenario, RID p_environment) { - - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->environment = p_environment; -} - -void VisualServerScene::scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) { - - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->camera_effects = p_camera_effects; -} - -void VisualServerScene::scenario_set_fallback_environment(RID p_scenario, RID p_environment) { - - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - scenario->fallback_environment = p_environment; -} - -void VisualServerScene::scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count) { - - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - VSG::scene_render->reflection_atlas_set_size(scenario->reflection_atlas, p_reflection_size, p_reflection_count); -} - -/* INSTANCING API */ - -void VisualServerScene::_instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies) { - - if (p_update_aabb) - p_instance->update_aabb = true; - if (p_update_dependencies) - p_instance->update_dependencies = true; - - if (p_instance->update_item.in_list()) - return; - - _instance_update_list.add(&p_instance->update_item); -} - -RID VisualServerScene::instance_create() { - - Instance *instance = memnew(Instance); - ERR_FAIL_COND_V(!instance, RID()); - - RID instance_rid = instance_owner.make_rid(instance); - instance->self = instance_rid; - - return instance_rid; -} - -void VisualServerScene::instance_set_base(RID p_instance, RID p_base) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - Scenario *scenario = instance->scenario; - - if (instance->base_type != VS::INSTANCE_NONE) { - //free anything related to that base - - if (scenario && instance->octree_id) { - scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away - instance->octree_id = 0; - } - - switch (instance->base_type) { - case VS::INSTANCE_LIGHT: { - - InstanceLightData *light = static_cast(instance->base_data); -#ifdef DEBUG_ENABLED - if (light->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from light."); - } -#endif - if (instance->scenario && light->D) { - instance->scenario->directional_lights.erase(light->D); - light->D = NULL; - } - VSG::scene_render->free(light->instance); - } break; - case VS::INSTANCE_REFLECTION_PROBE: { - - InstanceReflectionProbeData *reflection_probe = static_cast(instance->base_data); - VSG::scene_render->free(reflection_probe->instance); - if (reflection_probe->update_list.in_list()) { - reflection_probe_render_list.remove(&reflection_probe->update_list); - } - } break; - case VS::INSTANCE_LIGHTMAP_CAPTURE: { - - InstanceLightmapCaptureData *lightmap_capture = static_cast(instance->base_data); - //erase dependencies, since no longer a lightmap - while (lightmap_capture->users.front()) { - instance_set_use_lightmap(lightmap_capture->users.front()->get()->self, RID(), RID()); - } - } break; - case VS::INSTANCE_GI_PROBE: { - - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); -#ifdef DEBUG_ENABLED - if (gi_probe->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); - } -#endif -#ifdef DEBUG_ENABLED - if (gi_probe->lights.size()) { - ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); - } -#endif - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); - } - - if (instance->lightmap_capture) { - Instance *capture = (Instance *)instance->lightmap_capture; - InstanceLightmapCaptureData *lightmap_capture = static_cast(capture->base_data); - lightmap_capture->users.erase(instance); - instance->lightmap_capture = NULL; - instance->lightmap = RID(); - } - - VSG::scene_render->free(gi_probe->probe_instance); - - } break; - default: { - } - } - - if (instance->base_data) { - memdelete(instance->base_data); - instance->base_data = NULL; - } - - instance->blend_values.clear(); - instance->materials.clear(); - } - - instance->base_type = VS::INSTANCE_NONE; - instance->base = RID(); - - if (p_base.is_valid()) { - - instance->base_type = VSG::storage->get_base_type(p_base); - ERR_FAIL_COND(instance->base_type == VS::INSTANCE_NONE); - - switch (instance->base_type) { - case VS::INSTANCE_LIGHT: { - - InstanceLightData *light = memnew(InstanceLightData); - - if (scenario && VSG::storage->light_get_type(p_base) == VS::LIGHT_DIRECTIONAL) { - light->D = scenario->directional_lights.push_back(instance); - } - - light->instance = VSG::scene_render->light_instance_create(p_base); - - instance->base_data = light; - } break; - case VS::INSTANCE_MESH: - case VS::INSTANCE_MULTIMESH: - case VS::INSTANCE_IMMEDIATE: - case VS::INSTANCE_PARTICLES: { - - InstanceGeometryData *geom = memnew(InstanceGeometryData); - instance->base_data = geom; - if (instance->base_type == VS::INSTANCE_MESH) { - instance->blend_values.resize(VSG::storage->mesh_get_blend_shape_count(p_base)); - } - } break; - case VS::INSTANCE_REFLECTION_PROBE: { - - InstanceReflectionProbeData *reflection_probe = memnew(InstanceReflectionProbeData); - reflection_probe->owner = instance; - instance->base_data = reflection_probe; - - reflection_probe->instance = VSG::scene_render->reflection_probe_instance_create(p_base); - } break; - case VS::INSTANCE_LIGHTMAP_CAPTURE: { - - InstanceLightmapCaptureData *lightmap_capture = memnew(InstanceLightmapCaptureData); - instance->base_data = lightmap_capture; - //lightmap_capture->instance = VSG::scene_render->lightmap_capture_instance_create(p_base); - } break; - case VS::INSTANCE_GI_PROBE: { - - InstanceGIProbeData *gi_probe = memnew(InstanceGIProbeData); - instance->base_data = gi_probe; - gi_probe->owner = instance; - - if (scenario && !gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - - gi_probe->probe_instance = VSG::scene_render->gi_probe_instance_create(p_base); - - } break; - default: { - } - } - - instance->base = p_base; - - //forcefully update the dependency now, so if for some reason it gets removed, we can immediately clear it - VSG::storage->base_update_dependency(p_base, instance); - } - - _instance_queue_update(instance, true, true); -} -void VisualServerScene::instance_set_scenario(RID p_instance, RID p_scenario) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->scenario) { - - instance->scenario->instances.remove(&instance->scenario_item); - - if (instance->octree_id) { - instance->scenario->octree.erase(instance->octree_id); //make dependencies generated by the octree go away - instance->octree_id = 0; - } - - switch (instance->base_type) { - - case VS::INSTANCE_LIGHT: { - - InstanceLightData *light = static_cast(instance->base_data); -#ifdef DEBUG_ENABLED - if (light->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from light."); - } -#endif - if (light->D) { - instance->scenario->directional_lights.erase(light->D); - light->D = NULL; - } - } break; - case VS::INSTANCE_REFLECTION_PROBE: { - InstanceReflectionProbeData *reflection_probe = static_cast(instance->base_data); - VSG::scene_render->reflection_probe_release_atlas_index(reflection_probe->instance); - - } break; - case VS::INSTANCE_GI_PROBE: { - - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - -#ifdef DEBUG_ENABLED - if (gi_probe->geometries.size()) { - ERR_PRINT("BUG, indexing did not unpair geometries from GIProbe."); - } -#endif -#ifdef DEBUG_ENABLED - if (gi_probe->lights.size()) { - ERR_PRINT("BUG, indexing did not unpair lights from GIProbe."); - } -#endif - - if (gi_probe->update_element.in_list()) { - gi_probe_update_list.remove(&gi_probe->update_element); - } - } break; - default: { - } - } - - instance->scenario = NULL; - } - - if (p_scenario.is_valid()) { - - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND(!scenario); - - instance->scenario = scenario; - - scenario->instances.add(&instance->scenario_item); - - switch (instance->base_type) { - - case VS::INSTANCE_LIGHT: { - - InstanceLightData *light = static_cast(instance->base_data); - - if (VSG::storage->light_get_type(instance->base) == VS::LIGHT_DIRECTIONAL) { - light->D = scenario->directional_lights.push_back(instance); - } - } break; - case VS::INSTANCE_GI_PROBE: { - - InstanceGIProbeData *gi_probe = static_cast(instance->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - } break; - default: { - } - } - - _instance_queue_update(instance, true, true); - } -} -void VisualServerScene::instance_set_layer_mask(RID p_instance, uint32_t p_mask) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->layer_mask = p_mask; -} -void VisualServerScene::instance_set_transform(RID p_instance, const Transform &p_transform) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->transform == p_transform) - return; //must be checked to avoid worst evil - -#ifdef DEBUG_ENABLED - - for (int i = 0; i < 4; i++) { - const Vector3 &v = i < 3 ? p_transform.basis.elements[i] : p_transform.origin; - ERR_FAIL_COND(Math::is_inf(v.x)); - ERR_FAIL_COND(Math::is_nan(v.x)); - ERR_FAIL_COND(Math::is_inf(v.y)); - ERR_FAIL_COND(Math::is_nan(v.y)); - ERR_FAIL_COND(Math::is_inf(v.z)); - ERR_FAIL_COND(Math::is_nan(v.z)); - } - -#endif - instance->transform = p_transform; - _instance_queue_update(instance, true); -} -void VisualServerScene::instance_attach_object_instance_id(RID p_instance, ObjectID p_id) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->object_id = p_id; -} -void VisualServerScene::instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->update_item.in_list()) { - _update_dirty_instance(instance); - } - - ERR_FAIL_INDEX(p_shape, instance->blend_values.size()); - instance->blend_values.write[p_shape] = p_weight; -} - -void VisualServerScene::instance_set_surface_material(RID p_instance, int p_surface, RID p_material) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->base_type == VS::INSTANCE_MESH) { - //may not have been updated yet, may also have not been set yet. When updated will be correcte, worst case - instance->materials.resize(MAX(p_surface + 1, VSG::storage->mesh_get_surface_count(instance->base))); - } - - ERR_FAIL_INDEX(p_surface, instance->materials.size()); - - instance->materials.write[p_surface] = p_material; - - _instance_queue_update(instance, false, true); -} - -void VisualServerScene::instance_set_visible(RID p_instance, bool p_visible) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->visible == p_visible) - return; - - instance->visible = p_visible; - - switch (instance->base_type) { - case VS::INSTANCE_LIGHT: { - if (VSG::storage->light_get_type(instance->base) != VS::LIGHT_DIRECTIONAL && instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << VS::INSTANCE_LIGHT, p_visible ? VS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case VS::INSTANCE_REFLECTION_PROBE: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << VS::INSTANCE_REFLECTION_PROBE, p_visible ? VS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case VS::INSTANCE_LIGHTMAP_CAPTURE: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << VS::INSTANCE_LIGHTMAP_CAPTURE, p_visible ? VS::INSTANCE_GEOMETRY_MASK : 0); - } - - } break; - case VS::INSTANCE_GI_PROBE: { - if (instance->octree_id && instance->scenario) { - instance->scenario->octree.set_pairable(instance->octree_id, p_visible, 1 << VS::INSTANCE_GI_PROBE, p_visible ? (VS::INSTANCE_GEOMETRY_MASK | (1 << VS::INSTANCE_LIGHT)) : 0); - } - - } break; - default: { - } - } -} -inline bool is_geometry_instance(VisualServer::InstanceType p_type) { - return p_type == VS::INSTANCE_MESH || p_type == VS::INSTANCE_MULTIMESH || p_type == VS::INSTANCE_PARTICLES || p_type == VS::INSTANCE_IMMEDIATE; -} - -void VisualServerScene::instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->lightmap_capture) { - InstanceLightmapCaptureData *lightmap_capture = static_cast(((Instance *)instance->lightmap_capture)->base_data); - lightmap_capture->users.erase(instance); - instance->lightmap = RID(); - instance->lightmap_capture = NULL; - } - - if (p_lightmap_instance.is_valid()) { - Instance *lightmap_instance = instance_owner.getornull(p_lightmap_instance); - ERR_FAIL_COND(!lightmap_instance); - ERR_FAIL_COND(lightmap_instance->base_type != VS::INSTANCE_LIGHTMAP_CAPTURE); - instance->lightmap_capture = lightmap_instance; - - InstanceLightmapCaptureData *lightmap_capture = static_cast(((Instance *)instance->lightmap_capture)->base_data); - lightmap_capture->users.insert(instance); - instance->lightmap = p_lightmap; - } -} - -void VisualServerScene::instance_set_custom_aabb(RID p_instance, AABB p_aabb) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - ERR_FAIL_COND(!is_geometry_instance(instance->base_type)); - - if (p_aabb != AABB()) { - - // Set custom AABB - if (instance->custom_aabb == NULL) - instance->custom_aabb = memnew(AABB); - *instance->custom_aabb = p_aabb; - - } else { - - // Clear custom AABB - if (instance->custom_aabb != NULL) { - memdelete(instance->custom_aabb); - instance->custom_aabb = NULL; - } - } - - if (instance->scenario) - _instance_queue_update(instance, true, false); -} - -void VisualServerScene::instance_attach_skeleton(RID p_instance, RID p_skeleton) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - if (instance->skeleton == p_skeleton) - return; - - instance->skeleton = p_skeleton; - - if (p_skeleton.is_valid()) { - //update the dependency now, so if cleared, we remove it - VSG::storage->skeleton_update_dependency(p_skeleton, instance); - } - _instance_queue_update(instance, true, true); -} - -void VisualServerScene::instance_set_exterior(RID p_instance, bool p_enabled) { -} - -void VisualServerScene::instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) { - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->extra_margin = p_margin; - _instance_queue_update(instance, true, false); -} - -Vector VisualServerScene::instances_cull_aabb(const AABB &p_aabb, RID p_scenario) const { - - Vector instances; - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND_V(!scenario, instances); - - const_cast(this)->update_dirty_instances(); // check dirty instances before culling - - int culled = 0; - Instance *cull[1024]; - culled = scenario->octree.cull_aabb(p_aabb, cull, 1024); - - for (int i = 0; i < culled; i++) { - - Instance *instance = cull[i]; - ERR_CONTINUE(!instance); - if (instance->object_id.is_null()) - continue; - - instances.push_back(instance->object_id); - } - - return instances; -} -Vector VisualServerScene::instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { - - Vector instances; - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND_V(!scenario, instances); - const_cast(this)->update_dirty_instances(); // check dirty instances before culling - - int culled = 0; - Instance *cull[1024]; - culled = scenario->octree.cull_segment(p_from, p_from + p_to * 10000, cull, 1024); - - for (int i = 0; i < culled; i++) { - Instance *instance = cull[i]; - ERR_CONTINUE(!instance); - if (instance->object_id.is_null()) - continue; - - instances.push_back(instance->object_id); - } - - return instances; -} -Vector VisualServerScene::instances_cull_convex(const Vector &p_convex, RID p_scenario) const { - - Vector instances; - Scenario *scenario = scenario_owner.getornull(p_scenario); - ERR_FAIL_COND_V(!scenario, instances); - const_cast(this)->update_dirty_instances(); // check dirty instances before culling - - int culled = 0; - Instance *cull[1024]; - - culled = scenario->octree.cull_convex(p_convex, cull, 1024); - - for (int i = 0; i < culled; i++) { - - Instance *instance = cull[i]; - ERR_CONTINUE(!instance); - if (instance->object_id.is_null()) - continue; - - instances.push_back(instance->object_id); - } - - return instances; -} - -void VisualServerScene::instance_geometry_set_flag(RID p_instance, VS::InstanceFlags p_flags, bool p_enabled) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - //ERR_FAIL_COND(((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK)); - - switch (p_flags) { - - case VS::INSTANCE_FLAG_USE_BAKED_LIGHT: { - - instance->baked_light = p_enabled; - - } break; - case VS::INSTANCE_FLAG_USE_DYNAMIC_GI: { - - if (p_enabled == instance->dynamic_gi) { - //bye, redundant - return; - } - - if (instance->octree_id != 0) { - //remove from octree, it needs to be re-paired - instance->scenario->octree.erase(instance->octree_id); - instance->octree_id = 0; - _instance_queue_update(instance, true, true); - } - - //once out of octree, can be changed - instance->dynamic_gi = p_enabled; - - } break; - case VS::INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE: { - - instance->redraw_if_visible = p_enabled; - - } break; - default: { - } - } -} -void VisualServerScene::instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->cast_shadows = p_shadow_casting_setting; - _instance_queue_update(instance, false, true); -} -void VisualServerScene::instance_geometry_set_material_override(RID p_instance, RID p_material) { - - Instance *instance = instance_owner.getornull(p_instance); - ERR_FAIL_COND(!instance); - - instance->material_override = p_material; - _instance_queue_update(instance, false, true); -} - -void VisualServerScene::instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) { -} -void VisualServerScene::instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) { -} - -void VisualServerScene::_update_instance(Instance *p_instance) { - - p_instance->version++; - - if (p_instance->base_type == VS::INSTANCE_LIGHT) { - - InstanceLightData *light = static_cast(p_instance->base_data); - - VSG::scene_render->light_instance_set_transform(light->instance, p_instance->transform); - light->shadow_dirty = true; - } - - if (p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE) { - - InstanceReflectionProbeData *reflection_probe = static_cast(p_instance->base_data); - - VSG::scene_render->reflection_probe_instance_set_transform(reflection_probe->instance, p_instance->transform); - reflection_probe->reflection_dirty = true; - } - - if (p_instance->base_type == VS::INSTANCE_GI_PROBE) { - - InstanceGIProbeData *gi_probe = static_cast(p_instance->base_data); - - VSG::scene_render->gi_probe_instance_set_transform_to_data(gi_probe->probe_instance, p_instance->transform); - } - - if (p_instance->base_type == VS::INSTANCE_PARTICLES) { - - VSG::storage->particles_set_emission_transform(p_instance->base, p_instance->transform); - } - - if (p_instance->aabb.has_no_surface()) { - return; - } - - if ((1 << p_instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) { - - InstanceGeometryData *geom = static_cast(p_instance->base_data); - //make sure lights are updated if it casts shadow - - if (geom->can_cast_shadows) { - for (List::Element *E = geom->lighting.front(); E; E = E->next()) { - InstanceLightData *light = static_cast(E->get()->base_data); - light->shadow_dirty = true; - } - } - - if (!p_instance->lightmap_capture && geom->lightmap_captures.size()) { - //affected by lightmap captures, must update capture info! - _update_instance_lightmap_captures(p_instance); - } else { - if (!p_instance->lightmap_capture_data.empty()) { - p_instance->lightmap_capture_data.resize(0); //not in use, clear capture data - } - } - } - - p_instance->mirror = p_instance->transform.basis.determinant() < 0.0; - - AABB new_aabb; - - new_aabb = p_instance->transform.xform(p_instance->aabb); - - p_instance->transformed_aabb = new_aabb; - - if (!p_instance->scenario) { - - return; - } - - if (p_instance->octree_id == 0) { - - uint32_t base_type = 1 << p_instance->base_type; - uint32_t pairable_mask = 0; - bool pairable = false; - - if (p_instance->base_type == VS::INSTANCE_LIGHT || p_instance->base_type == VS::INSTANCE_REFLECTION_PROBE || p_instance->base_type == VS::INSTANCE_LIGHTMAP_CAPTURE) { - - pairable_mask = p_instance->visible ? VS::INSTANCE_GEOMETRY_MASK : 0; - pairable = true; - } - - if (p_instance->base_type == VS::INSTANCE_GI_PROBE) { - //lights and geometries - pairable_mask = p_instance->visible ? VS::INSTANCE_GEOMETRY_MASK | (1 << VS::INSTANCE_LIGHT) : 0; - pairable = true; - } - - // not inside octree - p_instance->octree_id = p_instance->scenario->octree.create(p_instance, new_aabb, 0, pairable, base_type, pairable_mask); - - } else { - - /* - if (new_aabb==p_instance->data.transformed_aabb) - return; - */ - - p_instance->scenario->octree.move(p_instance->octree_id, new_aabb); - } -} - -void VisualServerScene::_update_instance_aabb(Instance *p_instance) { - - AABB new_aabb; - - ERR_FAIL_COND(p_instance->base_type != VS::INSTANCE_NONE && !p_instance->base.is_valid()); - - switch (p_instance->base_type) { - case VisualServer::INSTANCE_NONE: { - - // do nothing - } break; - case VisualServer::INSTANCE_MESH: { - - if (p_instance->custom_aabb) - new_aabb = *p_instance->custom_aabb; - else - new_aabb = VSG::storage->mesh_get_aabb(p_instance->base, p_instance->skeleton); - - } break; - - case VisualServer::INSTANCE_MULTIMESH: { - - if (p_instance->custom_aabb) - new_aabb = *p_instance->custom_aabb; - else - new_aabb = VSG::storage->multimesh_get_aabb(p_instance->base); - - } break; - case VisualServer::INSTANCE_IMMEDIATE: { - - if (p_instance->custom_aabb) - new_aabb = *p_instance->custom_aabb; - else - new_aabb = VSG::storage->immediate_get_aabb(p_instance->base); - - } break; - case VisualServer::INSTANCE_PARTICLES: { - - if (p_instance->custom_aabb) - new_aabb = *p_instance->custom_aabb; - else - new_aabb = VSG::storage->particles_get_aabb(p_instance->base); - - } break; - case VisualServer::INSTANCE_LIGHT: { - - new_aabb = VSG::storage->light_get_aabb(p_instance->base); - - } break; - case VisualServer::INSTANCE_REFLECTION_PROBE: { - - new_aabb = VSG::storage->reflection_probe_get_aabb(p_instance->base); - - } break; - case VisualServer::INSTANCE_GI_PROBE: { - - new_aabb = VSG::storage->gi_probe_get_bounds(p_instance->base); - - } break; - case VisualServer::INSTANCE_LIGHTMAP_CAPTURE: { - - new_aabb = VSG::storage->lightmap_capture_get_bounds(p_instance->base); - - } break; - default: { - } - } - - // This is why I didn't re-use Instance::aabb to implement custom AABBs - if (p_instance->extra_margin) - new_aabb.grow_by(p_instance->extra_margin); - - p_instance->aabb = new_aabb; -} - -_FORCE_INLINE_ static void _light_capture_sample_octree(const RasterizerStorage::LightmapCaptureOctree *p_octree, int p_cell_subdiv, const Vector3 &p_pos, const Vector3 &p_dir, float p_level, Vector3 &r_color, float &r_alpha) { - - static const Vector3 aniso_normal[6] = { - Vector3(-1, 0, 0), - Vector3(1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, 1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, 1) - }; - - int size = 1 << (p_cell_subdiv - 1); - - int clamp_v = size - 1; - //first of all, clamp - Vector3 pos; - pos.x = CLAMP(p_pos.x, 0, clamp_v); - pos.y = CLAMP(p_pos.y, 0, clamp_v); - pos.z = CLAMP(p_pos.z, 0, clamp_v); - - float level = (p_cell_subdiv - 1) - p_level; - - int target_level; - float level_filter; - if (level <= 0.0) { - level_filter = 0; - target_level = 0; - } else { - target_level = Math::ceil(level); - level_filter = target_level - level; - } - - Vector3 color[2][8]; - float alpha[2][8]; - zeromem(alpha, sizeof(float) * 2 * 8); - - //find cell at given level first - - for (int c = 0; c < 2; c++) { - - int current_level = MAX(0, target_level - c); - int level_cell_size = (1 << (p_cell_subdiv - 1)) >> current_level; - - for (int n = 0; n < 8; n++) { - - int x = int(pos.x); - int y = int(pos.y); - int z = int(pos.z); - - if (n & 1) - x += level_cell_size; - if (n & 2) - y += level_cell_size; - if (n & 4) - z += level_cell_size; - - int ofs_x = 0; - int ofs_y = 0; - int ofs_z = 0; - - x = CLAMP(x, 0, clamp_v); - y = CLAMP(y, 0, clamp_v); - z = CLAMP(z, 0, clamp_v); - - int half = size / 2; - uint32_t cell = 0; - for (int i = 0; i < current_level; i++) { - - const RasterizerStorage::LightmapCaptureOctree *bc = &p_octree[cell]; - - int child = 0; - if (x >= ofs_x + half) { - child |= 1; - ofs_x += half; - } - if (y >= ofs_y + half) { - child |= 2; - ofs_y += half; - } - if (z >= ofs_z + half) { - child |= 4; - ofs_z += half; - } - - cell = bc->children[child]; - if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) - break; - - half >>= 1; - } - - if (cell == RasterizerStorage::LightmapCaptureOctree::CHILD_EMPTY) { - alpha[c][n] = 0; - } else { - alpha[c][n] = p_octree[cell].alpha; - - for (int i = 0; i < 6; i++) { - //anisotropic read light - float amount = p_dir.dot(aniso_normal[i]); - if (amount < 0) - amount = 0; - color[c][n].x += p_octree[cell].light[i][0] / 1024.0 * amount; - color[c][n].y += p_octree[cell].light[i][1] / 1024.0 * amount; - color[c][n].z += p_octree[cell].light[i][2] / 1024.0 * amount; - } - } - - //print_line("\tlev " + itos(c) + " - " + itos(n) + " alpha: " + rtos(cells[test_cell].alpha) + " col: " + color[c][n]); - } - } - - float target_level_size = size >> target_level; - Vector3 pos_fract[2]; - - pos_fract[0].x = Math::fmod(pos.x, target_level_size) / target_level_size; - pos_fract[0].y = Math::fmod(pos.y, target_level_size) / target_level_size; - pos_fract[0].z = Math::fmod(pos.z, target_level_size) / target_level_size; - - target_level_size = size >> MAX(0, target_level - 1); - - pos_fract[1].x = Math::fmod(pos.x, target_level_size) / target_level_size; - pos_fract[1].y = Math::fmod(pos.y, target_level_size) / target_level_size; - pos_fract[1].z = Math::fmod(pos.z, target_level_size) / target_level_size; - - float alpha_interp[2]; - Vector3 color_interp[2]; - - for (int i = 0; i < 2; i++) { - - Vector3 color_x00 = color[i][0].linear_interpolate(color[i][1], pos_fract[i].x); - Vector3 color_xy0 = color[i][2].linear_interpolate(color[i][3], pos_fract[i].x); - Vector3 blend_z0 = color_x00.linear_interpolate(color_xy0, pos_fract[i].y); - - Vector3 color_x0z = color[i][4].linear_interpolate(color[i][5], pos_fract[i].x); - Vector3 color_xyz = color[i][6].linear_interpolate(color[i][7], pos_fract[i].x); - Vector3 blend_z1 = color_x0z.linear_interpolate(color_xyz, pos_fract[i].y); - - color_interp[i] = blend_z0.linear_interpolate(blend_z1, pos_fract[i].z); - - float alpha_x00 = Math::lerp(alpha[i][0], alpha[i][1], pos_fract[i].x); - float alpha_xy0 = Math::lerp(alpha[i][2], alpha[i][3], pos_fract[i].x); - float alpha_z0 = Math::lerp(alpha_x00, alpha_xy0, pos_fract[i].y); - - float alpha_x0z = Math::lerp(alpha[i][4], alpha[i][5], pos_fract[i].x); - float alpha_xyz = Math::lerp(alpha[i][6], alpha[i][7], pos_fract[i].x); - float alpha_z1 = Math::lerp(alpha_x0z, alpha_xyz, pos_fract[i].y); - - alpha_interp[i] = Math::lerp(alpha_z0, alpha_z1, pos_fract[i].z); - } - - r_color = color_interp[0].linear_interpolate(color_interp[1], level_filter); - r_alpha = Math::lerp(alpha_interp[0], alpha_interp[1], level_filter); - - //print_line("pos: " + p_posf + " level " + rtos(p_level) + " down to " + itos(target_level) + "." + rtos(level_filter) + " color " + r_color + " alpha " + rtos(r_alpha)); -} - -_FORCE_INLINE_ static Color _light_capture_voxel_cone_trace(const RasterizerStorage::LightmapCaptureOctree *p_octree, const Vector3 &p_pos, const Vector3 &p_dir, float p_aperture, int p_cell_subdiv) { - - float bias = 0.0; //no need for bias here - float max_distance = (Vector3(1, 1, 1) * (1 << (p_cell_subdiv - 1))).length(); - - float dist = bias; - float alpha = 0.0; - Vector3 color; - - Vector3 scolor; - float salpha; - - while (dist < max_distance && alpha < 0.95) { - float diameter = MAX(1.0, 2.0 * p_aperture * dist); - _light_capture_sample_octree(p_octree, p_cell_subdiv, p_pos + dist * p_dir, p_dir, log2(diameter), scolor, salpha); - float a = (1.0 - alpha); - color += scolor * a; - alpha += a * salpha; - dist += diameter * 0.5; - } - - return Color(color.x, color.y, color.z, alpha); -} - -void VisualServerScene::_update_instance_lightmap_captures(Instance *p_instance) { - - InstanceGeometryData *geom = static_cast(p_instance->base_data); - - static const Vector3 cone_traces[12] = { - Vector3(0, 0, 1), - Vector3(0.866025, 0, 0.5), - Vector3(0.267617, 0.823639, 0.5), - Vector3(-0.700629, 0.509037, 0.5), - Vector3(-0.700629, -0.509037, 0.5), - Vector3(0.267617, -0.823639, 0.5), - Vector3(0, 0, -1), - Vector3(0.866025, 0, -0.5), - Vector3(0.267617, 0.823639, -0.5), - Vector3(-0.700629, 0.509037, -0.5), - Vector3(-0.700629, -0.509037, -0.5), - Vector3(0.267617, -0.823639, -0.5) - }; - - float cone_aperture = 0.577; // tan(angle) 60 degrees - - if (p_instance->lightmap_capture_data.empty()) { - p_instance->lightmap_capture_data.resize(12); - } - - //print_line("update captures for pos: " + p_instance->transform.origin); - - for (int i = 0; i < 12; i++) - new (&p_instance->lightmap_capture_data.ptrw()[i]) Color; - - //this could use some sort of blending.. - for (List::Element *E = geom->lightmap_captures.front(); E; E = E->next()) { - const Vector *octree = VSG::storage->lightmap_capture_get_octree_ptr(E->get()->base); - //print_line("octree size: " + itos(octree->size())); - if (octree->size() == 0) - continue; - Transform to_cell_xform = VSG::storage->lightmap_capture_get_octree_cell_transform(E->get()->base); - int cell_subdiv = VSG::storage->lightmap_capture_get_octree_cell_subdiv(E->get()->base); - to_cell_xform = to_cell_xform * E->get()->transform.affine_inverse(); - - const RasterizerStorage::LightmapCaptureOctree *octree_r = octree->ptr(); - - Vector3 pos = to_cell_xform.xform(p_instance->transform.origin); - - for (int i = 0; i < 12; i++) { - - Vector3 dir = to_cell_xform.basis.xform(cone_traces[i]).normalized(); - Color capture = _light_capture_voxel_cone_trace(octree_r, pos, dir, cone_aperture, cell_subdiv); - p_instance->lightmap_capture_data.write[i] += capture; - } - } -} - -bool VisualServerScene::_light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario) { - - InstanceLightData *light = static_cast(p_instance->base_data); - - Transform light_transform = p_instance->transform; - light_transform.orthonormalize(); //scale does not count on lights - - bool animated_material_found = false; - - switch (VSG::storage->light_get_type(p_instance->base)) { - - case VS::LIGHT_DIRECTIONAL: { - - float max_distance = p_cam_projection.get_z_far(); - float shadow_max = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_SHADOW_MAX_DISTANCE); - if (shadow_max > 0 && !p_cam_orthogonal) { //its impractical (and leads to unwanted behaviors) to set max distance in orthogonal camera - max_distance = MIN(shadow_max, max_distance); - } - max_distance = MAX(max_distance, p_cam_projection.get_z_near() + 0.001); - float min_distance = MIN(p_cam_projection.get_z_near(), max_distance); - - VS::LightDirectionalShadowDepthRangeMode depth_range_mode = VSG::storage->light_directional_get_shadow_depth_range_mode(p_instance->base); - - if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED) { - //optimize min/max - Vector planes = p_cam_projection.get_projection_planes(p_cam_transform); - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - Plane base(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2)); - //check distance max and min - - bool found_items = false; - float z_max = -1e20; - float z_min = 1e20; - - for (int i = 0; i < cull_count; i++) { - - Instance *instance = instance_shadow_cull_result[i]; - if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { - continue; - } - - if (static_cast(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - - float max, min; - instance->transformed_aabb.project_range_in_plane(base, min, max); - - if (max > z_max) { - z_max = max; - } - - if (min < z_min) { - z_min = min; - } - - found_items = true; - } - - if (found_items) { - min_distance = MAX(min_distance, z_min); - max_distance = MIN(max_distance, z_max); - } - } - - float range = max_distance - min_distance; - - int splits = 0; - switch (VSG::storage->light_directional_get_shadow_mode(p_instance->base)) { - case VS::LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL: splits = 1; break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS: splits = 2; break; - case VS::LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS: splits = 4; break; - } - - float distances[5]; - - distances[0] = min_distance; - for (int i = 0; i < splits; i++) { - distances[i + 1] = min_distance + VSG::storage->light_get_param(p_instance->base, VS::LightParam(VS::LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET + i)) * range; - }; - - distances[splits] = max_distance; - - float texture_size = VSG::scene_render->get_directional_light_shadow_size(light->instance); - - bool overlap = VSG::storage->light_directional_get_blend_splits(p_instance->base); - - float first_radius = 0.0; - - for (int i = 0; i < splits; i++) { - - RENDER_TIMESTAMP("Culling Directional Light split" + itos(i)); - - // setup a camera matrix for that range! - CameraMatrix camera_matrix; - - float aspect = p_cam_projection.get_aspect(); - - if (p_cam_orthogonal) { - - Vector2 vp_he = p_cam_projection.get_viewport_half_extents(); - - camera_matrix.set_orthogonal(vp_he.y * 2.0, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); - } else { - - float fov = p_cam_projection.get_fov(); - camera_matrix.set_perspective(fov, aspect, distances[(i == 0 || !overlap) ? i : i - 1], distances[i + 1], false); - } - - //obtain the frustum endpoints - - Vector3 endpoints[8]; // frustum plane endpoints - bool res = camera_matrix.get_endpoints(p_cam_transform, endpoints); - ERR_CONTINUE(!res); - - // obtain the light frustm ranges (given endpoints) - - Transform transform = light_transform; //discard scale and stabilize light - - Vector3 x_vec = transform.basis.get_axis(Vector3::AXIS_X).normalized(); - Vector3 y_vec = transform.basis.get_axis(Vector3::AXIS_Y).normalized(); - Vector3 z_vec = transform.basis.get_axis(Vector3::AXIS_Z).normalized(); - //z_vec points agsint the camera, like in default opengl - - float x_min = 0.f, x_max = 0.f; - float y_min = 0.f, y_max = 0.f; - float z_min = 0.f, z_max = 0.f; - - // FIXME: z_max_cam is defined, computed, but not used below when setting up - // ortho_camera. Commented out for now to fix warnings but should be investigated. - float x_min_cam = 0.f, x_max_cam = 0.f; - float y_min_cam = 0.f, y_max_cam = 0.f; - float z_min_cam = 0.f; - //float z_max_cam = 0.f; - - float bias_scale = 1.0; - - //used for culling - - for (int j = 0; j < 8; j++) { - - float d_x = x_vec.dot(endpoints[j]); - float d_y = y_vec.dot(endpoints[j]); - float d_z = z_vec.dot(endpoints[j]); - - if (j == 0 || d_x < x_min) - x_min = d_x; - if (j == 0 || d_x > x_max) - x_max = d_x; - - if (j == 0 || d_y < y_min) - y_min = d_y; - if (j == 0 || d_y > y_max) - y_max = d_y; - - if (j == 0 || d_z < z_min) - z_min = d_z; - if (j == 0 || d_z > z_max) - z_max = d_z; - } - - { - //camera viewport stuff - - Vector3 center; - - for (int j = 0; j < 8; j++) { - - center += endpoints[j]; - } - center /= 8.0; - - //center=x_vec*(x_max-x_min)*0.5 + y_vec*(y_max-y_min)*0.5 + z_vec*(z_max-z_min)*0.5; - - float radius = 0; - - for (int j = 0; j < 8; j++) { - - float d = center.distance_to(endpoints[j]); - if (d > radius) - radius = d; - } - - radius *= texture_size / (texture_size - 2.0); //add a texel by each side - - if (i == 0) { - first_radius = radius; - } else { - bias_scale = radius / first_radius; - } - - x_max_cam = x_vec.dot(center) + radius; - x_min_cam = x_vec.dot(center) - radius; - y_max_cam = y_vec.dot(center) + radius; - y_min_cam = y_vec.dot(center) - radius; - //z_max_cam = z_vec.dot(center) + radius; - z_min_cam = z_vec.dot(center) - radius; - - if (depth_range_mode == VS::LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE) { - //this trick here is what stabilizes the shadow (make potential jaggies to not move) - //at the cost of some wasted resolution. Still the quality increase is very well worth it - - float unit = radius * 2.0 / texture_size; - - x_max_cam = Math::stepify(x_max_cam, unit); - x_min_cam = Math::stepify(x_min_cam, unit); - y_max_cam = Math::stepify(y_max_cam, unit); - y_min_cam = Math::stepify(y_min_cam, unit); - } - } - - //now that we now all ranges, we can proceed to make the light frustum planes, for culling octree - - Vector light_frustum_planes; - light_frustum_planes.resize(6); - - //right/left - light_frustum_planes.write[0] = Plane(x_vec, x_max); - light_frustum_planes.write[1] = Plane(-x_vec, -x_min); - //top/bottom - light_frustum_planes.write[2] = Plane(y_vec, y_max); - light_frustum_planes.write[3] = Plane(-y_vec, -y_min); - //near/far - light_frustum_planes.write[4] = Plane(z_vec, z_max + 1e6); - light_frustum_planes.write[5] = Plane(-z_vec, -z_min); // z_min is ok, since casters further than far-light plane are not needed - - int cull_count = p_scenario->octree.cull_convex(light_frustum_planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - - // a pre pass will need to be needed to determine the actual z-near to be used - - Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); - - for (int j = 0; j < cull_count; j++) { - - float min, max; - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - continue; - } - - instance->transformed_aabb.project_range_in_plane(Plane(z_vec, 0), min, max); - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - if (max > z_max) - z_max = max; - } - - { - - CameraMatrix ortho_camera; - real_t half_x = (x_max_cam - x_min_cam) * 0.5; - real_t half_y = (y_max_cam - y_min_cam) * 0.5; - - ortho_camera.set_orthogonal(-half_x, half_x, -half_y, half_y, 0, (z_max - z_min_cam)); - - Transform ortho_transform; - ortho_transform.basis = transform.basis; - ortho_transform.origin = x_vec * (x_min_cam + half_x) + y_vec * (y_min_cam + half_y) + z_vec * z_max; - - VSG::scene_render->light_instance_set_shadow_transform(light->instance, ortho_camera, ortho_transform, 0, distances[i + 1], i, bias_scale); - } - - VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - } - - } break; - case VS::LIGHT_OMNI: { - - VS::LightOmniShadowMode shadow_mode = VSG::storage->light_omni_get_shadow_mode(p_instance->base); - - if (shadow_mode == VS::LIGHT_OMNI_SHADOW_DUAL_PARABOLOID || !VSG::scene_render->light_instances_can_render_shadow_cube()) { - - for (int i = 0; i < 2; i++) { - - //using this one ensures that raster deferred will have it - RENDER_TIMESTAMP("Culling Shadow Paraboloid" + itos(i)); - - float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE); - - float z = i == 0 ? -1 : 1; - Vector planes; - planes.resize(5); - planes.write[0] = light_transform.xform(Plane(Vector3(0, 0, z), radius)); - planes.write[1] = light_transform.xform(Plane(Vector3(1, 0, z).normalized(), radius)); - planes.write[2] = light_transform.xform(Plane(Vector3(-1, 0, z).normalized(), radius)); - planes.write[3] = light_transform.xform(Plane(Vector3(0, 1, z).normalized(), radius)); - planes.write[4] = light_transform.xform(Plane(Vector3(0, -1, z).normalized(), radius)); - - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - Plane near_plane(light_transform.origin, light_transform.basis.get_axis(2) * z); - - for (int j = 0; j < cull_count; j++) { - - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - } else { - if (static_cast(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - } - } - - VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, i); - VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - } - } else { //shadow cube - - float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE); - CameraMatrix cm; - cm.set_perspective(90, 1, 0.01, radius); - - for (int i = 0; i < 6; i++) { - - RENDER_TIMESTAMP("Culling Shadow Cube side" + itos(i)); - //using this one ensures that raster deferred will have it - - static const Vector3 view_normals[6] = { - Vector3(+1, 0, 0), - Vector3(-1, 0, 0), - Vector3(0, -1, 0), - Vector3(0, +1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1) - }; - static const Vector3 view_up[6] = { - Vector3(0, -1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, -1), - Vector3(0, 0, +1), - Vector3(0, -1, 0), - Vector3(0, -1, 0) - }; - - Transform xform = light_transform * Transform().looking_at(view_normals[i], view_up[i]); - - Vector planes = cm.get_projection_planes(xform); - - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - - Plane near_plane(xform.origin, -xform.basis.get_axis(2)); - for (int j = 0; j < cull_count; j++) { - - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - } else { - if (static_cast(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - } - } - - VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, xform, radius, 0, i); - VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, i, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - } - - //restore the regular DP matrix - VSG::scene_render->light_instance_set_shadow_transform(light->instance, CameraMatrix(), light_transform, radius, 0, 0); - } - - } break; - case VS::LIGHT_SPOT: { - - RENDER_TIMESTAMP("Culling Spot Light"); - - float radius = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_RANGE); - float angle = VSG::storage->light_get_param(p_instance->base, VS::LIGHT_PARAM_SPOT_ANGLE); - - CameraMatrix cm; - cm.set_perspective(angle * 2.0, 1.0, 0.01, radius); - - Vector planes = cm.get_projection_planes(light_transform); - int cull_count = p_scenario->octree.cull_convex(planes, instance_shadow_cull_result, MAX_INSTANCE_CULL, VS::INSTANCE_GEOMETRY_MASK); - - Plane near_plane(light_transform.origin, -light_transform.basis.get_axis(2)); - for (int j = 0; j < cull_count; j++) { - - Instance *instance = instance_shadow_cull_result[j]; - if (!instance->visible || !((1 << instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) || !static_cast(instance->base_data)->can_cast_shadows) { - cull_count--; - SWAP(instance_shadow_cull_result[j], instance_shadow_cull_result[cull_count]); - j--; - } else { - if (static_cast(instance->base_data)->material_is_animated) { - animated_material_found = true; - } - instance->depth = near_plane.distance_to(instance->transform.origin); - instance->depth_layer = 0; - } - } - - VSG::scene_render->light_instance_set_shadow_transform(light->instance, cm, light_transform, radius, 0, 0); - VSG::scene_render->render_shadow(light->instance, p_shadow_atlas, 0, (RasterizerScene::InstanceBase **)instance_shadow_cull_result, cull_count); - - } break; - } - - return animated_material_found; -} - -void VisualServerScene::render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { -// render to mono camera -#ifndef _3D_DISABLED - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - - /* STEP 1 - SETUP CAMERA */ - CameraMatrix camera_matrix; - bool ortho = false; - - switch (camera->type) { - case Camera::ORTHOGONAL: { - - camera_matrix.set_orthogonal( - camera->size, - p_viewport_size.width / (float)p_viewport_size.height, - camera->znear, - camera->zfar, - camera->vaspect); - ortho = true; - } break; - case Camera::PERSPECTIVE: { - - camera_matrix.set_perspective( - camera->fov, - p_viewport_size.width / (float)p_viewport_size.height, - camera->znear, - camera->zfar, - camera->vaspect); - ortho = false; - - } break; - case Camera::FRUSTUM: { - - camera_matrix.set_frustum( - camera->size, - p_viewport_size.width / (float)p_viewport_size.height, - camera->offset, - camera->znear, - camera->zfar, - camera->vaspect); - ortho = false; - } break; - } - - _prepare_scene(camera->transform, camera_matrix, ortho, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - _render_scene(p_render_buffers, camera->transform, camera_matrix, ortho, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); -#endif -} - -void VisualServerScene::render_camera(RID p_render_buffers, Ref &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas) { - // render for AR/VR interface - - Camera *camera = camera_owner.getornull(p_camera); - ERR_FAIL_COND(!camera); - - /* SETUP CAMERA, we are ignoring type and FOV here */ - float aspect = p_viewport_size.width / (float)p_viewport_size.height; - CameraMatrix camera_matrix = p_interface->get_projection_for_eye(p_eye, aspect, camera->znear, camera->zfar); - - // We also ignore our camera position, it will have been positioned with a slightly old tracking position. - // Instead we take our origin point and have our ar/vr interface add fresh tracking data! Whoohoo! - Transform world_origin = ARVRServer::get_singleton()->get_world_origin(); - Transform cam_transform = p_interface->get_transform_for_eye(p_eye, world_origin); - - // For stereo render we only prepare for our left eye and then reuse the outcome for our right eye - if (p_eye == ARVRInterface::EYE_LEFT) { - ///@TODO possibly move responsibility for this into our ARVRServer or ARVRInterface? - - // Center our transform, we assume basis is equal. - Transform mono_transform = cam_transform; - Transform right_transform = p_interface->get_transform_for_eye(ARVRInterface::EYE_RIGHT, world_origin); - mono_transform.origin += right_transform.origin; - mono_transform.origin *= 0.5; - - // We need to combine our projection frustums for culling. - // Ideally we should use our clipping planes for this and combine them, - // however our shadow map logic uses our projection matrix. - // Note: as our left and right frustums should be mirrored, we don't need our right projection matrix. - - // - get some base values we need - float eye_dist = (mono_transform.origin - cam_transform.origin).length(); - float z_near = camera_matrix.get_z_near(); // get our near plane - float z_far = camera_matrix.get_z_far(); // get our far plane - float width = (2.0 * z_near) / camera_matrix.matrix[0][0]; - float x_shift = width * camera_matrix.matrix[2][0]; - float height = (2.0 * z_near) / camera_matrix.matrix[1][1]; - float y_shift = height * camera_matrix.matrix[2][1]; - - // printf("Eye_dist = %f, Near = %f, Far = %f, Width = %f, Shift = %f\n", eye_dist, z_near, z_far, width, x_shift); - - // - calculate our near plane size (horizontal only, right_near is mirrored) - float left_near = -eye_dist - ((width - x_shift) * 0.5); - - // - calculate our far plane size (horizontal only, right_far is mirrored) - float left_far = -eye_dist - (z_far * (width - x_shift) * 0.5 / z_near); - float left_far_right_eye = eye_dist - (z_far * (width + x_shift) * 0.5 / z_near); - if (left_far > left_far_right_eye) { - // on displays smaller then double our iod, the right eye far frustrum can overtake the left eyes. - left_far = left_far_right_eye; - } - - // - figure out required z-shift - float slope = (left_far - left_near) / (z_far - z_near); - float z_shift = (left_near / slope) - z_near; - - // - figure out new vertical near plane size (this will be slightly oversized thanks to our z-shift) - float top_near = (height - y_shift) * 0.5; - top_near += (top_near / z_near) * z_shift; - float bottom_near = -(height + y_shift) * 0.5; - bottom_near += (bottom_near / z_near) * z_shift; - - // printf("Left_near = %f, Left_far = %f, Top_near = %f, Bottom_near = %f, Z_shift = %f\n", left_near, left_far, top_near, bottom_near, z_shift); - - // - generate our frustum - CameraMatrix combined_matrix; - combined_matrix.set_frustum(left_near, -left_near, bottom_near, top_near, z_near + z_shift, z_far + z_shift); - - // and finally move our camera back - Transform apply_z_shift; - apply_z_shift.origin = Vector3(0.0, 0.0, z_shift); // z negative is forward so this moves it backwards - mono_transform *= apply_z_shift; - - // now prepare our scene with our adjusted transform projection matrix - _prepare_scene(mono_transform, combined_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - } else if (p_eye == ARVRInterface::EYE_MONO) { - // For mono render, prepare as per usual - _prepare_scene(cam_transform, camera_matrix, false, camera->env, camera->effects, camera->visible_layers, p_scenario, p_shadow_atlas, RID()); - } - - // And render our scene... - _render_scene(p_render_buffers, cam_transform, camera_matrix, false, camera->env, camera->effects, p_scenario, p_shadow_atlas, RID(), -1); -}; - -void VisualServerScene::_prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows) { - // Note, in stereo rendering: - // - p_cam_transform will be a transform in the middle of our two eyes - // - p_cam_projection is a wider frustrum that encompasses both eyes - - Scenario *scenario = scenario_owner.getornull(p_scenario); - - render_pass++; - uint32_t camera_layer_mask = p_visible_layers; - - VSG::scene_render->set_scene_pass(render_pass); - - RENDER_TIMESTAMP("Frustum Culling"); - - //rasterizer->set_camera(camera->transform, camera_matrix,ortho); - - Vector planes = p_cam_projection.get_projection_planes(p_cam_transform); - - Plane near_plane(p_cam_transform.origin, -p_cam_transform.basis.get_axis(2).normalized()); - float z_far = p_cam_projection.get_z_far(); - - /* STEP 2 - CULL */ - instance_cull_count = scenario->octree.cull_convex(planes, instance_cull_result, MAX_INSTANCE_CULL); - light_cull_count = 0; - - reflection_probe_cull_count = 0; - gi_probe_cull_count = 0; - - //light_samplers_culled=0; - - /* - print_line("OT: "+rtos( (OS::get_singleton()->get_ticks_usec()-t)/1000.0)); - print_line("OTO: "+itos(p_scenario->octree.get_octant_count())); - print_line("OTE: "+itos(p_scenario->octree.get_elem_count())); - print_line("OTP: "+itos(p_scenario->octree.get_pair_count())); - */ - - /* STEP 3 - PROCESS PORTALS, VALIDATE ROOMS */ - //removed, will replace with culling - - /* STEP 4 - REMOVE FURTHER CULLED OBJECTS, ADD LIGHTS */ - - for (int i = 0; i < instance_cull_count; i++) { - - Instance *ins = instance_cull_result[i]; - - bool keep = false; - - if ((camera_layer_mask & ins->layer_mask) == 0) { - //failure - } else if (ins->base_type == VS::INSTANCE_LIGHT && ins->visible) { - - if (light_cull_count < MAX_LIGHTS_CULLED) { - - InstanceLightData *light = static_cast(ins->base_data); - - if (!light->geometries.empty()) { - //do not add this light if no geometry is affected by it.. - light_cull_result[light_cull_count] = ins; - light_instance_cull_result[light_cull_count] = light->instance; - if (p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(ins->base)) { - VSG::scene_render->light_instance_mark_visible(light->instance); //mark it visible for shadow allocation later - } - - light_cull_count++; - } - } - } else if (ins->base_type == VS::INSTANCE_REFLECTION_PROBE && ins->visible) { - - if (reflection_probe_cull_count < MAX_REFLECTION_PROBES_CULLED) { - - InstanceReflectionProbeData *reflection_probe = static_cast(ins->base_data); - - if (p_reflection_probe != reflection_probe->instance) { - //avoid entering The Matrix - - if (!reflection_probe->geometries.empty()) { - //do not add this light if no geometry is affected by it.. - - if (reflection_probe->reflection_dirty || VSG::scene_render->reflection_probe_instance_needs_redraw(reflection_probe->instance)) { - if (!reflection_probe->update_list.in_list()) { - reflection_probe->render_step = 0; - reflection_probe_render_list.add_last(&reflection_probe->update_list); - } - - reflection_probe->reflection_dirty = false; - } - - if (VSG::scene_render->reflection_probe_instance_has_reflection(reflection_probe->instance)) { - reflection_probe_instance_cull_result[reflection_probe_cull_count] = reflection_probe->instance; - reflection_probe_cull_count++; - } - } - } - } - - } else if (ins->base_type == VS::INSTANCE_GI_PROBE && ins->visible) { - - InstanceGIProbeData *gi_probe = static_cast(ins->base_data); - if (!gi_probe->update_element.in_list()) { - gi_probe_update_list.add(&gi_probe->update_element); - } - - if (gi_probe_cull_count < MAX_GI_PROBES_CULLED) { - gi_probe_instance_cull_result[gi_probe_cull_count] = gi_probe->probe_instance; - gi_probe_cull_count++; - } - - } else if (((1 << ins->base_type) & VS::INSTANCE_GEOMETRY_MASK) && ins->visible && ins->cast_shadows != VS::SHADOW_CASTING_SETTING_SHADOWS_ONLY) { - - keep = true; - - InstanceGeometryData *geom = static_cast(ins->base_data); - - if (ins->redraw_if_visible) { - VisualServerRaster::redraw_request(); - } - - if (ins->base_type == VS::INSTANCE_PARTICLES) { - //particles visible? process them - if (VSG::storage->particles_is_inactive(ins->base)) { - //but if nothing is going on, don't do it. - keep = false; - } else { - VSG::storage->particles_request_process(ins->base); - //particles visible? request redraw - VisualServerRaster::redraw_request(); - } - } - - if (geom->lighting_dirty) { - int l = 0; - //only called when lights AABB enter/exit this geometry - ins->light_instances.resize(geom->lighting.size()); - - for (List::Element *E = geom->lighting.front(); E; E = E->next()) { - - InstanceLightData *light = static_cast(E->get()->base_data); - - ins->light_instances.write[l++] = light->instance; - } - - geom->lighting_dirty = false; - } - - if (geom->reflection_dirty) { - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->reflection_probe_instances.resize(geom->reflection_probes.size()); - - for (List::Element *E = geom->reflection_probes.front(); E; E = E->next()) { - - InstanceReflectionProbeData *reflection_probe = static_cast(E->get()->base_data); - - ins->reflection_probe_instances.write[l++] = reflection_probe->instance; - } - - geom->reflection_dirty = false; - } - - if (geom->gi_probes_dirty) { - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->gi_probe_instances.resize(geom->gi_probes.size()); - - for (List::Element *E = geom->gi_probes.front(); E; E = E->next()) { - - InstanceGIProbeData *gi_probe = static_cast(E->get()->base_data); - - ins->gi_probe_instances.write[l++] = gi_probe->probe_instance; - } - - geom->gi_probes_dirty = false; - } - - ins->depth = near_plane.distance_to(ins->transform.origin); - ins->depth_layer = CLAMP(int(ins->depth * 16 / z_far), 0, 15); - } - - if (!keep) { - // remove, no reason to keep - instance_cull_count--; - SWAP(instance_cull_result[i], instance_cull_result[instance_cull_count]); - i--; - ins->last_render_pass = 0; // make invalid - } else { - - ins->last_render_pass = render_pass; - } - } - - /* STEP 5 - PROCESS LIGHTS */ - - RID *directional_light_ptr = &light_instance_cull_result[light_cull_count]; - directional_light_count = 0; - - // directional lights - { - - Instance **lights_with_shadow = (Instance **)alloca(sizeof(Instance *) * scenario->directional_lights.size()); - int directional_shadow_count = 0; - - for (List::Element *E = scenario->directional_lights.front(); E; E = E->next()) { - - if (light_cull_count + directional_light_count >= MAX_LIGHTS_CULLED) { - break; - } - - if (!E->get()->visible) - continue; - - InstanceLightData *light = static_cast(E->get()->base_data); - - //check shadow.. - - if (light) { - if (p_using_shadows && p_shadow_atlas.is_valid() && VSG::storage->light_has_shadow(E->get()->base)) { - lights_with_shadow[directional_shadow_count++] = E->get(); - } - //add to list - directional_light_ptr[directional_light_count++] = light->instance; - } - } - - VSG::scene_render->set_directional_shadow_count(directional_shadow_count); - - for (int i = 0; i < directional_shadow_count; i++) { - - RENDER_TIMESTAMP(">Rendering Directional Light " + itos(i)); - - _light_instance_update_shadow(lights_with_shadow[i], p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario); - - RENDER_TIMESTAMP(" sorter; - //sorter.sort(light_cull_result,light_cull_count); - for (int i = 0; i < light_cull_count; i++) { - - Instance *ins = light_cull_result[i]; - - if (!p_shadow_atlas.is_valid() || !VSG::storage->light_has_shadow(ins->base)) - continue; - - InstanceLightData *light = static_cast(ins->base_data); - - float coverage = 0.f; - - { //compute coverage - - Transform cam_xf = p_cam_transform; - float zn = p_cam_projection.get_z_near(); - Plane p(cam_xf.origin + cam_xf.basis.get_axis(2) * -zn, -cam_xf.basis.get_axis(2)); //camera near plane - - // near plane half width and height - Vector2 vp_half_extents = p_cam_projection.get_viewport_half_extents(); - - switch (VSG::storage->light_get_type(ins->base)) { - - case VS::LIGHT_OMNI: { - - float radius = VSG::storage->light_get_param(ins->base, VS::LIGHT_PARAM_RANGE); - - //get two points parallel to near plane - Vector3 points[2] = { - ins->transform.origin, - ins->transform.origin + cam_xf.basis.get_axis(0) * radius - }; - - if (!p_cam_orthogonal) { - //if using perspetive, map them to near plane - for (int j = 0; j < 2; j++) { - if (p.distance_to(points[j]) < 0) { - points[j].z = -zn; //small hack to keep size constant when hitting the screen - } - - p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane - } - } - - float screen_diameter = points[0].distance_to(points[1]) * 2; - coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); - } break; - case VS::LIGHT_SPOT: { - - float radius = VSG::storage->light_get_param(ins->base, VS::LIGHT_PARAM_RANGE); - float angle = VSG::storage->light_get_param(ins->base, VS::LIGHT_PARAM_SPOT_ANGLE); - - float w = radius * Math::sin(Math::deg2rad(angle)); - float d = radius * Math::cos(Math::deg2rad(angle)); - - Vector3 base = ins->transform.origin - ins->transform.basis.get_axis(2).normalized() * d; - - Vector3 points[2] = { - base, - base + cam_xf.basis.get_axis(0) * w - }; - - if (!p_cam_orthogonal) { - //if using perspetive, map them to near plane - for (int j = 0; j < 2; j++) { - if (p.distance_to(points[j]) < 0) { - points[j].z = -zn; //small hack to keep size constant when hitting the screen - } - - p.intersects_segment(cam_xf.origin, points[j], &points[j]); //map to plane - } - } - - float screen_diameter = points[0].distance_to(points[1]) * 2; - coverage = screen_diameter / (vp_half_extents.x + vp_half_extents.y); - - } break; - default: { - ERR_PRINT("Invalid Light Type"); - } - } - } - - if (light->shadow_dirty) { - light->last_version++; - light->shadow_dirty = false; - } - - bool redraw = VSG::scene_render->shadow_atlas_update_light(p_shadow_atlas, light->instance, coverage, light->last_version); - - if (redraw) { - //must redraw! - RENDER_TIMESTAMP(">Rendering Light " + itos(i)); - light->shadow_dirty = _light_instance_update_shadow(ins, p_cam_transform, p_cam_projection, p_cam_orthogonal, p_shadow_atlas, scenario); - RENDER_TIMESTAMP("environment.is_valid()) - environment = scenario->environment; - else - environment = scenario->fallback_environment; - - RID camera_effects; - if (p_force_camera_effects.is_valid()) { - camera_effects = p_force_camera_effects; - } else { - camera_effects = scenario->camera_effects; - } - /* PROCESS GEOMETRY AND DRAW SCENE */ - - RENDER_TIMESTAMP("Render Scene "); - VSG::scene_render->render_scene(p_render_buffers, p_cam_transform, p_cam_projection, p_cam_orthogonal, (RasterizerScene::InstanceBase **)instance_cull_result, instance_cull_count, light_instance_cull_result, light_cull_count + directional_light_count, reflection_probe_instance_cull_result, reflection_probe_cull_count, gi_probe_instance_cull_result, gi_probe_cull_count, environment, camera_effects, p_shadow_atlas, p_reflection_probe.is_valid() ? RID() : scenario->reflection_atlas, p_reflection_probe, p_reflection_probe_pass); -} - -void VisualServerScene::render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas) { - -#ifndef _3D_DISABLED - - Scenario *scenario = scenario_owner.getornull(p_scenario); - - RID environment; - if (scenario->environment.is_valid()) - environment = scenario->environment; - else - environment = scenario->fallback_environment; - RENDER_TIMESTAMP("Render Empty Scene "); - VSG::scene_render->render_scene(p_render_buffers, Transform(), CameraMatrix(), true, NULL, 0, NULL, 0, NULL, 0, NULL, 0, environment, RID(), p_shadow_atlas, scenario->reflection_atlas, RID(), 0); -#endif -} - -bool VisualServerScene::_render_reflection_probe_step(Instance *p_instance, int p_step) { - - InstanceReflectionProbeData *reflection_probe = static_cast(p_instance->base_data); - Scenario *scenario = p_instance->scenario; - ERR_FAIL_COND_V(!scenario, true); - - VisualServerRaster::redraw_request(); //update, so it updates in editor - - if (p_step == 0) { - - if (!VSG::scene_render->reflection_probe_instance_begin_render(reflection_probe->instance, scenario->reflection_atlas)) { - return true; //all full - } - } - - if (p_step >= 0 && p_step < 6) { - - static const Vector3 view_normals[6] = { - Vector3(+1, 0, 0), - Vector3(-1, 0, 0), - Vector3(0, +1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1) - }; - static const Vector3 view_up[6] = { - Vector3(0, -1, 0), - Vector3(0, -1, 0), - Vector3(0, 0, +1), - Vector3(0, 0, -1), - Vector3(0, -1, 0), - Vector3(0, -1, 0) - }; - - Vector3 extents = VSG::storage->reflection_probe_get_extents(p_instance->base); - Vector3 origin_offset = VSG::storage->reflection_probe_get_origin_offset(p_instance->base); - float max_distance = VSG::storage->reflection_probe_get_origin_max_distance(p_instance->base); - - Vector3 edge = view_normals[p_step] * extents; - float distance = ABS(view_normals[p_step].dot(edge) - view_normals[p_step].dot(origin_offset)); //distance from origin offset to actual view distance limit - - max_distance = MAX(max_distance, distance); - - //render cubemap side - CameraMatrix cm; - cm.set_perspective(90, 1, 0.01, max_distance); - - Transform local_view; - local_view.set_look_at(origin_offset, origin_offset + view_normals[p_step], view_up[p_step]); - - Transform xform = p_instance->transform * local_view; - - RID shadow_atlas; - - bool use_shadows = VSG::storage->reflection_probe_renders_shadows(p_instance->base); - if (use_shadows) { - - shadow_atlas = scenario->reflection_probe_shadow_atlas; - } - - RENDER_TIMESTAMP("Render Reflection Probe, Step " + itos(p_step)); - _prepare_scene(xform, cm, false, RID(), RID(), VSG::storage->reflection_probe_get_cull_mask(p_instance->base), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, use_shadows); - _render_scene(RID(), xform, cm, false, RID(), RID(), p_instance->scenario->self, shadow_atlas, reflection_probe->instance, p_step); - - } else { - //do roughness postprocess step until it believes it's done - RENDER_TIMESTAMP("Post-Process Reflection Probe, Step " + itos(p_step)); - return VSG::scene_render->reflection_probe_instance_postprocess_step(reflection_probe->instance); - } - - return false; -} - -void VisualServerScene::render_probes() { - - /* REFLECTION PROBES */ - - SelfList *ref_probe = reflection_probe_render_list.first(); - - bool busy = false; - - while (ref_probe) { - - SelfList *next = ref_probe->next(); - RID base = ref_probe->self()->owner->base; - - switch (VSG::storage->reflection_probe_get_update_mode(base)) { - - case VS::REFLECTION_PROBE_UPDATE_ONCE: { - if (busy) //already rendering something - break; - - bool done = _render_reflection_probe_step(ref_probe->self()->owner, ref_probe->self()->render_step); - if (done) { - reflection_probe_render_list.remove(ref_probe); - } else { - ref_probe->self()->render_step++; - } - - busy = true; //do not render another one of this kind - } break; - case VS::REFLECTION_PROBE_UPDATE_ALWAYS: { - - int step = 0; - bool done = false; - while (!done) { - done = _render_reflection_probe_step(ref_probe->self()->owner, step); - step++; - } - - reflection_probe_render_list.remove(ref_probe); - } break; - } - - ref_probe = next; - } - - /* GI PROBES */ - - SelfList *gi_probe = gi_probe_update_list.first(); - - if (gi_probe) { - RENDER_TIMESTAMP("Render GI Probes"); - } - - while (gi_probe) { - - SelfList *next = gi_probe->next(); - - InstanceGIProbeData *probe = gi_probe->self(); - //Instance *instance_probe = probe->owner; - - //check if probe must be setup, but don't do if on the lighting thread - - bool cache_dirty = false; - int cache_count = 0; - { - - int light_cache_size = probe->light_cache.size(); - const InstanceGIProbeData::LightCache *caches = probe->light_cache.ptr(); - const RID *instance_caches = probe->light_instances.ptr(); - - int idx = 0; //must count visible lights - for (Set::Element *E = probe->lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - if (cache_dirty) { - //do nothing, since idx must count all visible lights anyway - } else if (idx >= light_cache_size) { - cache_dirty = true; - } else { - - const InstanceGIProbeData::LightCache *cache = &caches[idx]; - - if ( - instance_caches[idx] != instance_light->instance || - cache->has_shadow != VSG::storage->light_has_shadow(instance->base) || - cache->type != VSG::storage->light_get_type(instance->base) || - cache->transform != instance->transform || - cache->color != VSG::storage->light_get_color(instance->base) || - cache->energy != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ENERGY) || - cache->bake_energy != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_INDIRECT_ENERGY) || - cache->radius != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_RANGE) || - cache->attenuation != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ATTENUATION) || - cache->spot_angle != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ANGLE) || - cache->spot_attenuation != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ATTENUATION)) { - cache_dirty = true; - } - } - - idx++; - } - - for (List::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { - - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - if (cache_dirty) { - //do nothing, since idx must count all visible lights anyway - } else if (idx >= light_cache_size) { - cache_dirty = true; - } else { - - const InstanceGIProbeData::LightCache *cache = &caches[idx]; - - if ( - instance_caches[idx] != instance_light->instance || - cache->has_shadow != VSG::storage->light_has_shadow(instance->base) || - cache->type != VSG::storage->light_get_type(instance->base) || - cache->transform != instance->transform || - cache->color != VSG::storage->light_get_color(instance->base) || - cache->energy != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ENERGY) || - cache->bake_energy != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_INDIRECT_ENERGY) || - cache->radius != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_RANGE) || - cache->attenuation != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ATTENUATION) || - cache->spot_angle != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ANGLE) || - cache->spot_attenuation != VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ATTENUATION)) { - cache_dirty = true; - } - } - - idx++; - } - - if (idx != light_cache_size) { - cache_dirty = true; - } - - cache_count = idx; - } - - bool update_lights = VSG::scene_render->gi_probe_needs_update(probe->probe_instance); - - if (cache_dirty) { - probe->light_cache.resize(cache_count); - probe->light_instances.resize(cache_count); - - if (cache_count) { - InstanceGIProbeData::LightCache *caches = probe->light_cache.ptrw(); - RID *instance_caches = probe->light_instances.ptrw(); - - int idx = 0; //must count visible lights - for (Set::Element *E = probe->lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - - InstanceGIProbeData::LightCache *cache = &caches[idx]; - - instance_caches[idx] = instance_light->instance; - cache->has_shadow = VSG::storage->light_has_shadow(instance->base); - cache->type = VSG::storage->light_get_type(instance->base); - cache->transform = instance->transform; - cache->color = VSG::storage->light_get_color(instance->base); - cache->energy = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ENERGY); - cache->bake_energy = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_INDIRECT_ENERGY); - cache->radius = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_RANGE); - cache->attenuation = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ATTENUATION); - cache->spot_angle = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ANGLE); - cache->spot_attenuation = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ATTENUATION); - - idx++; - } - for (List::Element *E = probe->owner->scenario->directional_lights.front(); E; E = E->next()) { - Instance *instance = E->get(); - InstanceLightData *instance_light = (InstanceLightData *)instance->base_data; - if (!instance->visible) { - continue; - } - - InstanceGIProbeData::LightCache *cache = &caches[idx]; - - instance_caches[idx] = instance_light->instance; - cache->has_shadow = VSG::storage->light_has_shadow(instance->base); - cache->type = VSG::storage->light_get_type(instance->base); - cache->transform = instance->transform; - cache->color = VSG::storage->light_get_color(instance->base); - cache->energy = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ENERGY); - cache->bake_energy = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_INDIRECT_ENERGY); - cache->radius = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_RANGE); - cache->attenuation = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_ATTENUATION); - cache->spot_angle = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ANGLE); - cache->spot_attenuation = VSG::storage->light_get_param(instance->base, VS::LIGHT_PARAM_SPOT_ATTENUATION); - - idx++; - } - } - - update_lights = true; - } - - instance_cull_count = 0; - for (List::Element *E = probe->dynamic_geometries.front(); E; E = E->next()) { - if (instance_cull_count < MAX_INSTANCE_CULL) { - Instance *ins = E->get().geometry; - if (!ins->visible) { - continue; - } - InstanceGeometryData *geom = (InstanceGeometryData *)ins->base_data; - - if (geom->gi_probes_dirty) { - //giprobes may be dirty, so update - int l = 0; - //only called when reflection probe AABB enter/exit this geometry - ins->gi_probe_instances.resize(geom->gi_probes.size()); - - for (List::Element *F = geom->gi_probes.front(); F; F = F->next()) { - - InstanceGIProbeData *gi_probe2 = static_cast(F->get()->base_data); - - ins->gi_probe_instances.write[l++] = gi_probe2->probe_instance; - } - - geom->gi_probes_dirty = false; - } - - instance_cull_result[instance_cull_count++] = E->get().geometry; - } - } - - VSG::scene_render->gi_probe_update(probe->probe_instance, update_lights, probe->light_instances, instance_cull_count, (RasterizerScene::InstanceBase **)instance_cull_result); - - gi_probe_update_list.remove(gi_probe); - - gi_probe = next; - } -} - -void VisualServerScene::_update_dirty_instance(Instance *p_instance) { - - if (p_instance->update_aabb) { - _update_instance_aabb(p_instance); - } - - if (p_instance->update_dependencies) { - - p_instance->instance_increase_version(); - - if (p_instance->base.is_valid()) { - VSG::storage->base_update_dependency(p_instance->base, p_instance); - } - - if (p_instance->material_override.is_valid()) { - VSG::storage->material_update_dependency(p_instance->material_override, p_instance); - } - - if (p_instance->base_type == VS::INSTANCE_MESH) { - //remove materials no longer used and un-own them - - int new_mat_count = VSG::storage->mesh_get_surface_count(p_instance->base); - p_instance->materials.resize(new_mat_count); - - int new_blend_shape_count = VSG::storage->mesh_get_blend_shape_count(p_instance->base); - if (new_blend_shape_count != p_instance->blend_values.size()) { - p_instance->blend_values.resize(new_blend_shape_count); - for (int i = 0; i < new_blend_shape_count; i++) { - p_instance->blend_values.write[i] = 0; - } - } - } - - if ((1 << p_instance->base_type) & VS::INSTANCE_GEOMETRY_MASK) { - - InstanceGeometryData *geom = static_cast(p_instance->base_data); - - bool can_cast_shadows = true; - bool is_animated = false; - - if (p_instance->cast_shadows == VS::SHADOW_CASTING_SETTING_OFF) { - can_cast_shadows = false; - } else if (p_instance->material_override.is_valid()) { - can_cast_shadows = VSG::storage->material_casts_shadows(p_instance->material_override); - is_animated = VSG::storage->material_is_animated(p_instance->material_override); - } else { - - if (p_instance->base_type == VS::INSTANCE_MESH) { - RID mesh = p_instance->base; - - if (mesh.is_valid()) { - bool cast_shadows = false; - - for (int i = 0; i < p_instance->materials.size(); i++) { - - RID mat = p_instance->materials[i].is_valid() ? p_instance->materials[i] : VSG::storage->mesh_surface_get_material(mesh, i); - - if (!mat.is_valid()) { - cast_shadows = true; - } else { - - if (VSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - - if (VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - VSG::storage->material_update_dependency(mat, p_instance); - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - - } else if (p_instance->base_type == VS::INSTANCE_MULTIMESH) { - RID mesh = VSG::storage->multimesh_get_mesh(p_instance->base); - if (mesh.is_valid()) { - - bool cast_shadows = false; - - int sc = VSG::storage->mesh_get_surface_count(mesh); - for (int i = 0; i < sc; i++) { - - RID mat = VSG::storage->mesh_surface_get_material(mesh, i); - - if (!mat.is_valid()) { - cast_shadows = true; - - } else { - - if (VSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - if (VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - VSG::storage->material_update_dependency(mat, p_instance); - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - - VSG::storage->base_update_dependency(mesh, p_instance); - } - } else if (p_instance->base_type == VS::INSTANCE_IMMEDIATE) { - - RID mat = VSG::storage->immediate_get_material(p_instance->base); - - can_cast_shadows = !mat.is_valid() || VSG::storage->material_casts_shadows(mat); - - if (mat.is_valid() && VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - if (mat.is_valid()) { - VSG::storage->material_update_dependency(mat, p_instance); - } - - } else if (p_instance->base_type == VS::INSTANCE_PARTICLES) { - - bool cast_shadows = false; - - int dp = VSG::storage->particles_get_draw_passes(p_instance->base); - - for (int i = 0; i < dp; i++) { - - RID mesh = VSG::storage->particles_get_draw_pass_mesh(p_instance->base, i); - if (!mesh.is_valid()) - continue; - - int sc = VSG::storage->mesh_get_surface_count(mesh); - for (int j = 0; j < sc; j++) { - - RID mat = VSG::storage->mesh_surface_get_material(mesh, j); - - if (!mat.is_valid()) { - cast_shadows = true; - } else { - - if (VSG::storage->material_casts_shadows(mat)) { - cast_shadows = true; - } - - if (VSG::storage->material_is_animated(mat)) { - is_animated = true; - } - - VSG::storage->material_update_dependency(mat, p_instance); - } - } - } - - if (!cast_shadows) { - can_cast_shadows = false; - } - } - } - - if (can_cast_shadows != geom->can_cast_shadows) { - //ability to cast shadows change, let lights now - for (List::Element *E = geom->lighting.front(); E; E = E->next()) { - InstanceLightData *light = static_cast(E->get()->base_data); - light->shadow_dirty = true; - } - - geom->can_cast_shadows = can_cast_shadows; - } - - geom->material_is_animated = is_animated; - } - - if (p_instance->skeleton.is_valid()) { - VSG::storage->skeleton_update_dependency(p_instance->skeleton, p_instance); - } - - p_instance->clean_up_dependencies(); - } - - _instance_update_list.remove(&p_instance->update_item); - - _update_instance(p_instance); - - p_instance->update_aabb = false; - p_instance->update_dependencies = false; -} - -void VisualServerScene::update_dirty_instances() { - - VSG::storage->update_dirty_resources(); - - while (_instance_update_list.first()) { - - _update_dirty_instance(_instance_update_list.first()->self()); - } -} - -bool VisualServerScene::free(RID p_rid) { - - if (camera_owner.owns(p_rid)) { - - Camera *camera = camera_owner.getornull(p_rid); - - camera_owner.free(p_rid); - memdelete(camera); - - } else if (scenario_owner.owns(p_rid)) { - - Scenario *scenario = scenario_owner.getornull(p_rid); - - while (scenario->instances.first()) { - instance_set_scenario(scenario->instances.first()->self()->self, RID()); - } - VSG::scene_render->free(scenario->reflection_probe_shadow_atlas); - VSG::scene_render->free(scenario->reflection_atlas); - scenario_owner.free(p_rid); - memdelete(scenario); - - } else if (instance_owner.owns(p_rid)) { - // delete the instance - - update_dirty_instances(); - - Instance *instance = instance_owner.getornull(p_rid); - - instance_set_use_lightmap(p_rid, RID(), RID()); - instance_set_scenario(p_rid, RID()); - instance_set_base(p_rid, RID()); - instance_geometry_set_material_override(p_rid, RID()); - instance_attach_skeleton(p_rid, RID()); - - update_dirty_instances(); //in case something changed this - - instance_owner.free(p_rid); - memdelete(instance); - } else { - return false; - } - - return true; -} - -VisualServerScene *VisualServerScene::singleton = NULL; - -VisualServerScene::VisualServerScene() { - - render_pass = 1; - singleton = this; -} - -VisualServerScene::~VisualServerScene() { -} diff --git a/servers/visual/visual_server_scene.h b/servers/visual/visual_server_scene.h deleted file mode 100644 index 8dbd60d3ff..0000000000 --- a/servers/visual/visual_server_scene.h +++ /dev/null @@ -1,440 +0,0 @@ -/*************************************************************************/ -/* visual_server_scene.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUALSERVERSCENE_H -#define VISUALSERVERSCENE_H - -#include "servers/visual/rasterizer.h" - -#include "core/math/geometry.h" -#include "core/math/octree.h" -#include "core/os/semaphore.h" -#include "core/os/thread.h" -#include "core/rid_owner.h" -#include "core/self_list.h" -#include "servers/arvr/arvr_interface.h" - -class VisualServerScene { -public: - enum { - - MAX_INSTANCE_CULL = 65536, - MAX_LIGHTS_CULLED = 4096, - MAX_REFLECTION_PROBES_CULLED = 4096, - MAX_GI_PROBES_CULLED = 4096, - MAX_ROOM_CULL = 32, - MAX_EXTERIOR_PORTALS = 128, - }; - - uint64_t render_pass; - - static VisualServerScene *singleton; - - /* CAMERA API */ - - struct Camera { - - enum Type { - PERSPECTIVE, - ORTHOGONAL, - FRUSTUM - }; - Type type; - float fov; - float znear, zfar; - float size; - Vector2 offset; - uint32_t visible_layers; - bool vaspect; - RID env; - RID effects; - - Transform transform; - - Camera() { - - visible_layers = 0xFFFFFFFF; - fov = 70; - type = PERSPECTIVE; - znear = 0.05; - zfar = 100; - size = 1.0; - offset = Vector2(); - vaspect = false; - } - }; - - mutable RID_PtrOwner camera_owner; - - virtual RID camera_create(); - virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far); - virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); - virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far); - virtual void camera_set_transform(RID p_camera, const Transform &p_transform); - virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers); - virtual void camera_set_environment(RID p_camera, RID p_env); - virtual void camera_set_camera_effects(RID p_camera, RID p_fx); - virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable); - - /* SCENARIO API */ - - struct Instance; - - struct Scenario { - - VS::ScenarioDebugMode debug; - RID self; - - Octree octree; - - List directional_lights; - RID environment; - RID fallback_environment; - RID camera_effects; - RID reflection_probe_shadow_atlas; - RID reflection_atlas; - - SelfList::List instances; - - Scenario() { debug = VS::SCENARIO_DEBUG_DISABLED; } - }; - - mutable RID_PtrOwner scenario_owner; - - static void *_instance_pair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int); - static void _instance_unpair(void *p_self, OctreeElementID, Instance *p_A, int, OctreeElementID, Instance *p_B, int, void *); - - virtual RID scenario_create(); - - virtual void scenario_set_debug(RID p_scenario, VS::ScenarioDebugMode p_debug_mode); - virtual void scenario_set_environment(RID p_scenario, RID p_environment); - virtual void scenario_set_camera_effects(RID p_scenario, RID p_fx); - virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment); - virtual void scenario_set_reflection_atlas_size(RID p_scenario, int p_reflection_size, int p_reflection_count); - - /* INSTANCING API */ - - struct InstanceBaseData { - - virtual ~InstanceBaseData() {} - }; - - struct Instance : RasterizerScene::InstanceBase { - - RID self; - //scenario stuff - OctreeElementID octree_id; - Scenario *scenario; - SelfList scenario_item; - - //aabb stuff - bool update_aabb; - bool update_dependencies; - - SelfList update_item; - - AABB *custom_aabb; // would using aabb directly with a bool be better? - float extra_margin; - ObjectID object_id; - - float lod_begin; - float lod_end; - float lod_begin_hysteresis; - float lod_end_hysteresis; - RID lod_instance; - - uint64_t last_render_pass; - uint64_t last_frame_pass; - - uint64_t version; // changes to this, and changes to base increase version - - InstanceBaseData *base_data; - - virtual void dependency_deleted(RID p_dependency) { - if (p_dependency == base) { - singleton->instance_set_base(self, RID()); - } else if (p_dependency == skeleton) { - singleton->instance_attach_skeleton(self, RID()); - } else { - singleton->_instance_queue_update(this, false, true); - } - } - - virtual void dependency_changed(bool p_aabb, bool p_dependencies) { - singleton->_instance_queue_update(this, p_aabb, p_dependencies); - } - - Instance() : - scenario_item(this), - update_item(this) { - - octree_id = 0; - scenario = NULL; - - update_aabb = false; - update_dependencies = false; - - extra_margin = 0; - - visible = true; - - lod_begin = 0; - lod_end = 0; - lod_begin_hysteresis = 0; - lod_end_hysteresis = 0; - - last_render_pass = 0; - last_frame_pass = 0; - version = 1; - base_data = NULL; - - custom_aabb = NULL; - } - - ~Instance() { - - if (base_data) - memdelete(base_data); - if (custom_aabb) - memdelete(custom_aabb); - } - }; - - SelfList::List _instance_update_list; - void _instance_queue_update(Instance *p_instance, bool p_update_aabb, bool p_update_dependencies = false); - - struct InstanceGeometryData : public InstanceBaseData { - - List lighting; - bool lighting_dirty; - bool can_cast_shadows; - bool material_is_animated; - - List reflection_probes; - bool reflection_dirty; - - List gi_probes; - bool gi_probes_dirty; - - List lightmap_captures; - - InstanceGeometryData() { - - lighting_dirty = false; - reflection_dirty = true; - can_cast_shadows = true; - material_is_animated = true; - gi_probes_dirty = true; - } - }; - - struct InstanceReflectionProbeData : public InstanceBaseData { - - Instance *owner; - - struct PairInfo { - List::Element *L; //reflection iterator in geometry - Instance *geometry; - }; - List geometries; - - RID instance; - bool reflection_dirty; - SelfList update_list; - - int render_step; - - InstanceReflectionProbeData() : - update_list(this) { - - reflection_dirty = true; - render_step = -1; - } - }; - - SelfList::List reflection_probe_render_list; - - struct InstanceLightData : public InstanceBaseData { - - struct PairInfo { - List::Element *L; //light iterator in geometry - Instance *geometry; - }; - - RID instance; - uint64_t last_version; - List::Element *D; // directional light in scenario - - bool shadow_dirty; - - List geometries; - - Instance *baked_light; - - InstanceLightData() { - - shadow_dirty = true; - D = NULL; - last_version = 0; - baked_light = NULL; - } - }; - - struct InstanceGIProbeData : public InstanceBaseData { - - Instance *owner; - - struct PairInfo { - List::Element *L; //gi probe iterator in geometry - Instance *geometry; - }; - - List geometries; - List dynamic_geometries; - - Set lights; - - struct LightCache { - - VS::LightType type; - Transform transform; - Color color; - float energy; - float bake_energy; - float radius; - float attenuation; - float spot_angle; - float spot_attenuation; - bool has_shadow; - }; - - Vector light_cache; - Vector light_instances; - - RID probe_instance; - - bool invalid; - uint32_t base_version; - - SelfList update_element; - - InstanceGIProbeData() : - update_element(this) { - invalid = true; - base_version = 0; - } - }; - - SelfList::List gi_probe_update_list; - - struct InstanceLightmapCaptureData : public InstanceBaseData { - - struct PairInfo { - List::Element *L; //iterator in geometry - Instance *geometry; - }; - List geometries; - - Set users; - - InstanceLightmapCaptureData() { - } - }; - - int instance_cull_count; - Instance *instance_cull_result[MAX_INSTANCE_CULL]; - Instance *instance_shadow_cull_result[MAX_INSTANCE_CULL]; //used for generating shadowmaps - Instance *light_cull_result[MAX_LIGHTS_CULLED]; - RID light_instance_cull_result[MAX_LIGHTS_CULLED]; - int light_cull_count; - int directional_light_count; - RID reflection_probe_instance_cull_result[MAX_REFLECTION_PROBES_CULLED]; - int reflection_probe_cull_count; - RID gi_probe_instance_cull_result[MAX_GI_PROBES_CULLED]; - int gi_probe_cull_count; - - RID_PtrOwner instance_owner; - - virtual RID instance_create(); - - virtual void instance_set_base(RID p_instance, RID p_base); - virtual void instance_set_scenario(RID p_instance, RID p_scenario); - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask); - virtual void instance_set_transform(RID p_instance, const Transform &p_transform); - virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id); - virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight); - virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material); - virtual void instance_set_visible(RID p_instance, bool p_visible); - virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap); - - virtual void instance_set_custom_aabb(RID p_instance, AABB p_aabb); - - virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton); - virtual void instance_set_exterior(RID p_instance, bool p_enabled); - - virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin); - - // don't use these in a game! - virtual Vector instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const; - virtual Vector instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; - virtual Vector instances_cull_convex(const Vector &p_convex, RID p_scenario = RID()) const; - - virtual void instance_geometry_set_flag(RID p_instance, VS::InstanceFlags p_flags, bool p_enabled); - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, VS::ShadowCastingSetting p_shadow_casting_setting); - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material); - - virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin); - virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance); - - _FORCE_INLINE_ void _update_instance(Instance *p_instance); - _FORCE_INLINE_ void _update_instance_aabb(Instance *p_instance); - _FORCE_INLINE_ void _update_dirty_instance(Instance *p_instance); - _FORCE_INLINE_ void _update_instance_lightmap_captures(Instance *p_instance); - - _FORCE_INLINE_ bool _light_instance_update_shadow(Instance *p_instance, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_shadow_atlas, Scenario *p_scenario); - - bool _render_reflection_probe_step(Instance *p_instance, int p_step); - void _prepare_scene(const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, uint32_t p_visible_layers, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, bool p_using_shadows = true); - void _render_scene(RID p_render_buffers, const Transform p_cam_transform, const CameraMatrix &p_cam_projection, bool p_cam_orthogonal, RID p_force_environment, RID p_force_camera_effects, RID p_scenario, RID p_shadow_atlas, RID p_reflection_probe, int p_reflection_probe_pass); - void render_empty_scene(RID p_render_buffers, RID p_scenario, RID p_shadow_atlas); - - void render_camera(RID p_render_buffers, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); - void render_camera(RID p_render_buffers, Ref &p_interface, ARVRInterface::Eyes p_eye, RID p_camera, RID p_scenario, Size2 p_viewport_size, RID p_shadow_atlas); - void update_dirty_instances(); - - void render_probes(); - - bool free(RID p_rid); - - VisualServerScene(); - virtual ~VisualServerScene(); -}; - -#endif // VISUALSERVERSCENE_H diff --git a/servers/visual/visual_server_viewport.cpp b/servers/visual/visual_server_viewport.cpp deleted file mode 100644 index 555d5f99c7..0000000000 --- a/servers/visual/visual_server_viewport.cpp +++ /dev/null @@ -1,780 +0,0 @@ -/*************************************************************************/ -/* visual_server_viewport.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server_viewport.h" - -#include "core/project_settings.h" -#include "visual_server_canvas.h" -#include "visual_server_globals.h" -#include "visual_server_scene.h" - -static Transform2D _canvas_get_transform(VisualServerViewport::Viewport *p_viewport, VisualServerCanvas::Canvas *p_canvas, VisualServerViewport::Viewport::CanvasData *p_canvas_data, const Vector2 &p_vp_size) { - - Transform2D xf = p_viewport->global_transform; - - float scale = 1.0; - if (p_viewport->canvas_map.has(p_canvas->parent)) { - xf = xf * p_viewport->canvas_map[p_canvas->parent].transform; - scale = p_canvas->parent_scale; - } - - xf = xf * p_canvas_data->transform; - - if (scale != 1.0 && !VSG::canvas->disable_scale) { - Vector2 pivot = p_vp_size * 0.5; - Transform2D xfpivot; - xfpivot.set_origin(pivot); - Transform2D xfscale; - xfscale.scale(Vector2(scale, scale)); - - xf = xfpivot.affine_inverse() * xf; - xf = xfscale * xf; - xf = xfpivot * xf; - } - - return xf; -} - -void VisualServerViewport::_draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye) { - - RENDER_TIMESTAMP(">Begin Rendering 3D Scene"); - - Ref arvr_interface; - if (ARVRServer::get_singleton() != NULL) { - arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - } - - if (p_viewport->use_arvr && arvr_interface.is_valid()) { - VSG::scene->render_camera(p_viewport->render_buffers, arvr_interface, p_eye, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); - } else { - VSG::scene->render_camera(p_viewport->render_buffers, p_viewport->camera, p_viewport->scenario, p_viewport->size, p_viewport->shadow_atlas); - } - RENDER_TIMESTAMP("get_default_clear_color(); - - if (!p_viewport->hide_canvas && !p_viewport->disable_environment && VSG::scene->scenario_owner.owns(p_viewport->scenario)) { - - VisualServerScene::Scenario *scenario = VSG::scene->scenario_owner.getornull(p_viewport->scenario); - ERR_FAIL_COND(!scenario); - if (VSG::scene_render->is_environment(scenario->environment)) { - scenario_draw_canvas_bg = VSG::scene_render->environment_get_background(scenario->environment) == VS::ENV_BG_CANVAS; - - scenario_canvas_max_layer = VSG::scene_render->environment_get_canvas_max_layer(scenario->environment); - } - } - - bool can_draw_3d = VSG::scene->camera_owner.owns(p_viewport->camera); - - if (p_viewport->clear_mode != VS::VIEWPORT_CLEAR_NEVER) { - if (p_viewport->transparent_bg) { - bgcolor = Color(0, 0, 0, 0); - } - if (p_viewport->clear_mode == VS::VIEWPORT_CLEAR_ONLY_NEXT_FRAME) { - p_viewport->clear_mode = VS::VIEWPORT_CLEAR_NEVER; - } - } - - if ((scenario_draw_canvas_bg || can_draw_3d) && !p_viewport->render_buffers.is_valid()) { - //wants to draw 3D but there is no render buffer, create - p_viewport->render_buffers = VSG::scene_render->render_buffers_create(); - VSG::scene_render->render_buffers_configure(p_viewport->render_buffers, p_viewport->render_target, p_viewport->size.width, p_viewport->size.height, p_viewport->msaa); - } - - VSG::storage->render_target_request_clear(p_viewport->render_target, bgcolor); - - if (!scenario_draw_canvas_bg && can_draw_3d) { - _draw_3d(p_viewport, p_eye); - } - - if (!p_viewport->hide_canvas) { - int i = 0; - - Map canvas_map; - - Rect2 clip_rect(0, 0, p_viewport->size.x, p_viewport->size.y); - RasterizerCanvas::Light *lights = NULL; - RasterizerCanvas::Light *lights_with_shadow = NULL; - RasterizerCanvas::Light *lights_with_mask = NULL; - Rect2 shadow_rect; - - int light_count = 0; - - RENDER_TIMESTAMP("Cull Canvas Lights"); - for (Map::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - - VisualServerCanvas::Canvas *canvas = static_cast(E->get().canvas); - - Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); - - //find lights in canvas - - for (Set::Element *F = canvas->lights.front(); F; F = F->next()) { - - RasterizerCanvas::Light *cl = F->get(); - if (cl->enabled && cl->texture.is_valid()) { - //not super efficient.. - Size2 tsize = VSG::storage->texture_size_with_proxy(cl->texture); - tsize *= cl->scale; - - Vector2 offset = tsize / 2.0; - cl->rect_cache = Rect2(-offset + cl->texture_offset, tsize); - cl->xform_cache = xf * cl->xform; - - if (clip_rect.intersects_transformed(cl->xform_cache, cl->rect_cache)) { - - cl->filter_next_ptr = lights; - lights = cl; - // cl->texture_cache = NULL; - Transform2D scale; - scale.scale(cl->rect_cache.size); - scale.elements[2] = cl->rect_cache.position; - cl->light_shader_xform = cl->xform * scale; - //cl->light_shader_pos = cl->xform_cache[2]; - if (cl->use_shadow) { - - cl->shadows_next_ptr = lights_with_shadow; - if (lights_with_shadow == NULL) { - shadow_rect = cl->xform_cache.xform(cl->rect_cache); - } else { - shadow_rect = shadow_rect.merge(cl->xform_cache.xform(cl->rect_cache)); - } - lights_with_shadow = cl; - cl->radius_cache = cl->rect_cache.size.length(); - } - if (cl->mode == VS::CANVAS_LIGHT_MODE_MASK) { - cl->mask_next_ptr = lights_with_mask; - lights_with_mask = cl; - } - - light_count++; - } - - //guess this is not needed, but keeping because it may be - //VSG::canvas_render->light_internal_update(cl->light_internal, cl); - } - } - - canvas_map[Viewport::CanvasKey(E->key(), E->get().layer, E->get().sublayer)] = &E->get(); - } - - if (lights_with_shadow) { - //update shadows if any - - RasterizerCanvas::LightOccluderInstance *occluders = NULL; - - RENDER_TIMESTAMP(">Render 2D Shadows"); - RENDER_TIMESTAMP("Cull Occluders"); - - //make list of occluders - for (Map::Element *E = p_viewport->canvas_map.front(); E; E = E->next()) { - - VisualServerCanvas::Canvas *canvas = static_cast(E->get().canvas); - Transform2D xf = _canvas_get_transform(p_viewport, canvas, &E->get(), clip_rect.size); - - for (Set::Element *F = canvas->occluders.front(); F; F = F->next()) { - - if (!F->get()->enabled) - continue; - F->get()->xform_cache = xf * F->get()->xform; - if (shadow_rect.intersects_transformed(F->get()->xform_cache, F->get()->aabb_cache)) { - - F->get()->next = occluders; - occluders = F->get(); - } - } - } - //update the light shadowmaps with them - - RasterizerCanvas::Light *light = lights_with_shadow; - while (light) { - - RENDER_TIMESTAMP("Render Shadow"); - - VSG::canvas_render->light_update_shadow(light->light_internal, light->xform_cache.affine_inverse(), light->item_shadow_mask, light->radius_cache / 1000.0, light->radius_cache * 1.1, occluders); - light = light->shadows_next_ptr; - } - - //VSG::canvas_render->reset_canvas(); - RENDER_TIMESTAMP("key().get_layer() > scenario_canvas_max_layer) { - if (!can_draw_3d) { - VSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); - } else { - _draw_3d(p_viewport, p_eye); - } - scenario_draw_canvas_bg = false; - } - - for (Map::Element *E = canvas_map.front(); E; E = E->next()) { - - VisualServerCanvas::Canvas *canvas = static_cast(E->get()->canvas); - - Transform2D xform = _canvas_get_transform(p_viewport, canvas, E->get(), clip_rect.size); - - RasterizerCanvas::Light *canvas_lights = NULL; - - RasterizerCanvas::Light *ptr = lights; - while (ptr) { - if (E->get()->layer >= ptr->layer_min && E->get()->layer <= ptr->layer_max) { - ptr->next_ptr = canvas_lights; - canvas_lights = ptr; - } - ptr = ptr->filter_next_ptr; - } - - VSG::canvas->render_canvas(p_viewport->render_target, canvas, xform, canvas_lights, lights_with_mask, clip_rect); - i++; - - if (scenario_draw_canvas_bg && E->key().get_layer() >= scenario_canvas_max_layer) { - if (!can_draw_3d) { - VSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); - } else { - _draw_3d(p_viewport, p_eye); - } - - scenario_draw_canvas_bg = false; - } - } - - if (scenario_draw_canvas_bg) { - if (!can_draw_3d) { - VSG::scene->render_empty_scene(p_viewport->render_buffers, p_viewport->scenario, p_viewport->shadow_atlas); - } else { - _draw_3d(p_viewport, p_eye); - } - } - - //VSG::canvas_render->canvas_debug_viewport_shadows(lights_with_shadow); - } - - if (VSG::storage->render_target_is_clear_requested(p_viewport->render_target)) { - //was never cleared in the end, force clear it - VSG::storage->render_target_do_clear_request(p_viewport->render_target); - } -} - -void VisualServerViewport::draw_viewports() { - -#if 0 - // get our arvr interface in case we need it - Ref arvr_interface; - - if (ARVRServer::get_singleton() != NULL) { - arvr_interface = ARVRServer::get_singleton()->get_primary_interface(); - - // process all our active interfaces - ARVRServer::get_singleton()->_process(); - } -#endif - - if (Engine::get_singleton()->is_editor_hint()) { - set_default_clear_color(GLOBAL_GET("rendering/environment/default_clear_color")); - } - - //sort viewports - active_viewports.sort_custom(); - - Map> blit_to_screen_list; - //draw viewports - RENDER_TIMESTAMP(">Render Viewports"); - - //determine what is visible - draw_viewports_pass++; - - for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order - - Viewport *vp = active_viewports[i]; - - if (vp->update_mode == VS::VIEWPORT_UPDATE_DISABLED) - continue; - - if (!vp->render_target.is_valid()) { - continue; - } - //ERR_CONTINUE(!vp->render_target.is_valid()); - - bool visible = vp->viewport_to_screen_rect != Rect2(); - - if (vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE) { - visible = true; - } - - if (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target)) { - visible = true; - } - - if (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE) { - Viewport *parent = viewport_owner.getornull(vp->parent); - if (parent && parent->last_pass == draw_viewports_pass) { - visible = true; - } - } - - visible = visible && vp->size.x > 1 && vp->size.y > 1; - - if (visible) { - vp->last_pass = draw_viewports_pass; - } - } - - for (int i = 0; i < active_viewports.size(); i++) { - - Viewport *vp = active_viewports[i]; - - if (vp->last_pass != draw_viewports_pass) { - continue; //should not draw - } - - RENDER_TIMESTAMP(">Rendering Viewport " + itos(i)); - - VSG::storage->render_target_set_as_unused(vp->render_target); -#if 0 - if (vp->use_arvr && arvr_interface.is_valid()) { - // override our size, make sure it matches our required size - vp->size = arvr_interface->get_render_targetsize(); - VSG::storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y); - - // render mono or left eye first - ARVRInterface::Eyes leftOrMono = arvr_interface->is_stereo() ? ARVRInterface::EYE_LEFT : ARVRInterface::EYE_MONO; - - // check for an external texture destination for our left eye/mono - VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(leftOrMono)); - - // set our render target as current - VSG::rasterizer->set_current_render_target(vp->render_target); - - // and draw left eye/mono - _draw_viewport(vp, leftOrMono); - arvr_interface->commit_for_eye(leftOrMono, vp->render_target, vp->viewport_to_screen_rect); - - // render right eye - if (leftOrMono == ARVRInterface::EYE_LEFT) { - // check for an external texture destination for our right eye - VSG::storage->render_target_set_external_texture(vp->render_target, arvr_interface->get_external_texture_for_eye(ARVRInterface::EYE_RIGHT)); - - // commit for eye may have changed the render target - VSG::rasterizer->set_current_render_target(vp->render_target); - - _draw_viewport(vp, ARVRInterface::EYE_RIGHT); - arvr_interface->commit_for_eye(ARVRInterface::EYE_RIGHT, vp->render_target, vp->viewport_to_screen_rect); - } - - // and for our frame timing, mark when we've finished committing our eyes - ARVRServer::get_singleton()->_mark_commit(); - } else { -#endif - { - VSG::storage->render_target_set_external_texture(vp->render_target, 0); - - VSG::scene_render->set_debug_draw_mode(vp->debug_draw); - VSG::storage->render_info_begin_capture(); - - // render standard mono camera - _draw_viewport(vp); - - VSG::storage->render_info_end_capture(); - vp->render_info[VS::VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_OBJECTS_IN_FRAME); - vp->render_info[VS::VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_VERTICES_IN_FRAME); - vp->render_info[VS::VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_MATERIAL_CHANGES_IN_FRAME); - vp->render_info[VS::VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SHADER_CHANGES_IN_FRAME); - vp->render_info[VS::VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_SURFACE_CHANGES_IN_FRAME); - vp->render_info[VS::VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME] = VSG::storage->get_captured_render_info(VS::INFO_DRAW_CALLS_IN_FRAME); - - if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && (!vp->viewport_render_direct_to_screen || !VSG::rasterizer->is_low_end())) { - //copy to screen if set as such - Rasterizer::BlitToScreen blit; - blit.render_target = vp->render_target; - if (vp->viewport_to_screen_rect != Rect2()) { - blit.rect = vp->viewport_to_screen_rect; - } else { - blit.rect.position = Vector2(); - blit.rect.size = vp->size; - } - - if (!blit_to_screen_list.has(vp->viewport_to_screen)) { - blit_to_screen_list[vp->viewport_to_screen] = Vector(); - } - - blit_to_screen_list[vp->viewport_to_screen].push_back(blit); - } - } - - if (vp->update_mode == VS::VIEWPORT_UPDATE_ONCE) { - vp->update_mode = VS::VIEWPORT_UPDATE_DISABLED; - } - - RENDER_TIMESTAMP("set_debug_draw_mode(VS::VIEWPORT_DEBUG_DRAW_DISABLED); - - RENDER_TIMESTAMP("prepare_for_blitting_render_targets(); - - for (Map>::Element *E = blit_to_screen_list.front(); E; E = E->next()) { - VSG::rasterizer->blit_render_targets_to_screen(E->key(), E->get().ptr(), E->get().size()); - } -} - -RID VisualServerViewport::viewport_create() { - - Viewport *viewport = memnew(Viewport); - - RID rid = viewport_owner.make_rid(viewport); - - viewport->self = rid; - viewport->hide_scenario = false; - viewport->hide_canvas = false; - viewport->render_target = VSG::storage->render_target_create(); - viewport->shadow_atlas = VSG::scene_render->shadow_atlas_create(); - viewport->viewport_render_direct_to_screen = false; - - return rid; -} - -void VisualServerViewport::viewport_set_use_arvr(RID p_viewport, bool p_use_arvr) { - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->use_arvr = p_use_arvr; -} - -void VisualServerViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) { - - ERR_FAIL_COND(p_width < 0 && p_height < 0); - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->size = Size2(p_width, p_height); - VSG::storage->render_target_set_size(viewport->render_target, p_width, p_height); - if (viewport->render_buffers.is_valid()) { - if (p_width == 0 || p_height == 0) { - VSG::scene_render->free(viewport->render_buffers); - viewport->render_buffers = RID(); - } else { - VSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, viewport->msaa); - } - } -} - -void VisualServerViewport::viewport_set_active(RID p_viewport, bool p_active) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - if (p_active) { - ERR_FAIL_COND(active_viewports.find(viewport) != -1); //already active - active_viewports.push_back(viewport); - } else { - active_viewports.erase(viewport); - } -} - -void VisualServerViewport::viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->parent = p_parent_viewport; -} - -void VisualServerViewport::viewport_set_clear_mode(RID p_viewport, VS::ViewportClearMode p_clear_mode) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->clear_mode = p_clear_mode; -} - -void VisualServerViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect, DisplayServer::WindowID p_screen) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - if (p_screen != DisplayServer::INVALID_WINDOW_ID) { - // If using GLES2 we can optimize this operation by rendering directly to system_fbo - // instead of rendering to fbo and copying to system_fbo after - if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { - - VSG::storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y); - VSG::storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y); - } - - viewport->viewport_to_screen_rect = p_rect; - viewport->viewport_to_screen = p_screen; - } else { - - // if render_direct_to_screen was used, reset size and position - if (VSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) { - - VSG::storage->render_target_set_position(viewport->render_target, 0, 0); - VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); - } - - viewport->viewport_to_screen_rect = Rect2(); - viewport->viewport_to_screen = DisplayServer::INVALID_WINDOW_ID; - } -} - -void VisualServerViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) { - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - if (p_enable == viewport->viewport_render_direct_to_screen) - return; - - // if disabled, reset render_target size and position - if (!p_enable) { - - VSG::storage->render_target_set_position(viewport->render_target, 0, 0); - VSG::storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y); - } - - VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_DIRECT_TO_SCREEN, p_enable); - viewport->viewport_render_direct_to_screen = p_enable; - - // if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation - if (VSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) { - - VSG::storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y); - VSG::storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y); - } -} - -void VisualServerViewport::viewport_set_update_mode(RID p_viewport, VS::ViewportUpdateMode p_mode) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->update_mode = p_mode; -} - -RID VisualServerViewport::viewport_get_texture(RID p_viewport) const { - - const Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND_V(!viewport, RID()); - - return VSG::storage->render_target_get_texture(viewport->render_target); -} - -void VisualServerViewport::viewport_set_hide_scenario(RID p_viewport, bool p_hide) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->hide_scenario = p_hide; -} -void VisualServerViewport::viewport_set_hide_canvas(RID p_viewport, bool p_hide) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->hide_canvas = p_hide; -} -void VisualServerViewport::viewport_set_disable_environment(RID p_viewport, bool p_disable) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->disable_environment = p_disable; -} - -void VisualServerViewport::viewport_attach_camera(RID p_viewport, RID p_camera) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->camera = p_camera; -} -void VisualServerViewport::viewport_set_scenario(RID p_viewport, RID p_scenario) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->scenario = p_scenario; -} -void VisualServerViewport::viewport_attach_canvas(RID p_viewport, RID p_canvas) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - ERR_FAIL_COND(viewport->canvas_map.has(p_canvas)); - VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas); - ERR_FAIL_COND(!canvas); - - canvas->viewports.insert(p_viewport); - viewport->canvas_map[p_canvas] = Viewport::CanvasData(); - viewport->canvas_map[p_canvas].layer = 0; - viewport->canvas_map[p_canvas].sublayer = 0; - viewport->canvas_map[p_canvas].canvas = canvas; -} - -void VisualServerViewport::viewport_remove_canvas(RID p_viewport, RID p_canvas) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - VisualServerCanvas::Canvas *canvas = VSG::canvas->canvas_owner.getornull(p_canvas); - ERR_FAIL_COND(!canvas); - - viewport->canvas_map.erase(p_canvas); - canvas->viewports.erase(p_viewport); -} -void VisualServerViewport::viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); - viewport->canvas_map[p_canvas].transform = p_offset; -} -void VisualServerViewport::viewport_set_transparent_background(RID p_viewport, bool p_enabled) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - VSG::storage->render_target_set_flag(viewport->render_target, RasterizerStorage::RENDER_TARGET_TRANSPARENT, p_enabled); - viewport->transparent_bg = p_enabled; -} - -void VisualServerViewport::viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->global_transform = p_transform; -} -void VisualServerViewport::viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - ERR_FAIL_COND(!viewport->canvas_map.has(p_canvas)); - viewport->canvas_map[p_canvas].layer = p_layer; - viewport->canvas_map[p_canvas].sublayer = p_sublayer; -} - -void VisualServerViewport::viewport_set_shadow_atlas_size(RID p_viewport, int p_size) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->shadow_atlas_size = p_size; - - VSG::scene_render->shadow_atlas_set_size(viewport->shadow_atlas, viewport->shadow_atlas_size); -} - -void VisualServerViewport::viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - VSG::scene_render->shadow_atlas_set_quadrant_subdivision(viewport->shadow_atlas, p_quadrant, p_subdiv); -} - -void VisualServerViewport::viewport_set_msaa(RID p_viewport, VS::ViewportMSAA p_msaa) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - if (viewport->msaa == p_msaa) { - return; - } - viewport->msaa = p_msaa; - if (viewport->render_buffers.is_valid()) { - VSG::scene_render->render_buffers_configure(viewport->render_buffers, viewport->render_target, viewport->size.width, viewport->size.height, p_msaa); - } -} - -int VisualServerViewport::viewport_get_render_info(RID p_viewport, VS::ViewportRenderInfo p_info) { - - ERR_FAIL_INDEX_V(p_info, VS::VIEWPORT_RENDER_INFO_MAX, -1); - - Viewport *viewport = viewport_owner.getornull(p_viewport); - if (!viewport) - return 0; //there should be a lock here.. - - return viewport->render_info[p_info]; -} - -void VisualServerViewport::viewport_set_debug_draw(RID p_viewport, VS::ViewportDebugDraw p_draw) { - - Viewport *viewport = viewport_owner.getornull(p_viewport); - ERR_FAIL_COND(!viewport); - - viewport->debug_draw = p_draw; -} - -bool VisualServerViewport::free(RID p_rid) { - - if (viewport_owner.owns(p_rid)) { - - Viewport *viewport = viewport_owner.getornull(p_rid); - - VSG::storage->free(viewport->render_target); - VSG::scene_render->free(viewport->shadow_atlas); - if (viewport->render_buffers.is_valid()) { - VSG::scene_render->free(viewport->render_buffers); - } - - while (viewport->canvas_map.front()) { - viewport_remove_canvas(p_rid, viewport->canvas_map.front()->key()); - } - - viewport_set_scenario(p_rid, RID()); - active_viewports.erase(viewport); - - viewport_owner.free(p_rid); - memdelete(viewport); - - return true; - } - - return false; -} - -void VisualServerViewport::set_default_clear_color(const Color &p_color) { - VSG::storage->set_default_clear_color(p_color); -} - -VisualServerViewport::VisualServerViewport() { -} diff --git a/servers/visual/visual_server_viewport.h b/servers/visual/visual_server_viewport.h deleted file mode 100644 index 06372376f8..0000000000 --- a/servers/visual/visual_server_viewport.h +++ /dev/null @@ -1,208 +0,0 @@ -/*************************************************************************/ -/* visual_server_viewport.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUALSERVERVIEWPORT_H -#define VISUALSERVERVIEWPORT_H - -#include "core/rid_owner.h" -#include "core/self_list.h" -#include "rasterizer.h" -#include "servers/arvr/arvr_interface.h" -#include "servers/visual_server.h" - -class VisualServerViewport { -public: - struct CanvasBase { - }; - - struct Viewport { - - RID self; - RID parent; - - bool use_arvr; /* use arvr interface to override camera positioning and projection matrices and control output */ - - Size2i size; - RID camera; - RID scenario; - - VS::ViewportUpdateMode update_mode; - RID render_target; - RID render_target_texture; - RID render_buffers; - - VS::ViewportMSAA msaa; - - DisplayServer::WindowID viewport_to_screen; - Rect2 viewport_to_screen_rect; - bool viewport_render_direct_to_screen; - - bool hide_scenario; - bool hide_canvas; - bool disable_environment; - bool disable_3d_by_usage; - bool keep_3d_linear; - - RID shadow_atlas; - int shadow_atlas_size; - - uint64_t last_pass = 0; - - int render_info[VS::VIEWPORT_RENDER_INFO_MAX]; - VS::ViewportDebugDraw debug_draw; - - VS::ViewportClearMode clear_mode; - - bool transparent_bg; - - struct CanvasKey { - - int64_t stacking; - RID canvas; - bool operator<(const CanvasKey &p_canvas) const { - if (stacking == p_canvas.stacking) - return canvas < p_canvas.canvas; - return stacking < p_canvas.stacking; - } - CanvasKey() { - stacking = 0; - } - CanvasKey(const RID &p_canvas, int p_layer, int p_sublayer) { - canvas = p_canvas; - int64_t sign = p_layer < 0 ? -1 : 1; - stacking = sign * (((int64_t)ABS(p_layer)) << 32) + p_sublayer; - } - int get_layer() const { return stacking >> 32; } - }; - - struct CanvasData { - - CanvasBase *canvas; - Transform2D transform; - int layer; - int sublayer; - }; - - Transform2D global_transform; - - Map canvas_map; - - Viewport() { - update_mode = VS::VIEWPORT_UPDATE_WHEN_VISIBLE; - clear_mode = VS::VIEWPORT_CLEAR_ALWAYS; - transparent_bg = false; - disable_environment = false; - viewport_to_screen = DisplayServer::INVALID_WINDOW_ID; - shadow_atlas_size = 0; - keep_3d_linear = false; - debug_draw = VS::VIEWPORT_DEBUG_DRAW_DISABLED; - msaa = VS::VIEWPORT_MSAA_DISABLED; - for (int i = 0; i < VS::VIEWPORT_RENDER_INFO_MAX; i++) { - render_info[i] = 0; - } - use_arvr = false; - } - }; - - uint64_t draw_viewports_pass = 0; - - mutable RID_PtrOwner viewport_owner; - - struct ViewportSort { - _FORCE_INLINE_ bool operator()(const Viewport *p_left, const Viewport *p_right) const { - - bool left_to_screen = p_left->viewport_to_screen_rect.size != Size2(); - bool right_to_screen = p_right->viewport_to_screen_rect.size != Size2(); - - if (left_to_screen == right_to_screen) { - - return p_right->parent == p_left->self; - } - return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1); - } - }; - - Vector active_viewports; - -private: - void _draw_3d(Viewport *p_viewport, ARVRInterface::Eyes p_eye); - void _draw_viewport(Viewport *p_viewport, ARVRInterface::Eyes p_eye = ARVRInterface::EYE_MONO); - -public: - RID viewport_create(); - - void viewport_set_use_arvr(RID p_viewport, bool p_use_arvr); - - void viewport_set_size(RID p_viewport, int p_width, int p_height); - - void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID); - void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable); - - void viewport_set_active(RID p_viewport, bool p_active); - void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport); - void viewport_set_update_mode(RID p_viewport, VS::ViewportUpdateMode p_mode); - void viewport_set_vflip(RID p_viewport, bool p_enable); - - void viewport_set_clear_mode(RID p_viewport, VS::ViewportClearMode p_clear_mode); - - RID viewport_get_texture(RID p_viewport) const; - - void viewport_set_hide_scenario(RID p_viewport, bool p_hide); - void viewport_set_hide_canvas(RID p_viewport, bool p_hide); - void viewport_set_disable_environment(RID p_viewport, bool p_disable); - - void viewport_attach_camera(RID p_viewport, RID p_camera); - void viewport_set_scenario(RID p_viewport, RID p_scenario); - void viewport_attach_canvas(RID p_viewport, RID p_canvas); - void viewport_remove_canvas(RID p_viewport, RID p_canvas); - void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset); - void viewport_set_transparent_background(RID p_viewport, bool p_enabled); - - void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform); - void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer); - - void viewport_set_shadow_atlas_size(RID p_viewport, int p_size); - void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv); - - void viewport_set_msaa(RID p_viewport, VS::ViewportMSAA p_msaa); - - virtual int viewport_get_render_info(RID p_viewport, VS::ViewportRenderInfo p_info); - virtual void viewport_set_debug_draw(RID p_viewport, VS::ViewportDebugDraw p_draw); - - void set_default_clear_color(const Color &p_color); - void draw_viewports(); - - bool free(RID p_rid); - - VisualServerViewport(); - virtual ~VisualServerViewport() {} -}; - -#endif // VISUALSERVERVIEWPORT_H diff --git a/servers/visual/visual_server_wrap_mt.cpp b/servers/visual/visual_server_wrap_mt.cpp deleted file mode 100644 index 4169144fc9..0000000000 --- a/servers/visual/visual_server_wrap_mt.cpp +++ /dev/null @@ -1,197 +0,0 @@ -/*************************************************************************/ -/* visual_server_wrap_mt.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server_wrap_mt.h" -#include "core/os/os.h" -#include "core/project_settings.h" -#include "servers/display_server.h" - -void VisualServerWrapMT::thread_exit() { - - exit = true; -} - -void VisualServerWrapMT::thread_draw(bool p_swap_buffers, double frame_step) { - - if (!atomic_decrement(&draw_pending)) { - - visual_server->draw(p_swap_buffers, frame_step); - } -} - -void VisualServerWrapMT::thread_flush() { - - atomic_decrement(&draw_pending); -} - -void VisualServerWrapMT::_thread_callback(void *_instance) { - - VisualServerWrapMT *vsmt = reinterpret_cast(_instance); - - vsmt->thread_loop(); -} - -void VisualServerWrapMT::thread_loop() { - - server_thread = Thread::get_caller_id(); - - DisplayServer::get_singleton()->make_rendering_thread(); - - visual_server->init(); - - exit = false; - draw_thread_up = true; - while (!exit) { - // flush commands one by one, until exit is requested - command_queue.wait_and_flush_one(); - } - - command_queue.flush_all(); // flush all - - visual_server->finish(); -} - -/* EVENT QUEUING */ - -void VisualServerWrapMT::sync() { - - if (create_thread) { - - atomic_increment(&draw_pending); - command_queue.push_and_sync(this, &VisualServerWrapMT::thread_flush); - } else { - - command_queue.flush_all(); //flush all pending from other threads - } -} - -void VisualServerWrapMT::draw(bool p_swap_buffers, double frame_step) { - - if (create_thread) { - - atomic_increment(&draw_pending); - command_queue.push(this, &VisualServerWrapMT::thread_draw, p_swap_buffers, frame_step); - } else { - - visual_server->draw(p_swap_buffers, frame_step); - } -} - -void VisualServerWrapMT::init() { - - if (create_thread) { - - print_verbose("VisualServerWrapMT: Creating render thread"); - DisplayServer::get_singleton()->release_rendering_thread(); - if (create_thread) { - thread = Thread::create(_thread_callback, this); - print_verbose("VisualServerWrapMT: Starting render thread"); - } - while (!draw_thread_up) { - OS::get_singleton()->delay_usec(1000); - } - print_verbose("VisualServerWrapMT: Finished render thread"); - } else { - - visual_server->init(); - } -} - -void VisualServerWrapMT::finish() { - - if (thread) { - - command_queue.push(this, &VisualServerWrapMT::thread_exit); - Thread::wait_to_finish(thread); - memdelete(thread); - - thread = NULL; - } else { - visual_server->finish(); - } - - sky_free_cached_ids(); - shader_free_cached_ids(); - material_free_cached_ids(); - mesh_free_cached_ids(); - multimesh_free_cached_ids(); - immediate_free_cached_ids(); - skeleton_free_cached_ids(); - directional_light_free_cached_ids(); - omni_light_free_cached_ids(); - spot_light_free_cached_ids(); - reflection_probe_free_cached_ids(); - gi_probe_free_cached_ids(); - lightmap_capture_free_cached_ids(); - particles_free_cached_ids(); - camera_free_cached_ids(); - viewport_free_cached_ids(); - environment_free_cached_ids(); - camera_effects_free_cached_ids(); - scenario_free_cached_ids(); - instance_free_cached_ids(); - canvas_free_cached_ids(); - canvas_item_free_cached_ids(); - canvas_light_occluder_free_cached_ids(); - canvas_occluder_polygon_free_cached_ids(); -} - -void VisualServerWrapMT::set_use_vsync_callback(bool p_enable) { - - singleton_mt->call_set_use_vsync(p_enable); -} - -VisualServerWrapMT *VisualServerWrapMT::singleton_mt = NULL; - -VisualServerWrapMT::VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread) : - command_queue(p_create_thread) { - - singleton_mt = this; - DisplayServer::switch_vsync_function = set_use_vsync_callback; //as this goes to another thread, make sure it goes properly - - visual_server = p_contained; - create_thread = p_create_thread; - thread = NULL; - draw_pending = 0; - draw_thread_up = false; - pool_max_size = GLOBAL_GET("memory/limits/multithreaded_server/rid_pool_prealloc"); - - if (!p_create_thread) { - server_thread = Thread::get_caller_id(); - } else { - server_thread = 0; - } -} - -VisualServerWrapMT::~VisualServerWrapMT() { - - memdelete(visual_server); - //finish(); -} diff --git a/servers/visual/visual_server_wrap_mt.h b/servers/visual/visual_server_wrap_mt.h deleted file mode 100644 index e043ac5214..0000000000 --- a/servers/visual/visual_server_wrap_mt.h +++ /dev/null @@ -1,678 +0,0 @@ -/*************************************************************************/ -/* visual_server_wrap_mt.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUAL_SERVER_WRAP_MT_H -#define VISUAL_SERVER_WRAP_MT_H - -#include "core/command_queue_mt.h" -#include "core/os/thread.h" -#include "servers/visual_server.h" - -class VisualServerWrapMT : public VisualServer { - - // the real visual server - mutable VisualServer *visual_server; - - mutable CommandQueueMT command_queue; - - static void _thread_callback(void *_instance); - void thread_loop(); - - Thread::ID server_thread; - volatile bool exit; - Thread *thread; - volatile bool draw_thread_up; - bool create_thread; - - uint64_t draw_pending; - void thread_draw(bool p_swap_buffers, double frame_step); - void thread_flush(); - - void thread_exit(); - - Mutex alloc_mutex; - - int pool_max_size; - - //#define DEBUG_SYNC - - static VisualServerWrapMT *singleton_mt; - -#ifdef DEBUG_SYNC -#define SYNC_DEBUG print_line("sync on: " + String(__FUNCTION__)); -#else -#define SYNC_DEBUG -#endif - -public: -#define ServerName VisualServer -#define ServerNameWrapMT VisualServerWrapMT -#define server_name visual_server -#include "servers/server_wrap_mt_common.h" - - //these go pass-through, as they can be called from any thread - virtual RID texture_2d_create(const Ref &p_image) { return visual_server->texture_2d_create(p_image); } - virtual RID texture_2d_layered_create(const Vector> &p_layers, TextureLayeredType p_layered_type) { return visual_server->texture_2d_layered_create(p_layers, p_layered_type); } - virtual RID texture_3d_create(const Vector> &p_slices) { return visual_server->texture_3d_create(p_slices); } - virtual RID texture_proxy_create(RID p_base) { return visual_server->texture_proxy_create(p_base); } - - //goes pass-through - virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0) { visual_server->texture_2d_update_immediate(p_texture, p_image, p_layer); } - //these go through command queue if they are in another thread - FUNC3(texture_2d_update, RID, const Ref &, int) - FUNC4(texture_3d_update, RID, const Ref &, int, int) - FUNC2(texture_proxy_update, RID, RID) - - //these also go pass-through - virtual RID texture_2d_placeholder_create() { return visual_server->texture_2d_placeholder_create(); } - virtual RID texture_2d_layered_placeholder_create() { return visual_server->texture_2d_layered_placeholder_create(); } - virtual RID texture_3d_placeholder_create() { return visual_server->texture_3d_placeholder_create(); } - - FUNC1RC(Ref, texture_2d_get, RID) - FUNC2RC(Ref, texture_2d_layer_get, RID, int) - FUNC3RC(Ref, texture_3d_slice_get, RID, int, int) - - FUNC2(texture_replace, RID, RID) - - FUNC3(texture_set_size_override, RID, int, int) -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - FUNC2(texture_bind, RID, uint32_t) -#endif - - FUNC3(texture_set_detect_3d_callback, RID, TextureDetectCallback, void *) - FUNC3(texture_set_detect_normal_callback, RID, TextureDetectCallback, void *) - FUNC3(texture_set_detect_roughness_callback, RID, TextureDetectRoughnessCallback, void *) - - FUNC2(texture_set_path, RID, const String &) - FUNC1RC(String, texture_get_path, RID) - FUNC1S(texture_debug_usage, List *) - - FUNC2(texture_set_force_redraw_if_visible, RID, bool) - - /* SHADER API */ - - FUNCRID(shader) - - FUNC2(shader_set_code, RID, const String &) - FUNC1RC(String, shader_get_code, RID) - - FUNC2SC(shader_get_param_list, RID, List *) - - FUNC3(shader_set_default_texture_param, RID, const StringName &, RID) - FUNC2RC(RID, shader_get_default_texture_param, RID, const StringName &) - FUNC2RC(Variant, shader_get_param_default, RID, const StringName &) - - /* COMMON MATERIAL API */ - - FUNCRID(material) - - FUNC2(material_set_shader, RID, RID) - - FUNC3(material_set_param, RID, const StringName &, const Variant &) - FUNC2RC(Variant, material_get_param, RID, const StringName &) - - FUNC2(material_set_render_priority, RID, int) - FUNC2(material_set_next_pass, RID, RID) - - /* MESH API */ - - virtual RID mesh_create_from_surfaces(const Vector &p_surfaces) { - return visual_server->mesh_create_from_surfaces(p_surfaces); - } - - FUNCRID(mesh) - - FUNC2(mesh_add_surface, RID, const SurfaceData &) - - FUNC1RC(int, mesh_get_blend_shape_count, RID) - - FUNC2(mesh_set_blend_shape_mode, RID, BlendShapeMode) - FUNC1RC(BlendShapeMode, mesh_get_blend_shape_mode, RID) - - FUNC4(mesh_surface_update_region, RID, int, int, const Vector &) - - FUNC3(mesh_surface_set_material, RID, int, RID) - FUNC2RC(RID, mesh_surface_get_material, RID, int) - - FUNC2RC(SurfaceData, mesh_get_surface, RID, int) - - FUNC1RC(int, mesh_get_surface_count, RID) - - FUNC2(mesh_set_custom_aabb, RID, const AABB &) - FUNC1RC(AABB, mesh_get_custom_aabb, RID) - - FUNC1(mesh_clear, RID) - - /* MULTIMESH API */ - - FUNCRID(multimesh) - - FUNC5(multimesh_allocate, RID, int, MultimeshTransformFormat, bool, bool) - FUNC1RC(int, multimesh_get_instance_count, RID) - - FUNC2(multimesh_set_mesh, RID, RID) - FUNC3(multimesh_instance_set_transform, RID, int, const Transform &) - FUNC3(multimesh_instance_set_transform_2d, RID, int, const Transform2D &) - FUNC3(multimesh_instance_set_color, RID, int, const Color &) - FUNC3(multimesh_instance_set_custom_data, RID, int, const Color &) - - FUNC1RC(RID, multimesh_get_mesh, RID) - FUNC1RC(AABB, multimesh_get_aabb, RID) - - FUNC2RC(Transform, multimesh_instance_get_transform, RID, int) - FUNC2RC(Transform2D, multimesh_instance_get_transform_2d, RID, int) - FUNC2RC(Color, multimesh_instance_get_color, RID, int) - FUNC2RC(Color, multimesh_instance_get_custom_data, RID, int) - - FUNC2(multimesh_set_buffer, RID, const Vector &) - FUNC1RC(Vector, multimesh_get_buffer, RID) - - FUNC2(multimesh_set_visible_instances, RID, int) - FUNC1RC(int, multimesh_get_visible_instances, RID) - - /* IMMEDIATE API */ - - FUNCRID(immediate) - FUNC3(immediate_begin, RID, PrimitiveType, RID) - FUNC2(immediate_vertex, RID, const Vector3 &) - FUNC2(immediate_normal, RID, const Vector3 &) - FUNC2(immediate_tangent, RID, const Plane &) - FUNC2(immediate_color, RID, const Color &) - FUNC2(immediate_uv, RID, const Vector2 &) - FUNC2(immediate_uv2, RID, const Vector2 &) - FUNC1(immediate_end, RID) - FUNC1(immediate_clear, RID) - FUNC2(immediate_set_material, RID, RID) - FUNC1RC(RID, immediate_get_material, RID) - - /* SKELETON API */ - - FUNCRID(skeleton) - FUNC3(skeleton_allocate, RID, int, bool) - FUNC1RC(int, skeleton_get_bone_count, RID) - FUNC3(skeleton_bone_set_transform, RID, int, const Transform &) - FUNC2RC(Transform, skeleton_bone_get_transform, RID, int) - FUNC3(skeleton_bone_set_transform_2d, RID, int, const Transform2D &) - FUNC2RC(Transform2D, skeleton_bone_get_transform_2d, RID, int) - FUNC2(skeleton_set_base_transform_2d, RID, const Transform2D &) - - /* Light API */ - - FUNCRID(directional_light) - FUNCRID(omni_light) - FUNCRID(spot_light) - - FUNC2(light_set_color, RID, const Color &) - FUNC3(light_set_param, RID, LightParam, float) - FUNC2(light_set_shadow, RID, bool) - FUNC2(light_set_shadow_color, RID, const Color &) - FUNC2(light_set_projector, RID, RID) - FUNC2(light_set_negative, RID, bool) - FUNC2(light_set_cull_mask, RID, uint32_t) - FUNC2(light_set_reverse_cull_face_mode, RID, bool) - FUNC2(light_set_use_gi, RID, bool) - - FUNC2(light_omni_set_shadow_mode, RID, LightOmniShadowMode) - - FUNC2(light_directional_set_shadow_mode, RID, LightDirectionalShadowMode) - FUNC2(light_directional_set_blend_splits, RID, bool) - FUNC2(light_directional_set_shadow_depth_range_mode, RID, LightDirectionalShadowDepthRangeMode) - - /* PROBE API */ - - FUNCRID(reflection_probe) - - FUNC2(reflection_probe_set_update_mode, RID, ReflectionProbeUpdateMode) - FUNC2(reflection_probe_set_intensity, RID, float) - FUNC2(reflection_probe_set_interior_ambient, RID, const Color &) - FUNC2(reflection_probe_set_interior_ambient_energy, RID, float) - FUNC2(reflection_probe_set_interior_ambient_probe_contribution, RID, float) - FUNC2(reflection_probe_set_max_distance, RID, float) - FUNC2(reflection_probe_set_extents, RID, const Vector3 &) - FUNC2(reflection_probe_set_origin_offset, RID, const Vector3 &) - FUNC2(reflection_probe_set_as_interior, RID, bool) - FUNC2(reflection_probe_set_enable_box_projection, RID, bool) - FUNC2(reflection_probe_set_enable_shadows, RID, bool) - FUNC2(reflection_probe_set_cull_mask, RID, uint32_t) - FUNC2(reflection_probe_set_resolution, RID, int) - - /* BAKED LIGHT API */ - - FUNCRID(gi_probe) - - FUNC8(gi_probe_allocate, RID, const Transform &, const AABB &, const Vector3i &, const Vector &, const Vector &, const Vector &, const Vector &) - - FUNC1RC(AABB, gi_probe_get_bounds, RID) - FUNC1RC(Vector3i, gi_probe_get_octree_size, RID) - FUNC1RC(Vector, gi_probe_get_octree_cells, RID) - FUNC1RC(Vector, gi_probe_get_data_cells, RID) - FUNC1RC(Vector, gi_probe_get_distance_field, RID) - FUNC1RC(Vector, gi_probe_get_level_counts, RID) - FUNC1RC(Transform, gi_probe_get_to_cell_xform, RID) - - FUNC2(gi_probe_set_dynamic_range, RID, float) - FUNC1RC(float, gi_probe_get_dynamic_range, RID) - - FUNC2(gi_probe_set_propagation, RID, float) - FUNC1RC(float, gi_probe_get_propagation, RID) - - FUNC2(gi_probe_set_energy, RID, float) - FUNC1RC(float, gi_probe_get_energy, RID) - - FUNC2(gi_probe_set_ao, RID, float) - FUNC1RC(float, gi_probe_get_ao, RID) - - FUNC2(gi_probe_set_ao_size, RID, float) - FUNC1RC(float, gi_probe_get_ao_size, RID) - - FUNC2(gi_probe_set_bias, RID, float) - FUNC1RC(float, gi_probe_get_bias, RID) - - FUNC2(gi_probe_set_normal_bias, RID, float) - FUNC1RC(float, gi_probe_get_normal_bias, RID) - - FUNC2(gi_probe_set_interior, RID, bool) - FUNC1RC(bool, gi_probe_is_interior, RID) - - FUNC2(gi_probe_set_use_two_bounces, RID, bool) - FUNC1RC(bool, gi_probe_is_using_two_bounces, RID) - - FUNC2(gi_probe_set_anisotropy_strength, RID, float) - FUNC1RC(float, gi_probe_get_anisotropy_strength, RID) - - /* LIGHTMAP CAPTURE */ - - FUNCRID(lightmap_capture) - - FUNC2(lightmap_capture_set_bounds, RID, const AABB &) - FUNC1RC(AABB, lightmap_capture_get_bounds, RID) - - FUNC2(lightmap_capture_set_octree, RID, const Vector &) - FUNC1RC(Vector, lightmap_capture_get_octree, RID) - FUNC2(lightmap_capture_set_octree_cell_transform, RID, const Transform &) - FUNC1RC(Transform, lightmap_capture_get_octree_cell_transform, RID) - FUNC2(lightmap_capture_set_octree_cell_subdiv, RID, int) - FUNC1RC(int, lightmap_capture_get_octree_cell_subdiv, RID) - FUNC2(lightmap_capture_set_energy, RID, float) - FUNC1RC(float, lightmap_capture_get_energy, RID) - - /* PARTICLES */ - - FUNCRID(particles) - - FUNC2(particles_set_emitting, RID, bool) - FUNC1R(bool, particles_get_emitting, RID) - FUNC2(particles_set_amount, RID, int) - FUNC2(particles_set_lifetime, RID, float) - FUNC2(particles_set_one_shot, RID, bool) - FUNC2(particles_set_pre_process_time, RID, float) - FUNC2(particles_set_explosiveness_ratio, RID, float) - FUNC2(particles_set_randomness_ratio, RID, float) - FUNC2(particles_set_custom_aabb, RID, const AABB &) - FUNC2(particles_set_speed_scale, RID, float) - FUNC2(particles_set_use_local_coordinates, RID, bool) - FUNC2(particles_set_process_material, RID, RID) - FUNC2(particles_set_fixed_fps, RID, int) - FUNC2(particles_set_fractional_delta, RID, bool) - FUNC1R(bool, particles_is_inactive, RID) - FUNC1(particles_request_process, RID) - FUNC1(particles_restart, RID) - - FUNC2(particles_set_draw_order, RID, VS::ParticlesDrawOrder) - - FUNC2(particles_set_draw_passes, RID, int) - FUNC3(particles_set_draw_pass_mesh, RID, int, RID) - FUNC2(particles_set_emission_transform, RID, const Transform &) - - FUNC1R(AABB, particles_get_current_aabb, RID) - - /* CAMERA API */ - - FUNCRID(camera) - FUNC4(camera_set_perspective, RID, float, float, float) - FUNC4(camera_set_orthogonal, RID, float, float, float) - FUNC5(camera_set_frustum, RID, float, Vector2, float, float) - FUNC2(camera_set_transform, RID, const Transform &) - FUNC2(camera_set_cull_mask, RID, uint32_t) - FUNC2(camera_set_environment, RID, RID) - FUNC2(camera_set_camera_effects, RID, RID) - FUNC2(camera_set_use_vertical_aspect, RID, bool) - - /* VIEWPORT TARGET API */ - - FUNCRID(viewport) - - FUNC2(viewport_set_use_arvr, RID, bool) - - FUNC3(viewport_set_size, RID, int, int) - - FUNC2(viewport_set_active, RID, bool) - FUNC2(viewport_set_parent_viewport, RID, RID) - - FUNC2(viewport_set_clear_mode, RID, ViewportClearMode) - - FUNC3(viewport_attach_to_screen, RID, const Rect2 &, DisplayServer::WindowID) - FUNC2(viewport_set_render_direct_to_screen, RID, bool) - - FUNC2(viewport_set_update_mode, RID, ViewportUpdateMode) - - FUNC1RC(RID, viewport_get_texture, RID) - - FUNC2(viewport_set_hide_scenario, RID, bool) - FUNC2(viewport_set_hide_canvas, RID, bool) - FUNC2(viewport_set_disable_environment, RID, bool) - - FUNC2(viewport_attach_camera, RID, RID) - FUNC2(viewport_set_scenario, RID, RID) - FUNC2(viewport_attach_canvas, RID, RID) - - FUNC2(viewport_remove_canvas, RID, RID) - FUNC3(viewport_set_canvas_transform, RID, RID, const Transform2D &) - FUNC2(viewport_set_transparent_background, RID, bool) - - FUNC2(viewport_set_global_canvas_transform, RID, const Transform2D &) - FUNC4(viewport_set_canvas_stacking, RID, RID, int, int) - FUNC2(viewport_set_shadow_atlas_size, RID, int) - FUNC3(viewport_set_shadow_atlas_quadrant_subdivision, RID, int, int) - FUNC2(viewport_set_msaa, RID, ViewportMSAA) - - //this passes directly to avoid stalling, but it's pretty dangerous, so don't call after freeing a viewport - virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) { - return visual_server->viewport_get_render_info(p_viewport, p_info); - } - - FUNC2(viewport_set_debug_draw, RID, ViewportDebugDraw) - - FUNC1(directional_shadow_atlas_set_size, int) - - /* SKY API */ - - FUNCRID(sky) - FUNC2(sky_set_radiance_size, RID, int) - FUNC2(sky_set_mode, RID, SkyMode) - FUNC2(sky_set_material, RID, RID) - - /* ENVIRONMENT API */ - - FUNCRID(environment) - - FUNC2(environment_set_background, RID, EnvironmentBG) - FUNC2(environment_set_sky, RID, RID) - FUNC2(environment_set_sky_custom_fov, RID, float) - FUNC2(environment_set_sky_orientation, RID, const Basis &) - FUNC2(environment_set_bg_color, RID, const Color &) - FUNC2(environment_set_bg_energy, RID, float) - FUNC2(environment_set_canvas_max_layer, RID, int) - FUNC7(environment_set_ambient_light, RID, const Color &, EnvironmentAmbientSource, float, float, EnvironmentReflectionSource, const Color &) - -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - FUNC2(environment_set_camera_feed_id, RID, int) -#endif - FUNC7(environment_set_ssr, RID, bool, int, float, float, float, bool) - FUNC9(environment_set_ssao, RID, bool, float, float, float, float, float, EnvironmentSSAOBlur, float) - - FUNC2(environment_set_ssao_quality, EnvironmentSSAOQuality, bool) - - FUNC12(environment_set_glow, RID, bool, int, float, float, float, float, EnvironmentGlowBlendMode, float, float, float, bool) - - FUNC9(environment_set_tonemap, RID, EnvironmentToneMapper, float, float, bool, float, float, float, float) - - FUNC6(environment_set_adjustment, RID, bool, float, float, float, RID) - - FUNC5(environment_set_fog, RID, bool, const Color &, const Color &, float) - FUNC7(environment_set_fog_depth, RID, bool, float, float, float, bool, float) - FUNC5(environment_set_fog_height, RID, bool, float, float, float) - - FUNC2(screen_space_roughness_limiter_set_active, bool, float) - - FUNCRID(camera_effects) - - FUNC2(camera_effects_set_dof_blur_quality, DOFBlurQuality, bool) - FUNC1(camera_effects_set_dof_blur_bokeh_shape, DOFBokehShape) - - FUNC8(camera_effects_set_dof_blur, RID, bool, float, float, bool, float, float, float) - FUNC3(camera_effects_set_custom_exposure, RID, bool, float) - - FUNCRID(scenario) - - FUNC2(scenario_set_debug, RID, ScenarioDebugMode) - FUNC2(scenario_set_environment, RID, RID) - FUNC2(scenario_set_camera_effects, RID, RID) - FUNC2(scenario_set_fallback_environment, RID, RID) - - /* INSTANCING API */ - FUNCRID(instance) - - FUNC2(instance_set_base, RID, RID) - FUNC2(instance_set_scenario, RID, RID) - FUNC2(instance_set_layer_mask, RID, uint32_t) - FUNC2(instance_set_transform, RID, const Transform &) - FUNC2(instance_attach_object_instance_id, RID, ObjectID) - FUNC3(instance_set_blend_shape_weight, RID, int, float) - FUNC3(instance_set_surface_material, RID, int, RID) - FUNC2(instance_set_visible, RID, bool) - FUNC3(instance_set_use_lightmap, RID, RID, RID) - - FUNC2(instance_set_custom_aabb, RID, AABB) - - FUNC2(instance_attach_skeleton, RID, RID) - FUNC2(instance_set_exterior, RID, bool) - - FUNC2(instance_set_extra_visibility_margin, RID, real_t) - - // don't use these in a game! - FUNC2RC(Vector, instances_cull_aabb, const AABB &, RID) - FUNC3RC(Vector, instances_cull_ray, const Vector3 &, const Vector3 &, RID) - FUNC2RC(Vector, instances_cull_convex, const Vector &, RID) - - FUNC3(instance_geometry_set_flag, RID, InstanceFlags, bool) - FUNC2(instance_geometry_set_cast_shadows_setting, RID, ShadowCastingSetting) - FUNC2(instance_geometry_set_material_override, RID, RID) - - FUNC5(instance_geometry_set_draw_range, RID, float, float, float, float) - FUNC2(instance_geometry_set_as_instance_lod, RID, RID) - - /* CANVAS (2D) */ - - FUNCRID(canvas) - FUNC3(canvas_set_item_mirroring, RID, RID, const Point2 &) - FUNC2(canvas_set_modulate, RID, const Color &) - FUNC3(canvas_set_parent, RID, RID, float) - FUNC1(canvas_set_disable_scale, bool) - - FUNCRID(canvas_item) - FUNC2(canvas_item_set_parent, RID, RID) - - FUNC2(canvas_item_set_visible, RID, bool) - FUNC2(canvas_item_set_light_mask, RID, int) - - FUNC2(canvas_item_set_update_when_visible, RID, bool) - - FUNC2(canvas_item_set_transform, RID, const Transform2D &) - FUNC2(canvas_item_set_clip, RID, bool) - FUNC2(canvas_item_set_distance_field_mode, RID, bool) - FUNC3(canvas_item_set_custom_rect, RID, bool, const Rect2 &) - FUNC2(canvas_item_set_modulate, RID, const Color &) - FUNC2(canvas_item_set_self_modulate, RID, const Color &) - - FUNC2(canvas_item_set_draw_behind_parent, RID, bool) - - FUNC2(canvas_item_set_default_texture_filter, RID, CanvasItemTextureFilter) - FUNC2(canvas_item_set_default_texture_repeat, RID, CanvasItemTextureRepeat) - - FUNC5(canvas_item_add_line, RID, const Point2 &, const Point2 &, const Color &, float) - FUNC4(canvas_item_add_polyline, RID, const Vector &, const Vector &, float) - FUNC4(canvas_item_add_multiline, RID, const Vector &, const Vector &, float) - FUNC3(canvas_item_add_rect, RID, const Rect2 &, const Color &) - FUNC4(canvas_item_add_circle, RID, const Point2 &, float, const Color &) - FUNC11(canvas_item_add_texture_rect, RID, const Rect2 &, RID, bool, const Color &, bool, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC12(canvas_item_add_texture_rect_region, RID, const Rect2 &, RID, const Rect2 &, const Color &, bool, RID, RID, const Color &, bool, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC15(canvas_item_add_nine_patch, RID, const Rect2 &, const Rect2 &, RID, const Vector2 &, const Vector2 &, NinePatchAxisMode, NinePatchAxisMode, bool, const Color &, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC11(canvas_item_add_primitive, RID, const Vector &, const Vector &, const Vector &, RID, float, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC10(canvas_item_add_polygon, RID, const Vector &, const Vector &, const Vector &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC14(canvas_item_add_triangle_array, RID, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, const Vector &, RID, int, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC10(canvas_item_add_mesh, RID, const RID &, const Transform2D &, const Color &, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC8(canvas_item_add_multimesh, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC8(canvas_item_add_particles, RID, RID, RID, RID, RID, const Color &, CanvasItemTextureFilter, CanvasItemTextureRepeat) - FUNC2(canvas_item_add_set_transform, RID, const Transform2D &) - FUNC2(canvas_item_add_clip_ignore, RID, bool) - FUNC2(canvas_item_set_sort_children_by_y, RID, bool) - FUNC2(canvas_item_set_z_index, RID, int) - FUNC2(canvas_item_set_z_as_relative_to_parent, RID, bool) - FUNC3(canvas_item_set_copy_to_backbuffer, RID, bool, const Rect2 &) - FUNC2(canvas_item_attach_skeleton, RID, RID) - - FUNC1(canvas_item_clear, RID) - FUNC2(canvas_item_set_draw_index, RID, int) - - FUNC2(canvas_item_set_material, RID, RID) - - FUNC2(canvas_item_set_use_parent_material, RID, bool) - - FUNC0R(RID, canvas_light_create) - FUNC2(canvas_light_attach_to_canvas, RID, RID) - FUNC2(canvas_light_set_enabled, RID, bool) - FUNC2(canvas_light_set_scale, RID, float) - FUNC2(canvas_light_set_transform, RID, const Transform2D &) - FUNC2(canvas_light_set_texture, RID, RID) - FUNC2(canvas_light_set_texture_offset, RID, const Vector2 &) - FUNC2(canvas_light_set_color, RID, const Color &) - FUNC2(canvas_light_set_height, RID, float) - FUNC2(canvas_light_set_energy, RID, float) - FUNC3(canvas_light_set_z_range, RID, int, int) - FUNC3(canvas_light_set_layer_range, RID, int, int) - FUNC2(canvas_light_set_item_cull_mask, RID, int) - FUNC2(canvas_light_set_item_shadow_cull_mask, RID, int) - - FUNC2(canvas_light_set_mode, RID, CanvasLightMode) - - FUNC2(canvas_light_set_shadow_enabled, RID, bool) - FUNC2(canvas_light_set_shadow_buffer_size, RID, int) - FUNC2(canvas_light_set_shadow_filter, RID, CanvasLightShadowFilter) - FUNC2(canvas_light_set_shadow_color, RID, const Color &) - FUNC2(canvas_light_set_shadow_smooth, RID, float) - - FUNCRID(canvas_light_occluder) - FUNC2(canvas_light_occluder_attach_to_canvas, RID, RID) - FUNC2(canvas_light_occluder_set_enabled, RID, bool) - FUNC2(canvas_light_occluder_set_polygon, RID, RID) - FUNC2(canvas_light_occluder_set_transform, RID, const Transform2D &) - FUNC2(canvas_light_occluder_set_light_mask, RID, int) - - FUNCRID(canvas_occluder_polygon) - FUNC3(canvas_occluder_polygon_set_shape, RID, const Vector &, bool) - FUNC2(canvas_occluder_polygon_set_shape_as_lines, RID, const Vector &) - - FUNC2(canvas_occluder_polygon_set_cull_mode, RID, CanvasOccluderPolygonCullMode) - - /* BLACK BARS */ - - FUNC4(black_bars_set_margins, int, int, int, int) - FUNC4(black_bars_set_images, RID, RID, RID, RID) - - /* FREE */ - - FUNC1(free, RID) - - /* EVENT QUEUING */ - - FUNC3(request_frame_drawn_callback, Object *, const StringName &, const Variant &) - - virtual void init(); - virtual void finish(); - virtual void draw(bool p_swap_buffers, double frame_step); - virtual void sync(); - FUNC0RC(bool, has_changed) - - /* RENDER INFO */ - - //this passes directly to avoid stalling - virtual int get_render_info(RenderInfo p_info) { - return visual_server->get_render_info(p_info); - } - - virtual String get_video_adapter_name() const { - return visual_server->get_video_adapter_name(); - } - - virtual String get_video_adapter_vendor() const { - return visual_server->get_video_adapter_vendor(); - } - - FUNC4(set_boot_image, const Ref &, const Color &, bool, bool) - FUNC1(set_default_clear_color, const Color &) - - FUNC0R(RID, get_test_cube) - - FUNC1(set_debug_generate_wireframes, bool) - - virtual bool has_feature(Features p_feature) const { - return visual_server->has_feature(p_feature); - } - virtual bool has_os_feature(const String &p_feature) const { - return visual_server->has_os_feature(p_feature); - } - - FUNC1(call_set_use_vsync, bool) - - static void set_use_vsync_callback(bool p_enable); - - virtual bool is_low_end() const { - return visual_server->is_low_end(); - } - - virtual uint64_t get_frame_profile_frame() { - return visual_server->get_frame_profile_frame(); - } - - virtual void set_frame_profiling_enabled(bool p_enabled) { - visual_server->set_frame_profiling_enabled(p_enabled); - } - - virtual Vector get_frame_profile() { - return visual_server->get_frame_profile(); - } - - VisualServerWrapMT(VisualServer *p_contained, bool p_create_thread); - ~VisualServerWrapMT(); - -#undef ServerName -#undef ServerNameWrapMT -#undef server_name -}; - -#ifdef DEBUG_SYNC -#undef DEBUG_SYNC -#endif -#undef SYNC_DEBUG - -#endif diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp deleted file mode 100644 index fecaf563db..0000000000 --- a/servers/visual_server.cpp +++ /dev/null @@ -1,2363 +0,0 @@ -/*************************************************************************/ -/* visual_server.cpp */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#include "visual_server.h" - -#include "core/method_bind_ext.gen.inc" -#include "core/project_settings.h" - -VisualServer *VisualServer::singleton = NULL; -VisualServer *(*VisualServer::create_func)() = NULL; - -VisualServer *VisualServer::get_singleton() { - - return singleton; -} - -VisualServer *VisualServer::create() { - - ERR_FAIL_COND_V(singleton, NULL); - - if (create_func) - return create_func(); - - return NULL; -} - -Array VisualServer::_texture_debug_usage_bind() { - - List list; - texture_debug_usage(&list); - Array arr; - for (const List::Element *E = list.front(); E; E = E->next()) { - - Dictionary dict; - dict["texture"] = E->get().texture; - dict["width"] = E->get().width; - dict["height"] = E->get().height; - dict["depth"] = E->get().depth; - dict["format"] = E->get().format; - dict["bytes"] = E->get().bytes; - dict["path"] = E->get().path; - arr.push_back(dict); - } - return arr; -} - -Array VisualServer::_shader_get_param_list_bind(RID p_shader) const { - - List l; - shader_get_param_list(p_shader, &l); - return convert_property_list(&l); -} - -static Array to_array(const Vector &ids) { - Array a; - a.resize(ids.size()); - for (int i = 0; i < ids.size(); ++i) { - a[i] = ids[i]; - } - return a; -} - -Array VisualServer::_instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario) const { - - Vector ids = instances_cull_aabb(p_aabb, p_scenario); - return to_array(ids); -} - -Array VisualServer::_instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario) const { - - Vector ids = instances_cull_ray(p_from, p_to, p_scenario); - return to_array(ids); -} - -Array VisualServer::_instances_cull_convex_bind(const Array &p_convex, RID p_scenario) const { - - Vector planes; - for (int i = 0; i < p_convex.size(); ++i) { - Variant v = p_convex[i]; - ERR_FAIL_COND_V(v.get_type() != Variant::PLANE, Array()); - planes.push_back(v); - } - - Vector ids = instances_cull_convex(planes, p_scenario); - return to_array(ids); -} - -RID VisualServer::get_test_texture() { - - if (test_texture.is_valid()) { - return test_texture; - }; - -#define TEST_TEXTURE_SIZE 256 - - Vector test_data; - test_data.resize(TEST_TEXTURE_SIZE * TEST_TEXTURE_SIZE * 3); - - { - uint8_t *w = test_data.ptrw(); - - for (int x = 0; x < TEST_TEXTURE_SIZE; x++) { - - for (int y = 0; y < TEST_TEXTURE_SIZE; y++) { - - Color c; - int r = 255 - (x + y) / 2; - - if ((x % (TEST_TEXTURE_SIZE / 8)) < 2 || (y % (TEST_TEXTURE_SIZE / 8)) < 2) { - - c.r = y; - c.g = r; - c.b = x; - - } else { - - c.r = r; - c.g = x; - c.b = y; - } - - w[(y * TEST_TEXTURE_SIZE + x) * 3 + 0] = uint8_t(CLAMP(c.r * 255, 0, 255)); - w[(y * TEST_TEXTURE_SIZE + x) * 3 + 1] = uint8_t(CLAMP(c.g * 255, 0, 255)); - w[(y * TEST_TEXTURE_SIZE + x) * 3 + 2] = uint8_t(CLAMP(c.b * 255, 0, 255)); - } - } - } - - Ref data = memnew(Image(TEST_TEXTURE_SIZE, TEST_TEXTURE_SIZE, false, Image::FORMAT_RGB8, test_data)); - - test_texture = texture_2d_create(data); - - return test_texture; -} - -void VisualServer::_free_internal_rids() { - - if (test_texture.is_valid()) - free(test_texture); - if (white_texture.is_valid()) - free(white_texture); - if (test_material.is_valid()) - free(test_material); -} - -RID VisualServer::_make_test_cube() { - - Vector vertices; - Vector normals; - Vector tangents; - Vector uvs; - -#define ADD_VTX(m_idx) \ - vertices.push_back(face_points[m_idx]); \ - normals.push_back(normal_points[m_idx]); \ - tangents.push_back(normal_points[m_idx][1]); \ - tangents.push_back(normal_points[m_idx][2]); \ - tangents.push_back(normal_points[m_idx][0]); \ - tangents.push_back(1.0); \ - uvs.push_back(Vector3(uv_points[m_idx * 2 + 0], uv_points[m_idx * 2 + 1], 0)); - - for (int i = 0; i < 6; i++) { - - Vector3 face_points[4]; - Vector3 normal_points[4]; - float uv_points[8] = { 0, 0, 0, 1, 1, 1, 1, 0 }; - - for (int j = 0; j < 4; j++) { - - float v[3]; - v[0] = 1.0; - v[1] = 1 - 2 * ((j >> 1) & 1); - v[2] = v[1] * (1 - 2 * (j & 1)); - - for (int k = 0; k < 3; k++) { - - if (i < 3) - face_points[j][(i + k) % 3] = v[k]; - else - face_points[3 - j][(i + k) % 3] = -v[k]; - } - normal_points[j] = Vector3(); - normal_points[j][i % 3] = (i >= 3 ? -1 : 1); - } - - //tri 1 - ADD_VTX(0); - ADD_VTX(1); - ADD_VTX(2); - //tri 2 - ADD_VTX(2); - ADD_VTX(3); - ADD_VTX(0); - } - - RID test_cube = mesh_create(); - - Array d; - d.resize(VS::ARRAY_MAX); - d[VisualServer::ARRAY_NORMAL] = normals; - d[VisualServer::ARRAY_TANGENT] = tangents; - d[VisualServer::ARRAY_TEX_UV] = uvs; - d[VisualServer::ARRAY_VERTEX] = vertices; - - Vector indices; - indices.resize(vertices.size()); - for (int i = 0; i < vertices.size(); i++) - indices.set(i, i); - d[VisualServer::ARRAY_INDEX] = indices; - - mesh_add_surface_from_arrays(test_cube, PRIMITIVE_TRIANGLES, d); - - /* - test_material = fixed_material_create(); - //material_set_flag(material, MATERIAL_FLAG_BILLBOARD_TOGGLE,true); - fixed_material_set_texture( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, get_test_texture() ); - fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR_EXP, 70 ); - fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_EMISSION, Color(0.2,0.2,0.2) ); - - fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_DIFFUSE, Color(1, 1, 1) ); - fixed_material_set_param( test_material, FIXED_MATERIAL_PARAM_SPECULAR, Color(1,1,1) ); -*/ - mesh_surface_set_material(test_cube, 0, test_material); - - return test_cube; -} - -RID VisualServer::make_sphere_mesh(int p_lats, int p_lons, float p_radius) { - - Vector vertices; - Vector normals; - - for (int i = 1; i <= p_lats; i++) { - double lat0 = Math_PI * (-0.5 + (double)(i - 1) / p_lats); - double z0 = Math::sin(lat0); - double zr0 = Math::cos(lat0); - - double lat1 = Math_PI * (-0.5 + (double)i / p_lats); - double z1 = Math::sin(lat1); - double zr1 = Math::cos(lat1); - - for (int j = p_lons; j >= 1; j--) { - - double lng0 = 2 * Math_PI * (double)(j - 1) / p_lons; - double x0 = Math::cos(lng0); - double y0 = Math::sin(lng0); - - double lng1 = 2 * Math_PI * (double)(j) / p_lons; - double x1 = Math::cos(lng1); - double y1 = Math::sin(lng1); - - Vector3 v[4] = { - Vector3(x1 * zr0, z0, y1 * zr0), - Vector3(x1 * zr1, z1, y1 * zr1), - Vector3(x0 * zr1, z1, y0 * zr1), - Vector3(x0 * zr0, z0, y0 * zr0) - }; - -#define ADD_POINT(m_idx) \ - normals.push_back(v[m_idx]); \ - vertices.push_back(v[m_idx] * p_radius); - - ADD_POINT(0); - ADD_POINT(1); - ADD_POINT(2); - - ADD_POINT(2); - ADD_POINT(3); - ADD_POINT(0); - } - } - - RID mesh = mesh_create(); - Array d; - d.resize(VS::ARRAY_MAX); - - d[ARRAY_VERTEX] = vertices; - d[ARRAY_NORMAL] = normals; - - mesh_add_surface_from_arrays(mesh, PRIMITIVE_TRIANGLES, d); - - return mesh; -} - -RID VisualServer::get_white_texture() { - - if (white_texture.is_valid()) - return white_texture; - - Vector wt; - wt.resize(16 * 3); - { - uint8_t *w = wt.ptrw(); - for (int i = 0; i < 16 * 3; i++) - w[i] = 255; - } - Ref white = memnew(Image(4, 4, 0, Image::FORMAT_RGB8, wt)); - white_texture = texture_2d_create(white); - return white_texture; -} - -#define SMALL_VEC2 Vector2(0.00001, 0.00001) -#define SMALL_VEC3 Vector3(0.00001, 0.00001, 0.00001) - -Error VisualServer::_surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, Vector &r_vertex_array, int p_vertex_array_len, Vector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb) { - - uint8_t *vw = r_vertex_array.ptrw(); - - uint8_t *iw = NULL; - if (r_index_array.size()) { - iw = r_index_array.ptrw(); - } - - int max_bone = 0; - - for (int ai = 0; ai < VS::ARRAY_MAX; ai++) { - - if (!(p_format & (1 << ai))) // no array - continue; - - switch (ai) { - - case VS::ARRAY_VERTEX: { - - if (p_format & VS::ARRAY_FLAG_USE_2D_VERTICES) { - - Vector array = p_arrays[ai]; - ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); - - const Vector2 *src = array.ptr(); - - // setting vertices means regenerating the AABB - Rect2 aabb; - - { - for (int i = 0; i < p_vertex_array_len; i++) { - - float vector[2] = { src[i].x, src[i].y }; - - copymem(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(float) * 2); - - if (i == 0) { - - aabb = Rect2(src[i], SMALL_VEC2); //must have a bit of size - } else { - - aabb.expand_to(src[i]); - } - } - } - - r_aabb = AABB(Vector3(aabb.position.x, aabb.position.y, 0), Vector3(aabb.size.x, aabb.size.y, 0)); - - } else { - Vector array = p_arrays[ai]; - ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); - - const Vector3 *src = array.ptr(); - - // setting vertices means regenerating the AABB - AABB aabb; - - { - for (int i = 0; i < p_vertex_array_len; i++) { - - float vector[3] = { src[i].x, src[i].y, src[i].z }; - - copymem(&vw[p_offsets[ai] + i * p_stride], vector, sizeof(float) * 3); - - if (i == 0) { - - aabb = AABB(src[i], SMALL_VEC3); - } else { - - aabb.expand_to(src[i]); - } - } - } - - r_aabb = aabb; - } - - } break; - case VS::ARRAY_NORMAL: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_VECTOR3_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); - - const Vector3 *src = array.ptr(); - - // setting vertices means regenerating the AABB - - if (p_format & ARRAY_COMPRESS_NORMAL) { - - for (int i = 0; i < p_vertex_array_len; i++) { - - int8_t vector[4] = { - (int8_t)CLAMP(src[i].x * 127, -128, 127), - (int8_t)CLAMP(src[i].y * 127, -128, 127), - (int8_t)CLAMP(src[i].z * 127, -128, 127), - 0, - }; - - copymem(&vw[p_offsets[ai] + i * p_stride], vector, 4); - } - - } else { - for (int i = 0; i < p_vertex_array_len; i++) { - - float vector[3] = { src[i].x, src[i].y, src[i].z }; - copymem(&vw[p_offsets[ai] + i * p_stride], vector, 3 * 4); - } - } - - } break; - - case VS::ARRAY_TANGENT: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_vertex_array_len * 4, ERR_INVALID_PARAMETER); - - const real_t *src = array.ptr(); - - if (p_format & ARRAY_COMPRESS_TANGENT) { - - for (int i = 0; i < p_vertex_array_len; i++) { - int8_t xyzw[4] = { - (int8_t)CLAMP(src[i * 4 + 0] * 127, -128, 127), - (int8_t)CLAMP(src[i * 4 + 1] * 127, -128, 127), - (int8_t)CLAMP(src[i * 4 + 2] * 127, -128, 127), - (int8_t)CLAMP(src[i * 4 + 3] * 127, -128, 127) - }; - - copymem(&vw[p_offsets[ai] + i * p_stride], xyzw, 4); - } - - } else { - for (int i = 0; i < p_vertex_array_len; i++) { - - float xyzw[4] = { - src[i * 4 + 0], - src[i * 4 + 1], - src[i * 4 + 2], - src[i * 4 + 3] - }; - - copymem(&vw[p_offsets[ai] + i * p_stride], xyzw, 4 * 4); - } - } - - } break; - case VS::ARRAY_COLOR: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_COLOR_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); - - const Color *src = array.ptr(); - - if (p_format & ARRAY_COMPRESS_COLOR) { - - for (int i = 0; i < p_vertex_array_len; i++) { - - uint8_t colors[4]; - - for (int j = 0; j < 4; j++) { - - colors[j] = CLAMP(int((src[i][j]) * 255.0), 0, 255); - } - - copymem(&vw[p_offsets[ai] + i * p_stride], colors, 4); - } - } else { - - for (int i = 0; i < p_vertex_array_len; i++) { - - copymem(&vw[p_offsets[ai] + i * p_stride], &src[i], 4 * 4); - } - } - - } break; - case VS::ARRAY_TEX_UV: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_VECTOR2_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); - - const Vector2 *src = array.ptr(); - - if (p_format & ARRAY_COMPRESS_TEX_UV) { - - for (int i = 0; i < p_vertex_array_len; i++) { - - uint16_t uv[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) }; - copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 2); - } - - } else { - for (int i = 0; i < p_vertex_array_len; i++) { - - float uv[2] = { src[i].x, src[i].y }; - - copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 4); - } - } - - } break; - - case VS::ARRAY_TEX_UV2: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_VECTOR3_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_VECTOR2_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_vertex_array_len, ERR_INVALID_PARAMETER); - - const Vector2 *src = array.ptr(); - - if (p_format & ARRAY_COMPRESS_TEX_UV2) { - - for (int i = 0; i < p_vertex_array_len; i++) { - - uint16_t uv[2] = { Math::make_half_float(src[i].x), Math::make_half_float(src[i].y) }; - copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 2); - } - - } else { - for (int i = 0; i < p_vertex_array_len; i++) { - - float uv[2] = { src[i].x, src[i].y }; - - copymem(&vw[p_offsets[ai] + i * p_stride], uv, 2 * 4); - } - } - } break; - case VS::ARRAY_WEIGHTS: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_vertex_array_len * VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER); - - const real_t *src = array.ptr(); - - { - - for (int i = 0; i < p_vertex_array_len; i++) { - - uint16_t data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) { - data[j] = CLAMP(src[i * VS::ARRAY_WEIGHTS_SIZE + j] * 65535, 0, 65535); - } - - copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4); - } - } - - } break; - case VS::ARRAY_BONES: { - - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_INT32_ARRAY && p_arrays[ai].get_type() != Variant::PACKED_FLOAT32_ARRAY, ERR_INVALID_PARAMETER); - - Vector array = p_arrays[ai]; - - ERR_FAIL_COND_V(array.size() != p_vertex_array_len * VS::ARRAY_WEIGHTS_SIZE, ERR_INVALID_PARAMETER); - - const int *src = array.ptr(); - - for (int i = 0; i < p_vertex_array_len; i++) { - - uint16_t data[VS::ARRAY_WEIGHTS_SIZE]; - for (int j = 0; j < VS::ARRAY_WEIGHTS_SIZE; j++) { - data[j] = src[i * VS::ARRAY_WEIGHTS_SIZE + j]; - max_bone = MAX(data[j], max_bone); - } - - copymem(&vw[p_offsets[ai] + i * p_stride], data, 2 * 4); - } - - } break; - case VS::ARRAY_INDEX: { - - ERR_FAIL_NULL_V(iw, ERR_INVALID_DATA); - ERR_FAIL_COND_V(p_index_array_len <= 0, ERR_INVALID_DATA); - ERR_FAIL_COND_V(p_arrays[ai].get_type() != Variant::PACKED_INT32_ARRAY, ERR_INVALID_PARAMETER); - - Vector indices = p_arrays[ai]; - ERR_FAIL_COND_V(indices.size() == 0, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(indices.size() != p_index_array_len, ERR_INVALID_PARAMETER); - - /* determine whether using 16 or 32 bits indices */ - - const int *src = indices.ptr(); - - for (int i = 0; i < p_index_array_len; i++) { - - if (p_vertex_array_len < (1 << 16)) { - uint16_t v = src[i]; - - copymem(&iw[i * 2], &v, 2); - } else { - uint32_t v = src[i]; - - copymem(&iw[i * 4], &v, 4); - } - } - } break; - default: { - ERR_FAIL_V(ERR_INVALID_DATA); - } - } - } - - if (p_format & VS::ARRAY_FORMAT_BONES) { - //create AABBs for each detected bone - int total_bones = max_bone + 1; - - bool first = r_bone_aabb.size() == 0; - - r_bone_aabb.resize(total_bones); - - if (first) { - for (int i = 0; i < total_bones; i++) { - r_bone_aabb.write[i].size = Vector3(-1, -1, -1); //negative means unused - } - } - - Vector vertices = p_arrays[VS::ARRAY_VERTEX]; - Vector bones = p_arrays[VS::ARRAY_BONES]; - Vector weights = p_arrays[VS::ARRAY_WEIGHTS]; - - bool any_valid = false; - - if (vertices.size() && bones.size() == vertices.size() * 4 && weights.size() == bones.size()) { - - int vs = vertices.size(); - const Vector3 *rv = vertices.ptr(); - const int *rb = bones.ptr(); - const float *rw = weights.ptr(); - - AABB *bptr = r_bone_aabb.ptrw(); - - for (int i = 0; i < vs; i++) { - - Vector3 v = rv[i]; - for (int j = 0; j < 4; j++) { - - int idx = rb[i * 4 + j]; - float w = rw[i * 4 + j]; - if (w == 0) - continue; //break; - ERR_FAIL_INDEX_V(idx, total_bones, ERR_INVALID_DATA); - - if (bptr[idx].size.x < 0) { - //first - bptr[idx] = AABB(v, SMALL_VEC3); - any_valid = true; - } else { - bptr[idx].expand_to(v); - } - } - } - } - - if (!any_valid && first) { - - r_bone_aabb.clear(); - } - } - return OK; -} - -uint32_t VisualServer::mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const { - uint32_t offsets[ARRAY_MAX]; - mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets); - return offsets[p_array_index]; -} - -uint32_t VisualServer::mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const { - uint32_t offsets[ARRAY_MAX]; - return mesh_surface_make_offsets_from_format(p_format, p_vertex_len, p_index_len, offsets); -} - -uint32_t VisualServer::mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const { - - int total_elem_size = 0; - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - - r_offsets[i] = 0; //reset - - if (!(p_format & (1 << i))) // no array - continue; - - int elem_size = 0; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { - elem_size = 2; - } else { - elem_size = 3; - } - - { - elem_size *= sizeof(float); - } - - if (elem_size == 6) { - elem_size = 8; - } - - } break; - case VS::ARRAY_NORMAL: { - - if (p_format & ARRAY_COMPRESS_NORMAL) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 3; - } - - } break; - - case VS::ARRAY_TANGENT: { - if (p_format & ARRAY_COMPRESS_TANGENT) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 4; - } - - } break; - case VS::ARRAY_COLOR: { - - if (p_format & ARRAY_COMPRESS_COLOR) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 4; - } - } break; - case VS::ARRAY_TEX_UV: { - if (p_format & ARRAY_COMPRESS_TEX_UV) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 2; - } - - } break; - - case VS::ARRAY_TEX_UV2: { - if (p_format & ARRAY_COMPRESS_TEX_UV2) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 2; - } - - } break; - case VS::ARRAY_WEIGHTS: { - - elem_size = sizeof(uint16_t) * 4; - - } break; - case VS::ARRAY_BONES: { - - elem_size = sizeof(uint16_t) * 4; - - } break; - case VS::ARRAY_INDEX: { - - if (p_index_len <= 0) { - ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); - break; - } - /* determine whether using 16 or 32 bits indices */ - if (p_vertex_len >= (1 << 16)) { - - elem_size = 4; - - } else { - elem_size = 2; - } - r_offsets[i] = elem_size; - continue; - } - default: { - ERR_FAIL_V(0); - } - } - - r_offsets[i] = total_elem_size; - total_elem_size += elem_size; - } - return total_elem_size; -} - -Error VisualServer::mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_compress_format) { - - ERR_FAIL_INDEX_V(p_primitive, VS::PRIMITIVE_MAX, ERR_INVALID_PARAMETER); - ERR_FAIL_COND_V(p_arrays.size() != VS::ARRAY_MAX, ERR_INVALID_PARAMETER); - - uint32_t format = 0; - - // validation - int index_array_len = 0; - int array_len = 0; - - for (int i = 0; i < p_arrays.size(); i++) { - - if (p_arrays[i].get_type() == Variant::NIL) - continue; - - format |= (1 << i); - - if (i == VS::ARRAY_VERTEX) { - - Variant var = p_arrays[i]; - switch (var.get_type()) { - case Variant::PACKED_VECTOR2_ARRAY: { - Vector v2 = var; - } break; - case Variant::PACKED_VECTOR3_ARRAY: { - Vector v3 = var; - } break; - default: { - Array v = var; - } break; - } - - array_len = PackedVector3Array(p_arrays[i]).size(); - ERR_FAIL_COND_V(array_len == 0, ERR_INVALID_DATA); - } else if (i == VS::ARRAY_INDEX) { - - index_array_len = PackedInt32Array(p_arrays[i]).size(); - } - } - - ERR_FAIL_COND_V((format & VS::ARRAY_FORMAT_VERTEX) == 0, ERR_INVALID_PARAMETER); // mandatory - - if (p_blend_shapes.size()) { - //validate format for morphs - for (int i = 0; i < p_blend_shapes.size(); i++) { - - uint32_t bsformat = 0; - Array arr = p_blend_shapes[i]; - for (int j = 0; j < arr.size(); j++) { - - if (arr[j].get_type() != Variant::NIL) - bsformat |= (1 << j); - } - - ERR_FAIL_COND_V((bsformat) != (format & (VS::ARRAY_FORMAT_INDEX - 1)), ERR_INVALID_PARAMETER); - } - } - - uint32_t offsets[VS::ARRAY_MAX]; - - int total_elem_size = 0; - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - - offsets[i] = 0; //reset - - if (!(format & (1 << i))) // no array - continue; - - int elem_size = 0; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - Variant arr = p_arrays[0]; - if (arr.get_type() == Variant::PACKED_VECTOR2_ARRAY) { - elem_size = 2; - p_compress_format |= ARRAY_FLAG_USE_2D_VERTICES; - } else if (arr.get_type() == Variant::PACKED_VECTOR3_ARRAY) { - p_compress_format &= ~ARRAY_FLAG_USE_2D_VERTICES; - elem_size = 3; - } else { - elem_size = (p_compress_format & ARRAY_FLAG_USE_2D_VERTICES) ? 2 : 3; - } - - { - elem_size *= sizeof(float); - } - - } break; - case VS::ARRAY_NORMAL: { - - if (p_compress_format & ARRAY_COMPRESS_NORMAL) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 3; - } - - } break; - - case VS::ARRAY_TANGENT: { - if (p_compress_format & ARRAY_COMPRESS_TANGENT) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 4; - } - - } break; - case VS::ARRAY_COLOR: { - - if (p_compress_format & ARRAY_COMPRESS_COLOR) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 4; - } - } break; - case VS::ARRAY_TEX_UV: { - if (p_compress_format & ARRAY_COMPRESS_TEX_UV) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 2; - } - - } break; - - case VS::ARRAY_TEX_UV2: { - if (p_compress_format & ARRAY_COMPRESS_TEX_UV2) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 2; - } - - } break; - case VS::ARRAY_WEIGHTS: { - - elem_size = sizeof(uint16_t) * 4; - - } break; - case VS::ARRAY_BONES: { - - elem_size = sizeof(uint16_t) * 4; - - } break; - case VS::ARRAY_INDEX: { - - if (index_array_len <= 0) { - ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); - break; - } - /* determine whether using 16 or 32 bits indices */ - if (array_len >= (1 << 16)) { - - elem_size = 4; - - } else { - elem_size = 2; - } - offsets[i] = elem_size; - continue; - } - default: { - ERR_FAIL_V(ERR_BUG); - } - } - - offsets[i] = total_elem_size; - total_elem_size += elem_size; - } - - uint32_t mask = (1 << ARRAY_MAX) - 1; - format |= (~mask) & p_compress_format; //make the full format - - int array_size = total_elem_size * array_len; - - Vector vertex_array; - vertex_array.resize(array_size); - - int index_array_size = offsets[VS::ARRAY_INDEX] * index_array_len; - - Vector index_array; - index_array.resize(index_array_size); - - AABB aabb; - Vector bone_aabb; - - Error err = _surface_set_data(p_arrays, format, offsets, total_elem_size, vertex_array, array_len, index_array, index_array_len, aabb, bone_aabb); - ERR_FAIL_COND_V_MSG(err != OK, ERR_INVALID_DATA, "Invalid array format for surface."); - - Vector> blend_shape_data; - - for (int i = 0; i < p_blend_shapes.size(); i++) { - - Vector vertex_array_shape; - vertex_array_shape.resize(array_size); - Vector noindex; - - AABB laabb; - Error err2 = _surface_set_data(p_blend_shapes[i], format & ~ARRAY_FORMAT_INDEX, offsets, total_elem_size, vertex_array_shape, array_len, noindex, 0, laabb, bone_aabb); - aabb.merge_with(laabb); - ERR_FAIL_COND_V_MSG(err2 != OK, ERR_INVALID_DATA, "Invalid blend shape array format for surface."); - - blend_shape_data.push_back(vertex_array_shape); - } - Vector lods; - if (index_array_len) { - - List keys; - p_lods.get_key_list(&keys); - for (List::Element *E = keys.front(); E; E = E->next()) { - float distance = E->get(); - ERR_CONTINUE(distance <= 0.0); - Vector indices = p_lods[E->get()]; - ERR_CONTINUE(indices.size() == 0); - uint32_t index_count = indices.size(); - ERR_CONTINUE(index_count >= (uint32_t)index_array_len); //should be smaller.. - - const int *r = indices.ptr(); - - Vector data; - if (array_len <= 65536) { - //16 bits indices - data.resize(indices.size() * 2); - uint8_t *w = data.ptrw(); - uint16_t *index_ptr = (uint16_t *)w; - for (uint32_t i = 0; i < index_count; i++) { - index_ptr[i] = r[i]; - } - } else { - //32 bits indices - data.resize(indices.size() * 4); - uint8_t *w = data.ptrw(); - uint32_t *index_ptr = (uint32_t *)w; - for (uint32_t i = 0; i < index_count; i++) { - index_ptr[i] = r[i]; - } - } - - SurfaceData::LOD lod; - lod.edge_length = distance; - lod.index_data = data; - lods.push_back(lod); - } - } - - SurfaceData &surface_data = *r_surface_data; - surface_data.format = format; - surface_data.primitive = p_primitive; - surface_data.aabb = aabb; - surface_data.vertex_data = vertex_array; - surface_data.vertex_count = array_len; - surface_data.index_data = index_array; - surface_data.index_count = index_array_len; - surface_data.blend_shapes = blend_shape_data; - surface_data.bone_aabbs = bone_aabb; - surface_data.lods = lods; - - return OK; -} - -void VisualServer::mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes, const Dictionary &p_lods, uint32_t p_compress_format) { - - SurfaceData sd; - Error err = mesh_create_surface_data_from_arrays(&sd, p_primitive, p_arrays, p_blend_shapes, p_lods, p_compress_format); - if (err != OK) { - return; - } - mesh_add_surface(p_mesh, sd); -} - -Array VisualServer::_get_array_from_surface(uint32_t p_format, Vector p_vertex_data, int p_vertex_len, Vector p_index_data, int p_index_len) const { - - uint32_t offsets[ARRAY_MAX]; - - int total_elem_size = 0; - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - - offsets[i] = 0; //reset - - if (!(p_format & (1 << i))) // no array - continue; - - int elem_size = 0; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { - elem_size = 2; - } else { - elem_size = 3; - } - - { - elem_size *= sizeof(float); - } - - } break; - case VS::ARRAY_NORMAL: { - - if (p_format & ARRAY_COMPRESS_NORMAL) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 3; - } - - } break; - - case VS::ARRAY_TANGENT: { - if (p_format & ARRAY_COMPRESS_TANGENT) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 4; - } - - } break; - case VS::ARRAY_COLOR: { - - if (p_format & ARRAY_COMPRESS_COLOR) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 4; - } - } break; - case VS::ARRAY_TEX_UV: { - if (p_format & ARRAY_COMPRESS_TEX_UV) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 2; - } - - } break; - - case VS::ARRAY_TEX_UV2: { - if (p_format & ARRAY_COMPRESS_TEX_UV2) { - elem_size = sizeof(uint32_t); - } else { - elem_size = sizeof(float) * 2; - } - - } break; - case VS::ARRAY_WEIGHTS: { - - elem_size = sizeof(uint16_t) * 4; - - } break; - case VS::ARRAY_BONES: { - - elem_size = sizeof(uint16_t) * 4; - - } break; - case VS::ARRAY_INDEX: { - - if (p_index_len <= 0) { - ERR_PRINT("index_array_len==NO_INDEX_ARRAY"); - break; - } - /* determine whether using 16 or 32 bits indices */ - if (p_vertex_len >= (1 << 16)) { - - elem_size = 4; - - } else { - elem_size = 2; - } - offsets[i] = elem_size; - continue; - } - default: { - ERR_FAIL_V(Array()); - } - } - - offsets[i] = total_elem_size; - total_elem_size += elem_size; - } - - Array ret; - ret.resize(VS::ARRAY_MAX); - - const uint8_t *r = p_vertex_data.ptr(); - - for (int i = 0; i < VS::ARRAY_MAX; i++) { - - if (!(p_format & (1 << i))) - continue; - - switch (i) { - - case VS::ARRAY_VERTEX: { - - if (p_format & ARRAY_FLAG_USE_2D_VERTICES) { - - Vector arr_2d; - arr_2d.resize(p_vertex_len); - - { - - Vector2 *w = arr_2d.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector2(v[0], v[1]); - } - } - - ret[i] = arr_2d; - } else { - - Vector arr_3d; - arr_3d.resize(p_vertex_len); - - { - - Vector3 *w = arr_3d.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector3(v[0], v[1], v[2]); - } - } - - ret[i] = arr_3d; - } - - } break; - case VS::ARRAY_NORMAL: { - Vector arr; - arr.resize(p_vertex_len); - - if (p_format & ARRAY_COMPRESS_NORMAL) { - - Vector3 *w = arr.ptrw(); - const float multiplier = 1.f / 127.f; - - for (int j = 0; j < p_vertex_len; j++) { - - const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector3(float(v[0]) * multiplier, float(v[1]) * multiplier, float(v[2]) * multiplier); - } - } else { - Vector3 *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector3(v[0], v[1], v[2]); - } - } - - ret[i] = arr; - - } break; - - case VS::ARRAY_TANGENT: { - Vector arr; - arr.resize(p_vertex_len * 4); - if (p_format & ARRAY_COMPRESS_TANGENT) { - float *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const int8_t *v = (const int8_t *)&r[j * total_elem_size + offsets[i]]; - for (int k = 0; k < 4; k++) { - w[j * 4 + k] = float(v[k] / 127.0); - } - } - } else { - - float *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - for (int k = 0; k < 4; k++) { - w[j * 4 + k] = v[k]; - } - } - } - - ret[i] = arr; - - } break; - case VS::ARRAY_COLOR: { - - Vector arr; - arr.resize(p_vertex_len); - - if (p_format & ARRAY_COMPRESS_COLOR) { - - Color *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const uint8_t *v = (const uint8_t *)&r[j * total_elem_size + offsets[i]]; - w[j] = Color(float(v[0] / 255.0), float(v[1] / 255.0), float(v[2] / 255.0), float(v[3] / 255.0)); - } - } else { - Color *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - w[j] = Color(v[0], v[1], v[2], v[3]); - } - } - - ret[i] = arr; - } break; - case VS::ARRAY_TEX_UV: { - - Vector arr; - arr.resize(p_vertex_len); - - if (p_format & ARRAY_COMPRESS_TEX_UV) { - - Vector2 *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1])); - } - } else { - - Vector2 *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector2(v[0], v[1]); - } - } - - ret[i] = arr; - } break; - - case VS::ARRAY_TEX_UV2: { - Vector arr; - arr.resize(p_vertex_len); - - if (p_format & ARRAY_COMPRESS_TEX_UV2) { - - Vector2 *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector2(Math::halfptr_to_float(&v[0]), Math::halfptr_to_float(&v[1])); - } - } else { - - Vector2 *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const float *v = (const float *)&r[j * total_elem_size + offsets[i]]; - w[j] = Vector2(v[0], v[1]); - } - } - - ret[i] = arr; - - } break; - case VS::ARRAY_WEIGHTS: { - - Vector arr; - arr.resize(p_vertex_len * 4); - { - float *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; - for (int k = 0; k < 4; k++) { - w[j * 4 + k] = float(v[k] / 65535.0); - } - } - } - - ret[i] = arr; - - } break; - case VS::ARRAY_BONES: { - - Vector arr; - arr.resize(p_vertex_len * 4); - - int *w = arr.ptrw(); - - for (int j = 0; j < p_vertex_len; j++) { - - const uint16_t *v = (const uint16_t *)&r[j * total_elem_size + offsets[i]]; - for (int k = 0; k < 4; k++) { - w[j * 4 + k] = v[k]; - } - } - - ret[i] = arr; - - } break; - case VS::ARRAY_INDEX: { - /* determine whether using 16 or 32 bits indices */ - - const uint8_t *ir = p_index_data.ptr(); - - Vector arr; - arr.resize(p_index_len); - if (p_vertex_len < (1 << 16)) { - - int *w = arr.ptrw(); - - for (int j = 0; j < p_index_len; j++) { - - const uint16_t *v = (const uint16_t *)&ir[j * 2]; - w[j] = *v; - } - } else { - - int *w = arr.ptrw(); - - for (int j = 0; j < p_index_len; j++) { - const int *v = (const int *)&ir[j * 4]; - w[j] = *v; - } - } - ret[i] = arr; - } break; - default: { - ERR_FAIL_V(ret); - } - } - } - - return ret; -} - -Array VisualServer::mesh_surface_get_arrays(RID p_mesh, int p_surface) const { - - SurfaceData sd = mesh_get_surface(p_mesh, p_surface); - return mesh_create_arrays_from_surface_data(sd); -} - -Dictionary VisualServer::mesh_surface_get_lods(RID p_mesh, int p_surface) const { - - SurfaceData sd = mesh_get_surface(p_mesh, p_surface); - ERR_FAIL_COND_V(sd.vertex_count == 0, Dictionary()); - - Dictionary ret; - - for (int i = 0; i < sd.lods.size(); i++) { - Vector lods; - if (sd.vertex_count <= 65536) { - uint32_t lc = sd.lods[i].index_data.size() / 2; - lods.resize(lc); - const uint8_t *r = sd.lods[i].index_data.ptr(); - const uint16_t *rptr = (const uint16_t *)r; - int *w = lods.ptrw(); - for (uint32_t j = 0; j < lc; j++) { - w[j] = rptr[i]; - } - } else { - uint32_t lc = sd.lods[i].index_data.size() / 4; - lods.resize(lc); - const uint8_t *r = sd.lods[i].index_data.ptr(); - const uint32_t *rptr = (const uint32_t *)r; - int *w = lods.ptrw(); - for (uint32_t j = 0; j < lc; j++) { - w[j] = rptr[i]; - } - } - - ret[sd.lods[i].edge_length] = lods; - } - - return ret; -} - -Array VisualServer::mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const { - - SurfaceData sd = mesh_get_surface(p_mesh, p_surface); - ERR_FAIL_COND_V(sd.vertex_count == 0, Array()); - - Vector> blend_shape_data = sd.blend_shapes; - - if (blend_shape_data.size() > 0) { - int vertex_len = sd.vertex_count; - - Vector index_data = sd.index_data; - int index_len = sd.index_count; - - uint32_t format = sd.format; - - Array blend_shape_array; - blend_shape_array.resize(blend_shape_data.size()); - for (int i = 0; i < blend_shape_data.size(); i++) { - blend_shape_array.set(i, _get_array_from_surface(format, blend_shape_data[i], vertex_len, index_data, index_len)); - } - - return blend_shape_array; - } else { - return Array(); - } -} - -Array VisualServer::mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const { - - Vector vertex_data = p_data.vertex_data; - - ERR_FAIL_COND_V(vertex_data.size() == 0, Array()); - int vertex_len = p_data.vertex_count; - - Vector index_data = p_data.index_data; - int index_len = p_data.index_count; - - uint32_t format = p_data.format; - - return _get_array_from_surface(format, vertex_data, vertex_len, index_data, index_len); -} -#if 0 -Array VisualServer::_mesh_surface_get_skeleton_aabb_bind(RID p_mesh, int p_surface) const { - - Vector vec = VS::get_singleton()->mesh_surface_get_skeleton_aabb(p_mesh, p_surface); - Array arr; - for (int i = 0; i < vec.size(); i++) { - arr[i] = vec[i]; - } - return arr; -} -#endif -void VisualServer::_bind_methods() { - - ClassDB::bind_method(D_METHOD("force_sync"), &VisualServer::sync); - ClassDB::bind_method(D_METHOD("force_draw", "swap_buffers", "frame_step"), &VisualServer::draw, DEFVAL(true), DEFVAL(0.0)); - -#ifndef _MSC_VER -#warning TODO all texture methods need re-binding -#endif - - ClassDB::bind_method(D_METHOD("texture_2d_create", "image"), &VisualServer::texture_2d_create); - ClassDB::bind_method(D_METHOD("texture_2d_get", "texture"), &VisualServer::texture_2d_get); - -#ifndef _3D_DISABLED - ClassDB::bind_method(D_METHOD("sky_create"), &VisualServer::sky_create); - ClassDB::bind_method(D_METHOD("sky_set_material", "sky", "material"), &VisualServer::sky_set_material); -#endif - ClassDB::bind_method(D_METHOD("shader_create"), &VisualServer::shader_create); - ClassDB::bind_method(D_METHOD("shader_set_code", "shader", "code"), &VisualServer::shader_set_code); - ClassDB::bind_method(D_METHOD("shader_get_code", "shader"), &VisualServer::shader_get_code); - ClassDB::bind_method(D_METHOD("shader_get_param_list", "shader"), &VisualServer::_shader_get_param_list_bind); - ClassDB::bind_method(D_METHOD("shader_set_default_texture_param", "shader", "name", "texture"), &VisualServer::shader_set_default_texture_param); - ClassDB::bind_method(D_METHOD("shader_get_default_texture_param", "shader", "name"), &VisualServer::shader_get_default_texture_param); - ClassDB::bind_method(D_METHOD("shader_get_param_default", "material", "parameter"), &VisualServer::shader_get_param_default); - - ClassDB::bind_method(D_METHOD("material_create"), &VisualServer::material_create); - ClassDB::bind_method(D_METHOD("material_set_shader", "shader_material", "shader"), &VisualServer::material_set_shader); - ClassDB::bind_method(D_METHOD("material_set_param", "material", "parameter", "value"), &VisualServer::material_set_param); - ClassDB::bind_method(D_METHOD("material_get_param", "material", "parameter"), &VisualServer::material_get_param); - ClassDB::bind_method(D_METHOD("material_set_render_priority", "material", "priority"), &VisualServer::material_set_render_priority); - - ClassDB::bind_method(D_METHOD("material_set_next_pass", "material", "next_material"), &VisualServer::material_set_next_pass); - - ClassDB::bind_method(D_METHOD("mesh_create"), &VisualServer::mesh_create); - ClassDB::bind_method(D_METHOD("mesh_surface_get_format_offset", "format", "vertex_len", "index_len", "array_index"), &VisualServer::mesh_surface_get_format_offset); - ClassDB::bind_method(D_METHOD("mesh_surface_get_format_stride", "format", "vertex_len", "index_len"), &VisualServer::mesh_surface_get_format_stride); - ClassDB::bind_method(D_METHOD("mesh_add_surface_from_arrays", "mesh", "primitive", "arrays", "blend_shapes", "lods", "compress_format"), &VisualServer::mesh_add_surface_from_arrays, DEFVAL(Array()), DEFVAL(Dictionary()), DEFVAL(ARRAY_COMPRESS_DEFAULT)); - ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_count", "mesh"), &VisualServer::mesh_get_blend_shape_count); - ClassDB::bind_method(D_METHOD("mesh_set_blend_shape_mode", "mesh", "mode"), &VisualServer::mesh_set_blend_shape_mode); - ClassDB::bind_method(D_METHOD("mesh_get_blend_shape_mode", "mesh"), &VisualServer::mesh_get_blend_shape_mode); - ClassDB::bind_method(D_METHOD("mesh_surface_update_region", "mesh", "surface", "offset", "data"), &VisualServer::mesh_surface_update_region); - ClassDB::bind_method(D_METHOD("mesh_surface_set_material", "mesh", "surface", "material"), &VisualServer::mesh_surface_set_material); - ClassDB::bind_method(D_METHOD("mesh_surface_get_material", "mesh", "surface"), &VisualServer::mesh_surface_get_material); - ClassDB::bind_method(D_METHOD("mesh_surface_get_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_arrays); - ClassDB::bind_method(D_METHOD("mesh_surface_get_blend_shape_arrays", "mesh", "surface"), &VisualServer::mesh_surface_get_blend_shape_arrays); - ClassDB::bind_method(D_METHOD("mesh_get_surface_count", "mesh"), &VisualServer::mesh_get_surface_count); - ClassDB::bind_method(D_METHOD("mesh_set_custom_aabb", "mesh", "aabb"), &VisualServer::mesh_set_custom_aabb); - ClassDB::bind_method(D_METHOD("mesh_get_custom_aabb", "mesh"), &VisualServer::mesh_get_custom_aabb); - ClassDB::bind_method(D_METHOD("mesh_clear", "mesh"), &VisualServer::mesh_clear); - - ClassDB::bind_method(D_METHOD("multimesh_create"), &VisualServer::multimesh_create); - ClassDB::bind_method(D_METHOD("multimesh_allocate", "multimesh", "instances", "transform_format", "color_format", "custom_data_format"), &VisualServer::multimesh_allocate, DEFVAL(false), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("multimesh_get_instance_count", "multimesh"), &VisualServer::multimesh_get_instance_count); - ClassDB::bind_method(D_METHOD("multimesh_set_mesh", "multimesh", "mesh"), &VisualServer::multimesh_set_mesh); - ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform); - ClassDB::bind_method(D_METHOD("multimesh_instance_set_transform_2d", "multimesh", "index", "transform"), &VisualServer::multimesh_instance_set_transform_2d); - ClassDB::bind_method(D_METHOD("multimesh_instance_set_color", "multimesh", "index", "color"), &VisualServer::multimesh_instance_set_color); - ClassDB::bind_method(D_METHOD("multimesh_instance_set_custom_data", "multimesh", "index", "custom_data"), &VisualServer::multimesh_instance_set_custom_data); - ClassDB::bind_method(D_METHOD("multimesh_get_mesh", "multimesh"), &VisualServer::multimesh_get_mesh); - ClassDB::bind_method(D_METHOD("multimesh_get_aabb", "multimesh"), &VisualServer::multimesh_get_aabb); - ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform); - ClassDB::bind_method(D_METHOD("multimesh_instance_get_transform_2d", "multimesh", "index"), &VisualServer::multimesh_instance_get_transform_2d); - ClassDB::bind_method(D_METHOD("multimesh_instance_get_color", "multimesh", "index"), &VisualServer::multimesh_instance_get_color); - ClassDB::bind_method(D_METHOD("multimesh_instance_get_custom_data", "multimesh", "index"), &VisualServer::multimesh_instance_get_custom_data); - ClassDB::bind_method(D_METHOD("multimesh_set_visible_instances", "multimesh", "visible"), &VisualServer::multimesh_set_visible_instances); - ClassDB::bind_method(D_METHOD("multimesh_get_visible_instances", "multimesh"), &VisualServer::multimesh_get_visible_instances); - ClassDB::bind_method(D_METHOD("multimesh_set_buffer", "multimesh", "buffer"), &VisualServer::multimesh_set_buffer); - ClassDB::bind_method(D_METHOD("multimesh_get_buffer", "multimesh"), &VisualServer::multimesh_get_buffer); -#ifndef _3D_DISABLED - ClassDB::bind_method(D_METHOD("immediate_create"), &VisualServer::immediate_create); - ClassDB::bind_method(D_METHOD("immediate_begin", "immediate", "primitive", "texture"), &VisualServer::immediate_begin, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("immediate_vertex", "immediate", "vertex"), &VisualServer::immediate_vertex); - ClassDB::bind_method(D_METHOD("immediate_vertex_2d", "immediate", "vertex"), &VisualServer::immediate_vertex_2d); - ClassDB::bind_method(D_METHOD("immediate_normal", "immediate", "normal"), &VisualServer::immediate_normal); - ClassDB::bind_method(D_METHOD("immediate_tangent", "immediate", "tangent"), &VisualServer::immediate_tangent); - ClassDB::bind_method(D_METHOD("immediate_color", "immediate", "color"), &VisualServer::immediate_color); - ClassDB::bind_method(D_METHOD("immediate_uv", "immediate", "tex_uv"), &VisualServer::immediate_uv); - ClassDB::bind_method(D_METHOD("immediate_uv2", "immediate", "tex_uv"), &VisualServer::immediate_uv2); - ClassDB::bind_method(D_METHOD("immediate_end", "immediate"), &VisualServer::immediate_end); - ClassDB::bind_method(D_METHOD("immediate_clear", "immediate"), &VisualServer::immediate_clear); - ClassDB::bind_method(D_METHOD("immediate_set_material", "immediate", "material"), &VisualServer::immediate_set_material); - ClassDB::bind_method(D_METHOD("immediate_get_material", "immediate"), &VisualServer::immediate_get_material); -#endif - - ClassDB::bind_method(D_METHOD("skeleton_create"), &VisualServer::skeleton_create); - ClassDB::bind_method(D_METHOD("skeleton_allocate", "skeleton", "bones", "is_2d_skeleton"), &VisualServer::skeleton_allocate, DEFVAL(false)); - ClassDB::bind_method(D_METHOD("skeleton_get_bone_count", "skeleton"), &VisualServer::skeleton_get_bone_count); - ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform", "skeleton", "bone", "transform"), &VisualServer::skeleton_bone_set_transform); - ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform", "skeleton", "bone"), &VisualServer::skeleton_bone_get_transform); - ClassDB::bind_method(D_METHOD("skeleton_bone_set_transform_2d", "skeleton", "bone", "transform"), &VisualServer::skeleton_bone_set_transform_2d); - ClassDB::bind_method(D_METHOD("skeleton_bone_get_transform_2d", "skeleton", "bone"), &VisualServer::skeleton_bone_get_transform_2d); - -#ifndef _3D_DISABLED - ClassDB::bind_method(D_METHOD("directional_light_create"), &VisualServer::directional_light_create); - ClassDB::bind_method(D_METHOD("omni_light_create"), &VisualServer::omni_light_create); - ClassDB::bind_method(D_METHOD("spot_light_create"), &VisualServer::spot_light_create); - - ClassDB::bind_method(D_METHOD("light_set_color", "light", "color"), &VisualServer::light_set_color); - ClassDB::bind_method(D_METHOD("light_set_param", "light", "param", "value"), &VisualServer::light_set_param); - ClassDB::bind_method(D_METHOD("light_set_shadow", "light", "enabled"), &VisualServer::light_set_shadow); - ClassDB::bind_method(D_METHOD("light_set_shadow_color", "light", "color"), &VisualServer::light_set_shadow_color); - ClassDB::bind_method(D_METHOD("light_set_projector", "light", "texture"), &VisualServer::light_set_projector); - ClassDB::bind_method(D_METHOD("light_set_negative", "light", "enable"), &VisualServer::light_set_negative); - ClassDB::bind_method(D_METHOD("light_set_cull_mask", "light", "mask"), &VisualServer::light_set_cull_mask); - ClassDB::bind_method(D_METHOD("light_set_reverse_cull_face_mode", "light", "enabled"), &VisualServer::light_set_reverse_cull_face_mode); - ClassDB::bind_method(D_METHOD("light_set_use_gi", "light", "enabled"), &VisualServer::light_set_use_gi); - - ClassDB::bind_method(D_METHOD("light_omni_set_shadow_mode", "light", "mode"), &VisualServer::light_omni_set_shadow_mode); - - ClassDB::bind_method(D_METHOD("light_directional_set_shadow_mode", "light", "mode"), &VisualServer::light_directional_set_shadow_mode); - ClassDB::bind_method(D_METHOD("light_directional_set_blend_splits", "light", "enable"), &VisualServer::light_directional_set_blend_splits); - ClassDB::bind_method(D_METHOD("light_directional_set_shadow_depth_range_mode", "light", "range_mode"), &VisualServer::light_directional_set_shadow_depth_range_mode); - - ClassDB::bind_method(D_METHOD("reflection_probe_create"), &VisualServer::reflection_probe_create); - ClassDB::bind_method(D_METHOD("reflection_probe_set_update_mode", "probe", "mode"), &VisualServer::reflection_probe_set_update_mode); - ClassDB::bind_method(D_METHOD("reflection_probe_set_intensity", "probe", "intensity"), &VisualServer::reflection_probe_set_intensity); - ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient", "probe", "color"), &VisualServer::reflection_probe_set_interior_ambient); - ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_energy", "probe", "energy"), &VisualServer::reflection_probe_set_interior_ambient_energy); - ClassDB::bind_method(D_METHOD("reflection_probe_set_interior_ambient_probe_contribution", "probe", "contrib"), &VisualServer::reflection_probe_set_interior_ambient_probe_contribution); - ClassDB::bind_method(D_METHOD("reflection_probe_set_max_distance", "probe", "distance"), &VisualServer::reflection_probe_set_max_distance); - ClassDB::bind_method(D_METHOD("reflection_probe_set_extents", "probe", "extents"), &VisualServer::reflection_probe_set_extents); - ClassDB::bind_method(D_METHOD("reflection_probe_set_origin_offset", "probe", "offset"), &VisualServer::reflection_probe_set_origin_offset); - ClassDB::bind_method(D_METHOD("reflection_probe_set_as_interior", "probe", "enable"), &VisualServer::reflection_probe_set_as_interior); - ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_box_projection", "probe", "enable"), &VisualServer::reflection_probe_set_enable_box_projection); - ClassDB::bind_method(D_METHOD("reflection_probe_set_enable_shadows", "probe", "enable"), &VisualServer::reflection_probe_set_enable_shadows); - ClassDB::bind_method(D_METHOD("reflection_probe_set_cull_mask", "probe", "layers"), &VisualServer::reflection_probe_set_cull_mask); - -#ifndef _MSC_VER -#warning TODO all giprobe methods need re-binding -#endif -#if 0 - ClassDB::bind_method(D_METHOD("gi_probe_create"), &VisualServer::gi_probe_create); - ClassDB::bind_method(D_METHOD("gi_probe_set_bounds", "probe", "bounds"), &VisualServer::gi_probe_set_bounds); - ClassDB::bind_method(D_METHOD("gi_probe_get_bounds", "probe"), &VisualServer::gi_probe_get_bounds); - ClassDB::bind_method(D_METHOD("gi_probe_set_cell_size", "probe", "range"), &VisualServer::gi_probe_set_cell_size); - ClassDB::bind_method(D_METHOD("gi_probe_get_cell_size", "probe"), &VisualServer::gi_probe_get_cell_size); - ClassDB::bind_method(D_METHOD("gi_probe_set_to_cell_xform", "probe", "xform"), &VisualServer::gi_probe_set_to_cell_xform); - ClassDB::bind_method(D_METHOD("gi_probe_get_to_cell_xform", "probe"), &VisualServer::gi_probe_get_to_cell_xform); - ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_data", "probe", "data"), &VisualServer::gi_probe_set_dynamic_data); - ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_data", "probe"), &VisualServer::gi_probe_get_dynamic_data); - ClassDB::bind_method(D_METHOD("gi_probe_set_dynamic_range", "probe", "range"), &VisualServer::gi_probe_set_dynamic_range); - ClassDB::bind_method(D_METHOD("gi_probe_get_dynamic_range", "probe"), &VisualServer::gi_probe_get_dynamic_range); - ClassDB::bind_method(D_METHOD("gi_probe_set_energy", "probe", "energy"), &VisualServer::gi_probe_set_energy); - ClassDB::bind_method(D_METHOD("gi_probe_get_energy", "probe"), &VisualServer::gi_probe_get_energy); - ClassDB::bind_method(D_METHOD("gi_probe_set_bias", "probe", "bias"), &VisualServer::gi_probe_set_bias); - ClassDB::bind_method(D_METHOD("gi_probe_get_bias", "probe"), &VisualServer::gi_probe_get_bias); - ClassDB::bind_method(D_METHOD("gi_probe_set_normal_bias", "probe", "bias"), &VisualServer::gi_probe_set_normal_bias); - ClassDB::bind_method(D_METHOD("gi_probe_get_normal_bias", "probe"), &VisualServer::gi_probe_get_normal_bias); - ClassDB::bind_method(D_METHOD("gi_probe_set_propagation", "probe", "propagation"), &VisualServer::gi_probe_set_propagation); - ClassDB::bind_method(D_METHOD("gi_probe_get_propagation", "probe"), &VisualServer::gi_probe_get_propagation); - ClassDB::bind_method(D_METHOD("gi_probe_set_interior", "probe", "enable"), &VisualServer::gi_probe_set_interior); - ClassDB::bind_method(D_METHOD("gi_probe_is_interior", "probe"), &VisualServer::gi_probe_is_interior); - ClassDB::bind_method(D_METHOD("gi_probe_set_compress", "probe", "enable"), &VisualServer::gi_probe_set_compress); - ClassDB::bind_method(D_METHOD("gi_probe_is_compressed", "probe"), &VisualServer::gi_probe_is_compressed); -#endif - - ClassDB::bind_method(D_METHOD("lightmap_capture_create"), &VisualServer::lightmap_capture_create); - ClassDB::bind_method(D_METHOD("lightmap_capture_set_bounds", "capture", "bounds"), &VisualServer::lightmap_capture_set_bounds); - ClassDB::bind_method(D_METHOD("lightmap_capture_get_bounds", "capture"), &VisualServer::lightmap_capture_get_bounds); - ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree", "capture", "octree"), &VisualServer::lightmap_capture_set_octree); - ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_transform", "capture", "xform"), &VisualServer::lightmap_capture_set_octree_cell_transform); - ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_transform", "capture"), &VisualServer::lightmap_capture_get_octree_cell_transform); - ClassDB::bind_method(D_METHOD("lightmap_capture_set_octree_cell_subdiv", "capture", "subdiv"), &VisualServer::lightmap_capture_set_octree_cell_subdiv); - ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree_cell_subdiv", "capture"), &VisualServer::lightmap_capture_get_octree_cell_subdiv); - ClassDB::bind_method(D_METHOD("lightmap_capture_get_octree", "capture"), &VisualServer::lightmap_capture_get_octree); - ClassDB::bind_method(D_METHOD("lightmap_capture_set_energy", "capture", "energy"), &VisualServer::lightmap_capture_set_energy); - ClassDB::bind_method(D_METHOD("lightmap_capture_get_energy", "capture"), &VisualServer::lightmap_capture_get_energy); -#endif - ClassDB::bind_method(D_METHOD("particles_create"), &VisualServer::particles_create); - ClassDB::bind_method(D_METHOD("particles_set_emitting", "particles", "emitting"), &VisualServer::particles_set_emitting); - ClassDB::bind_method(D_METHOD("particles_get_emitting", "particles"), &VisualServer::particles_get_emitting); - ClassDB::bind_method(D_METHOD("particles_set_amount", "particles", "amount"), &VisualServer::particles_set_amount); - ClassDB::bind_method(D_METHOD("particles_set_lifetime", "particles", "lifetime"), &VisualServer::particles_set_lifetime); - ClassDB::bind_method(D_METHOD("particles_set_one_shot", "particles", "one_shot"), &VisualServer::particles_set_one_shot); - ClassDB::bind_method(D_METHOD("particles_set_pre_process_time", "particles", "time"), &VisualServer::particles_set_pre_process_time); - ClassDB::bind_method(D_METHOD("particles_set_explosiveness_ratio", "particles", "ratio"), &VisualServer::particles_set_explosiveness_ratio); - ClassDB::bind_method(D_METHOD("particles_set_randomness_ratio", "particles", "ratio"), &VisualServer::particles_set_randomness_ratio); - ClassDB::bind_method(D_METHOD("particles_set_custom_aabb", "particles", "aabb"), &VisualServer::particles_set_custom_aabb); - ClassDB::bind_method(D_METHOD("particles_set_speed_scale", "particles", "scale"), &VisualServer::particles_set_speed_scale); - ClassDB::bind_method(D_METHOD("particles_set_use_local_coordinates", "particles", "enable"), &VisualServer::particles_set_use_local_coordinates); - ClassDB::bind_method(D_METHOD("particles_set_process_material", "particles", "material"), &VisualServer::particles_set_process_material); - ClassDB::bind_method(D_METHOD("particles_set_fixed_fps", "particles", "fps"), &VisualServer::particles_set_fixed_fps); - ClassDB::bind_method(D_METHOD("particles_set_fractional_delta", "particles", "enable"), &VisualServer::particles_set_fractional_delta); - ClassDB::bind_method(D_METHOD("particles_is_inactive", "particles"), &VisualServer::particles_is_inactive); - ClassDB::bind_method(D_METHOD("particles_request_process", "particles"), &VisualServer::particles_request_process); - ClassDB::bind_method(D_METHOD("particles_restart", "particles"), &VisualServer::particles_restart); - ClassDB::bind_method(D_METHOD("particles_set_draw_order", "particles", "order"), &VisualServer::particles_set_draw_order); - ClassDB::bind_method(D_METHOD("particles_set_draw_passes", "particles", "count"), &VisualServer::particles_set_draw_passes); - ClassDB::bind_method(D_METHOD("particles_set_draw_pass_mesh", "particles", "pass", "mesh"), &VisualServer::particles_set_draw_pass_mesh); - ClassDB::bind_method(D_METHOD("particles_get_current_aabb", "particles"), &VisualServer::particles_get_current_aabb); - ClassDB::bind_method(D_METHOD("particles_set_emission_transform", "particles", "transform"), &VisualServer::particles_set_emission_transform); - - ClassDB::bind_method(D_METHOD("camera_create"), &VisualServer::camera_create); - ClassDB::bind_method(D_METHOD("camera_set_perspective", "camera", "fovy_degrees", "z_near", "z_far"), &VisualServer::camera_set_perspective); - ClassDB::bind_method(D_METHOD("camera_set_orthogonal", "camera", "size", "z_near", "z_far"), &VisualServer::camera_set_orthogonal); - ClassDB::bind_method(D_METHOD("camera_set_frustum", "camera", "size", "offset", "z_near", "z_far"), &VisualServer::camera_set_frustum); - ClassDB::bind_method(D_METHOD("camera_set_transform", "camera", "transform"), &VisualServer::camera_set_transform); - ClassDB::bind_method(D_METHOD("camera_set_cull_mask", "camera", "layers"), &VisualServer::camera_set_cull_mask); - ClassDB::bind_method(D_METHOD("camera_set_environment", "camera", "env"), &VisualServer::camera_set_environment); - ClassDB::bind_method(D_METHOD("camera_set_use_vertical_aspect", "camera", "enable"), &VisualServer::camera_set_use_vertical_aspect); - - ClassDB::bind_method(D_METHOD("viewport_create"), &VisualServer::viewport_create); - ClassDB::bind_method(D_METHOD("viewport_set_use_arvr", "viewport", "use_arvr"), &VisualServer::viewport_set_use_arvr); - ClassDB::bind_method(D_METHOD("viewport_set_size", "viewport", "width", "height"), &VisualServer::viewport_set_size); - ClassDB::bind_method(D_METHOD("viewport_set_active", "viewport", "active"), &VisualServer::viewport_set_active); - ClassDB::bind_method(D_METHOD("viewport_set_parent_viewport", "viewport", "parent_viewport"), &VisualServer::viewport_set_parent_viewport); - ClassDB::bind_method(D_METHOD("viewport_attach_to_screen", "viewport", "rect", "screen"), &VisualServer::viewport_attach_to_screen, DEFVAL(Rect2()), DEFVAL(DisplayServer::MAIN_WINDOW_ID)); - ClassDB::bind_method(D_METHOD("viewport_set_render_direct_to_screen", "viewport", "enabled"), &VisualServer::viewport_set_render_direct_to_screen); - - ClassDB::bind_method(D_METHOD("viewport_set_update_mode", "viewport", "update_mode"), &VisualServer::viewport_set_update_mode); - ClassDB::bind_method(D_METHOD("viewport_set_clear_mode", "viewport", "clear_mode"), &VisualServer::viewport_set_clear_mode); - ClassDB::bind_method(D_METHOD("viewport_get_texture", "viewport"), &VisualServer::viewport_get_texture); - ClassDB::bind_method(D_METHOD("viewport_set_hide_scenario", "viewport", "hidden"), &VisualServer::viewport_set_hide_scenario); - ClassDB::bind_method(D_METHOD("viewport_set_hide_canvas", "viewport", "hidden"), &VisualServer::viewport_set_hide_canvas); - ClassDB::bind_method(D_METHOD("viewport_set_disable_environment", "viewport", "disabled"), &VisualServer::viewport_set_disable_environment); - ClassDB::bind_method(D_METHOD("viewport_attach_camera", "viewport", "camera"), &VisualServer::viewport_attach_camera); - ClassDB::bind_method(D_METHOD("viewport_set_scenario", "viewport", "scenario"), &VisualServer::viewport_set_scenario); - ClassDB::bind_method(D_METHOD("viewport_attach_canvas", "viewport", "canvas"), &VisualServer::viewport_attach_canvas); - ClassDB::bind_method(D_METHOD("viewport_remove_canvas", "viewport", "canvas"), &VisualServer::viewport_remove_canvas); - ClassDB::bind_method(D_METHOD("viewport_set_canvas_transform", "viewport", "canvas", "offset"), &VisualServer::viewport_set_canvas_transform); - ClassDB::bind_method(D_METHOD("viewport_set_transparent_background", "viewport", "enabled"), &VisualServer::viewport_set_transparent_background); - ClassDB::bind_method(D_METHOD("viewport_set_global_canvas_transform", "viewport", "transform"), &VisualServer::viewport_set_global_canvas_transform); - ClassDB::bind_method(D_METHOD("viewport_set_canvas_stacking", "viewport", "canvas", "layer", "sublayer"), &VisualServer::viewport_set_canvas_stacking); - ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_size", "viewport", "size"), &VisualServer::viewport_set_shadow_atlas_size); - ClassDB::bind_method(D_METHOD("viewport_set_shadow_atlas_quadrant_subdivision", "viewport", "quadrant", "subdivision"), &VisualServer::viewport_set_shadow_atlas_quadrant_subdivision); - ClassDB::bind_method(D_METHOD("viewport_set_msaa", "viewport", "msaa"), &VisualServer::viewport_set_msaa); - ClassDB::bind_method(D_METHOD("viewport_get_render_info", "viewport", "info"), &VisualServer::viewport_get_render_info); - ClassDB::bind_method(D_METHOD("viewport_set_debug_draw", "viewport", "draw"), &VisualServer::viewport_set_debug_draw); - - ClassDB::bind_method(D_METHOD("environment_create"), &VisualServer::environment_create); - ClassDB::bind_method(D_METHOD("environment_set_background", "env", "bg"), &VisualServer::environment_set_background); - ClassDB::bind_method(D_METHOD("environment_set_sky", "env", "sky"), &VisualServer::environment_set_sky); - ClassDB::bind_method(D_METHOD("environment_set_sky_custom_fov", "env", "scale"), &VisualServer::environment_set_sky_custom_fov); - ClassDB::bind_method(D_METHOD("environment_set_sky_orientation", "env", "orientation"), &VisualServer::environment_set_sky_orientation); - ClassDB::bind_method(D_METHOD("environment_set_bg_color", "env", "color"), &VisualServer::environment_set_bg_color); - ClassDB::bind_method(D_METHOD("environment_set_bg_energy", "env", "energy"), &VisualServer::environment_set_bg_energy); - ClassDB::bind_method(D_METHOD("environment_set_canvas_max_layer", "env", "max_layer"), &VisualServer::environment_set_canvas_max_layer); - ClassDB::bind_method(D_METHOD("environment_set_ambient_light", "env", "color", "ambient", "energy", "sky_contibution", "reflection_source", "ao_color"), &VisualServer::environment_set_ambient_light, DEFVAL(VS::ENV_AMBIENT_SOURCE_BG), DEFVAL(1.0), DEFVAL(0.0), DEFVAL(VS::ENV_REFLECTION_SOURCE_BG), DEFVAL(Color())); - ClassDB::bind_method(D_METHOD("environment_set_glow", "env", "enable", "level_flags", "intensity", "strength", "mix", "bloom_threshold", "blend_mode", "hdr_bleed_threshold", "hdr_bleed_scale", "hdr_luminance_cap", "bicubic_upscale"), &VisualServer::environment_set_glow); - ClassDB::bind_method(D_METHOD("environment_set_tonemap", "env", "tone_mapper", "exposure", "white", "auto_exposure", "min_luminance", "max_luminance", "auto_exp_speed", "auto_exp_grey"), &VisualServer::environment_set_tonemap); - ClassDB::bind_method(D_METHOD("environment_set_adjustment", "env", "enable", "brightness", "contrast", "saturation", "ramp"), &VisualServer::environment_set_adjustment); - ClassDB::bind_method(D_METHOD("environment_set_ssr", "env", "enable", "max_steps", "fade_in", "fade_out", "depth_tolerance", "roughness"), &VisualServer::environment_set_ssr); - ClassDB::bind_method(D_METHOD("environment_set_ssao", "env", "enable", "radius", "intensity", "bias", "light_affect", "ao_channel_affect", "blur", "bilateral_sharpness"), &VisualServer::environment_set_ssao); - ClassDB::bind_method(D_METHOD("environment_set_fog", "env", "enable", "color", "sun_color", "sun_amount"), &VisualServer::environment_set_fog); - - ClassDB::bind_method(D_METHOD("environment_set_fog_depth", "env", "enable", "depth_begin", "depth_end", "depth_curve", "transmit", "transmit_curve"), &VisualServer::environment_set_fog_depth); - - ClassDB::bind_method(D_METHOD("environment_set_fog_height", "env", "enable", "min_height", "max_height", "height_curve"), &VisualServer::environment_set_fog_height); - - ClassDB::bind_method(D_METHOD("scenario_create"), &VisualServer::scenario_create); - ClassDB::bind_method(D_METHOD("scenario_set_debug", "scenario", "debug_mode"), &VisualServer::scenario_set_debug); - ClassDB::bind_method(D_METHOD("scenario_set_environment", "scenario", "environment"), &VisualServer::scenario_set_environment); - ClassDB::bind_method(D_METHOD("scenario_set_fallback_environment", "scenario", "environment"), &VisualServer::scenario_set_fallback_environment); - -#ifndef _3D_DISABLED - - ClassDB::bind_method(D_METHOD("instance_create2", "base", "scenario"), &VisualServer::instance_create2); - ClassDB::bind_method(D_METHOD("instance_create"), &VisualServer::instance_create); - ClassDB::bind_method(D_METHOD("instance_set_base", "instance", "base"), &VisualServer::instance_set_base); - ClassDB::bind_method(D_METHOD("instance_set_scenario", "instance", "scenario"), &VisualServer::instance_set_scenario); - ClassDB::bind_method(D_METHOD("instance_set_layer_mask", "instance", "mask"), &VisualServer::instance_set_layer_mask); - ClassDB::bind_method(D_METHOD("instance_set_transform", "instance", "transform"), &VisualServer::instance_set_transform); - ClassDB::bind_method(D_METHOD("instance_attach_object_instance_id", "instance", "id"), &VisualServer::instance_attach_object_instance_id); - ClassDB::bind_method(D_METHOD("instance_set_blend_shape_weight", "instance", "shape", "weight"), &VisualServer::instance_set_blend_shape_weight); - ClassDB::bind_method(D_METHOD("instance_set_surface_material", "instance", "surface", "material"), &VisualServer::instance_set_surface_material); - ClassDB::bind_method(D_METHOD("instance_set_visible", "instance", "visible"), &VisualServer::instance_set_visible); - ClassDB::bind_method(D_METHOD("instance_set_use_lightmap", "instance", "lightmap_instance", "lightmap"), &VisualServer::instance_set_use_lightmap); - ClassDB::bind_method(D_METHOD("instance_set_custom_aabb", "instance", "aabb"), &VisualServer::instance_set_custom_aabb); - ClassDB::bind_method(D_METHOD("instance_attach_skeleton", "instance", "skeleton"), &VisualServer::instance_attach_skeleton); - ClassDB::bind_method(D_METHOD("instance_set_exterior", "instance", "enabled"), &VisualServer::instance_set_exterior); - ClassDB::bind_method(D_METHOD("instance_set_extra_visibility_margin", "instance", "margin"), &VisualServer::instance_set_extra_visibility_margin); - ClassDB::bind_method(D_METHOD("instance_geometry_set_flag", "instance", "flag", "enabled"), &VisualServer::instance_geometry_set_flag); - ClassDB::bind_method(D_METHOD("instance_geometry_set_cast_shadows_setting", "instance", "shadow_casting_setting"), &VisualServer::instance_geometry_set_cast_shadows_setting); - ClassDB::bind_method(D_METHOD("instance_geometry_set_material_override", "instance", "material"), &VisualServer::instance_geometry_set_material_override); - ClassDB::bind_method(D_METHOD("instance_geometry_set_draw_range", "instance", "min", "max", "min_margin", "max_margin"), &VisualServer::instance_geometry_set_draw_range); - ClassDB::bind_method(D_METHOD("instance_geometry_set_as_instance_lod", "instance", "as_lod_of_instance"), &VisualServer::instance_geometry_set_as_instance_lod); - - ClassDB::bind_method(D_METHOD("instances_cull_aabb", "aabb", "scenario"), &VisualServer::_instances_cull_aabb_bind, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("instances_cull_ray", "from", "to", "scenario"), &VisualServer::_instances_cull_ray_bind, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("instances_cull_convex", "convex", "scenario"), &VisualServer::_instances_cull_convex_bind, DEFVAL(RID())); -#endif - ClassDB::bind_method(D_METHOD("canvas_create"), &VisualServer::canvas_create); - ClassDB::bind_method(D_METHOD("canvas_set_item_mirroring", "canvas", "item", "mirroring"), &VisualServer::canvas_set_item_mirroring); - ClassDB::bind_method(D_METHOD("canvas_set_modulate", "canvas", "color"), &VisualServer::canvas_set_modulate); -#ifndef _MSC_VER -#warning TODO method bindings need to be fixed -#endif -#if 0 - - ClassDB::bind_method(D_METHOD("canvas_item_create"), &VisualServer::canvas_item_create); - ClassDB::bind_method(D_METHOD("canvas_item_set_parent", "item", "parent"), &VisualServer::canvas_item_set_parent); - ClassDB::bind_method(D_METHOD("canvas_item_set_visible", "item", "visible"), &VisualServer::canvas_item_set_visible); - ClassDB::bind_method(D_METHOD("canvas_item_set_light_mask", "item", "mask"), &VisualServer::canvas_item_set_light_mask); - ClassDB::bind_method(D_METHOD("canvas_item_set_transform", "item", "transform"), &VisualServer::canvas_item_set_transform); - ClassDB::bind_method(D_METHOD("canvas_item_set_clip", "item", "clip"), &VisualServer::canvas_item_set_clip); - ClassDB::bind_method(D_METHOD("canvas_item_set_distance_field_mode", "item", "enabled"), &VisualServer::canvas_item_set_distance_field_mode); - ClassDB::bind_method(D_METHOD("canvas_item_set_custom_rect", "item", "use_custom_rect", "rect"), &VisualServer::canvas_item_set_custom_rect, DEFVAL(Rect2())); - ClassDB::bind_method(D_METHOD("canvas_item_set_modulate", "item", "color"), &VisualServer::canvas_item_set_modulate); - ClassDB::bind_method(D_METHOD("canvas_item_set_self_modulate", "item", "color"), &VisualServer::canvas_item_set_self_modulate); - ClassDB::bind_method(D_METHOD("canvas_item_set_draw_behind_parent", "item", "enabled"), &VisualServer::canvas_item_set_draw_behind_parent); - ClassDB::bind_method(D_METHOD("canvas_item_add_line", "item", "from", "to", "color", "width", "antialiased"), &VisualServer::canvas_item_add_line, DEFVAL(1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_polyline", "item", "points", "colors", "width", "antialiased"), &VisualServer::canvas_item_add_polyline, DEFVAL(1.0), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_rect", "item", "rect", "color"), &VisualServer::canvas_item_add_rect); - ClassDB::bind_method(D_METHOD("canvas_item_add_circle", "item", "pos", "radius", "color"), &VisualServer::canvas_item_add_circle); - ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect", "item", "rect", "texture", "tile", "modulate", "transpose", "normal_map"), &VisualServer::canvas_item_add_texture_rect, DEFVAL(false), DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_texture_rect_region", "item", "rect", "texture", "src_rect", "modulate", "transpose", "normal_map", "clip_uv"), &VisualServer::canvas_item_add_texture_rect_region, DEFVAL(Color(1, 1, 1)), DEFVAL(false), DEFVAL(RID()), DEFVAL(true)); - ClassDB::bind_method(D_METHOD("canvas_item_add_nine_patch", "item", "rect", "source", "texture", "topleft", "bottomright", "x_axis_mode", "y_axis_mode", "draw_center", "modulate", "normal_map"), &VisualServer::canvas_item_add_nine_patch, DEFVAL(NINE_PATCH_STRETCH), DEFVAL(NINE_PATCH_STRETCH), DEFVAL(true), DEFVAL(Color(1, 1, 1)), DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_primitive", "item", "points", "colors", "uvs", "texture", "width", "normal_map"), &VisualServer::canvas_item_add_primitive, DEFVAL(1.0), DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_polygon", "item", "points", "colors", "uvs", "texture", "normal_map", "antialiased"), &VisualServer::canvas_item_add_polygon, DEFVAL(Vector()), DEFVAL(RID()), DEFVAL(RID()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_triangle_array", "item", "indices", "points", "colors", "uvs", "bones", "weights", "texture", "count", "normal_map", "antialiased"), &VisualServer::canvas_item_add_triangle_array, DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(Vector()), DEFVAL(RID()), DEFVAL(-1), DEFVAL(RID()), DEFVAL(false)); - ClassDB::bind_method(D_METHOD("canvas_item_add_mesh", "item", "mesh", "transform", "modulate", "texture", "normal_map"), &VisualServer::canvas_item_add_mesh, DEFVAL(Transform2D()), DEFVAL(Color(1, 1, 1)), DEFVAL(RID()), DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_multimesh", "item", "mesh", "texture", "normal_map"), &VisualServer::canvas_item_add_multimesh, DEFVAL(RID())); - ClassDB::bind_method(D_METHOD("canvas_item_add_particles", "item", "particles", "texture", "normal_map"), &VisualServer::canvas_item_add_particles); - ClassDB::bind_method(D_METHOD("canvas_item_add_set_transform", "item", "transform"), &VisualServer::canvas_item_add_set_transform); - ClassDB::bind_method(D_METHOD("canvas_item_add_clip_ignore", "item", "ignore"), &VisualServer::canvas_item_add_clip_ignore); - ClassDB::bind_method(D_METHOD("canvas_item_set_sort_children_by_y", "item", "enabled"), &VisualServer::canvas_item_set_sort_children_by_y); -#endif - ClassDB::bind_method(D_METHOD("canvas_item_set_z_index", "item", "z_index"), &VisualServer::canvas_item_set_z_index); - ClassDB::bind_method(D_METHOD("canvas_item_set_z_as_relative_to_parent", "item", "enabled"), &VisualServer::canvas_item_set_z_as_relative_to_parent); - ClassDB::bind_method(D_METHOD("canvas_item_set_copy_to_backbuffer", "item", "enabled", "rect"), &VisualServer::canvas_item_set_copy_to_backbuffer); - ClassDB::bind_method(D_METHOD("canvas_item_clear", "item"), &VisualServer::canvas_item_clear); - ClassDB::bind_method(D_METHOD("canvas_item_set_draw_index", "item", "index"), &VisualServer::canvas_item_set_draw_index); - ClassDB::bind_method(D_METHOD("canvas_item_set_material", "item", "material"), &VisualServer::canvas_item_set_material); - ClassDB::bind_method(D_METHOD("canvas_item_set_use_parent_material", "item", "enabled"), &VisualServer::canvas_item_set_use_parent_material); - ClassDB::bind_method(D_METHOD("canvas_light_create"), &VisualServer::canvas_light_create); - ClassDB::bind_method(D_METHOD("canvas_light_attach_to_canvas", "light", "canvas"), &VisualServer::canvas_light_attach_to_canvas); - ClassDB::bind_method(D_METHOD("canvas_light_set_enabled", "light", "enabled"), &VisualServer::canvas_light_set_enabled); - ClassDB::bind_method(D_METHOD("canvas_light_set_scale", "light", "scale"), &VisualServer::canvas_light_set_scale); - ClassDB::bind_method(D_METHOD("canvas_light_set_transform", "light", "transform"), &VisualServer::canvas_light_set_transform); - ClassDB::bind_method(D_METHOD("canvas_light_set_texture", "light", "texture"), &VisualServer::canvas_light_set_texture); - ClassDB::bind_method(D_METHOD("canvas_light_set_texture_offset", "light", "offset"), &VisualServer::canvas_light_set_texture_offset); - ClassDB::bind_method(D_METHOD("canvas_light_set_color", "light", "color"), &VisualServer::canvas_light_set_color); - ClassDB::bind_method(D_METHOD("canvas_light_set_height", "light", "height"), &VisualServer::canvas_light_set_height); - ClassDB::bind_method(D_METHOD("canvas_light_set_energy", "light", "energy"), &VisualServer::canvas_light_set_energy); - ClassDB::bind_method(D_METHOD("canvas_light_set_z_range", "light", "min_z", "max_z"), &VisualServer::canvas_light_set_z_range); - ClassDB::bind_method(D_METHOD("canvas_light_set_layer_range", "light", "min_layer", "max_layer"), &VisualServer::canvas_light_set_layer_range); - ClassDB::bind_method(D_METHOD("canvas_light_set_item_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_cull_mask); - ClassDB::bind_method(D_METHOD("canvas_light_set_item_shadow_cull_mask", "light", "mask"), &VisualServer::canvas_light_set_item_shadow_cull_mask); - ClassDB::bind_method(D_METHOD("canvas_light_set_mode", "light", "mode"), &VisualServer::canvas_light_set_mode); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_enabled", "light", "enabled"), &VisualServer::canvas_light_set_shadow_enabled); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_buffer_size", "light", "size"), &VisualServer::canvas_light_set_shadow_buffer_size); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_filter", "light", "filter"), &VisualServer::canvas_light_set_shadow_filter); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_color", "light", "color"), &VisualServer::canvas_light_set_shadow_color); - ClassDB::bind_method(D_METHOD("canvas_light_set_shadow_smooth", "light", "smooth"), &VisualServer::canvas_light_set_shadow_smooth); - - ClassDB::bind_method(D_METHOD("canvas_light_occluder_create"), &VisualServer::canvas_light_occluder_create); - ClassDB::bind_method(D_METHOD("canvas_light_occluder_attach_to_canvas", "occluder", "canvas"), &VisualServer::canvas_light_occluder_attach_to_canvas); - ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_enabled", "occluder", "enabled"), &VisualServer::canvas_light_occluder_set_enabled); - ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_polygon", "occluder", "polygon"), &VisualServer::canvas_light_occluder_set_polygon); - ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_transform", "occluder", "transform"), &VisualServer::canvas_light_occluder_set_transform); - ClassDB::bind_method(D_METHOD("canvas_light_occluder_set_light_mask", "occluder", "mask"), &VisualServer::canvas_light_occluder_set_light_mask); - - ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_create"), &VisualServer::canvas_occluder_polygon_create); - ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape", "occluder_polygon", "shape", "closed"), &VisualServer::canvas_occluder_polygon_set_shape); - ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_shape_as_lines", "occluder_polygon", "shape"), &VisualServer::canvas_occluder_polygon_set_shape_as_lines); - ClassDB::bind_method(D_METHOD("canvas_occluder_polygon_set_cull_mode", "occluder_polygon", "mode"), &VisualServer::canvas_occluder_polygon_set_cull_mode); - - ClassDB::bind_method(D_METHOD("black_bars_set_margins", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_margins); - ClassDB::bind_method(D_METHOD("black_bars_set_images", "left", "top", "right", "bottom"), &VisualServer::black_bars_set_images); - - ClassDB::bind_method(D_METHOD("free_rid", "rid"), &VisualServer::free); // shouldn't conflict with Object::free() - - ClassDB::bind_method(D_METHOD("request_frame_drawn_callback", "where", "method", "userdata"), &VisualServer::request_frame_drawn_callback); - ClassDB::bind_method(D_METHOD("has_changed"), &VisualServer::has_changed); - ClassDB::bind_method(D_METHOD("init"), &VisualServer::init); - ClassDB::bind_method(D_METHOD("finish"), &VisualServer::finish); - ClassDB::bind_method(D_METHOD("get_render_info", "info"), &VisualServer::get_render_info); - ClassDB::bind_method(D_METHOD("get_video_adapter_name"), &VisualServer::get_video_adapter_name); - ClassDB::bind_method(D_METHOD("get_video_adapter_vendor"), &VisualServer::get_video_adapter_vendor); -#ifndef _3D_DISABLED - - ClassDB::bind_method(D_METHOD("make_sphere_mesh", "latitudes", "longitudes", "radius"), &VisualServer::make_sphere_mesh); - ClassDB::bind_method(D_METHOD("get_test_cube"), &VisualServer::get_test_cube); -#endif - ClassDB::bind_method(D_METHOD("get_test_texture"), &VisualServer::get_test_texture); - ClassDB::bind_method(D_METHOD("get_white_texture"), &VisualServer::get_white_texture); - - ClassDB::bind_method(D_METHOD("set_boot_image", "image", "color", "scale", "use_filter"), &VisualServer::set_boot_image, DEFVAL(true)); - ClassDB::bind_method(D_METHOD("set_default_clear_color", "color"), &VisualServer::set_default_clear_color); - - ClassDB::bind_method(D_METHOD("has_feature", "feature"), &VisualServer::has_feature); - ClassDB::bind_method(D_METHOD("has_os_feature", "feature"), &VisualServer::has_os_feature); - ClassDB::bind_method(D_METHOD("set_debug_generate_wireframes", "generate"), &VisualServer::set_debug_generate_wireframes); - - BIND_CONSTANT(NO_INDEX_ARRAY); - BIND_CONSTANT(ARRAY_WEIGHTS_SIZE); - BIND_CONSTANT(CANVAS_ITEM_Z_MIN); - BIND_CONSTANT(CANVAS_ITEM_Z_MAX); - BIND_CONSTANT(MAX_GLOW_LEVELS); - BIND_CONSTANT(MAX_CURSORS); - - BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MIN); - BIND_CONSTANT(MATERIAL_RENDER_PRIORITY_MAX); - - BIND_ENUM_CONSTANT(TEXTURE_LAYERED_2D_ARRAY); - BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP); - BIND_ENUM_CONSTANT(TEXTURE_LAYERED_CUBEMAP_ARRAY); - - BIND_ENUM_CONSTANT(CUBEMAP_LAYER_LEFT); - BIND_ENUM_CONSTANT(CUBEMAP_LAYER_RIGHT); - BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BOTTOM); - BIND_ENUM_CONSTANT(CUBEMAP_LAYER_TOP); - BIND_ENUM_CONSTANT(CUBEMAP_LAYER_FRONT); - BIND_ENUM_CONSTANT(CUBEMAP_LAYER_BACK); - - BIND_ENUM_CONSTANT(SHADER_SPATIAL); - BIND_ENUM_CONSTANT(SHADER_CANVAS_ITEM); - BIND_ENUM_CONSTANT(SHADER_PARTICLES); - BIND_ENUM_CONSTANT(SHADER_SKY); - BIND_ENUM_CONSTANT(SHADER_MAX); - - BIND_ENUM_CONSTANT(ARRAY_VERTEX); - BIND_ENUM_CONSTANT(ARRAY_NORMAL); - BIND_ENUM_CONSTANT(ARRAY_TANGENT); - BIND_ENUM_CONSTANT(ARRAY_COLOR); - BIND_ENUM_CONSTANT(ARRAY_TEX_UV); - BIND_ENUM_CONSTANT(ARRAY_TEX_UV2); - BIND_ENUM_CONSTANT(ARRAY_BONES); - BIND_ENUM_CONSTANT(ARRAY_WEIGHTS); - BIND_ENUM_CONSTANT(ARRAY_INDEX); - BIND_ENUM_CONSTANT(ARRAY_MAX); - - BIND_ENUM_CONSTANT(ARRAY_FORMAT_VERTEX); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_NORMAL); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_TANGENT); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_COLOR); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_TEX_UV2); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_BONES); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_WEIGHTS); - BIND_ENUM_CONSTANT(ARRAY_FORMAT_INDEX); - - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_NORMAL); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TANGENT); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_COLOR); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_TEX_UV2); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_INDEX); - BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_2D_VERTICES); - BIND_ENUM_CONSTANT(ARRAY_FLAG_USE_DYNAMIC_UPDATE); - BIND_ENUM_CONSTANT(ARRAY_COMPRESS_DEFAULT); - - BIND_ENUM_CONSTANT(PRIMITIVE_POINTS); - BIND_ENUM_CONSTANT(PRIMITIVE_LINES); - BIND_ENUM_CONSTANT(PRIMITIVE_LINE_STRIP); - BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLES); - BIND_ENUM_CONSTANT(PRIMITIVE_TRIANGLE_STRIP); - BIND_ENUM_CONSTANT(PRIMITIVE_MAX); - - BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_NORMALIZED); - BIND_ENUM_CONSTANT(BLEND_SHAPE_MODE_RELATIVE); - - BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_2D); - BIND_ENUM_CONSTANT(MULTIMESH_TRANSFORM_3D); - - BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL); - BIND_ENUM_CONSTANT(LIGHT_OMNI); - BIND_ENUM_CONSTANT(LIGHT_SPOT); - - BIND_ENUM_CONSTANT(LIGHT_PARAM_ENERGY); - BIND_ENUM_CONSTANT(LIGHT_PARAM_INDIRECT_ENERGY); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SPECULAR); - BIND_ENUM_CONSTANT(LIGHT_PARAM_RANGE); - BIND_ENUM_CONSTANT(LIGHT_PARAM_ATTENUATION); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ANGLE); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SPOT_ATTENUATION); - BIND_ENUM_CONSTANT(LIGHT_PARAM_CONTACT_SHADOW_SIZE); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_MAX_DISTANCE); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_FADE_START); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_NORMAL_BIAS); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS); - BIND_ENUM_CONSTANT(LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE); - BIND_ENUM_CONSTANT(LIGHT_PARAM_MAX); - - BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_DUAL_PARABOLOID); - BIND_ENUM_CONSTANT(LIGHT_OMNI_SHADOW_CUBE); - - BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL); - BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS); - BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS); - - BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE); - BIND_ENUM_CONSTANT(LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED); - - BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ONCE); - BIND_ENUM_CONSTANT(REFLECTION_PROBE_UPDATE_ALWAYS); - - BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_INDEX); - BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_LIFETIME); - BIND_ENUM_CONSTANT(PARTICLES_DRAW_ORDER_VIEW_DEPTH); - - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE); - BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS); - - BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS); - BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_NEVER); - BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ONLY_NEXT_FRAME); - - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_2X); - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X); - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X); - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X); - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_2X); - BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_4X); - - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME); - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME); - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME); - BIND_ENUM_CONSTANT(VIEWPORT_RENDER_INFO_MAX); - - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DISABLED); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_UNSHADED); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_LIGHTING); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_OVERDRAW); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_WIREFRAME); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_SSAO); - BIND_ENUM_CONSTANT(VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER); - - BIND_ENUM_CONSTANT(SKY_MODE_QUALITY); - BIND_ENUM_CONSTANT(SKY_MODE_REALTIME); - - BIND_ENUM_CONSTANT(ENV_BG_CLEAR_COLOR); - BIND_ENUM_CONSTANT(ENV_BG_COLOR); - BIND_ENUM_CONSTANT(ENV_BG_SKY); - BIND_ENUM_CONSTANT(ENV_BG_CANVAS); - BIND_ENUM_CONSTANT(ENV_BG_KEEP); - BIND_ENUM_CONSTANT(ENV_BG_CAMERA_FEED); - BIND_ENUM_CONSTANT(ENV_BG_MAX); - - BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_BG); - BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_DISABLED); - BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_COLOR); - BIND_ENUM_CONSTANT(ENV_AMBIENT_SOURCE_SKY); - - BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_BG); - BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_DISABLED); - BIND_ENUM_CONSTANT(ENV_REFLECTION_SOURCE_SKY); - - BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_ADDITIVE); - BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_SCREEN); - BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_SOFTLIGHT); - BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_REPLACE); - BIND_ENUM_CONSTANT(ENV_GLOW_BLEND_MODE_MIX); - - BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_LINEAR); - BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_REINHARD); - BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_FILMIC); - BIND_ENUM_CONSTANT(ENV_TONE_MAPPER_ACES); - - BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_DISABLED); - BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_1x1); - BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_2x2); - BIND_ENUM_CONSTANT(ENV_SSAO_BLUR_3x3); - - BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_LOW); - BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_MEDIUM); - BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_HIGH); - BIND_ENUM_CONSTANT(ENV_SSAO_QUALITY_ULTRA); - - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_VERY_LOW); - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_LOW); - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_MEDIUM); - BIND_ENUM_CONSTANT(DOF_BLUR_QUALITY_HIGH); - - BIND_ENUM_CONSTANT(DOF_BOKEH_BOX); - BIND_ENUM_CONSTANT(DOF_BOKEH_HEXAGON); - BIND_ENUM_CONSTANT(DOF_BOKEH_CIRCLE); - - BIND_ENUM_CONSTANT(SCENARIO_DEBUG_DISABLED); - BIND_ENUM_CONSTANT(SCENARIO_DEBUG_WIREFRAME); - BIND_ENUM_CONSTANT(SCENARIO_DEBUG_OVERDRAW); - BIND_ENUM_CONSTANT(SCENARIO_DEBUG_SHADELESS); - - BIND_ENUM_CONSTANT(INSTANCE_NONE); - BIND_ENUM_CONSTANT(INSTANCE_MESH); - BIND_ENUM_CONSTANT(INSTANCE_MULTIMESH); - BIND_ENUM_CONSTANT(INSTANCE_IMMEDIATE); - BIND_ENUM_CONSTANT(INSTANCE_PARTICLES); - BIND_ENUM_CONSTANT(INSTANCE_LIGHT); - BIND_ENUM_CONSTANT(INSTANCE_REFLECTION_PROBE); - BIND_ENUM_CONSTANT(INSTANCE_GI_PROBE); - BIND_ENUM_CONSTANT(INSTANCE_LIGHTMAP_CAPTURE); - BIND_ENUM_CONSTANT(INSTANCE_MAX); - BIND_ENUM_CONSTANT(INSTANCE_GEOMETRY_MASK); - - BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_BAKED_LIGHT); - BIND_ENUM_CONSTANT(INSTANCE_FLAG_USE_DYNAMIC_GI); - BIND_ENUM_CONSTANT(INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE); - BIND_ENUM_CONSTANT(INSTANCE_FLAG_MAX); - - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_OFF); - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_ON); - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_DOUBLE_SIDED); - BIND_ENUM_CONSTANT(SHADOW_CASTING_SETTING_SHADOWS_ONLY); - - BIND_ENUM_CONSTANT(NINE_PATCH_STRETCH); - BIND_ENUM_CONSTANT(NINE_PATCH_TILE); - BIND_ENUM_CONSTANT(NINE_PATCH_TILE_FIT); - - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_DEFAULT); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_NEAREST); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_LINEAR); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_FILTER_MAX); - - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_ENABLED); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MIRROR); - BIND_ENUM_CONSTANT(CANVAS_ITEM_TEXTURE_REPEAT_MAX); - - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_ADD); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_SUB); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MIX); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_MODE_MASK); - - BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_NONE); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF5); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_PCF13); - BIND_ENUM_CONSTANT(CANVAS_LIGHT_FILTER_MAX); - - BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_DISABLED); - BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE); - BIND_ENUM_CONSTANT(CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE); - - BIND_ENUM_CONSTANT(INFO_OBJECTS_IN_FRAME); - BIND_ENUM_CONSTANT(INFO_VERTICES_IN_FRAME); - BIND_ENUM_CONSTANT(INFO_MATERIAL_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(INFO_SHADER_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(INFO_SURFACE_CHANGES_IN_FRAME); - BIND_ENUM_CONSTANT(INFO_DRAW_CALLS_IN_FRAME); - BIND_ENUM_CONSTANT(INFO_USAGE_VIDEO_MEM_TOTAL); - BIND_ENUM_CONSTANT(INFO_VIDEO_MEM_USED); - BIND_ENUM_CONSTANT(INFO_TEXTURE_MEM_USED); - BIND_ENUM_CONSTANT(INFO_VERTEX_MEM_USED); - - BIND_ENUM_CONSTANT(FEATURE_SHADERS); - BIND_ENUM_CONSTANT(FEATURE_MULTITHREADED); - - ADD_SIGNAL(MethodInfo("frame_pre_draw")); - ADD_SIGNAL(MethodInfo("frame_post_draw")); -} - -void VisualServer::_canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector &p_margins, const Color &p_modulate) { - - ERR_FAIL_COND(p_margins.size() != 4); - //canvas_item_add_style_box(p_item,p_rect,p_source,p_texture,Vector2(p_margins[0],p_margins[1]),Vector2(p_margins[2],p_margins[3]),true,p_modulate); -} - -void VisualServer::_camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) { - - camera_set_orthogonal(p_camera, p_size, p_z_near, p_z_far); -} - -void VisualServer::mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data) { - - Vector vertices; - Vector normals; - - for (int i = 0; i < p_mesh_data.faces.size(); i++) { - - const Geometry::MeshData::Face &f = p_mesh_data.faces[i]; - - for (int j = 2; j < f.indices.size(); j++) { - -#define _ADD_VERTEX(m_idx) \ - vertices.push_back(p_mesh_data.vertices[f.indices[m_idx]]); \ - normals.push_back(f.plane.normal); - - _ADD_VERTEX(0); - _ADD_VERTEX(j - 1); - _ADD_VERTEX(j); - } - } - - Array d; - d.resize(VS::ARRAY_MAX); - d[ARRAY_VERTEX] = vertices; - d[ARRAY_NORMAL] = normals; - mesh_add_surface_from_arrays(p_mesh, PRIMITIVE_TRIANGLES, d); -} - -void VisualServer::mesh_add_surface_from_planes(RID p_mesh, const Vector &p_planes) { - - Geometry::MeshData mdata = Geometry::build_convex_mesh(p_planes); - mesh_add_surface_from_mesh_data(p_mesh, mdata); -} - -void VisualServer::immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex) { - immediate_vertex(p_immediate, Vector3(p_vertex.x, p_vertex.y, 0)); -} - -RID VisualServer::instance_create2(RID p_base, RID p_scenario) { - - RID instance = instance_create(); - instance_set_base(instance, p_base); - instance_set_scenario(instance, p_scenario); - return instance; -} - -VisualServer::VisualServer() { - - //ERR_FAIL_COND(singleton); - singleton = this; - - GLOBAL_DEF_RST("rendering/vram_compression/import_bptc", false); - GLOBAL_DEF_RST("rendering/vram_compression/import_s3tc", true); - GLOBAL_DEF_RST("rendering/vram_compression/import_etc", false); - GLOBAL_DEF_RST("rendering/vram_compression/import_etc2", true); - GLOBAL_DEF_RST("rendering/vram_compression/import_pvrtc", false); - - GLOBAL_DEF("rendering/quality/directional_shadow/size", 4096); - GLOBAL_DEF("rendering/quality/directional_shadow/size.mobile", 2048); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/directional_shadow/size", PropertyInfo(Variant::INT, "rendering/quality/directional_shadow/size", PROPERTY_HINT_RANGE, "256,16384")); - GLOBAL_DEF("rendering/quality/shadow_atlas/size", 4096); - GLOBAL_DEF("rendering/quality/shadow_atlas/size.mobile", 2048); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/size", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/size", PROPERTY_HINT_RANGE, "256,16384")); - GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_0_subdiv", 1); - GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_1_subdiv", 2); - GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_2_subdiv", 3); - GLOBAL_DEF("rendering/quality/shadow_atlas/quadrant_3_subdiv", 4); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_0_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_0_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_1_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_1_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_2_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_2_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadow_atlas/quadrant_3_subdiv", PropertyInfo(Variant::INT, "rendering/quality/shadow_atlas/quadrant_3_subdiv", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows")); - - GLOBAL_DEF("rendering/quality/shadows/filter_mode", 1); - GLOBAL_DEF("rendering/quality/shadows/filter_mode.mobile", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/shadows/filter_mode", PropertyInfo(Variant::INT, "rendering/quality/shadows/filter_mode", PROPERTY_HINT_ENUM, "Disabled (Fastest),PCF5,PCF13 (Slowest)")); - - GLOBAL_DEF("rendering/quality/reflections/roughness_layers", 8); - GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections", true); - GLOBAL_DEF("rendering/quality/reflections/texture_array_reflections.mobile", false); - GLOBAL_DEF("rendering/quality/reflections/ggx_samples", 1024); - GLOBAL_DEF("rendering/quality/reflections/ggx_samples.mobile", 128); - GLOBAL_DEF("rendering/quality/reflections/fast_filter_high_quality", false); - GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size", 256); - GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_size.mobile", 128); - GLOBAL_DEF("rendering/quality/reflection_atlas/reflection_count", 64); - - GLOBAL_DEF("rendering/quality/gi_probes/anisotropic", false); - GLOBAL_DEF("rendering/quality/gi_probes/quality", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/gi_probes/quality", PropertyInfo(Variant::INT, "rendering/quality/gi_probes/quality", PROPERTY_HINT_ENUM, "Ultra-Low (1 cone - fastest),Medium (4 cones), High (6 cones - slowest)")); - - GLOBAL_DEF("rendering/quality/shading/force_vertex_shading", false); - GLOBAL_DEF("rendering/quality/shading/force_vertex_shading.mobile", true); - GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley", false); - GLOBAL_DEF("rendering/quality/shading/force_lambert_over_burley.mobile", true); - GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx", false); - GLOBAL_DEF("rendering/quality/shading/force_blinn_over_ggx.mobile", true); - - GLOBAL_DEF("rendering/quality/depth_prepass/enable", true); - GLOBAL_DEF("rendering/quality/depth_prepass/disable_for_vendors", "PowerVR,Mali,Adreno,Apple"); - - GLOBAL_DEF("rendering/quality/filters/use_nearest_mipmap_filter", false); - GLOBAL_DEF("rendering/quality/filters/max_anisotropy", 4); - - GLOBAL_DEF("rendering/quality/filters/depth_of_field_bokeh_shape", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/depth_of_field_bokeh_shape", PropertyInfo(Variant::INT, "rendering/quality/filters/depth_of_field_bokeh_shape", PROPERTY_HINT_ENUM, "Box (Fastest),Hexagon,Circle (Slowest)")); - GLOBAL_DEF("rendering/quality/filters/depth_of_field_bokeh_quality", 2); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/depth_of_field_bokeh_quality", PropertyInfo(Variant::INT, "rendering/quality/filters/depth_of_field_bokeh_quality", PROPERTY_HINT_ENUM, "Very Low (Fast),Low,Medium,High (Slow)")); - GLOBAL_DEF("rendering/quality/filters/depth_of_field_use_jitter", false); - - GLOBAL_DEF("rendering/quality/ssao/quality", 1); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/ssao/quality", PropertyInfo(Variant::INT, "rendering/quality/ssao/quality", PROPERTY_HINT_ENUM, "Low (Fast),Medium,High (Slow),Ultra (Very Slow)")); - GLOBAL_DEF("rendering/quality/ssao/half_size", false); - - GLOBAL_DEF("rendering/quality/filters/screen_space_roughness_limiter", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/screen_space_roughness_limiter", PropertyInfo(Variant::INT, "rendering/quality/filters/screen_space_roughness_limiter", PROPERTY_HINT_ENUM, "Disabled,Enabled (Small Cost)")); - GLOBAL_DEF("rendering/quality/filters/screen_space_roughness_limiter_curve", 1.0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/screen_space_roughness_limiter_curve", PropertyInfo(Variant::FLOAT, "rendering/quality/filters/screen_space_roughness_limiter_curve", PROPERTY_HINT_EXP_EASING, "0.01,8,0.01")); -} - -VisualServer::~VisualServer() { - - singleton = NULL; -} diff --git a/servers/visual_server.h b/servers/visual_server.h deleted file mode 100644 index 506800cc7d..0000000000 --- a/servers/visual_server.h +++ /dev/null @@ -1,1157 +0,0 @@ -/*************************************************************************/ -/* visual_server.h */ -/*************************************************************************/ -/* This file is part of: */ -/* GODOT ENGINE */ -/* https://godotengine.org */ -/*************************************************************************/ -/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */ -/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining */ -/* a copy of this software and associated documentation files (the */ -/* "Software"), to deal in the Software without restriction, including */ -/* without limitation the rights to use, copy, modify, merge, publish, */ -/* distribute, sublicense, and/or sell copies of the Software, and to */ -/* permit persons to whom the Software is furnished to do so, subject to */ -/* the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be */ -/* included in all copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ -/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ -/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ -/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ -/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ -/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ -/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -/*************************************************************************/ - -#ifndef VISUAL_SERVER_H -#define VISUAL_SERVER_H - -#include "core/image.h" -#include "core/math/geometry.h" -#include "core/math/transform_2d.h" -#include "core/object.h" -#include "core/rid.h" -#include "core/variant.h" -#include "servers/display_server.h" - -class VisualServer : public Object { - - GDCLASS(VisualServer, Object); - - static VisualServer *singleton; - - int mm_policy; - - void _camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far); - void _canvas_item_add_style_box(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector &p_margins, const Color &p_modulate = Color(1, 1, 1)); - Array _get_array_from_surface(uint32_t p_format, Vector p_vertex_data, int p_vertex_len, Vector p_index_data, int p_index_len) const; - -protected: - RID _make_test_cube(); - void _free_internal_rids(); - RID test_texture; - RID white_texture; - RID test_material; - - Error _surface_set_data(Array p_arrays, uint32_t p_format, uint32_t *p_offsets, uint32_t p_stride, Vector &r_vertex_array, int p_vertex_array_len, Vector &r_index_array, int p_index_array_len, AABB &r_aabb, Vector &r_bone_aabb); - - static VisualServer *(*create_func)(); - static void _bind_methods(); - -public: - static VisualServer *get_singleton(); - static VisualServer *create(); - - enum { - NO_INDEX_ARRAY = -1, - ARRAY_WEIGHTS_SIZE = 4, - CANVAS_ITEM_Z_MIN = -4096, - CANVAS_ITEM_Z_MAX = 4096, - MAX_GLOW_LEVELS = 7, - MAX_CURSORS = 8, - }; - - /* TEXTURE API */ - - enum TextureLayeredType { - TEXTURE_LAYERED_2D_ARRAY, - TEXTURE_LAYERED_CUBEMAP, - TEXTURE_LAYERED_CUBEMAP_ARRAY, - }; - - enum CubeMapLayer { - - CUBEMAP_LAYER_LEFT, - CUBEMAP_LAYER_RIGHT, - CUBEMAP_LAYER_BOTTOM, - CUBEMAP_LAYER_TOP, - CUBEMAP_LAYER_FRONT, - CUBEMAP_LAYER_BACK - }; - - virtual RID texture_2d_create(const Ref &p_image) = 0; - virtual RID texture_2d_layered_create(const Vector> &p_layers, TextureLayeredType p_layered_type) = 0; - virtual RID texture_3d_create(const Vector> &p_slices) = 0; //all slices, then all the mipmaps, must be coherent - virtual RID texture_proxy_create(RID p_base) = 0; - - virtual void texture_2d_update_immediate(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; //mostly used for video and streaming - virtual void texture_2d_update(RID p_texture, const Ref &p_image, int p_layer = 0) = 0; - virtual void texture_3d_update(RID p_texture, const Ref &p_image, int p_depth, int p_mipmap) = 0; - virtual void texture_proxy_update(RID p_texture, RID p_proxy_to) = 0; - - //these two APIs can be used together or in combination with the others. - virtual RID texture_2d_placeholder_create() = 0; - virtual RID texture_2d_layered_placeholder_create() = 0; - virtual RID texture_3d_placeholder_create() = 0; - - virtual Ref texture_2d_get(RID p_texture) const = 0; - virtual Ref texture_2d_layer_get(RID p_texture, int p_layer) const = 0; - virtual Ref texture_3d_slice_get(RID p_texture, int p_depth, int p_mipmap) const = 0; - - virtual void texture_replace(RID p_texture, RID p_by_texture) = 0; - virtual void texture_set_size_override(RID p_texture, int p_width, int p_height) = 0; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - virtual void texture_bind(RID p_texture, uint32_t p_texture_no) = 0; -#endif - - virtual void texture_set_path(RID p_texture, const String &p_path) = 0; - virtual String texture_get_path(RID p_texture) const = 0; - - typedef void (*TextureDetectCallback)(void *); - - virtual void texture_set_detect_3d_callback(RID p_texture, TextureDetectCallback p_callback, void *p_userdata) = 0; - virtual void texture_set_detect_normal_callback(RID p_texture, TextureDetectCallback p_callback, void *p_userdata) = 0; - - enum TextureDetectRoughnessChannel { - TEXTURE_DETECT_ROUGNHESS_R, - TEXTURE_DETECT_ROUGNHESS_G, - TEXTURE_DETECT_ROUGNHESS_B, - TEXTURE_DETECT_ROUGNHESS_A, - TEXTURE_DETECT_ROUGNHESS_GRAY, - }; - - typedef void (*TextureDetectRoughnessCallback)(void *, const String &, TextureDetectRoughnessChannel); - virtual void texture_set_detect_roughness_callback(RID p_texture, TextureDetectRoughnessCallback p_callback, void *p_userdata) = 0; - - struct TextureInfo { - RID texture; - uint32_t width; - uint32_t height; - uint32_t depth; - Image::Format format; - int bytes; - String path; - }; - - virtual void texture_debug_usage(List *r_info) = 0; - Array _texture_debug_usage_bind(); - - virtual void texture_set_force_redraw_if_visible(RID p_texture, bool p_enable) = 0; - - /* SHADER API */ - - enum ShaderMode { - - SHADER_SPATIAL, - SHADER_CANVAS_ITEM, - SHADER_PARTICLES, - SHADER_SKY, - SHADER_MAX - }; - - virtual RID shader_create() = 0; - - virtual void shader_set_code(RID p_shader, const String &p_code) = 0; - virtual String shader_get_code(RID p_shader) const = 0; - virtual void shader_get_param_list(RID p_shader, List *p_param_list) const = 0; - Array _shader_get_param_list_bind(RID p_shader) const; - virtual Variant shader_get_param_default(RID p_shader, const StringName &p_param) const = 0; - - virtual void shader_set_default_texture_param(RID p_shader, const StringName &p_name, RID p_texture) = 0; - virtual RID shader_get_default_texture_param(RID p_shader, const StringName &p_name) const = 0; - - /* COMMON MATERIAL API */ - - enum { - MATERIAL_RENDER_PRIORITY_MIN = -128, - MATERIAL_RENDER_PRIORITY_MAX = 127, - - }; - virtual RID material_create() = 0; - - virtual void material_set_shader(RID p_shader_material, RID p_shader) = 0; - - virtual void material_set_param(RID p_material, const StringName &p_param, const Variant &p_value) = 0; - virtual Variant material_get_param(RID p_material, const StringName &p_param) const = 0; - - virtual void material_set_render_priority(RID p_material, int priority) = 0; - - virtual void material_set_next_pass(RID p_material, RID p_next_material) = 0; - - /* MESH API */ - - enum ArrayType { - - ARRAY_VERTEX = 0, - ARRAY_NORMAL = 1, - ARRAY_TANGENT = 2, - ARRAY_COLOR = 3, - ARRAY_TEX_UV = 4, - ARRAY_TEX_UV2 = 5, - ARRAY_BONES = 6, - ARRAY_WEIGHTS = 7, - ARRAY_INDEX = 8, - ARRAY_MAX = 9 - }; - - enum ArrayFormat { - /* ARRAY FORMAT FLAGS */ - ARRAY_FORMAT_VERTEX = 1 << ARRAY_VERTEX, // mandatory - ARRAY_FORMAT_NORMAL = 1 << ARRAY_NORMAL, - ARRAY_FORMAT_TANGENT = 1 << ARRAY_TANGENT, - ARRAY_FORMAT_COLOR = 1 << ARRAY_COLOR, - ARRAY_FORMAT_TEX_UV = 1 << ARRAY_TEX_UV, - ARRAY_FORMAT_TEX_UV2 = 1 << ARRAY_TEX_UV2, - ARRAY_FORMAT_BONES = 1 << ARRAY_BONES, - ARRAY_FORMAT_WEIGHTS = 1 << ARRAY_WEIGHTS, - ARRAY_FORMAT_INDEX = 1 << ARRAY_INDEX, - - ARRAY_COMPRESS_BASE = (ARRAY_INDEX + 1), - ARRAY_COMPRESS_NORMAL = 1 << (ARRAY_NORMAL + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_TANGENT = 1 << (ARRAY_TANGENT + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_COLOR = 1 << (ARRAY_COLOR + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_TEX_UV = 1 << (ARRAY_TEX_UV + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_TEX_UV2 = 1 << (ARRAY_TEX_UV2 + ARRAY_COMPRESS_BASE), - ARRAY_COMPRESS_INDEX = 1 << (ARRAY_INDEX + ARRAY_COMPRESS_BASE), - - ARRAY_FLAG_USE_2D_VERTICES = ARRAY_COMPRESS_INDEX << 1, - ARRAY_FLAG_USE_DYNAMIC_UPDATE = ARRAY_COMPRESS_INDEX << 3, - - ARRAY_COMPRESS_DEFAULT = ARRAY_COMPRESS_NORMAL | ARRAY_COMPRESS_TANGENT | ARRAY_COMPRESS_COLOR | ARRAY_COMPRESS_TEX_UV | ARRAY_COMPRESS_TEX_UV2 - - }; - - enum PrimitiveType { - PRIMITIVE_POINTS, - PRIMITIVE_LINES, - PRIMITIVE_LINE_STRIP, - PRIMITIVE_TRIANGLES, - PRIMITIVE_TRIANGLE_STRIP, - PRIMITIVE_MAX, - }; - - struct SurfaceData { - - PrimitiveType primitive = PRIMITIVE_MAX; - - uint32_t format = 0; - Vector vertex_data; - uint32_t vertex_count = 0; - Vector index_data; - uint32_t index_count = 0; - - AABB aabb; - struct LOD { - float edge_length; - Vector index_data; - }; - Vector lods; - Vector bone_aabbs; - - Vector> blend_shapes; - - RID material; - }; - - virtual RID mesh_create_from_surfaces(const Vector &p_surfaces) = 0; - virtual RID mesh_create() = 0; - - virtual uint32_t mesh_surface_get_format_offset(uint32_t p_format, int p_vertex_len, int p_index_len, int p_array_index) const; - virtual uint32_t mesh_surface_get_format_stride(uint32_t p_format, int p_vertex_len, int p_index_len) const; - /// Returns stride - virtual uint32_t mesh_surface_make_offsets_from_format(uint32_t p_format, int p_vertex_len, int p_index_len, uint32_t *r_offsets) const; - virtual Error mesh_create_surface_data_from_arrays(SurfaceData *r_surface_data, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT); - Array mesh_create_arrays_from_surface_data(const SurfaceData &p_data) const; - Array mesh_surface_get_arrays(RID p_mesh, int p_surface) const; - Array mesh_surface_get_blend_shape_arrays(RID p_mesh, int p_surface) const; - Dictionary mesh_surface_get_lods(RID p_mesh, int p_surface) const; - - virtual void mesh_add_surface_from_arrays(RID p_mesh, PrimitiveType p_primitive, const Array &p_arrays, const Array &p_blend_shapes = Array(), const Dictionary &p_lods = Dictionary(), uint32_t p_compress_format = ARRAY_COMPRESS_DEFAULT); - virtual void mesh_add_surface(RID p_mesh, const SurfaceData &p_surface) = 0; - - virtual int mesh_get_blend_shape_count(RID p_mesh) const = 0; - - enum BlendShapeMode { - BLEND_SHAPE_MODE_NORMALIZED, - BLEND_SHAPE_MODE_RELATIVE, - }; - - virtual void mesh_set_blend_shape_mode(RID p_mesh, BlendShapeMode p_mode) = 0; - virtual BlendShapeMode mesh_get_blend_shape_mode(RID p_mesh) const = 0; - - virtual void mesh_surface_update_region(RID p_mesh, int p_surface, int p_offset, const Vector &p_data) = 0; - - virtual void mesh_surface_set_material(RID p_mesh, int p_surface, RID p_material) = 0; - virtual RID mesh_surface_get_material(RID p_mesh, int p_surface) const = 0; - - virtual SurfaceData mesh_get_surface(RID p_mesh, int p_surface) const = 0; - - virtual int mesh_get_surface_count(RID p_mesh) const = 0; - - virtual void mesh_set_custom_aabb(RID p_mesh, const AABB &p_aabb) = 0; - virtual AABB mesh_get_custom_aabb(RID p_mesh) const = 0; - - virtual void mesh_clear(RID p_mesh) = 0; - - /* MULTIMESH API */ - - virtual RID multimesh_create() = 0; - - enum MultimeshTransformFormat { - MULTIMESH_TRANSFORM_2D, - MULTIMESH_TRANSFORM_3D, - }; - - virtual void multimesh_allocate(RID p_multimesh, int p_instances, MultimeshTransformFormat p_transform_format, bool p_use_colors = false, bool p_use_custom_data = false) = 0; - virtual int multimesh_get_instance_count(RID p_multimesh) const = 0; - - virtual void multimesh_set_mesh(RID p_multimesh, RID p_mesh) = 0; - virtual void multimesh_instance_set_transform(RID p_multimesh, int p_index, const Transform &p_transform) = 0; - virtual void multimesh_instance_set_transform_2d(RID p_multimesh, int p_index, const Transform2D &p_transform) = 0; - virtual void multimesh_instance_set_color(RID p_multimesh, int p_index, const Color &p_color) = 0; - virtual void multimesh_instance_set_custom_data(RID p_multimesh, int p_index, const Color &p_color) = 0; - - virtual RID multimesh_get_mesh(RID p_multimesh) const = 0; - virtual AABB multimesh_get_aabb(RID p_multimesh) const = 0; - - virtual Transform multimesh_instance_get_transform(RID p_multimesh, int p_index) const = 0; - virtual Transform2D multimesh_instance_get_transform_2d(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_color(RID p_multimesh, int p_index) const = 0; - virtual Color multimesh_instance_get_custom_data(RID p_multimesh, int p_index) const = 0; - - virtual void multimesh_set_buffer(RID p_multimesh, const Vector &p_buffer) = 0; - virtual Vector multimesh_get_buffer(RID p_multimesh) const = 0; - - virtual void multimesh_set_visible_instances(RID p_multimesh, int p_visible) = 0; - virtual int multimesh_get_visible_instances(RID p_multimesh) const = 0; - - /* IMMEDIATE API */ - - virtual RID immediate_create() = 0; - virtual void immediate_begin(RID p_immediate, PrimitiveType p_rimitive, RID p_texture = RID()) = 0; - virtual void immediate_vertex(RID p_immediate, const Vector3 &p_vertex) = 0; - virtual void immediate_vertex_2d(RID p_immediate, const Vector2 &p_vertex); - virtual void immediate_normal(RID p_immediate, const Vector3 &p_normal) = 0; - virtual void immediate_tangent(RID p_immediate, const Plane &p_tangent) = 0; - virtual void immediate_color(RID p_immediate, const Color &p_color) = 0; - virtual void immediate_uv(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_uv2(RID p_immediate, const Vector2 &tex_uv) = 0; - virtual void immediate_end(RID p_immediate) = 0; - virtual void immediate_clear(RID p_immediate) = 0; - virtual void immediate_set_material(RID p_immediate, RID p_material) = 0; - virtual RID immediate_get_material(RID p_immediate) const = 0; - - /* SKELETON API */ - - virtual RID skeleton_create() = 0; - virtual void skeleton_allocate(RID p_skeleton, int p_bones, bool p_2d_skeleton = false) = 0; - virtual int skeleton_get_bone_count(RID p_skeleton) const = 0; - virtual void skeleton_bone_set_transform(RID p_skeleton, int p_bone, const Transform &p_transform) = 0; - virtual Transform skeleton_bone_get_transform(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_bone_set_transform_2d(RID p_skeleton, int p_bone, const Transform2D &p_transform) = 0; - virtual Transform2D skeleton_bone_get_transform_2d(RID p_skeleton, int p_bone) const = 0; - virtual void skeleton_set_base_transform_2d(RID p_skeleton, const Transform2D &p_base_transform) = 0; - - /* Light API */ - - enum LightType { - LIGHT_DIRECTIONAL, - LIGHT_OMNI, - LIGHT_SPOT - }; - - enum LightParam { - - LIGHT_PARAM_ENERGY, - LIGHT_PARAM_INDIRECT_ENERGY, - LIGHT_PARAM_SPECULAR, - LIGHT_PARAM_RANGE, - LIGHT_PARAM_ATTENUATION, - LIGHT_PARAM_SPOT_ANGLE, - LIGHT_PARAM_SPOT_ATTENUATION, - LIGHT_PARAM_CONTACT_SHADOW_SIZE, - LIGHT_PARAM_SHADOW_MAX_DISTANCE, - LIGHT_PARAM_SHADOW_SPLIT_1_OFFSET, - LIGHT_PARAM_SHADOW_SPLIT_2_OFFSET, - LIGHT_PARAM_SHADOW_SPLIT_3_OFFSET, - LIGHT_PARAM_SHADOW_FADE_START, - LIGHT_PARAM_SHADOW_NORMAL_BIAS, - LIGHT_PARAM_SHADOW_BIAS, - LIGHT_PARAM_SHADOW_BIAS_SPLIT_SCALE, - LIGHT_PARAM_MAX - }; - - virtual RID directional_light_create() = 0; - virtual RID omni_light_create() = 0; - virtual RID spot_light_create() = 0; - - virtual void light_set_color(RID p_light, const Color &p_color) = 0; - virtual void light_set_param(RID p_light, LightParam p_param, float p_value) = 0; - virtual void light_set_shadow(RID p_light, bool p_enabled) = 0; - virtual void light_set_shadow_color(RID p_light, const Color &p_color) = 0; - virtual void light_set_projector(RID p_light, RID p_texture) = 0; - virtual void light_set_negative(RID p_light, bool p_enable) = 0; - virtual void light_set_cull_mask(RID p_light, uint32_t p_mask) = 0; - virtual void light_set_reverse_cull_face_mode(RID p_light, bool p_enabled) = 0; - virtual void light_set_use_gi(RID p_light, bool p_enable) = 0; - - // omni light - enum LightOmniShadowMode { - LIGHT_OMNI_SHADOW_DUAL_PARABOLOID, - LIGHT_OMNI_SHADOW_CUBE, - }; - - virtual void light_omni_set_shadow_mode(RID p_light, LightOmniShadowMode p_mode) = 0; - - // directional light - enum LightDirectionalShadowMode { - LIGHT_DIRECTIONAL_SHADOW_ORTHOGONAL, - LIGHT_DIRECTIONAL_SHADOW_PARALLEL_2_SPLITS, - LIGHT_DIRECTIONAL_SHADOW_PARALLEL_4_SPLITS - }; - - virtual void light_directional_set_shadow_mode(RID p_light, LightDirectionalShadowMode p_mode) = 0; - virtual void light_directional_set_blend_splits(RID p_light, bool p_enable) = 0; - - enum LightDirectionalShadowDepthRangeMode { - LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_STABLE, - LIGHT_DIRECTIONAL_SHADOW_DEPTH_RANGE_OPTIMIZED, - - }; - - virtual void light_directional_set_shadow_depth_range_mode(RID p_light, LightDirectionalShadowDepthRangeMode p_range_mode) = 0; - - /* PROBE API */ - - virtual RID reflection_probe_create() = 0; - - enum ReflectionProbeUpdateMode { - REFLECTION_PROBE_UPDATE_ONCE, - REFLECTION_PROBE_UPDATE_ALWAYS, - }; - - virtual void reflection_probe_set_update_mode(RID p_probe, ReflectionProbeUpdateMode p_mode) = 0; - virtual void reflection_probe_set_intensity(RID p_probe, float p_intensity) = 0; - virtual void reflection_probe_set_interior_ambient(RID p_probe, const Color &p_color) = 0; - virtual void reflection_probe_set_interior_ambient_energy(RID p_probe, float p_energy) = 0; - virtual void reflection_probe_set_interior_ambient_probe_contribution(RID p_probe, float p_contrib) = 0; - virtual void reflection_probe_set_max_distance(RID p_probe, float p_distance) = 0; - virtual void reflection_probe_set_extents(RID p_probe, const Vector3 &p_extents) = 0; - virtual void reflection_probe_set_origin_offset(RID p_probe, const Vector3 &p_offset) = 0; - virtual void reflection_probe_set_as_interior(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_enable_box_projection(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_enable_shadows(RID p_probe, bool p_enable) = 0; - virtual void reflection_probe_set_cull_mask(RID p_probe, uint32_t p_layers) = 0; - virtual void reflection_probe_set_resolution(RID p_probe, int p_resolution) = 0; - - /* GI PROBE API */ - - virtual RID gi_probe_create() = 0; - - virtual void gi_probe_allocate(RID p_gi_probe, const Transform &p_to_cell_xform, const AABB &p_aabb, const Vector3i &p_octree_size, const Vector &p_octree_cells, const Vector &p_data_cells, const Vector &p_distance_field, const Vector &p_level_counts) = 0; - - virtual AABB gi_probe_get_bounds(RID p_gi_probe) const = 0; - virtual Vector3i gi_probe_get_octree_size(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_octree_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_data_cells(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_distance_field(RID p_gi_probe) const = 0; - virtual Vector gi_probe_get_level_counts(RID p_gi_probe) const = 0; - virtual Transform gi_probe_get_to_cell_xform(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_dynamic_range(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_dynamic_range(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_propagation(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_propagation(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_energy(RID p_gi_probe, float p_energy) = 0; - virtual float gi_probe_get_energy(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_ao(RID p_gi_probe, float p_ao) = 0; - virtual float gi_probe_get_ao(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_ao_size(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_ao_size(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_bias(RID p_gi_probe, float p_bias) = 0; - virtual float gi_probe_get_bias(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_normal_bias(RID p_gi_probe, float p_range) = 0; - virtual float gi_probe_get_normal_bias(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_interior(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_interior(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_use_two_bounces(RID p_gi_probe, bool p_enable) = 0; - virtual bool gi_probe_is_using_two_bounces(RID p_gi_probe) const = 0; - - virtual void gi_probe_set_anisotropy_strength(RID p_gi_probe, float p_strength) = 0; - virtual float gi_probe_get_anisotropy_strength(RID p_gi_probe) const = 0; - - /* LIGHTMAP CAPTURE */ - - virtual RID lightmap_capture_create() = 0; - virtual void lightmap_capture_set_bounds(RID p_capture, const AABB &p_bounds) = 0; - virtual AABB lightmap_capture_get_bounds(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree(RID p_capture, const Vector &p_octree) = 0; - virtual void lightmap_capture_set_octree_cell_transform(RID p_capture, const Transform &p_xform) = 0; - virtual Transform lightmap_capture_get_octree_cell_transform(RID p_capture) const = 0; - virtual void lightmap_capture_set_octree_cell_subdiv(RID p_capture, int p_subdiv) = 0; - virtual int lightmap_capture_get_octree_cell_subdiv(RID p_capture) const = 0; - virtual Vector lightmap_capture_get_octree(RID p_capture) const = 0; - virtual void lightmap_capture_set_energy(RID p_capture, float p_energy) = 0; - virtual float lightmap_capture_get_energy(RID p_capture) const = 0; - - /* PARTICLES API */ - - virtual RID particles_create() = 0; - - virtual void particles_set_emitting(RID p_particles, bool p_emitting) = 0; - virtual bool particles_get_emitting(RID p_particles) = 0; - virtual void particles_set_amount(RID p_particles, int p_amount) = 0; - virtual void particles_set_lifetime(RID p_particles, float p_lifetime) = 0; - virtual void particles_set_one_shot(RID p_particles, bool p_one_shot) = 0; - virtual void particles_set_pre_process_time(RID p_particles, float p_time) = 0; - virtual void particles_set_explosiveness_ratio(RID p_particles, float p_ratio) = 0; - virtual void particles_set_randomness_ratio(RID p_particles, float p_ratio) = 0; - virtual void particles_set_custom_aabb(RID p_particles, const AABB &p_aabb) = 0; - virtual void particles_set_speed_scale(RID p_particles, float p_scale) = 0; - virtual void particles_set_use_local_coordinates(RID p_particles, bool p_enable) = 0; - virtual void particles_set_process_material(RID p_particles, RID p_material) = 0; - virtual void particles_set_fixed_fps(RID p_particles, int p_fps) = 0; - virtual void particles_set_fractional_delta(RID p_particles, bool p_enable) = 0; - virtual bool particles_is_inactive(RID p_particles) = 0; - virtual void particles_request_process(RID p_particles) = 0; - virtual void particles_restart(RID p_particles) = 0; - - enum ParticlesDrawOrder { - PARTICLES_DRAW_ORDER_INDEX, - PARTICLES_DRAW_ORDER_LIFETIME, - PARTICLES_DRAW_ORDER_VIEW_DEPTH, - }; - - virtual void particles_set_draw_order(RID p_particles, ParticlesDrawOrder p_order) = 0; - - virtual void particles_set_draw_passes(RID p_particles, int p_count) = 0; - virtual void particles_set_draw_pass_mesh(RID p_particles, int p_pass, RID p_mesh) = 0; - - virtual AABB particles_get_current_aabb(RID p_particles) = 0; - - virtual void particles_set_emission_transform(RID p_particles, const Transform &p_transform) = 0; //this is only used for 2D, in 3D it's automatic - - /* CAMERA API */ - - virtual RID camera_create() = 0; - virtual void camera_set_perspective(RID p_camera, float p_fovy_degrees, float p_z_near, float p_z_far) = 0; - virtual void camera_set_orthogonal(RID p_camera, float p_size, float p_z_near, float p_z_far) = 0; - virtual void camera_set_frustum(RID p_camera, float p_size, Vector2 p_offset, float p_z_near, float p_z_far) = 0; - virtual void camera_set_transform(RID p_camera, const Transform &p_transform) = 0; - virtual void camera_set_cull_mask(RID p_camera, uint32_t p_layers) = 0; - virtual void camera_set_environment(RID p_camera, RID p_env) = 0; - virtual void camera_set_camera_effects(RID p_camera, RID p_camera_effects) = 0; - virtual void camera_set_use_vertical_aspect(RID p_camera, bool p_enable) = 0; - - /* - enum ParticlesCollisionMode { - PARTICLES_COLLISION_NONE, - PARTICLES_COLLISION_TEXTURE, - PARTICLES_COLLISION_CUBEMAP, - }; - - virtual void particles_set_collision(RID p_particles,ParticlesCollisionMode p_mode,const Transform&, p_xform,const RID p_depth_tex,const RID p_normal_tex)=0; -*/ - /* VIEWPORT TARGET API */ - - virtual RID viewport_create() = 0; - - virtual void viewport_set_use_arvr(RID p_viewport, bool p_use_arvr) = 0; - virtual void viewport_set_size(RID p_viewport, int p_width, int p_height) = 0; - virtual void viewport_set_active(RID p_viewport, bool p_active) = 0; - virtual void viewport_set_parent_viewport(RID p_viewport, RID p_parent_viewport) = 0; - - virtual void viewport_attach_to_screen(RID p_viewport, const Rect2 &p_rect = Rect2(), DisplayServer::WindowID p_screen = DisplayServer::MAIN_WINDOW_ID) = 0; - virtual void viewport_set_render_direct_to_screen(RID p_viewport, bool p_enable) = 0; - - enum ViewportUpdateMode { - VIEWPORT_UPDATE_DISABLED, - VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated - VIEWPORT_UPDATE_WHEN_VISIBLE, // default - VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE, - VIEWPORT_UPDATE_ALWAYS - }; - - virtual void viewport_set_update_mode(RID p_viewport, ViewportUpdateMode p_mode) = 0; - - enum ViewportClearMode { - - VIEWPORT_CLEAR_ALWAYS, - VIEWPORT_CLEAR_NEVER, - VIEWPORT_CLEAR_ONLY_NEXT_FRAME - }; - - virtual void viewport_set_clear_mode(RID p_viewport, ViewportClearMode p_clear_mode) = 0; - - virtual RID viewport_get_texture(RID p_viewport) const = 0; - - virtual void viewport_set_hide_scenario(RID p_viewport, bool p_hide) = 0; - virtual void viewport_set_hide_canvas(RID p_viewport, bool p_hide) = 0; - virtual void viewport_set_disable_environment(RID p_viewport, bool p_disable) = 0; - - virtual void viewport_attach_camera(RID p_viewport, RID p_camera) = 0; - virtual void viewport_set_scenario(RID p_viewport, RID p_scenario) = 0; - virtual void viewport_attach_canvas(RID p_viewport, RID p_canvas) = 0; - virtual void viewport_remove_canvas(RID p_viewport, RID p_canvas) = 0; - virtual void viewport_set_canvas_transform(RID p_viewport, RID p_canvas, const Transform2D &p_offset) = 0; - virtual void viewport_set_transparent_background(RID p_viewport, bool p_enabled) = 0; - - virtual void viewport_set_global_canvas_transform(RID p_viewport, const Transform2D &p_transform) = 0; - virtual void viewport_set_canvas_stacking(RID p_viewport, RID p_canvas, int p_layer, int p_sublayer) = 0; - - virtual void viewport_set_shadow_atlas_size(RID p_viewport, int p_size) = 0; - virtual void viewport_set_shadow_atlas_quadrant_subdivision(RID p_viewport, int p_quadrant, int p_subdiv) = 0; - - enum ViewportMSAA { - VIEWPORT_MSAA_DISABLED, - VIEWPORT_MSAA_2X, - VIEWPORT_MSAA_4X, - VIEWPORT_MSAA_8X, - VIEWPORT_MSAA_16X, - VIEWPORT_MSAA_EXT_2X, - VIEWPORT_MSAA_EXT_4X, - }; - - virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0; - - enum ViewportRenderInfo { - - VIEWPORT_RENDER_INFO_OBJECTS_IN_FRAME, - VIEWPORT_RENDER_INFO_VERTICES_IN_FRAME, - VIEWPORT_RENDER_INFO_MATERIAL_CHANGES_IN_FRAME, - VIEWPORT_RENDER_INFO_SHADER_CHANGES_IN_FRAME, - VIEWPORT_RENDER_INFO_SURFACE_CHANGES_IN_FRAME, - VIEWPORT_RENDER_INFO_DRAW_CALLS_IN_FRAME, - VIEWPORT_RENDER_INFO_MAX - }; - - virtual int viewport_get_render_info(RID p_viewport, ViewportRenderInfo p_info) = 0; - - enum ViewportDebugDraw { - VIEWPORT_DEBUG_DRAW_DISABLED, - VIEWPORT_DEBUG_DRAW_UNSHADED, - VIEWPORT_DEBUG_DRAW_LIGHTING, - VIEWPORT_DEBUG_DRAW_OVERDRAW, - VIEWPORT_DEBUG_DRAW_WIREFRAME, - VIEWPORT_DEBUG_DRAW_NORMAL_BUFFER, - VIEWPORT_DEBUG_DRAW_GI_PROBE_ALBEDO, - VIEWPORT_DEBUG_DRAW_GI_PROBE_LIGHTING, - VIEWPORT_DEBUG_DRAW_GI_PROBE_EMISSION, - VIEWPORT_DEBUG_DRAW_SHADOW_ATLAS, - VIEWPORT_DEBUG_DRAW_DIRECTIONAL_SHADOW_ATLAS, - VIEWPORT_DEBUG_DRAW_SCENE_LUMINANCE, - VIEWPORT_DEBUG_DRAW_SSAO, - VIEWPORT_DEBUG_DRAW_ROUGHNESS_LIMITER, - - }; - - virtual void viewport_set_debug_draw(RID p_viewport, ViewportDebugDraw p_draw) = 0; - - virtual void directional_shadow_atlas_set_size(int p_size) = 0; - - /* SKY API */ - - enum SkyMode { - SKY_MODE_QUALITY, - SKY_MODE_REALTIME - }; - - virtual RID sky_create() = 0; - virtual void sky_set_radiance_size(RID p_sky, int p_radiance_size) = 0; - virtual void sky_set_mode(RID p_sky, SkyMode p_mode) = 0; - virtual void sky_set_material(RID p_sky, RID p_material) = 0; - - /* ENVIRONMENT API */ - - virtual RID environment_create() = 0; - - enum EnvironmentBG { - - ENV_BG_CLEAR_COLOR, - ENV_BG_COLOR, - ENV_BG_SKY, - ENV_BG_CANVAS, - ENV_BG_KEEP, - ENV_BG_CAMERA_FEED, - ENV_BG_MAX - }; - - enum EnvironmentAmbientSource { - ENV_AMBIENT_SOURCE_BG, - ENV_AMBIENT_SOURCE_DISABLED, - ENV_AMBIENT_SOURCE_COLOR, - ENV_AMBIENT_SOURCE_SKY, - }; - - enum EnvironmentReflectionSource { - ENV_REFLECTION_SOURCE_BG, - ENV_REFLECTION_SOURCE_DISABLED, - ENV_REFLECTION_SOURCE_SKY, - }; - - virtual void environment_set_background(RID p_env, EnvironmentBG p_bg) = 0; - virtual void environment_set_sky(RID p_env, RID p_sky) = 0; - virtual void environment_set_sky_custom_fov(RID p_env, float p_scale) = 0; - virtual void environment_set_sky_orientation(RID p_env, const Basis &p_orientation) = 0; - virtual void environment_set_bg_color(RID p_env, const Color &p_color) = 0; - virtual void environment_set_bg_energy(RID p_env, float p_energy) = 0; - virtual void environment_set_canvas_max_layer(RID p_env, int p_max_layer) = 0; - virtual void environment_set_ambient_light(RID p_env, const Color &p_color, EnvironmentAmbientSource p_ambient = ENV_AMBIENT_SOURCE_BG, float p_energy = 1.0, float p_sky_contribution = 0.0, EnvironmentReflectionSource p_reflection_source = ENV_REFLECTION_SOURCE_BG, const Color &p_ao_color = Color()) = 0; -// FIXME: Disabled during Vulkan refactoring, should be ported. -#if 0 - virtual void environment_set_camera_feed_id(RID p_env, int p_camera_feed_id) = 0; -#endif - - enum EnvironmentGlowBlendMode { - ENV_GLOW_BLEND_MODE_ADDITIVE, - ENV_GLOW_BLEND_MODE_SCREEN, - ENV_GLOW_BLEND_MODE_SOFTLIGHT, - ENV_GLOW_BLEND_MODE_REPLACE, - ENV_GLOW_BLEND_MODE_MIX, - }; - virtual void environment_set_glow(RID p_env, bool p_enable, int p_level_flags, float p_intensity, float p_strength, float p_mix, float p_bloom_threshold, EnvironmentGlowBlendMode p_blend_mode, float p_hdr_bleed_threshold, float p_hdr_bleed_scale, float p_hdr_luminance_cap, bool p_bicubic_upscale) = 0; - - enum EnvironmentToneMapper { - ENV_TONE_MAPPER_LINEAR, - ENV_TONE_MAPPER_REINHARD, - ENV_TONE_MAPPER_FILMIC, - ENV_TONE_MAPPER_ACES - }; - - virtual void environment_set_tonemap(RID p_env, EnvironmentToneMapper p_tone_mapper, float p_exposure, float p_white, bool p_auto_exposure, float p_min_luminance, float p_max_luminance, float p_auto_exp_speed, float p_auto_exp_grey) = 0; - virtual void environment_set_adjustment(RID p_env, bool p_enable, float p_brightness, float p_contrast, float p_saturation, RID p_ramp) = 0; - - virtual void environment_set_ssr(RID p_env, bool p_enable, int p_max_steps, float p_fade_in, float p_fade_out, float p_depth_tolerance, bool p_roughness) = 0; - - enum EnvironmentSSAOBlur { - ENV_SSAO_BLUR_DISABLED, - ENV_SSAO_BLUR_1x1, - ENV_SSAO_BLUR_2x2, - ENV_SSAO_BLUR_3x3, - }; - - virtual void environment_set_ssao(RID p_env, bool p_enable, float p_radius, float p_intensity, float p_bias, float p_light_affect, float p_ao_channel_affect, EnvironmentSSAOBlur p_blur, float p_bilateral_sharpness) = 0; - - enum EnvironmentSSAOQuality { - ENV_SSAO_QUALITY_LOW, - ENV_SSAO_QUALITY_MEDIUM, - ENV_SSAO_QUALITY_HIGH, - ENV_SSAO_QUALITY_ULTRA, - }; - - virtual void environment_set_ssao_quality(EnvironmentSSAOQuality p_quality, bool p_half_size) = 0; - - virtual void environment_set_fog(RID p_env, bool p_enable, const Color &p_color, const Color &p_sun_color, float p_sun_amount) = 0; - virtual void environment_set_fog_depth(RID p_env, bool p_enable, float p_depth_begin, float p_depth_end, float p_depth_curve, bool p_transmit, float p_transmit_curve) = 0; - virtual void environment_set_fog_height(RID p_env, bool p_enable, float p_min_height, float p_max_height, float p_height_curve) = 0; - - virtual void screen_space_roughness_limiter_set_active(bool p_enable, float p_curve) = 0; - - /* CAMERA EFFECTS */ - - virtual RID camera_effects_create() = 0; - - enum DOFBlurQuality { - DOF_BLUR_QUALITY_VERY_LOW, - DOF_BLUR_QUALITY_LOW, - DOF_BLUR_QUALITY_MEDIUM, - DOF_BLUR_QUALITY_HIGH, - }; - - virtual void camera_effects_set_dof_blur_quality(DOFBlurQuality p_quality, bool p_use_jitter) = 0; - - enum DOFBokehShape { - DOF_BOKEH_BOX, - DOF_BOKEH_HEXAGON, - DOF_BOKEH_CIRCLE - }; - - virtual void camera_effects_set_dof_blur_bokeh_shape(DOFBokehShape p_shape) = 0; - - virtual void camera_effects_set_dof_blur(RID p_camera_effects, bool p_far_enable, float p_far_distance, float p_far_transition, bool p_near_enable, float p_near_distance, float p_near_transition, float p_amount) = 0; - virtual void camera_effects_set_custom_exposure(RID p_camera_effects, bool p_enable, float p_exposure) = 0; - - /* SCENARIO API */ - - virtual RID scenario_create() = 0; - - enum ScenarioDebugMode { - SCENARIO_DEBUG_DISABLED, - SCENARIO_DEBUG_WIREFRAME, - SCENARIO_DEBUG_OVERDRAW, - SCENARIO_DEBUG_SHADELESS, - - }; - - virtual void scenario_set_debug(RID p_scenario, ScenarioDebugMode p_debug_mode) = 0; - virtual void scenario_set_environment(RID p_scenario, RID p_environment) = 0; - virtual void scenario_set_fallback_environment(RID p_scenario, RID p_environment) = 0; - virtual void scenario_set_camera_effects(RID p_scenario, RID p_camera_effects) = 0; - - /* INSTANCING API */ - - enum InstanceType { - - INSTANCE_NONE, - INSTANCE_MESH, - INSTANCE_MULTIMESH, - INSTANCE_IMMEDIATE, - INSTANCE_PARTICLES, - INSTANCE_LIGHT, - INSTANCE_REFLECTION_PROBE, - INSTANCE_GI_PROBE, - INSTANCE_LIGHTMAP_CAPTURE, - INSTANCE_MAX, - - INSTANCE_GEOMETRY_MASK = (1 << INSTANCE_MESH) | (1 << INSTANCE_MULTIMESH) | (1 << INSTANCE_IMMEDIATE) | (1 << INSTANCE_PARTICLES) - }; - - virtual RID instance_create2(RID p_base, RID p_scenario); - - virtual RID instance_create() = 0; - - virtual void instance_set_base(RID p_instance, RID p_base) = 0; - virtual void instance_set_scenario(RID p_instance, RID p_scenario) = 0; - virtual void instance_set_layer_mask(RID p_instance, uint32_t p_mask) = 0; - virtual void instance_set_transform(RID p_instance, const Transform &p_transform) = 0; - virtual void instance_attach_object_instance_id(RID p_instance, ObjectID p_id) = 0; - virtual void instance_set_blend_shape_weight(RID p_instance, int p_shape, float p_weight) = 0; - virtual void instance_set_surface_material(RID p_instance, int p_surface, RID p_material) = 0; - virtual void instance_set_visible(RID p_instance, bool p_visible) = 0; - - virtual void instance_set_use_lightmap(RID p_instance, RID p_lightmap_instance, RID p_lightmap) = 0; - - virtual void instance_set_custom_aabb(RID p_instance, AABB aabb) = 0; - - virtual void instance_attach_skeleton(RID p_instance, RID p_skeleton) = 0; - virtual void instance_set_exterior(RID p_instance, bool p_enabled) = 0; - - virtual void instance_set_extra_visibility_margin(RID p_instance, real_t p_margin) = 0; - - // don't use these in a game! - virtual Vector instances_cull_aabb(const AABB &p_aabb, RID p_scenario = RID()) const = 0; - virtual Vector instances_cull_ray(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const = 0; - virtual Vector instances_cull_convex(const Vector &p_convex, RID p_scenario = RID()) const = 0; - - Array _instances_cull_aabb_bind(const AABB &p_aabb, RID p_scenario = RID()) const; - Array _instances_cull_ray_bind(const Vector3 &p_from, const Vector3 &p_to, RID p_scenario = RID()) const; - Array _instances_cull_convex_bind(const Array &p_convex, RID p_scenario = RID()) const; - - enum InstanceFlags { - INSTANCE_FLAG_USE_BAKED_LIGHT, - INSTANCE_FLAG_USE_DYNAMIC_GI, - INSTANCE_FLAG_DRAW_NEXT_FRAME_IF_VISIBLE, - INSTANCE_FLAG_MAX - }; - - enum ShadowCastingSetting { - SHADOW_CASTING_SETTING_OFF, - SHADOW_CASTING_SETTING_ON, - SHADOW_CASTING_SETTING_DOUBLE_SIDED, - SHADOW_CASTING_SETTING_SHADOWS_ONLY, - }; - - virtual void instance_geometry_set_flag(RID p_instance, InstanceFlags p_flags, bool p_enabled) = 0; - virtual void instance_geometry_set_cast_shadows_setting(RID p_instance, ShadowCastingSetting p_shadow_casting_setting) = 0; - virtual void instance_geometry_set_material_override(RID p_instance, RID p_material) = 0; - - virtual void instance_geometry_set_draw_range(RID p_instance, float p_min, float p_max, float p_min_margin, float p_max_margin) = 0; - virtual void instance_geometry_set_as_instance_lod(RID p_instance, RID p_as_lod_of_instance) = 0; - - /* CANVAS (2D) */ - - virtual RID canvas_create() = 0; - virtual void canvas_set_item_mirroring(RID p_canvas, RID p_item, const Point2 &p_mirroring) = 0; - virtual void canvas_set_modulate(RID p_canvas, const Color &p_color) = 0; - virtual void canvas_set_parent(RID p_canvas, RID p_parent, float p_scale) = 0; - - virtual void canvas_set_disable_scale(bool p_disable) = 0; - - virtual RID canvas_item_create() = 0; - virtual void canvas_item_set_parent(RID p_item, RID p_parent) = 0; - - virtual void canvas_item_set_visible(RID p_item, bool p_visible) = 0; - virtual void canvas_item_set_light_mask(RID p_item, int p_mask) = 0; - - virtual void canvas_item_set_update_when_visible(RID p_item, bool p_update) = 0; - - virtual void canvas_item_set_transform(RID p_item, const Transform2D &p_transform) = 0; - virtual void canvas_item_set_clip(RID p_item, bool p_clip) = 0; - virtual void canvas_item_set_distance_field_mode(RID p_item, bool p_enable) = 0; - virtual void canvas_item_set_custom_rect(RID p_item, bool p_custom_rect, const Rect2 &p_rect = Rect2()) = 0; - virtual void canvas_item_set_modulate(RID p_item, const Color &p_color) = 0; - virtual void canvas_item_set_self_modulate(RID p_item, const Color &p_color) = 0; - - virtual void canvas_item_set_draw_behind_parent(RID p_item, bool p_enable) = 0; - - enum NinePatchAxisMode { - NINE_PATCH_STRETCH, - NINE_PATCH_TILE, - NINE_PATCH_TILE_FIT, - }; - - enum CanvasItemTextureFilter { - CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item - CANVAS_ITEM_TEXTURE_FILTER_NEAREST, - CANVAS_ITEM_TEXTURE_FILTER_LINEAR, - CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, - CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, - CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, - CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, - CANVAS_ITEM_TEXTURE_FILTER_MAX - }; - - enum CanvasItemTextureRepeat { - CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT, //uses canvas item setting for draw command, uses global setting for canvas item - CANVAS_ITEM_TEXTURE_REPEAT_DISABLED, - CANVAS_ITEM_TEXTURE_REPEAT_ENABLED, - CANVAS_ITEM_TEXTURE_REPEAT_MIRROR, - CANVAS_ITEM_TEXTURE_REPEAT_MAX, - }; - - //takes effect only for new draw commands - virtual void canvas_item_set_default_texture_filter(RID p_item, CanvasItemTextureFilter p_filter) = 0; - virtual void canvas_item_set_default_texture_repeat(RID p_item, CanvasItemTextureRepeat p_repeat) = 0; - - virtual void canvas_item_add_line(RID p_item, const Point2 &p_from, const Point2 &p_to, const Color &p_color, float p_width = 1.0) = 0; - virtual void canvas_item_add_polyline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0) = 0; - virtual void canvas_item_add_multiline(RID p_item, const Vector &p_points, const Vector &p_colors, float p_width = 1.0) = 0; - virtual void canvas_item_add_rect(RID p_item, const Rect2 &p_rect, const Color &p_color) = 0; - virtual void canvas_item_add_circle(RID p_item, const Point2 &p_pos, float p_radius, const Color &p_color) = 0; - virtual void canvas_item_add_texture_rect(RID p_item, const Rect2 &p_rect, RID p_texture, bool p_tile = false, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_texture_rect_region(RID p_item, const Rect2 &p_rect, RID p_texture, const Rect2 &p_src_rect, const Color &p_modulate = Color(1, 1, 1), bool p_transpose = false, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), bool p_clip_uv = false, CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_nine_patch(RID p_item, const Rect2 &p_rect, const Rect2 &p_source, RID p_texture, const Vector2 &p_topleft, const Vector2 &p_bottomright, NinePatchAxisMode p_x_axis_mode = NINE_PATCH_STRETCH, NinePatchAxisMode p_y_axis_mode = NINE_PATCH_STRETCH, bool p_draw_center = true, const Color &p_modulate = Color(1, 1, 1), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_primitive(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs, RID p_texture, float p_width = 1.0, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_polygon(RID p_item, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_triangle_array(RID p_item, const Vector &p_indices, const Vector &p_points, const Vector &p_colors, const Vector &p_uvs = Vector(), const Vector &p_bones = Vector(), const Vector &p_weights = Vector(), RID p_texture = RID(), int p_count = -1, RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_mesh(RID p_item, const RID &p_mesh, const Transform2D &p_transform = Transform2D(), const Color &p_modulate = Color(1, 1, 1), RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_multimesh(RID p_item, RID p_mesh, RID p_texture = RID(), RID p_normal_map = RID(), RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_particles(RID p_item, RID p_particles, RID p_texture, RID p_normal_map, RID p_specular_map = RID(), const Color &p_specular_color_shininess = Color(), CanvasItemTextureFilter p_texture_filter = CANVAS_ITEM_TEXTURE_FILTER_DEFAULT, CanvasItemTextureRepeat = CANVAS_ITEM_TEXTURE_REPEAT_DEFAULT) = 0; - virtual void canvas_item_add_set_transform(RID p_item, const Transform2D &p_transform) = 0; - virtual void canvas_item_add_clip_ignore(RID p_item, bool p_ignore) = 0; - virtual void canvas_item_set_sort_children_by_y(RID p_item, bool p_enable) = 0; - virtual void canvas_item_set_z_index(RID p_item, int p_z) = 0; - virtual void canvas_item_set_z_as_relative_to_parent(RID p_item, bool p_enable) = 0; - virtual void canvas_item_set_copy_to_backbuffer(RID p_item, bool p_enable, const Rect2 &p_rect) = 0; - - virtual void canvas_item_attach_skeleton(RID p_item, RID p_skeleton) = 0; - - virtual void canvas_item_clear(RID p_item) = 0; - virtual void canvas_item_set_draw_index(RID p_item, int p_index) = 0; - - virtual void canvas_item_set_material(RID p_item, RID p_material) = 0; - - virtual void canvas_item_set_use_parent_material(RID p_item, bool p_enable) = 0; - - virtual RID canvas_light_create() = 0; - virtual void canvas_light_attach_to_canvas(RID p_light, RID p_canvas) = 0; - virtual void canvas_light_set_enabled(RID p_light, bool p_enabled) = 0; - virtual void canvas_light_set_scale(RID p_light, float p_scale) = 0; - virtual void canvas_light_set_transform(RID p_light, const Transform2D &p_transform) = 0; - virtual void canvas_light_set_texture(RID p_light, RID p_texture) = 0; - virtual void canvas_light_set_texture_offset(RID p_light, const Vector2 &p_offset) = 0; - virtual void canvas_light_set_color(RID p_light, const Color &p_color) = 0; - virtual void canvas_light_set_height(RID p_light, float p_height) = 0; - virtual void canvas_light_set_energy(RID p_light, float p_energy) = 0; - virtual void canvas_light_set_z_range(RID p_light, int p_min_z, int p_max_z) = 0; - virtual void canvas_light_set_layer_range(RID p_light, int p_min_layer, int p_max_layer) = 0; - virtual void canvas_light_set_item_cull_mask(RID p_light, int p_mask) = 0; - virtual void canvas_light_set_item_shadow_cull_mask(RID p_light, int p_mask) = 0; - - enum CanvasLightMode { - CANVAS_LIGHT_MODE_ADD, - CANVAS_LIGHT_MODE_SUB, - CANVAS_LIGHT_MODE_MIX, - CANVAS_LIGHT_MODE_MASK, - }; - - virtual void canvas_light_set_mode(RID p_light, CanvasLightMode p_mode) = 0; - - enum CanvasLightShadowFilter { - CANVAS_LIGHT_FILTER_NONE, - CANVAS_LIGHT_FILTER_PCF5, - CANVAS_LIGHT_FILTER_PCF13, - CANVAS_LIGHT_FILTER_MAX - }; - - virtual void canvas_light_set_shadow_enabled(RID p_light, bool p_enabled) = 0; - virtual void canvas_light_set_shadow_buffer_size(RID p_light, int p_size) = 0; - virtual void canvas_light_set_shadow_filter(RID p_light, CanvasLightShadowFilter p_filter) = 0; - virtual void canvas_light_set_shadow_color(RID p_light, const Color &p_color) = 0; - virtual void canvas_light_set_shadow_smooth(RID p_light, float p_smooth) = 0; - - virtual RID canvas_light_occluder_create() = 0; - virtual void canvas_light_occluder_attach_to_canvas(RID p_occluder, RID p_canvas) = 0; - virtual void canvas_light_occluder_set_enabled(RID p_occluder, bool p_enabled) = 0; - virtual void canvas_light_occluder_set_polygon(RID p_occluder, RID p_polygon) = 0; - virtual void canvas_light_occluder_set_transform(RID p_occluder, const Transform2D &p_xform) = 0; - virtual void canvas_light_occluder_set_light_mask(RID p_occluder, int p_mask) = 0; - - virtual RID canvas_occluder_polygon_create() = 0; - virtual void canvas_occluder_polygon_set_shape(RID p_occluder_polygon, const Vector &p_shape, bool p_closed) = 0; - virtual void canvas_occluder_polygon_set_shape_as_lines(RID p_occluder_polygon, const Vector &p_shape) = 0; - - enum CanvasOccluderPolygonCullMode { - CANVAS_OCCLUDER_POLYGON_CULL_DISABLED, - CANVAS_OCCLUDER_POLYGON_CULL_CLOCKWISE, - CANVAS_OCCLUDER_POLYGON_CULL_COUNTER_CLOCKWISE, - }; - virtual void canvas_occluder_polygon_set_cull_mode(RID p_occluder_polygon, CanvasOccluderPolygonCullMode p_mode) = 0; - - /* BLACK BARS */ - - virtual void black_bars_set_margins(int p_left, int p_top, int p_right, int p_bottom) = 0; - virtual void black_bars_set_images(RID p_left, RID p_top, RID p_right, RID p_bottom) = 0; - - /* FREE */ - - virtual void free(RID p_rid) = 0; ///< free RIDs associated with the visual server - - virtual void request_frame_drawn_callback(Object *p_where, const StringName &p_method, const Variant &p_userdata) = 0; - - /* EVENT QUEUING */ - - virtual void draw(bool p_swap_buffers = true, double frame_step = 0.0) = 0; - virtual void sync() = 0; - virtual bool has_changed() const = 0; - virtual void init() = 0; - virtual void finish() = 0; - - /* STATUS INFORMATION */ - - enum RenderInfo { - - INFO_OBJECTS_IN_FRAME, - INFO_VERTICES_IN_FRAME, - INFO_MATERIAL_CHANGES_IN_FRAME, - INFO_SHADER_CHANGES_IN_FRAME, - INFO_SURFACE_CHANGES_IN_FRAME, - INFO_DRAW_CALLS_IN_FRAME, - INFO_USAGE_VIDEO_MEM_TOTAL, - INFO_VIDEO_MEM_USED, - INFO_TEXTURE_MEM_USED, - INFO_VERTEX_MEM_USED, - }; - - virtual int get_render_info(RenderInfo p_info) = 0; - virtual String get_video_adapter_name() const = 0; - virtual String get_video_adapter_vendor() const = 0; - - struct FrameProfileArea { - String name; - float gpu_msec; - float cpu_msec; - }; - - virtual void set_frame_profiling_enabled(bool p_enable) = 0; - virtual Vector get_frame_profile() = 0; - virtual uint64_t get_frame_profile_frame() = 0; - - /* Materials for 2D on 3D */ - - /* TESTING */ - - virtual RID get_test_cube() = 0; - - virtual RID get_test_texture(); - virtual RID get_white_texture(); - - virtual RID make_sphere_mesh(int p_lats, int p_lons, float p_radius); - - virtual void mesh_add_surface_from_mesh_data(RID p_mesh, const Geometry::MeshData &p_mesh_data); - virtual void mesh_add_surface_from_planes(RID p_mesh, const Vector &p_planes); - - virtual void set_boot_image(const Ref &p_image, const Color &p_color, bool p_scale, bool p_use_filter = true) = 0; - virtual void set_default_clear_color(const Color &p_color) = 0; - - enum Features { - FEATURE_SHADERS, - FEATURE_MULTITHREADED, - }; - - virtual bool has_feature(Features p_feature) const = 0; - - virtual bool has_os_feature(const String &p_feature) const = 0; - - virtual void set_debug_generate_wireframes(bool p_generate) = 0; - - virtual void call_set_use_vsync(bool p_enable) = 0; - - virtual bool is_low_end() const = 0; - - VisualServer(); - virtual ~VisualServer(); -}; - -// make variant understand the enums -VARIANT_ENUM_CAST(VisualServer::TextureLayeredType); -VARIANT_ENUM_CAST(VisualServer::CubeMapLayer); -VARIANT_ENUM_CAST(VisualServer::ShaderMode); -VARIANT_ENUM_CAST(VisualServer::ArrayType); -VARIANT_ENUM_CAST(VisualServer::ArrayFormat); -VARIANT_ENUM_CAST(VisualServer::PrimitiveType); -VARIANT_ENUM_CAST(VisualServer::BlendShapeMode); -VARIANT_ENUM_CAST(VisualServer::MultimeshTransformFormat); -VARIANT_ENUM_CAST(VisualServer::LightType); -VARIANT_ENUM_CAST(VisualServer::LightParam); -VARIANT_ENUM_CAST(VisualServer::LightOmniShadowMode); -VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowMode); -VARIANT_ENUM_CAST(VisualServer::LightDirectionalShadowDepthRangeMode); -VARIANT_ENUM_CAST(VisualServer::ReflectionProbeUpdateMode); -VARIANT_ENUM_CAST(VisualServer::ParticlesDrawOrder); -VARIANT_ENUM_CAST(VisualServer::ViewportUpdateMode); -VARIANT_ENUM_CAST(VisualServer::ViewportClearMode); -VARIANT_ENUM_CAST(VisualServer::ViewportMSAA); -VARIANT_ENUM_CAST(VisualServer::ViewportRenderInfo); -VARIANT_ENUM_CAST(VisualServer::ViewportDebugDraw); -VARIANT_ENUM_CAST(VisualServer::SkyMode); -VARIANT_ENUM_CAST(VisualServer::EnvironmentBG); -VARIANT_ENUM_CAST(VisualServer::EnvironmentAmbientSource); -VARIANT_ENUM_CAST(VisualServer::EnvironmentReflectionSource); -VARIANT_ENUM_CAST(VisualServer::EnvironmentGlowBlendMode); -VARIANT_ENUM_CAST(VisualServer::EnvironmentToneMapper); -VARIANT_ENUM_CAST(VisualServer::EnvironmentSSAOQuality); -VARIANT_ENUM_CAST(VisualServer::EnvironmentSSAOBlur); -VARIANT_ENUM_CAST(VisualServer::DOFBlurQuality); -VARIANT_ENUM_CAST(VisualServer::DOFBokehShape); -VARIANT_ENUM_CAST(VisualServer::ScenarioDebugMode); -VARIANT_ENUM_CAST(VisualServer::InstanceType); -VARIANT_ENUM_CAST(VisualServer::InstanceFlags); -VARIANT_ENUM_CAST(VisualServer::ShadowCastingSetting); -VARIANT_ENUM_CAST(VisualServer::NinePatchAxisMode); -VARIANT_ENUM_CAST(VisualServer::CanvasItemTextureFilter); -VARIANT_ENUM_CAST(VisualServer::CanvasItemTextureRepeat); -VARIANT_ENUM_CAST(VisualServer::CanvasLightMode); -VARIANT_ENUM_CAST(VisualServer::CanvasLightShadowFilter); -VARIANT_ENUM_CAST(VisualServer::CanvasOccluderPolygonCullMode); -VARIANT_ENUM_CAST(VisualServer::RenderInfo); -VARIANT_ENUM_CAST(VisualServer::Features); - -//typedef VisualServer VS; // makes it easier to use -#define VS VisualServer - -#endif -- cgit v1.2.3