Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYimingWu <xp8110@outlook.com>2020-06-04 13:57:28 +0300
committerYimingWu <xp8110@outlook.com>2020-06-04 13:57:28 +0300
commitbfbf0bb7f7a0191b65fc724d5dfea225e6293c6b (patch)
tree042f37d28c9e1cf0ce5a0fb4fd4235288f62d36e
parent3b52dfe549f0c2fca7e0cd499b85fb098e9b4da9 (diff)
parent78017916f7c7a8ec8907c9b993214ff8ec3c3557 (diff)
Merge remote-tracking branch 'origin/master' into temp-lanpr-reviewtemp-lanpr-review
# Conflicts: # release/datafiles/locale # release/scripts/addons
-rw-r--r--build_files/build_environment/cmake/harvest.cmake8
-rw-r--r--build_files/build_environment/cmake/jpeg.cmake15
-rw-r--r--build_files/build_environment/cmake/openimageio.cmake64
-rw-r--r--build_files/build_environment/cmake/png.cmake2
-rw-r--r--build_files/build_environment/cmake/versions.cmake44
-rw-r--r--build_files/build_environment/patches/openimageio.diff36
-rw-r--r--build_files/build_environment/patches/openimageio_gdi.diff26
-rw-r--r--build_files/build_environment/patches/openimageio_static_libs.diff22
-rw-r--r--build_files/build_environment/patches/osl.diff19
-rw-r--r--build_files/cmake/platform/platform_win32.cmake2
-rw-r--r--doc/python_api/examples/gpu.1.py20
-rw-r--r--doc/python_api/examples/gpu.10.py76
-rw-r--r--doc/python_api/examples/gpu.11.py65
-rw-r--r--doc/python_api/examples/gpu.2.py38
-rw-r--r--doc/python_api/examples/gpu.3.py44
-rw-r--r--doc/python_api/examples/gpu.4.py39
-rw-r--r--doc/python_api/examples/gpu.5.py37
-rw-r--r--doc/python_api/examples/gpu.6.py31
-rw-r--r--doc/python_api/examples/gpu.7.py77
-rw-r--r--doc/python_api/examples/gpu.8.py92
-rw-r--r--doc/python_api/examples/gpu.9.py61
-rwxr-xr-xdoc/python_api/sphinx_doc_update.py2
-rw-r--r--intern/cycles/blender/addon/properties.py7
-rw-r--r--intern/cycles/blender/addon/ui.py24
-rw-r--r--intern/cycles/blender/blender_object.cpp6
-rw-r--r--intern/cycles/kernel/bvh/bvh.h8
-rw-r--r--intern/cycles/kernel/closure/bsdf.h32
-rw-r--r--intern/cycles/kernel/kernel_camera.h16
-rw-r--r--intern/cycles/kernel/kernel_light.h8
-rw-r--r--intern/cycles/kernel/kernel_passes.h2
-rw-r--r--intern/cycles/kernel/kernel_types.h3
-rw-r--r--intern/cycles/render/light.cpp22
-rw-r--r--intern/cycles/render/light.h5
-rw-r--r--intern/cycles/render/object.cpp2
-rw-r--r--intern/cycles/render/object.h1
-rw-r--r--intern/cycles/util/util_guarded_allocator.h1
-rw-r--r--intern/ghost/intern/GHOST_SystemWayland.cpp3
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.cpp9
-rw-r--r--intern/ghost/intern/GHOST_WindowWayland.h3
-rw-r--r--intern/opencolorio/ocio_impl_glsl.cc17
-rw-r--r--release/scripts/modules/bl_app_template_utils.py22
-rw-r--r--release/scripts/presets/keyconfig/keymap_data/blender_default.py22
-rw-r--r--release/scripts/startup/bl_operators/sequencer.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_output.py10
-rw-r--r--release/scripts/startup/bl_ui/properties_paint_common.py2
-rw-r--r--release/scripts/startup/bl_ui/properties_physics_fluid.py2
-rw-r--r--release/scripts/startup/bl_ui/space_sequencer.py57
-rw-r--r--release/scripts/startup/bl_ui/space_toolsystem_toolbar.py20
-rw-r--r--release/scripts/startup/bl_ui/space_userpref.py4
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py1
-rw-r--r--source/blender/blenkernel/BKE_bvhutils.h37
-rw-r--r--source/blender/blenkernel/BKE_collection.h4
-rw-r--r--source/blender/blenkernel/BKE_gpencil.h4
-rw-r--r--source/blender/blenkernel/BKE_paint.h1
-rw-r--r--source/blender/blenkernel/BKE_pbvh.h93
-rw-r--r--source/blender/blenkernel/intern/blender.c4
-rw-r--r--source/blender/blenkernel/intern/brush.c2
-rw-r--r--source/blender/blenkernel/intern/bvhutils.c433
-rw-r--r--source/blender/blenkernel/intern/collection.c34
-rw-r--r--source/blender/blenkernel/intern/gpencil.c17
-rw-r--r--source/blender/blenkernel/intern/lib_override.c12
-rw-r--r--source/blender/blenkernel/intern/mesh_remap.c2
-rw-r--r--source/blender/blenkernel/intern/mesh_runtime.c6
-rw-r--r--source/blender/blenkernel/intern/pbvh.c786
-rw-r--r--source/blender/blenkernel/intern/pbvh_bmesh.c437
-rw-r--r--source/blender/blenkernel/intern/scene.c1
-rw-r--r--source/blender/blenkernel/intern/seqprefetch.c7
-rw-r--r--source/blender/blenkernel/intern/studiolight.c4
-rw-r--r--source/blender/blenkernel/intern/unit.c111
-rw-r--r--source/blender/blenloader/BLO_undofile.h26
-rw-r--r--source/blender/blenloader/intern/readfile.c1
-rw-r--r--source/blender/blenloader/intern/undofile.c49
-rw-r--r--source/blender/blenloader/intern/versioning_290.c2
-rw-r--r--source/blender/blenloader/intern/versioning_defaults.c3
-rw-r--r--source/blender/blenloader/intern/writefile.c68
-rw-r--r--source/blender/bmesh/intern/bmesh_marking.c2
-rw-r--r--source/blender/depsgraph/intern/builder/deg_builder_relations.cc10
-rw-r--r--source/blender/draw/CMakeLists.txt5
-rw-r--r--source/blender/draw/engines/basic/basic_engine.c25
-rw-r--r--source/blender/draw/engines/basic/shaders/depth_frag.glsl (renamed from source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl)0
-rw-r--r--source/blender/draw/engines/basic/shaders/depth_vert.glsl (renamed from source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl)4
-rw-r--r--source/blender/draw/engines/eevee/eevee_data.c15
-rw-r--r--source/blender/draw/engines/eevee/eevee_depth_of_field.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_effects.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_engine.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightcache.c8
-rw-r--r--source/blender/draw/engines/eevee/eevee_lightprobes.c91
-rw-r--r--source/blender/draw/engines/eevee/eevee_lookdev.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_lut_gen.c198
-rw-r--r--source/blender/draw/engines/eevee/eevee_materials.c2352
-rw-r--r--source/blender/draw/engines/eevee/eevee_mist.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_occlusion.c12
-rw-r--r--source/blender/draw/engines/eevee/eevee_private.h170
-rw-r--r--source/blender/draw/engines/eevee/eevee_render.c16
-rw-r--r--source/blender/draw/engines/eevee/eevee_renderpasses.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_screen_raytrace.c6
-rw-r--r--source/blender/draw/engines/eevee/eevee_shaders.c488
-rw-r--r--source/blender/draw/engines/eevee/eevee_shadows.c44
-rw-r--r--source/blender/draw/engines/eevee/eevee_subsurface.c133
-rw-r--r--source/blender/draw/engines/eevee/eevee_temporal_sampling.c3
-rw-r--r--source/blender/draw/engines/eevee/eevee_volumes.c33
-rw-r--r--source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl10
-rw-r--r--source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl8
-rw-r--r--source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl2
-rw-r--r--source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl27
-rw-r--r--source/blender/draw/engines/eevee/shaders/prepass_frag.glsl21
-rw-r--r--source/blender/draw/engines/external/external_engine.c18
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_antialiasing.c5
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_cache_utils.c2
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.c7
-rw-r--r--source/blender/draw/engines/gpencil/gpencil_engine.h2
-rw-r--r--source/blender/draw/engines/overlay/overlay_armature.c24
-rw-r--r--source/blender/draw/engines/overlay/overlay_extra.c24
-rw-r--r--source/blender/draw/engines/overlay/overlay_facing.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_gpencil.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_motion_path.c4
-rw-r--r--source/blender/draw/engines/overlay/overlay_outline.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_particle.c8
-rw-r--r--source/blender/draw/engines/overlay/overlay_pointcloud.c2
-rw-r--r--source/blender/draw/engines/overlay/overlay_wireframe.c8
-rw-r--r--source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl1
-rw-r--r--source/blender/draw/engines/workbench/workbench_effect_antialiasing.c5
-rw-r--r--source/blender/draw/engines/workbench/workbench_materials.c6
-rw-r--r--source/blender/draw/engines/workbench/workbench_opaque.c16
-rw-r--r--source/blender/draw/engines/workbench/workbench_shader.c33
-rw-r--r--source/blender/draw/engines/workbench/workbench_transparent.c12
-rw-r--r--source/blender/draw/intern/DRW_render.h28
-rw-r--r--source/blender/draw/intern/draw_cache.c6
-rw-r--r--source/blender/draw/intern/draw_cache_extract.h5
-rw-r--r--source/blender/draw/intern/draw_cache_extract_mesh.c501
-rw-r--r--source/blender/draw/intern/draw_cache_impl.h4
-rw-r--r--source/blender/draw/intern/draw_cache_impl_gpencil.c11
-rw-r--r--source/blender/draw/intern/draw_cache_impl_mesh.c25
-rw-r--r--source/blender/draw/intern/draw_common.h12
-rw-r--r--source/blender/draw/intern/draw_hair.c53
-rw-r--r--source/blender/draw/intern/draw_manager.c55
-rw-r--r--source/blender/draw/intern/draw_manager.h53
-rw-r--r--source/blender/draw/intern/draw_manager_data.c218
-rw-r--r--source/blender/draw/intern/draw_manager_exec.c244
-rw-r--r--source/blender/draw/intern/draw_manager_shader.c25
-rw-r--r--source/blender/draw/intern/draw_manager_texture.c4
-rw-r--r--source/blender/editors/animation/anim_draw.c61
-rw-r--r--source/blender/editors/animation/keyframing.c4
-rw-r--r--source/blender/editors/curve/editfont_undo.c2
-rw-r--r--source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c24
-rw-r--r--source/blender/editors/gpencil/annotate_paint.c46
-rw-r--r--source/blender/editors/gpencil/gpencil_edit.c26
-rw-r--r--source/blender/editors/gpencil/gpencil_paint.c13
-rw-r--r--source/blender/editors/gpencil/gpencil_select.c118
-rw-r--r--source/blender/editors/gpencil/gpencil_utils.c7
-rw-r--r--source/blender/editors/include/ED_anim_api.h3
-rw-r--r--source/blender/editors/include/ED_object.h11
-rw-r--r--source/blender/editors/include/ED_transform.h25
-rw-r--r--source/blender/editors/include/UI_interface.h6
-rw-r--r--source/blender/editors/interface/interface_eyedropper_color.c34
-rw-r--r--source/blender/editors/interface/interface_icons.c10
-rw-r--r--source/blender/editors/interface/interface_templates.c13
-rw-r--r--source/blender/editors/io/io_alembic.c2
-rw-r--r--source/blender/editors/mask/mask_draw.c2
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c1
-rw-r--r--source/blender/editors/mesh/editmesh_loopcut.c23
-rw-r--r--source/blender/editors/object/object_edit.c85
-rw-r--r--source/blender/editors/object/object_modes.c82
-rw-r--r--source/blender/editors/object/object_relations.c18
-rw-r--r--source/blender/editors/physics/particle_edit.c4
-rw-r--r--source/blender/editors/physics/particle_edit_undo.c2
-rw-r--r--source/blender/editors/screen/glutil.c4
-rw-r--r--source/blender/editors/screen/workspace_edit.c5
-rw-r--r--source/blender/editors/sculpt_paint/paint_cursor.c14
-rw-r--r--source/blender/editors/sculpt_paint/paint_image.c22
-rw-r--r--source/blender/editors/sculpt_paint/paint_intern.h5
-rw-r--r--source/blender/editors/sculpt_paint/paint_stroke.c18
-rw-r--r--source/blender/editors/sculpt_paint/paint_vertex.c34
-rw-r--r--source/blender/editors/sculpt_paint/sculpt.c14
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_automasking.c2
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_cloth.c324
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_filter_mesh.c6
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_intern.h10
-rw-r--r--source/blender/editors/sculpt_paint/sculpt_pose.c128
-rw-r--r--source/blender/editors/space_action/action_edit.c2
-rw-r--r--source/blender/editors/space_buttons/buttons_texture.c2
-rw-r--r--source/blender/editors/space_graph/graph_edit.c2
-rw-r--r--source/blender/editors/space_image/image_draw.c6
-rw-r--r--source/blender/editors/space_image/image_undo.c2
-rw-r--r--source/blender/editors/space_nla/nla_edit.c2
-rw-r--r--source/blender/editors/space_node/drawnode.c2
-rw-r--r--source/blender/editors/space_outliner/outliner_tree.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_draw.c4
-rw-r--r--source/blender/editors/space_sequencer/sequencer_edit.c52
-rw-r--r--source/blender/editors/space_sequencer/sequencer_intern.h1
-rw-r--r--source/blender/editors/space_sequencer/sequencer_select.c25
-rw-r--r--source/blender/editors/space_userpref/userpref_ops.c69
-rw-r--r--source/blender/editors/space_view3d/view3d_buttons.c2
-rw-r--r--source/blender/editors/space_view3d/view3d_edit.c6
-rw-r--r--source/blender/editors/transform/transform.c64
-rw-r--r--source/blender/editors/transform/transform.h85
-rw-r--r--source/blender/editors/transform/transform_constraints.c24
-rw-r--r--source/blender/editors/transform/transform_constraints.h2
-rw-r--r--source/blender/editors/transform/transform_convert.c8
-rw-r--r--source/blender/editors/transform/transform_generics.c33
-rw-r--r--source/blender/editors/transform/transform_gizmo_3d.c95
-rw-r--r--source/blender/editors/transform/transform_mode_align.c4
-rw-r--r--source/blender/editors/transform/transform_mode_baketime.c4
-rw-r--r--source/blender/editors/transform/transform_mode_bbone_resize.c4
-rw-r--r--source/blender/editors/transform/transform_mode_bend.c4
-rw-r--r--source/blender/editors/transform/transform_mode_boneenvelope.c4
-rw-r--r--source/blender/editors/transform/transform_mode_boneroll.c4
-rw-r--r--source/blender/editors/transform/transform_mode_curveshrinkfatten.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_bevelweight.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_crease.c4
-rw-r--r--source/blender/editors/transform/transform_mode_edge_seq_slide.c4
-rw-r--r--source/blender/editors/transform/transform_mode_gpopacity.c4
-rw-r--r--source/blender/editors/transform/transform_mode_gpshrinkfatten.c4
-rw-r--r--source/blender/editors/transform/transform_mode_maskshrinkfatten.c8
-rw-r--r--source/blender/editors/transform/transform_mode_mirror.c8
-rw-r--r--source/blender/editors/transform/transform_mode_push_pull.c4
-rw-r--r--source/blender/editors/transform/transform_mode_resize.c4
-rw-r--r--source/blender/editors/transform/transform_mode_rotate.c4
-rw-r--r--source/blender/editors/transform/transform_mode_shear.c5
-rw-r--r--source/blender/editors/transform/transform_mode_shrink_fatten.c4
-rw-r--r--source/blender/editors/transform/transform_mode_skin_resize.c5
-rw-r--r--source/blender/editors/transform/transform_mode_tilt.c4
-rw-r--r--source/blender/editors/transform/transform_mode_tosphere.c4
-rw-r--r--source/blender/editors/transform/transform_mode_trackball.c4
-rw-r--r--source/blender/editors/transform/transform_mode_translate.c4
-rw-r--r--source/blender/editors/transform/transform_orientations.c203
-rw-r--r--source/blender/editors/transform/transform_snap.c10
-rw-r--r--source/blender/editors/transform/transform_snap_object.c344
-rw-r--r--source/blender/editors/util/ed_util.c6
-rw-r--r--source/blender/editors/uvedit/uvedit_draw.c18
-rw-r--r--source/blender/editors/uvedit/uvedit_ops.c137
-rw-r--r--source/blender/gpu/GPU_draw.h2
-rw-r--r--source/blender/gpu/GPU_material.h14
-rw-r--r--source/blender/gpu/GPU_shader.h7
-rw-r--r--source/blender/gpu/GPU_shader_interface.h37
-rw-r--r--source/blender/gpu/GPU_texture.h28
-rw-r--r--source/blender/gpu/GPU_vertex_format.h5
-rw-r--r--source/blender/gpu/intern/gpu_batch.c6
-rw-r--r--source/blender/gpu/intern/gpu_codegen.c2
-rw-r--r--source/blender/gpu/intern/gpu_draw.c39
-rw-r--r--source/blender/gpu/intern/gpu_extensions.c2
-rw-r--r--source/blender/gpu/intern/gpu_immediate.c39
-rw-r--r--source/blender/gpu/intern/gpu_material.c8
-rw-r--r--source/blender/gpu/intern/gpu_node_graph.c30
-rw-r--r--source/blender/gpu/intern/gpu_shader.c52
-rw-r--r--source/blender/gpu/intern/gpu_shader_interface.c454
-rw-r--r--source/blender/gpu/intern/gpu_texture.c232
-rw-r--r--source/blender/gpu/intern/gpu_vertex_format.c89
-rw-r--r--source/blender/gpu/intern/gpu_viewport.c2
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl10
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl7
-rw-r--r--source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl168
-rw-r--r--source/blender/makesdna/DNA_brush_types.h1
-rw-r--r--source/blender/makesdna/DNA_mesh_types.h5
-rw-r--r--source/blender/makesdna/DNA_scene_types.h2
-rw-r--r--source/blender/makesrna/RNA_define.h1
-rw-r--r--source/blender/makesrna/intern/makesrna.c34
-rw-r--r--source/blender/makesrna/intern/rna_brush.c5
-rw-r--r--source/blender/makesrna/intern/rna_camera.c16
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c138
-rw-r--r--source/blender/makesrna/intern/rna_define.c206
-rw-r--r--source/blender/makesrna/intern/rna_fluid.c5
-rw-r--r--source/blender/makesrna/intern/rna_internal.h9
-rw-r--r--source/blender/makesrna/intern/rna_light.c60
-rw-r--r--source/blender/makesrna/intern/rna_modifier.c242
-rw-r--r--source/blender/makesrna/intern/rna_render.c2
-rw-r--r--source/blender/makesrna/intern/rna_scene.c4
-rw-r--r--source/blender/makesrna/intern/rna_sequencer.c2
-rw-r--r--source/blender/makesrna/intern/rna_ui_api.c17
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c2
-rw-r--r--source/blender/modifiers/intern/MOD_skin.c8
-rw-r--r--source/blender/modifiers/intern/MOD_weld.c14
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_output_material.c13
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_environment.c56
-rw-r--r--source/blender/nodes/shader/nodes/node_shader_tex_image.c165
-rw-r--r--source/blender/python/gpu/gpu_py_shader.c4
-rw-r--r--source/blender/python/intern/bpy_app_handlers.c12
-rw-r--r--source/blender/python/intern/bpy_rna_callback.c8
-rw-r--r--source/blender/windowmanager/WM_api.h14
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c2
-rw-r--r--source/blender/windowmanager/intern/wm_draw.c6
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c30
-rw-r--r--source/blender/windowmanager/intern/wm_files.c273
-rw-r--r--source/blender/windowmanager/intern/wm_gesture.c2
-rw-r--r--source/blender/windowmanager/intern/wm_init_exit.c2
-rw-r--r--source/blender/windowmanager/intern/wm_operators.c18
-rw-r--r--source/blender/windowmanager/intern/wm_window.c84
-rw-r--r--source/blender/windowmanager/wm_files.h2
m---------source/tools0
290 files changed, 7131 insertions, 6599 deletions
diff --git a/build_files/build_environment/cmake/harvest.cmake b/build_files/build_environment/cmake/harvest.cmake
index d05a06c9518..9acafe8f8e6 100644
--- a/build_files/build_environment/cmake/harvest.cmake
+++ b/build_files/build_environment/cmake/harvest.cmake
@@ -31,10 +31,6 @@ if(BUILD_MODE STREQUAL Release)
COMMAND # jpeg rename libfile + copy include
${CMAKE_COMMAND} -E copy ${LIBDIR}/jpg/lib/jpeg-static.lib ${HARVEST_TARGET}/jpeg/lib/libjpeg.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/jpg/include/ ${HARVEST_TARGET}/jpeg/include/ &&
- # OpenImageIO
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/include ${HARVEST_TARGET}/OpenImageIO/include &&
- ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/lib ${HARVEST_TARGET}/OpenImageIO/lib &&
- ${CMAKE_COMMAND} -E copy ${LIBDIR}/OpenImageIO/bin/idiff.exe ${HARVEST_TARGET}/OpenImageIO/bin/idiff.exe &&
# png
${CMAKE_COMMAND} -E copy ${LIBDIR}/png/lib/libpng16_static.lib ${HARVEST_TARGET}/png/lib/libpng.lib &&
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/png/include/ ${HARVEST_TARGET}/png/include/ &&
@@ -55,9 +51,7 @@ endif()
if(BUILD_MODE STREQUAL Debug)
add_custom_target(Harvest_Debug_Results
- # OpenImageIO
- COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_d.lib &&
- ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO_Util.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_Util_d.lib &&
+ COMMAND
# hdf5
${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/hdf5/lib ${HARVEST_TARGET}/hdf5/lib &&
DEPENDS Package_Python
diff --git a/build_files/build_environment/cmake/jpeg.cmake b/build_files/build_environment/cmake/jpeg.cmake
index 0d611219353..e0200d84897 100644
--- a/build_files/build_environment/cmake/jpeg.cmake
+++ b/build_files/build_environment/cmake/jpeg.cmake
@@ -42,20 +42,17 @@ if(WIN32)
set(JPEG_LIBRARY jpeg-staticd${LIBEXT})
endif()
else(WIN32)
- # autoconf for unix
- if(APPLE)
- set(JPEG_EXTRA_ARGS --host x86_64-apple-darwin --with-jpeg8)
- else()
- set(JPEG_EXTRA_ARGS --with-jpeg8)
- endif()
+ # cmake for unix
+ set(JPEG_EXTRA_ARGS
+ -DWITH_JPEG8=ON
+ -DENABLE_STATIC=ON
+ -DENABLE_SHARED=OFF
+ -DCMAKE_INSTALL_LIBDIR=${LIBDIR}/jpg/lib)
ExternalProject_Add(external_jpeg
URL ${JPEG_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${JPEG_HASH}
- CONFIGURE_COMMAND ${CONFIGURE_ENV} && autoreconf -fiv && ${CONFIGURE_COMMAND} --prefix=${LIBDIR}/jpg NASM=yasm ${JPEG_EXTRA_ARGS}
- BUILD_IN_SOURCE 1
- BUILD_COMMAND ${CONFIGURE_ENV} && make install
PREFIX ${BUILD_DIR}/jpg
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/jpg ${DEFAULT_CMAKE_FLAGS} ${JPEG_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/jpg
diff --git a/build_files/build_environment/cmake/openimageio.cmake b/build_files/build_environment/cmake/openimageio.cmake
index 27e04a1f1d1..6ff238468fb 100644
--- a/build_files/build_environment/cmake/openimageio.cmake
+++ b/build_files/build_environment/cmake/openimageio.cmake
@@ -32,7 +32,7 @@ endif()
if(WIN32)
set(PNG_LIBNAME libpng16_static${LIBEXT})
- set(OIIO_SIMD_FLAGS -DUSE_SIMD=sse2 -DOPJ_STATIC=1)
+ set(OIIO_SIMD_FLAGS -DUSE_SIMD=sse2)
set(OPENJPEG_POSTFIX _msvc)
else()
set(PNG_LIBNAME libpng${LIBEXT})
@@ -49,23 +49,17 @@ endif()
if(MSVC)
set(OPENJPEG_FLAGS
- -DOPENJPEG_HOME=${LIBDIR}/openjpeg_msvc
- -DOPENJPEG_INCLUDE_DIR=${LIBDIR}/openjpeg_msvc/include/openjpeg-${OPENJPEG_SHORT_VERSION}
- -DOPENJPEG_LIBRARY=${LIBDIR}/openjpeg_msvc/lib/openjp2${LIBEXT}
- -DOPENJPEG_LIBRARY_DEBUG=${LIBDIR}/openjpeg_msvc/lib/openjp2${LIBEXT}
+ -DOpenJpeg_ROOT=${LIBDIR}/openjpeg_msvc
)
else()
set(OPENJPEG_FLAGS
- -DOPENJPEG_INCLUDE_DIR=${LIBDIR}/openjpeg/include/openjpeg-${OPENJPEG_SHORT_VERSION}
- -DOPENJPEG_LIBRARY=${LIBDIR}/openjpeg/lib/${OPENJPEG_LIBRARY}
+ -DOpenJpeg_ROOT=${LIBDIR}/openjpeg
)
endif()
set(OPENIMAGEIO_EXTRA_ARGS
- -DBUILDSTATIC=ON
+ -DBUILD_SHARED_LIBS=OFF
${OPENIMAGEIO_LINKSTATIC}
- -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/openexr/
- -DOPENEXR_ILMIMF_LIBRARIES=${LIBDIR}/openexr/lib/IlmImf${OPENEXR_VERSION_POSTFIX}${LIBEXT}
-DBoost_COMPILER:STRING=${BOOST_COMPILER_STRING}
-DBoost_USE_MULTITHREADED=ON
-DBoost_USE_STATIC_LIBS=ON
@@ -74,6 +68,14 @@ set(OPENIMAGEIO_EXTRA_ARGS
-DBOOST_LIBRARYDIR=${LIBDIR}/boost/lib/
-DBoost_NO_SYSTEM_PATHS=ON
-OIIO_BUILD_CPP11=ON
+ -DUSE_LIBSQUISH=OFF
+ -DUSE_QT5=OFF
+ -DUSE_NUKE=OFF
+ -DUSE_OPENVDB=OFF
+ -DUSE_BZIP2=OFF
+ -DUSE_FREETYPE=OFF
+ -DUSE_DCMTK=OFF
+ -DUSE_LIBHEIF=OFF
-DUSE_OPENGL=OFF
-DUSE_TBB=OFF
-DUSE_FIELD3D=OFF
@@ -81,15 +83,12 @@ set(OPENIMAGEIO_EXTRA_ARGS
-DUSE_PYTHON=OFF
-DUSE_GIF=OFF
-DUSE_OPENCV=OFF
- -DUSE_OPENSSL=OFF
-DUSE_OPENJPEG=ON
-DUSE_FFMPEG=OFF
-DUSE_PTEX=OFF
-DUSE_FREETYPE=OFF
-DUSE_LIBRAW=OFF
- -DUSE_PYTHON=OFF
- -DUSE_PYTHON3=OFF
- -DUSE_OCIO=OFF
+ -DUSE_OPENCOLORIO=OFF
-DUSE_WEBP=${WITH_WEBP}
-DOIIO_BUILD_TOOLS=${OIIO_TOOLS}
-DOIIO_BUILD_TESTS=OFF
@@ -103,17 +102,13 @@ set(OPENIMAGEIO_EXTRA_ARGS
-DJPEG_LIBRARY=${LIBDIR}/jpg/lib/${JPEG_LIBRARY}
-DJPEG_INCLUDE_DIR=${LIBDIR}/jpg/include
${OPENJPEG_FLAGS}
- -DOCIO_PATH=${LIBDIR}/opencolorio/
-DOpenEXR_USE_STATIC_LIBS=On
- -DOPENEXR_HOME=${LIBDIR}/openexr/
- -DILMBASE_INCLUDE_PATH=${LIBDIR}/openexr/
- -DILMBASE_PACKAGE_PREFIX=${LIBDIR}/openexr/
-DILMBASE_INCLUDE_DIR=${LIBDIR}/openexr/include/
+ -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/
-DOPENEXR_HALF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}Half${OPENEXR_VERSION_POSTFIX}${LIBEXT}
-DOPENEXR_IMATH_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}Imath${OPENEXR_VERSION_POSTFIX}${LIBEXT}
-DOPENEXR_ILMTHREAD_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmThread${OPENEXR_VERSION_POSTFIX}${LIBEXT}
-DOPENEXR_IEX_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}Iex${OPENEXR_VERSION_POSTFIX}${LIBEXT}
- -DOPENEXR_INCLUDE_DIR=${LIBDIR}/openexr/include/
-DOPENEXR_ILMIMF_LIBRARY=${LIBDIR}/openexr/lib/${LIBPREFIX}IlmImf${OPENEXR_VERSION_POSTFIX}${LIBEXT}
-DSTOP_ON_WARNING=OFF
${WEBP_FLAGS}
@@ -125,27 +120,38 @@ ExternalProject_Add(external_openimageio
DOWNLOAD_DIR ${DOWNLOAD_DIR}
URL_HASH MD5=${OPENIMAGEIO_HASH}
PREFIX ${BUILD_DIR}/openimageio
- PATCH_COMMAND
- ${PATCH_CMD} -p 0 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/src/include < ${PATCH_DIR}/openimageio_gdi.diff &&
- ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio_static_libs.diff
+ PATCH_COMMAND ${PATCH_CMD} -p 1 -N -d ${BUILD_DIR}/openimageio/src/external_openimageio/ < ${PATCH_DIR}/openimageio.diff
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/openimageio ${DEFAULT_CMAKE_FLAGS} ${OPENIMAGEIO_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/openimageio
)
add_dependencies(
external_openimageio
- external_png external_zlib
+ external_png
+ external_zlib
external_openexr
external_jpeg
external_boost
external_tiff
- external_opencolorio
external_openjpeg${OPENJPEG_POSTFIX}
${WEBP_DEP}
)
-if(NOT WIN32)
- add_dependencies(
- external_openimageio
- external_opencolorio_extra
- )
+
+if(WIN32)
+ if(BUILD_MODE STREQUAL Release)
+ ExternalProject_Add_Step(external_openimageio after_install
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/include ${HARVEST_TARGET}/OpenImageIO/include
+ COMMAND ${CMAKE_COMMAND} -E copy_directory ${LIBDIR}/OpenImageIO/lib ${HARVEST_TARGET}/OpenImageIO/lib
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/OpenImageIO/bin/idiff.exe ${HARVEST_TARGET}/OpenImageIO/bin/idiff.exe
+
+ DEPENDEES install
+ )
+ endif()
+ if(BUILD_MODE STREQUAL Debug)
+ ExternalProject_Add_Step(external_openimageio after_install
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_d.lib
+ COMMAND ${CMAKE_COMMAND} -E copy ${LIBDIR}/openimageio/lib/OpenImageIO_Util.lib ${HARVEST_TARGET}/openimageio/lib/OpenImageIO_Util_d.lib
+ DEPENDEES install
+ )
+ endif()
endif()
diff --git a/build_files/build_environment/cmake/png.cmake b/build_files/build_environment/cmake/png.cmake
index 2bf32b77ce9..8dd3c25b88b 100644
--- a/build_files/build_environment/cmake/png.cmake
+++ b/build_files/build_environment/cmake/png.cmake
@@ -25,7 +25,7 @@ set(PNG_EXTRA_ARGS
ExternalProject_Add(external_png
URL ${PNG_URI}
DOWNLOAD_DIR ${DOWNLOAD_DIR}
- URL_HASH MD5=${PNG_HASH}
+ URL_HASH SHA256=${PNG_HASH}
PREFIX ${BUILD_DIR}/png
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/png ${DEFAULT_CMAKE_FLAGS} ${PNG_EXTRA_ARGS}
INSTALL_DIR ${LIBDIR}/png
diff --git a/build_files/build_environment/cmake/versions.cmake b/build_files/build_environment/cmake/versions.cmake
index 70c4b0948b3..c1dcf98318c 100644
--- a/build_files/build_environment/cmake/versions.cmake
+++ b/build_files/build_environment/cmake/versions.cmake
@@ -24,13 +24,13 @@ set(OPENAL_VERSION 1.20.1)
set(OPENAL_URI http://openal-soft.org/openal-releases/openal-soft-${OPENAL_VERSION}.tar.bz2)
set(OPENAL_HASH 556695068ce8375b89986083d810fd35)
-set(PNG_VERSION 1.6.35)
+set(PNG_VERSION 1.6.37)
set(PNG_URI http://prdownloads.sourceforge.net/libpng/libpng-${PNG_VERSION}.tar.xz)
-set(PNG_HASH 678b7e696a62a193ed3503b04bf449d6)
+set(PNG_HASH 505e70834d35383537b6491e7ae8641f1a4bed1876dbfe361201fc80868d88ca)
-set(JPEG_VERSION 1.5.3)
+set(JPEG_VERSION 2.0.4)
set(JPEG_URI https://github.com/libjpeg-turbo/libjpeg-turbo/archive/${JPEG_VERSION}.tar.gz)
-set(JPEG_HASH 5b7549d440b86c98a517355c102d155e)
+set(JPEG_HASH 44c43e4a9fb352f47090804529317c88)
set(BOOST_VERSION 1.70.0)
set(BOOST_VERSION_NODOTS 1_70_0)
@@ -113,9 +113,9 @@ set(OPENCOLLADA_VERSION v1.6.68)
set(OPENCOLLADA_URI https://github.com/KhronosGroup/OpenCOLLADA/archive/${OPENCOLLADA_VERSION}.tar.gz)
set(OPENCOLLADA_HASH ee7dae874019fea7be11613d07567493)
-set(OPENCOLORIO_VERSION 1.1.0)
-set(OPENCOLORIO_URI https://github.com/imageworks/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz)
-set(OPENCOLORIO_HASH 802d8f5b1d1fe316ec5f76511aa611b8)
+set(OPENCOLORIO_VERSION 1.1.1)
+set(OPENCOLORIO_URI https://github.com/AcademySoftwareFoundation/OpenColorIO/archive/v${OPENCOLORIO_VERSION}.tar.gz)
+set(OPENCOLORIO_HASH 23d8b9ac81599305539a5a8674b94a3d)
set(LLVM_VERSION 9.0.1)
set(LLVM_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/llvm-${LLVM_VERSION}.src.tar.xz)
@@ -127,17 +127,17 @@ set(CLANG_HASH 13468e4a44940efef1b75e8641752f90)
set(OPENMP_URI https://github.com/llvm/llvm-project/releases/download/llvmorg-${LLVM_VERSION}/openmp-${LLVM_VERSION}.src.tar.xz)
set(OPENMP_HASH 6eade16057edbdecb3c4eef9daa2bfcf)
-set(OPENIMAGEIO_VERSION 1.8.13)
+set(OPENIMAGEIO_VERSION 2.1.15.0)
set(OPENIMAGEIO_URI https://github.com/OpenImageIO/oiio/archive/Release-${OPENIMAGEIO_VERSION}.tar.gz)
-set(OPENIMAGEIO_HASH f5526c3c9878029ee900d84856683f93)
+set(OPENIMAGEIO_HASH f03aa5e3ac4795af04771ee4146e9832)
-set(TIFF_VERSION 4.0.9)
+set(TIFF_VERSION 4.1.0)
set(TIFF_URI http://download.osgeo.org/libtiff/tiff-${TIFF_VERSION}.tar.gz)
-set(TIFF_HASH 54bad211279cc93eb4fca31ba9bfdc79)
+set(TIFF_HASH 2165e7aba557463acc0664e71a3ed424)
-set(OSL_VERSION 1.10.9)
+set(OSL_VERSION 1.10.10)
set(OSL_URI https://github.com/imageworks/OpenShadingLanguage/archive/Release-${OSL_VERSION}.tar.gz)
-set(OSL_HASH a94f1e8506f7e8f5e993653de5c5fa00)
+set(OSL_HASH 00dec08a93c8084e53848b9ad047889f)
set(PYTHON_VERSION 3.7.4)
set(PYTHON_SHORT_VERSION 3.7)
@@ -199,12 +199,10 @@ set(XVIDCORE_VERSION 1.3.7)
set(XVIDCORE_URI https://downloads.xvid.com/downloads/xvidcore-${XVIDCORE_VERSION}.tar.gz)
set(XVIDCORE_HASH abbdcbd39555691dd1c9b4d08f0a031376a3b211652c0d8b3b8aa9be1303ce2d)
-# This has to be in sync with the version in blenders /extern folder.
-set(OPENJPEG_VERSION 2.3.0)
+set(OPENJPEG_VERSION 2.3.1)
set(OPENJPEG_SHORT_VERSION 2.3)
-# Use slightly newer commit after release which includes a cmake fix
-set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/66297f07a43.zip)
-set(OPENJPEG_HASH 8242b18d908c7c42174e4231a741cfa7ce7c26b6ed5c9644feb9df7b3054310b)
+set(OPENJPEG_URI https://github.com/uclouvain/openjpeg/archive/v${OPENJPEG_VERSION}.tar.gz)
+set(OPENJPEG_HASH 63f5a4713ecafc86de51bfad89cc07bb788e9bba24ebbf0c4ca637621aadb6a9)
set(FFMPEG_VERSION 4.2.3)
set(FFMPEG_URI http://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2)
@@ -214,9 +212,9 @@ set(FFTW_VERSION 3.3.8)
set(FFTW_URI http://www.fftw.org/fftw-${FFTW_VERSION}.tar.gz)
set(FFTW_HASH 8aac833c943d8e90d51b697b27d4384d)
-set(ICONV_VERSION 1.15)
+set(ICONV_VERSION 1.16)
set(ICONV_URI http://ftp.gnu.org/pub/gnu/libiconv/libiconv-${ICONV_VERSION}.tar.gz)
-set(ICONV_HASH ace8b5f2db42f7b3b3057585e80d9808)
+set(ICONV_HASH 7d2a800b952942bb2880efb00cfd524c)
set(LAPACK_VERSION 3.6.0)
set(LAPACK_URI http://www.netlib.org/lapack/lapack-${LAPACK_VERSION}.tgz)
@@ -263,9 +261,9 @@ set(LCMS_VERSION 2.9)
set(LCMS_URI https://nchc.dl.sourceforge.net/project/lcms/lcms/${LCMS_VERSION}/lcms2-${LCMS_VERSION}.tar.gz)
set(LCMS_HASH 8de1b7724f578d2995c8fdfa35c3ad0e)
-set(PUGIXML_VERSION 1.9)
-set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v1.9.tar.gz)
-set(PUGIXML_HASH 9346ca1dce2c48f1748c12fdac41a714)
+set(PUGIXML_VERSION 1.10)
+set(PUGIXML_URI https://github.com/zeux/pugixml/archive/v${PUGIXML_VERSION}.tar.gz)
+set(PUGIXML_HASH 0c208b0664c7fb822bf1b49ad035e8fd)
set(FLEXBISON_VERSION 2.5.5)
set(FLEXBISON_URI http://prdownloads.sourceforge.net/winflexbison//win_flex_bison-2.5.5.zip)
diff --git a/build_files/build_environment/patches/openimageio.diff b/build_files/build_environment/patches/openimageio.diff
new file mode 100644
index 00000000000..d05fc1f295f
--- /dev/null
+++ b/build_files/build_environment/patches/openimageio.diff
@@ -0,0 +1,36 @@
+diff -Naur orig/CMakeLists.txt external_openimageio/CMakeLists.txt
+--- orig/CMakeLists.txt 2020-05-10 21:43:52 -0600
++++ external_openimageio/CMakeLists.txt 2020-05-13 17:03:35 -0600
+@@ -170,7 +170,7 @@
+ add_subdirectory (src/iinfo)
+ add_subdirectory (src/maketx)
+ add_subdirectory (src/oiiotool)
+- add_subdirectory (src/testtex)
++ #add_subdirectory (src/testtex)
+ add_subdirectory (src/iv)
+ endif ()
+
+diff -Naur orig/src/cmake/compiler.cmake external_openimageio/src/cmake/compiler.cmake
+--- orig/src/cmake/compiler.cmake 2020-05-10 21:43:52 -0600
++++ external_openimageio/src/cmake/compiler.cmake 2020-05-13 17:02:54 -0600
+@@ -172,6 +172,7 @@
+ add_definitions (-D_CRT_NONSTDC_NO_WARNINGS)
+ add_definitions (-D_SCL_SECURE_NO_WARNINGS)
+ add_definitions (-DJAS_WIN_MSVC_BUILD)
++ add_definitions (-DOPJ_STATIC)
+ endif (MSVC)
+
+ if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD"
+diff -Naur orig/src/include/OpenImageIO/platform.h external_openimageio/src/include/OpenImageIO/platform.h
+--- orig/src/include/OpenImageIO/platform.h 2020-05-10 21:43:52 -0600
++++ external_openimageio/src/include/OpenImageIO/platform.h 2020-05-13 17:04:36 -0600
+@@ -41,6 +41,9 @@
+ # ifndef NOMINMAX
+ # define NOMINMAX
+ # endif
++# ifndef NOGDI
++# define NOGDI
++# endif
+ # include <windows.h>
+ #endif
+
diff --git a/build_files/build_environment/patches/openimageio_gdi.diff b/build_files/build_environment/patches/openimageio_gdi.diff
deleted file mode 100644
index af0c90638de..00000000000
--- a/build_files/build_environment/patches/openimageio_gdi.diff
+++ /dev/null
@@ -1,26 +0,0 @@
-Index: OpenImageIO/osdep.h
-===================================================================
---- OpenImageIO/osdep.h (revision 61595)
-+++ OpenImageIO/osdep.h (working copy)
-@@ -34,6 +34,7 @@
- # define WIN32_LEAN_AND_MEAN
- # define VC_EXTRALEAN
- # define NOMINMAX
-+# define NOGDI
- # include <windows.h>
- #endif
-
-Index: OpenImageIO/platform.h
-===================================================================
---- OpenImageIO/platform.h (revision 61595)
-+++ OpenImageIO/platform.h (working copy)
-@@ -77,6 +77,9 @@
- # ifndef NOMINMAX
- # define NOMINMAX
- # endif
-+# ifndef NOGDI
-+# define NOGDI
-+# endif
- # include <windows.h>
- #endif
-
diff --git a/build_files/build_environment/patches/openimageio_static_libs.diff b/build_files/build_environment/patches/openimageio_static_libs.diff
deleted file mode 100644
index 6a2e58bd139..00000000000
--- a/build_files/build_environment/patches/openimageio_static_libs.diff
+++ /dev/null
@@ -1,22 +0,0 @@
-diff -Naur external_openimageio.orig/src/cmake/compiler.cmake external_openimageio/src/cmake/compiler.cmake
---- external_openimageio.orig/src/cmake/compiler.cmake 2018-07-31 23:45:19 -0600
-+++ external_openimageio/src/cmake/compiler.cmake 2018-08-16 12:50:12 -0600
-@@ -152,6 +152,7 @@
- add_definitions (-D_CRT_NONSTDC_NO_WARNINGS)
- add_definitions (-D_SCL_SECURE_NO_WARNINGS)
- add_definitions (-DJAS_WIN_MSVC_BUILD)
-+ add_definitions (-DOPJ_STATIC)
- endif (MSVC)
-
- # Use ccache if found
---- external_openimageio.orig/CMakeLists.txt 2018-07-31 23:45:19 -0600
-+++ external_openimageio/CMakeLists.txt 2018-08-17 15:22:56 -0600
-@@ -169,7 +169,7 @@
- add_subdirectory (src/iinfo)
- add_subdirectory (src/maketx)
- add_subdirectory (src/oiiotool)
-- add_subdirectory (src/testtex)
-+# add_subdirectory (src/testtex)
- add_subdirectory (src/iv)
- endif ()
-
diff --git a/build_files/build_environment/patches/osl.diff b/build_files/build_environment/patches/osl.diff
index b9b5937ae2b..989800174e2 100644
--- a/build_files/build_environment/patches/osl.diff
+++ b/build_files/build_environment/patches/osl.diff
@@ -48,3 +48,22 @@ diff -Naur OpenShadingLanguage-Release-1.9.9/src/liboslexec/llvm_util.cpp extern
size_t
LLVM_Util::total_jit_memory_held ()
+diff -Naur OpenShadingLanguage-Release-1.9.9/CMakeLists.txt external_osl/CMakeLists.txt
+ --- orig/CMakeLists.txt 2020-01-27 16:22:31 -0700
++++ external_osl/CMakeLists.txt 2020-05-13 18:04:52 -0600
+@@ -102,10 +102,11 @@
+ set (OPTIX_EXTRA_LIBS CACHE STRING "Extra lib targets needed for OptiX")
+ set (CUDA_TARGET_ARCH "sm_35" CACHE STRING "CUDA GPU architecture (e.g. sm_35)")
+
+-# set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static")
+-# if (USE_OIIO_STATIC)
+-# add_definitions ("-DOIIO_STATIC_BUILD=1")
+-# endif ()
++set (USE_OIIO_STATIC ON CACHE BOOL "If OIIO is built static")
++if (USE_OIIO_STATIC)
++ add_definitions ("-DOIIO_STATIC_BUILD=1")
++ add_definitions ("-DOIIO_STATIC_DEFINE=1")
++endif ()
+
+ set (OSL_NO_DEFAULT_TEXTURESYSTEM OFF CACHE BOOL "Do not use create a raw OIIO::TextureSystem")
+ if (OSL_NO_DEFAULT_TEXTURESYSTEM) \ No newline at end of file
diff --git a/build_files/cmake/platform/platform_win32.cmake b/build_files/cmake/platform/platform_win32.cmake
index 57bfe19a5bc..db939b1d00c 100644
--- a/build_files/cmake/platform/platform_win32.cmake
+++ b/build_files/cmake/platform/platform_win32.cmake
@@ -478,7 +478,7 @@ if(WITH_OPENIMAGEIO)
set(OPENIMAGEIO_DEFINITIONS "-DUSE_TBB=0")
set(OPENCOLORIO_DEFINITIONS "-DOCIO_STATIC_BUILD")
set(OPENIMAGEIO_IDIFF "${OPENIMAGEIO}/bin/idiff.exe")
- add_definitions(-DOIIO_STATIC_BUILD)
+ add_definitions(-DOIIO_STATIC_DEFINE)
add_definitions(-DOIIO_NO_SSE=1)
endif()
diff --git a/doc/python_api/examples/gpu.1.py b/doc/python_api/examples/gpu.1.py
index 831349e5430..a014e69c2d2 100644
--- a/doc/python_api/examples/gpu.1.py
+++ b/doc/python_api/examples/gpu.1.py
@@ -119,4 +119,24 @@ Examples
To try these examples, just copy them into Blenders text editor and execute them.
To keep the examples relatively small, they just register a draw function that can't easily be removed anymore.
Blender has to be restarted in order to delete the draw handlers.
+
+3D Lines with Single Color
+--------------------------
"""
+
+import bpy
+import gpu
+from gpu_extras.batch import batch_for_shader
+
+coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
+shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
+batch = batch_for_shader(shader, 'LINES', {"pos": coords})
+
+
+def draw():
+ shader.bind()
+ shader.uniform_float("color", (1, 1, 0, 1))
+ batch.draw(shader)
+
+
+bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
diff --git a/doc/python_api/examples/gpu.10.py b/doc/python_api/examples/gpu.10.py
index a4db576ecc0..2f255b7127d 100644
--- a/doc/python_api/examples/gpu.10.py
+++ b/doc/python_api/examples/gpu.10.py
@@ -1,41 +1,65 @@
"""
-Rendering the 3D View into a Texture
-------------------------------------
+Custom Shader for dotted 3D Line
+--------------------------------
-The scene has to have a camera for this example to work.
-You could also make this independent of a specific camera,
-but Blender does not expose good functions to create view and projection matrices yet.
+In this example the arc length (distance to the first point on the line) is calculated in every vertex.
+Between the vertex and fragment shader that value is automatically interpolated
+for all points that will be visible on the screen.
+In the fragment shader the ``sin`` of the arc length is calculated.
+Based on the result a decision is made on whether the fragment should be drawn or not.
"""
import bpy
-import bgl
import gpu
-from gpu_extras.presets import draw_texture_2d
+from random import random
+from mathutils import Vector
+from gpu_extras.batch import batch_for_shader
-WIDTH = 512
-HEIGHT = 256
+vertex_shader = '''
+ uniform mat4 u_ViewProjectionMatrix;
-offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)
+ in vec3 position;
+ in float arcLength;
+ out float v_ArcLength;
-def draw():
- context = bpy.context
- scene = context.scene
+ void main()
+ {
+ v_ArcLength = arcLength;
+ gl_Position = u_ViewProjectionMatrix * vec4(position, 1.0f);
+ }
+'''
+
+fragment_shader = '''
+ uniform float u_Scale;
+
+ in float v_ArcLength;
- view_matrix = scene.camera.matrix_world.inverted()
+ void main()
+ {
+ if (step(sin(v_ArcLength * u_Scale), 0.5) == 1) discard;
+ gl_FragColor = vec4(1.0);
+ }
+'''
- projection_matrix = scene.camera.calc_matrix_camera(
- context.evaluated_depsgraph_get(), x=WIDTH, y=HEIGHT)
+coords = [Vector((random(), random(), random())) * 5 for _ in range(5)]
- offscreen.draw_view3d(
- scene,
- context.view_layer,
- context.space_data,
- context.region,
- view_matrix,
- projection_matrix)
+arc_lengths = [0]
+for a, b in zip(coords[:-1], coords[1:]):
+ arc_lengths.append(arc_lengths[-1] + (a - b).length)
- bgl.glDisable(bgl.GL_DEPTH_TEST)
- draw_texture_2d(offscreen.color_texture, (10, 10), WIDTH, HEIGHT)
+shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
+batch = batch_for_shader(
+ shader, 'LINE_STRIP',
+ {"position": coords, "arcLength": arc_lengths},
+)
+
+
+def draw():
+ shader.bind()
+ matrix = bpy.context.region_data.perspective_matrix
+ shader.uniform_float("u_ViewProjectionMatrix", matrix)
+ shader.uniform_float("u_Scale", 10)
+ batch.draw(shader)
-bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
+bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
diff --git a/doc/python_api/examples/gpu.11.py b/doc/python_api/examples/gpu.11.py
deleted file mode 100644
index 2f255b7127d..00000000000
--- a/doc/python_api/examples/gpu.11.py
+++ /dev/null
@@ -1,65 +0,0 @@
-"""
-Custom Shader for dotted 3D Line
---------------------------------
-
-In this example the arc length (distance to the first point on the line) is calculated in every vertex.
-Between the vertex and fragment shader that value is automatically interpolated
-for all points that will be visible on the screen.
-In the fragment shader the ``sin`` of the arc length is calculated.
-Based on the result a decision is made on whether the fragment should be drawn or not.
-"""
-import bpy
-import gpu
-from random import random
-from mathutils import Vector
-from gpu_extras.batch import batch_for_shader
-
-vertex_shader = '''
- uniform mat4 u_ViewProjectionMatrix;
-
- in vec3 position;
- in float arcLength;
-
- out float v_ArcLength;
-
- void main()
- {
- v_ArcLength = arcLength;
- gl_Position = u_ViewProjectionMatrix * vec4(position, 1.0f);
- }
-'''
-
-fragment_shader = '''
- uniform float u_Scale;
-
- in float v_ArcLength;
-
- void main()
- {
- if (step(sin(v_ArcLength * u_Scale), 0.5) == 1) discard;
- gl_FragColor = vec4(1.0);
- }
-'''
-
-coords = [Vector((random(), random(), random())) * 5 for _ in range(5)]
-
-arc_lengths = [0]
-for a, b in zip(coords[:-1], coords[1:]):
- arc_lengths.append(arc_lengths[-1] + (a - b).length)
-
-shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
-batch = batch_for_shader(
- shader, 'LINE_STRIP',
- {"position": coords, "arcLength": arc_lengths},
-)
-
-
-def draw():
- shader.bind()
- matrix = bpy.context.region_data.perspective_matrix
- shader.uniform_float("u_ViewProjectionMatrix", matrix)
- shader.uniform_float("u_Scale", 10)
- batch.draw(shader)
-
-
-bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
diff --git a/doc/python_api/examples/gpu.2.py b/doc/python_api/examples/gpu.2.py
index d1e8ac32589..4bee9acebe3 100644
--- a/doc/python_api/examples/gpu.2.py
+++ b/doc/python_api/examples/gpu.2.py
@@ -1,19 +1,45 @@
"""
-3D Lines with Single Color
---------------------------
+Triangle with Custom Shader
+---------------------------
"""
import bpy
import gpu
from gpu_extras.batch import batch_for_shader
-coords = [(1, 1, 1), (-2, 0, 0), (-2, -1, 3), (0, 1, 1)]
-shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
-batch = batch_for_shader(shader, 'LINES', {"pos": coords})
+vertex_shader = '''
+ uniform mat4 viewProjectionMatrix;
+
+ in vec3 position;
+ out vec3 pos;
+
+ void main()
+ {
+ pos = position;
+ gl_Position = viewProjectionMatrix * vec4(position, 1.0f);
+ }
+'''
+
+fragment_shader = '''
+ uniform float brightness;
+
+ in vec3 pos;
+
+ void main()
+ {
+ gl_FragColor = vec4(pos * brightness, 1.0);
+ }
+'''
+
+coords = [(1, 1, 1), (2, 0, 0), (-2, -1, 3)]
+shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
+batch = batch_for_shader(shader, 'TRIS', {"position": coords})
def draw():
shader.bind()
- shader.uniform_float("color", (1, 1, 0, 1))
+ matrix = bpy.context.region_data.perspective_matrix
+ shader.uniform_float("viewProjectionMatrix", matrix)
+ shader.uniform_float("brightness", 0.5)
batch.draw(shader)
diff --git a/doc/python_api/examples/gpu.3.py b/doc/python_api/examples/gpu.3.py
index 4bee9acebe3..0c86b52bcf5 100644
--- a/doc/python_api/examples/gpu.3.py
+++ b/doc/python_api/examples/gpu.3.py
@@ -1,45 +1,29 @@
"""
-Triangle with Custom Shader
----------------------------
+Wireframe Cube using Index Buffer
+---------------------------------
"""
import bpy
import gpu
from gpu_extras.batch import batch_for_shader
-vertex_shader = '''
- uniform mat4 viewProjectionMatrix;
+coords = (
+ (-1, -1, -1), (+1, -1, -1),
+ (-1, +1, -1), (+1, +1, -1),
+ (-1, -1, +1), (+1, -1, +1),
+ (-1, +1, +1), (+1, +1, +1))
- in vec3 position;
- out vec3 pos;
+indices = (
+ (0, 1), (0, 2), (1, 3), (2, 3),
+ (4, 5), (4, 6), (5, 7), (6, 7),
+ (0, 4), (1, 5), (2, 6), (3, 7))
- void main()
- {
- pos = position;
- gl_Position = viewProjectionMatrix * vec4(position, 1.0f);
- }
-'''
-
-fragment_shader = '''
- uniform float brightness;
-
- in vec3 pos;
-
- void main()
- {
- gl_FragColor = vec4(pos * brightness, 1.0);
- }
-'''
-
-coords = [(1, 1, 1), (2, 0, 0), (-2, -1, 3)]
-shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
-batch = batch_for_shader(shader, 'TRIS', {"position": coords})
+shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
+batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)
def draw():
shader.bind()
- matrix = bpy.context.region_data.perspective_matrix
- shader.uniform_float("viewProjectionMatrix", matrix)
- shader.uniform_float("brightness", 0.5)
+ shader.uniform_float("color", (1, 0, 0, 1))
batch.draw(shader)
diff --git a/doc/python_api/examples/gpu.4.py b/doc/python_api/examples/gpu.4.py
index 0c86b52bcf5..e05290a9442 100644
--- a/doc/python_api/examples/gpu.4.py
+++ b/doc/python_api/examples/gpu.4.py
@@ -1,30 +1,39 @@
"""
-Wireframe Cube using Index Buffer
----------------------------------
+Mesh with Random Vertex Colors
+------------------------------
"""
import bpy
import gpu
+import bgl
+import numpy as np
+from random import random
from gpu_extras.batch import batch_for_shader
-coords = (
- (-1, -1, -1), (+1, -1, -1),
- (-1, +1, -1), (+1, +1, -1),
- (-1, -1, +1), (+1, -1, +1),
- (-1, +1, +1), (+1, +1, +1))
+mesh = bpy.context.active_object.data
+mesh.calc_loop_triangles()
-indices = (
- (0, 1), (0, 2), (1, 3), (2, 3),
- (4, 5), (4, 6), (5, 7), (6, 7),
- (0, 4), (1, 5), (2, 6), (3, 7))
+vertices = np.empty((len(mesh.vertices), 3), 'f')
+indices = np.empty((len(mesh.loop_triangles), 3), 'i')
-shader = gpu.shader.from_builtin('3D_UNIFORM_COLOR')
-batch = batch_for_shader(shader, 'LINES', {"pos": coords}, indices=indices)
+mesh.vertices.foreach_get(
+ "co", np.reshape(vertices, len(mesh.vertices) * 3))
+mesh.loop_triangles.foreach_get(
+ "vertices", np.reshape(indices, len(mesh.loop_triangles) * 3))
+
+vertex_colors = [(random(), random(), random(), 1) for _ in range(len(mesh.vertices))]
+
+shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
+batch = batch_for_shader(
+ shader, 'TRIS',
+ {"pos": vertices, "color": vertex_colors},
+ indices=indices,
+)
def draw():
- shader.bind()
- shader.uniform_float("color", (1, 0, 0, 1))
+ bgl.glEnable(bgl.GL_DEPTH_TEST)
batch.draw(shader)
+ bgl.glDisable(bgl.GL_DEPTH_TEST)
bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
diff --git a/doc/python_api/examples/gpu.5.py b/doc/python_api/examples/gpu.5.py
index e05290a9442..2edde46a364 100644
--- a/doc/python_api/examples/gpu.5.py
+++ b/doc/python_api/examples/gpu.5.py
@@ -1,39 +1,26 @@
"""
-Mesh with Random Vertex Colors
-------------------------------
+2D Rectangle
+------------
"""
import bpy
import gpu
-import bgl
-import numpy as np
-from random import random
from gpu_extras.batch import batch_for_shader
-mesh = bpy.context.active_object.data
-mesh.calc_loop_triangles()
+vertices = (
+ (100, 100), (300, 100),
+ (100, 200), (300, 200))
-vertices = np.empty((len(mesh.vertices), 3), 'f')
-indices = np.empty((len(mesh.loop_triangles), 3), 'i')
+indices = (
+ (0, 1, 2), (2, 1, 3))
-mesh.vertices.foreach_get(
- "co", np.reshape(vertices, len(mesh.vertices) * 3))
-mesh.loop_triangles.foreach_get(
- "vertices", np.reshape(indices, len(mesh.loop_triangles) * 3))
-
-vertex_colors = [(random(), random(), random(), 1) for _ in range(len(mesh.vertices))]
-
-shader = gpu.shader.from_builtin('3D_SMOOTH_COLOR')
-batch = batch_for_shader(
- shader, 'TRIS',
- {"pos": vertices, "color": vertex_colors},
- indices=indices,
-)
+shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
+batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices)
def draw():
- bgl.glEnable(bgl.GL_DEPTH_TEST)
+ shader.bind()
+ shader.uniform_float("color", (0, 0.5, 0.5, 1.0))
batch.draw(shader)
- bgl.glDisable(bgl.GL_DEPTH_TEST)
-bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
+bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
diff --git a/doc/python_api/examples/gpu.6.py b/doc/python_api/examples/gpu.6.py
index 2edde46a364..69af65e163e 100644
--- a/doc/python_api/examples/gpu.6.py
+++ b/doc/python_api/examples/gpu.6.py
@@ -1,25 +1,36 @@
"""
-2D Rectangle
-------------
+2D Image
+--------
+
+To use this example you have to provide an image that should be displayed.
"""
import bpy
import gpu
+import bgl
from gpu_extras.batch import batch_for_shader
-vertices = (
- (100, 100), (300, 100),
- (100, 200), (300, 200))
+IMAGE_NAME = "Untitled"
+image = bpy.data.images[IMAGE_NAME]
-indices = (
- (0, 1, 2), (2, 1, 3))
+shader = gpu.shader.from_builtin('2D_IMAGE')
+batch = batch_for_shader(
+ shader, 'TRI_FAN',
+ {
+ "pos": ((100, 100), (200, 100), (200, 200), (100, 200)),
+ "texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)),
+ },
+)
-shader = gpu.shader.from_builtin('2D_UNIFORM_COLOR')
-batch = batch_for_shader(shader, 'TRIS', {"pos": vertices}, indices=indices)
+if image.gl_load():
+ raise Exception()
def draw():
+ bgl.glActiveTexture(bgl.GL_TEXTURE0)
+ bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
+
shader.bind()
- shader.uniform_float("color", (0, 0.5, 0.5, 1.0))
+ shader.uniform_int("image", 0)
batch.draw(shader)
diff --git a/doc/python_api/examples/gpu.7.py b/doc/python_api/examples/gpu.7.py
index 69af65e163e..56cbb93c61a 100644
--- a/doc/python_api/examples/gpu.7.py
+++ b/doc/python_api/examples/gpu.7.py
@@ -1,37 +1,86 @@
"""
-2D Image
---------
+Generate a texture using Offscreen Rendering
+--------------------------------------------
-To use this example you have to provide an image that should be displayed.
+#. Create an :class:`gpu.types.GPUOffScreen` object.
+#. Draw some circles into it.
+#. Make a new shader for drawing a planar texture in 3D.
+#. Draw the generated texture using the new shader.
"""
import bpy
import gpu
import bgl
+from mathutils import Matrix
from gpu_extras.batch import batch_for_shader
+from gpu_extras.presets import draw_circle_2d
-IMAGE_NAME = "Untitled"
-image = bpy.data.images[IMAGE_NAME]
+# Create and fill offscreen
+##########################################
-shader = gpu.shader.from_builtin('2D_IMAGE')
+offscreen = gpu.types.GPUOffScreen(512, 512)
+
+with offscreen.bind():
+ bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
+ with gpu.matrix.push_pop():
+ # reset matrices -> use normalized device coordinates [-1, 1]
+ gpu.matrix.load_matrix(Matrix.Identity(4))
+ gpu.matrix.load_projection_matrix(Matrix.Identity(4))
+
+ amount = 10
+ for i in range(-amount, amount + 1):
+ x_pos = i / amount
+ draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200)
+
+
+# Drawing the generated texture in 3D space
+#############################################
+
+vertex_shader = '''
+ uniform mat4 modelMatrix;
+ uniform mat4 viewProjectionMatrix;
+
+ in vec2 position;
+ in vec2 uv;
+
+ out vec2 uvInterp;
+
+ void main()
+ {
+ uvInterp = uv;
+ gl_Position = viewProjectionMatrix * modelMatrix * vec4(position, 0.0, 1.0);
+ }
+'''
+
+fragment_shader = '''
+ uniform sampler2D image;
+
+ in vec2 uvInterp;
+
+ void main()
+ {
+ gl_FragColor = texture(image, uvInterp);
+ }
+'''
+
+shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
batch = batch_for_shader(
shader, 'TRI_FAN',
{
- "pos": ((100, 100), (200, 100), (200, 200), (100, 200)),
- "texCoord": ((0, 0), (1, 0), (1, 1), (0, 1)),
+ "position": ((-1, -1), (1, -1), (1, 1), (-1, 1)),
+ "uv": ((0, 0), (1, 0), (1, 1), (0, 1)),
},
)
-if image.gl_load():
- raise Exception()
-
def draw():
bgl.glActiveTexture(bgl.GL_TEXTURE0)
- bgl.glBindTexture(bgl.GL_TEXTURE_2D, image.bindcode)
+ bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture)
shader.bind()
- shader.uniform_int("image", 0)
+ shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4))
+ shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix)
+ shader.uniform_float("image", 0)
batch.draw(shader)
-bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
+bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
diff --git a/doc/python_api/examples/gpu.8.py b/doc/python_api/examples/gpu.8.py
index 56cbb93c61a..470bd8a2dad 100644
--- a/doc/python_api/examples/gpu.8.py
+++ b/doc/python_api/examples/gpu.8.py
@@ -1,23 +1,28 @@
"""
-Generate a texture using Offscreen Rendering
---------------------------------------------
+Copy Offscreen Rendering result back to RAM
+-------------------------------------------
-#. Create an :class:`gpu.types.GPUOffScreen` object.
-#. Draw some circles into it.
-#. Make a new shader for drawing a planar texture in 3D.
-#. Draw the generated texture using the new shader.
+This will create a new image with the given name.
+If it already exists, it will override the existing one.
+
+Currently almost all of the execution time is spent in the last line.
+In the future this will hopefully be solved by implementing the Python buffer protocol
+for :class:`bgl.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``).
"""
import bpy
import gpu
import bgl
+import random
from mathutils import Matrix
-from gpu_extras.batch import batch_for_shader
from gpu_extras.presets import draw_circle_2d
-# Create and fill offscreen
-##########################################
+IMAGE_NAME = "Generated Image"
+WIDTH = 512
+HEIGHT = 512
+RING_AMOUNT = 10
+
-offscreen = gpu.types.GPUOffScreen(512, 512)
+offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)
with offscreen.bind():
bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
@@ -26,61 +31,20 @@ with offscreen.bind():
gpu.matrix.load_matrix(Matrix.Identity(4))
gpu.matrix.load_projection_matrix(Matrix.Identity(4))
- amount = 10
- for i in range(-amount, amount + 1):
- x_pos = i / amount
- draw_circle_2d((x_pos, 0.0), (1, 1, 1, 1), 0.5, 200)
-
-
-# Drawing the generated texture in 3D space
-#############################################
-
-vertex_shader = '''
- uniform mat4 modelMatrix;
- uniform mat4 viewProjectionMatrix;
-
- in vec2 position;
- in vec2 uv;
-
- out vec2 uvInterp;
-
- void main()
- {
- uvInterp = uv;
- gl_Position = viewProjectionMatrix * modelMatrix * vec4(position, 0.0, 1.0);
- }
-'''
-
-fragment_shader = '''
- uniform sampler2D image;
-
- in vec2 uvInterp;
-
- void main()
- {
- gl_FragColor = texture(image, uvInterp);
- }
-'''
-
-shader = gpu.types.GPUShader(vertex_shader, fragment_shader)
-batch = batch_for_shader(
- shader, 'TRI_FAN',
- {
- "position": ((-1, -1), (1, -1), (1, 1), (-1, 1)),
- "uv": ((0, 0), (1, 0), (1, 1), (0, 1)),
- },
-)
-
+ for i in range(RING_AMOUNT):
+ draw_circle_2d(
+ (random.uniform(-1, 1), random.uniform(-1, 1)),
+ (1, 1, 1, 1), random.uniform(0.1, 1), 20)
-def draw():
- bgl.glActiveTexture(bgl.GL_TEXTURE0)
- bgl.glBindTexture(bgl.GL_TEXTURE_2D, offscreen.color_texture)
+ buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4)
+ bgl.glReadBuffer(bgl.GL_BACK)
+ bgl.glReadPixels(0, 0, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
- shader.bind()
- shader.uniform_float("modelMatrix", Matrix.Translation((1, 2, 3)) @ Matrix.Scale(3, 4))
- shader.uniform_float("viewProjectionMatrix", bpy.context.region_data.perspective_matrix)
- shader.uniform_float("image", 0)
- batch.draw(shader)
+offscreen.free()
-bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_VIEW')
+if not IMAGE_NAME in bpy.data.images:
+ bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT)
+image = bpy.data.images[IMAGE_NAME]
+image.scale(WIDTH, HEIGHT)
+image.pixels = [v / 255 for v in buffer]
diff --git a/doc/python_api/examples/gpu.9.py b/doc/python_api/examples/gpu.9.py
index 470bd8a2dad..a4db576ecc0 100644
--- a/doc/python_api/examples/gpu.9.py
+++ b/doc/python_api/examples/gpu.9.py
@@ -1,50 +1,41 @@
"""
-Copy Offscreen Rendering result back to RAM
--------------------------------------------
+Rendering the 3D View into a Texture
+------------------------------------
-This will create a new image with the given name.
-If it already exists, it will override the existing one.
-
-Currently almost all of the execution time is spent in the last line.
-In the future this will hopefully be solved by implementing the Python buffer protocol
-for :class:`bgl.Buffer` and :class:`bpy.types.Image.pixels` (aka ``bpy_prop_array``).
+The scene has to have a camera for this example to work.
+You could also make this independent of a specific camera,
+but Blender does not expose good functions to create view and projection matrices yet.
"""
import bpy
-import gpu
import bgl
-import random
-from mathutils import Matrix
-from gpu_extras.presets import draw_circle_2d
+import gpu
+from gpu_extras.presets import draw_texture_2d
-IMAGE_NAME = "Generated Image"
WIDTH = 512
-HEIGHT = 512
-RING_AMOUNT = 10
-
+HEIGHT = 256
offscreen = gpu.types.GPUOffScreen(WIDTH, HEIGHT)
-with offscreen.bind():
- bgl.glClear(bgl.GL_COLOR_BUFFER_BIT)
- with gpu.matrix.push_pop():
- # reset matrices -> use normalized device coordinates [-1, 1]
- gpu.matrix.load_matrix(Matrix.Identity(4))
- gpu.matrix.load_projection_matrix(Matrix.Identity(4))
- for i in range(RING_AMOUNT):
- draw_circle_2d(
- (random.uniform(-1, 1), random.uniform(-1, 1)),
- (1, 1, 1, 1), random.uniform(0.1, 1), 20)
+def draw():
+ context = bpy.context
+ scene = context.scene
+
+ view_matrix = scene.camera.matrix_world.inverted()
+
+ projection_matrix = scene.camera.calc_matrix_camera(
+ context.evaluated_depsgraph_get(), x=WIDTH, y=HEIGHT)
- buffer = bgl.Buffer(bgl.GL_BYTE, WIDTH * HEIGHT * 4)
- bgl.glReadBuffer(bgl.GL_BACK)
- bgl.glReadPixels(0, 0, WIDTH, HEIGHT, bgl.GL_RGBA, bgl.GL_UNSIGNED_BYTE, buffer)
+ offscreen.draw_view3d(
+ scene,
+ context.view_layer,
+ context.space_data,
+ context.region,
+ view_matrix,
+ projection_matrix)
-offscreen.free()
+ bgl.glDisable(bgl.GL_DEPTH_TEST)
+ draw_texture_2d(offscreen.color_texture, (10, 10), WIDTH, HEIGHT)
-if not IMAGE_NAME in bpy.data.images:
- bpy.data.images.new(IMAGE_NAME, WIDTH, HEIGHT)
-image = bpy.data.images[IMAGE_NAME]
-image.scale(WIDTH, HEIGHT)
-image.pixels = [v / 255 for v in buffer]
+bpy.types.SpaceView3D.draw_handler_add(draw, (), 'WINDOW', 'POST_PIXEL')
diff --git a/doc/python_api/sphinx_doc_update.py b/doc/python_api/sphinx_doc_update.py
index 6b24f4c4c09..4495fca9274 100755
--- a/doc/python_api/sphinx_doc_update.py
+++ b/doc/python_api/sphinx_doc_update.py
@@ -128,7 +128,7 @@ def main():
" f.write('%d\\n' % is_beta)\n"
" f.write('%s\\n' % branch)\n"
" f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1]))\n"
- " f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1]))\n"
+ " f.write('%d.%d\\n' % (bpy.app.version[0], bpy.app.version[1])\n"
" if (is_release or is_beta) else '%s\\n' % branch)\n"
" f.write('%d_%d' % (bpy.app.version[0], bpy.app.version[1]))\n"
)
diff --git a/intern/cycles/blender/addon/properties.py b/intern/cycles/blender/addon/properties.py
index c91e210bbd8..da18ac7c693 100644
--- a/intern/cycles/blender/addon/properties.py
+++ b/intern/cycles/blender/addon/properties.py
@@ -1205,6 +1205,13 @@ class CyclesObjectSettings(bpy.types.PropertyGroup):
default=1.0,
)
+ shadow_terminator_offset: FloatProperty(
+ name="Shadow Terminator Offset",
+ description="Push the shadow terminator towards the light to hide artifacts on low poly geometry",
+ min=0.0, max=1.0,
+ default=0.0,
+ )
+
is_shadow_catcher: BoolProperty(
name="Shadow Catcher",
description="Only render shadows on this object, for compositing renders into real footage",
diff --git a/intern/cycles/blender/addon/ui.py b/intern/cycles/blender/addon/ui.py
index a15daee706f..78a44881743 100644
--- a/intern/cycles/blender/addon/ui.py
+++ b/intern/cycles/blender/addon/ui.py
@@ -1209,6 +1209,27 @@ def has_geometry_visibility(ob):
return ob and ((ob.type in {'MESH', 'CURVE', 'SURFACE', 'FONT', 'META', 'LIGHT'}) or
(ob.instance_type == 'COLLECTION' and ob.instance_collection))
+class CYCLES_OBJECT_PT_shading(CyclesButtonsPanel, Panel):
+ bl_label = "Shading"
+ bl_context = "object"
+ bl_options = {'DEFAULT_CLOSED'}
+
+ @classmethod
+ def poll(cls, context):
+ return CyclesButtonsPanel.poll(context) and (context.object)
+
+ def draw(self, context):
+ layout = self.layout
+ layout.use_property_split = True
+
+ flow = layout.grid_flow(row_major=False, columns=0, even_columns=True, even_rows=False, align=False)
+ layout = self.layout
+ ob = context.object
+ cob = ob.cycles
+
+ if has_geometry_visibility(ob):
+ col = flow.column()
+ col.prop(cob, "shadow_terminator_offset")
class CYCLES_OBJECT_PT_visibility(CyclesButtonsPanel, Panel):
bl_label = "Visibility"
@@ -1367,7 +1388,7 @@ class CYCLES_LIGHT_PT_light(CyclesButtonsPanel, Panel):
col.separator()
if light.type in {'POINT', 'SPOT'}:
- col.prop(light, "shadow_soft_size", text="Size")
+ col.prop(light, "shadow_soft_size", text="Radius")
elif light.type == 'SUN':
col.prop(light, "angle")
elif light.type == 'AREA':
@@ -2268,6 +2289,7 @@ classes = (
CYCLES_CAMERA_PT_dof_aperture,
CYCLES_PT_context_material,
CYCLES_OBJECT_PT_motion_blur,
+ CYCLES_OBJECT_PT_shading,
CYCLES_OBJECT_PT_visibility,
CYCLES_OBJECT_PT_visibility_ray_visibility,
CYCLES_OBJECT_PT_visibility_culling,
diff --git a/intern/cycles/blender/blender_object.cpp b/intern/cycles/blender/blender_object.cpp
index a461982a538..c28586d0f63 100644
--- a/intern/cycles/blender/blender_object.cpp
+++ b/intern/cycles/blender/blender_object.cpp
@@ -238,6 +238,12 @@ Object *BlenderSync::sync_object(BL::Depsgraph &b_depsgraph,
object_updated = true;
}
+ float shadow_terminator_offset = get_float(cobject, "shadow_terminator_offset");
+ if (shadow_terminator_offset != object->shadow_terminator_offset) {
+ object->shadow_terminator_offset = shadow_terminator_offset;
+ object_updated = true;
+ }
+
/* sync the asset name for Cryptomatte */
BL::Object parent = b_ob.parent();
ustring parent_name;
diff --git a/intern/cycles/kernel/bvh/bvh.h b/intern/cycles/kernel/bvh/bvh.h
index b3992c03a9a..9b9df883b62 100644
--- a/intern/cycles/kernel/bvh/bvh.h
+++ b/intern/cycles/kernel/bvh/bvh.h
@@ -300,7 +300,9 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg,
// Is set to zero on miss or if ray is aborted, so can be used as return value
uint p5 = max_hits;
- local_isect->num_hits = 0; // Initialize hit count to zero
+ if (local_isect) {
+ local_isect->num_hits = 0; // Initialize hit count to zero
+ }
optixTrace(scene_intersect_valid(ray) ? kernel_data.bvh.scene : 0,
ray->P,
ray->D,
@@ -323,7 +325,9 @@ ccl_device_intersect bool scene_intersect_local(KernelGlobals *kg,
return p5;
# else /* __KERNEL_OPTIX__ */
if (!scene_intersect_valid(ray)) {
- local_isect->num_hits = 0;
+ if (local_isect) {
+ local_isect->num_hits = 0;
+ }
return false;
}
diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h
index dc80e67a891..4cc61e8ee71 100644
--- a/intern/cycles/kernel/closure/bsdf.h
+++ b/intern/cycles/kernel/closure/bsdf.h
@@ -97,6 +97,18 @@ ccl_device_inline float bump_shadowing_term(float3 Ng, float3 N, float3 I)
return -g2 * g + g2 + g;
}
+/* Shadow terminator workaround, taken from Appleseed.
+ * Original code is under the MIT License
+ * Copyright (c) 2019 Francois Beaune, The appleseedhq Organization */
+ccl_device_inline float shift_cos_in(float cos_in, const float frequency_multiplier)
+{
+ cos_in = min(cos_in, 1.0f);
+
+ const float angle = fast_acosf(cos_in);
+ const float val = max(cosf(angle * frequency_multiplier), 0.0f) / cos_in;
+ return val;
+}
+
ccl_device_inline int bsdf_sample(KernelGlobals *kg,
ShaderData *sd,
const ShaderClosure *sc,
@@ -444,9 +456,17 @@ ccl_device_inline int bsdf_sample(KernelGlobals *kg,
}
}
}
- else if (label & LABEL_DIFFUSE) {
- if (!isequal_float3(sc->N, sd->N)) {
- *eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in);
+ else {
+ /* Shadow terminator offset. */
+ const float frequency_multiplier =
+ kernel_tex_fetch(__objects, sd->object).shadow_terminator_offset;
+ if (frequency_multiplier > 1.0f) {
+ *eval *= shift_cos_in(dot(*omega_in, sc->N), frequency_multiplier);
+ }
+ if (label & LABEL_DIFFUSE) {
+ if (!isequal_float3(sc->N, sd->N)) {
+ *eval *= bump_shadowing_term((label & LABEL_TRANSMIT) ? -sd->N : sd->N, sc->N, *omega_in);
+ }
}
}
@@ -561,6 +581,12 @@ ccl_device_inline
eval *= bump_shadowing_term(sd->N, sc->N, omega_in);
}
}
+ /* Shadow terminator offset. */
+ const float frequency_multiplier =
+ kernel_tex_fetch(__objects, sd->object).shadow_terminator_offset;
+ if (frequency_multiplier > 1.0f) {
+ eval *= shift_cos_in(dot(omega_in, sc->N), frequency_multiplier);
+ }
}
else {
switch (sc->type) {
diff --git a/intern/cycles/kernel/kernel_camera.h b/intern/cycles/kernel/kernel_camera.h
index 62ce04ba48f..445cf9eb44b 100644
--- a/intern/cycles/kernel/kernel_camera.h
+++ b/intern/cycles/kernel/kernel_camera.h
@@ -441,8 +441,22 @@ ccl_device_inline float camera_distance(KernelGlobals *kg, float3 P)
float3 camD = make_float3(cameratoworld.x.z, cameratoworld.y.z, cameratoworld.z.z);
return fabsf(dot((P - camP), camD));
}
- else
+ else {
return len(P - camP);
+ }
+}
+
+ccl_device_inline float camera_z_depth(KernelGlobals *kg, float3 P)
+{
+ if (kernel_data.cam.type != CAMERA_PANORAMA) {
+ Transform worldtocamera = kernel_data.cam.worldtocamera;
+ return transform_point(&worldtocamera, P).z;
+ }
+ else {
+ Transform cameratoworld = kernel_data.cam.cameratoworld;
+ float3 camP = make_float3(cameratoworld.x.w, cameratoworld.y.w, cameratoworld.z.w);
+ return len(P - camP);
+ }
}
ccl_device_inline float3 camera_direction_from_point(KernelGlobals *kg, float3 P)
diff --git a/intern/cycles/kernel/kernel_light.h b/intern/cycles/kernel/kernel_light.h
index d918abed381..04472212d0c 100644
--- a/intern/cycles/kernel/kernel_light.h
+++ b/intern/cycles/kernel/kernel_light.h
@@ -249,13 +249,13 @@ ccl_device float3 background_map_sample(KernelGlobals *kg, float randu, float ra
float u = (index_u + du) / res_x;
/* compute pdf */
- float denom = cdf_last_u.x * cdf_last_v.x;
float sin_theta = sinf(M_PI_F * v);
+ float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x;
if (sin_theta == 0.0f || denom == 0.0f)
*pdf = 0.0f;
else
- *pdf = (cdf_u.x * cdf_v.x) / (M_2PI_F * M_PI_F * sin_theta * denom);
+ *pdf = (cdf_u.x * cdf_v.x) / denom;
/* compute direction */
return equirectangular_to_direction(u, v);
@@ -284,7 +284,7 @@ ccl_device float background_map_pdf(KernelGlobals *kg, float3 direction)
index_v * cdf_width + res_x);
float2 cdf_last_v = kernel_tex_fetch(__light_background_marginal_cdf, res_y);
- float denom = cdf_last_u.x * cdf_last_v.x;
+ float denom = (M_2PI_F * M_PI_F * sin_theta) * cdf_last_u.x * cdf_last_v.x;
if (denom == 0.0f)
return 0.0f;
@@ -294,7 +294,7 @@ ccl_device float background_map_pdf(KernelGlobals *kg, float3 direction)
index_v * cdf_width + index_u);
float2 cdf_v = kernel_tex_fetch(__light_background_marginal_cdf, index_v);
- return (cdf_u.x * cdf_v.x) / (M_2PI_F * M_PI_F * sin_theta * denom);
+ return (cdf_u.x * cdf_v.x) / denom;
}
ccl_device_inline bool background_portal_data_fetch_and_check_side(
diff --git a/intern/cycles/kernel/kernel_passes.h b/intern/cycles/kernel/kernel_passes.h
index 7437e540a1f..753cf4561b2 100644
--- a/intern/cycles/kernel/kernel_passes.h
+++ b/intern/cycles/kernel/kernel_passes.h
@@ -194,7 +194,7 @@ ccl_device_inline void kernel_write_data_passes(KernelGlobals *kg,
average(shader_bsdf_alpha(kg, sd)) >= kernel_data.film.pass_alpha_threshold) {
if (state->sample == 0) {
if (flag & PASSMASK(DEPTH)) {
- float depth = camera_distance(kg, sd->P);
+ float depth = camera_z_depth(kg, sd->P);
kernel_write_pass_float(buffer + kernel_data.film.pass_depth, depth);
}
if (flag & PASSMASK(OBJECT_ID)) {
diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h
index 304835a1685..630d00a4e71 100644
--- a/intern/cycles/kernel/kernel_types.h
+++ b/intern/cycles/kernel/kernel_types.h
@@ -1480,6 +1480,9 @@ typedef struct KernelObject {
float cryptomatte_object;
float cryptomatte_asset;
+
+ float shadow_terminator_offset;
+ float pad1, pad2, pad3;
} KernelObject;
static_assert_align(KernelObject, 16);
diff --git a/intern/cycles/render/light.cpp b/intern/cycles/render/light.cpp
index cd19b03ac53..cb7474017fa 100644
--- a/intern/cycles/render/light.cpp
+++ b/intern/cycles/render/light.cpp
@@ -120,6 +120,7 @@ NODE_DEFINE(Light)
SOCKET_VECTOR(dir, "Dir", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_FLOAT(size, "Size", 0.0f);
+ SOCKET_FLOAT(angle, "Angle", 0.0f);
SOCKET_VECTOR(axisu, "Axis U", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_FLOAT(sizeu, "Size U", 1.0f);
@@ -183,6 +184,8 @@ LightManager::LightManager()
need_update = true;
need_update_background = true;
use_light_visibility = false;
+ last_background_enabled = false;
+ last_background_resolution = 0;
}
LightManager::~LightManager()
@@ -202,7 +205,7 @@ bool LightManager::has_background_light(Scene *scene)
return false;
}
-void LightManager::disable_ineffective_light(Scene *scene)
+void LightManager::test_enabled_lights(Scene *scene)
{
/* Make all lights enabled by default, and perform some preliminary checks
* needed for finer-tuning of settings (for example, check whether we've
@@ -215,6 +218,9 @@ void LightManager::disable_ineffective_light(Scene *scene)
has_background |= light->type == LIGHT_BACKGROUND;
}
+ bool background_enabled = false;
+ int background_resolution = 0;
+
if (has_background) {
/* Ignore background light if:
* - If unsupported on a device
@@ -226,9 +232,18 @@ void LightManager::disable_ineffective_light(Scene *scene)
foreach (Light *light, scene->lights) {
if (light->type == LIGHT_BACKGROUND) {
light->is_enabled = !disable_mis;
+ background_enabled = !disable_mis;
+ background_resolution = light->map_resolution;
}
}
}
+
+ if (last_background_enabled != background_enabled ||
+ last_background_resolution != background_resolution) {
+ last_background_enabled = background_enabled;
+ last_background_resolution = background_resolution;
+ need_update_background = true;
+ }
}
bool LightManager::object_usable_as_light(Object *object)
@@ -902,12 +917,13 @@ void LightManager::device_update(Device *device,
VLOG(1) << "Total " << scene->lights.size() << " lights.";
+ /* Detect which lights are enabled, also determins if we need to update the background. */
+ test_enabled_lights(scene);
+
device_free(device, dscene, need_update_background);
use_light_visibility = false;
- disable_ineffective_light(scene);
-
device_update_points(device, dscene, scene);
if (progress.get_cancel())
return;
diff --git a/intern/cycles/render/light.h b/intern/cycles/render/light.h
index 1a99b2b76ae..d136e8f1a08 100644
--- a/intern/cycles/render/light.h
+++ b/intern/cycles/render/light.h
@@ -112,7 +112,7 @@ class LightManager {
* which doesn't contribute to the scene or which is only used for MIS
* and scene doesn't need MIS.
*/
- void disable_ineffective_light(Scene *scene);
+ void test_enabled_lights(Scene *scene);
void device_update_points(Device *device, DeviceScene *dscene, Scene *scene);
void device_update_distribution(Device *device,
@@ -136,6 +136,9 @@ class LightManager {
vector<IESSlot *> ies_slots;
thread_mutex ies_mutex;
+
+ bool last_background_enabled;
+ int last_background_resolution;
};
CCL_NAMESPACE_END
diff --git a/intern/cycles/render/object.cpp b/intern/cycles/render/object.cpp
index 90a1d90019d..61deef4cd76 100644
--- a/intern/cycles/render/object.cpp
+++ b/intern/cycles/render/object.cpp
@@ -101,6 +101,7 @@ NODE_DEFINE(Object)
SOCKET_POINT(dupli_generated, "Dupli Generated", make_float3(0.0f, 0.0f, 0.0f));
SOCKET_POINT2(dupli_uv, "Dupli UV", make_float2(0.0f, 0.0f));
SOCKET_TRANSFORM_ARRAY(motion, "Motion", array<Transform>());
+ SOCKET_FLOAT(shadow_terminator_offset, "Terminator Offset", 0.0f);
SOCKET_BOOLEAN(is_shadow_catcher, "Shadow Catcher", false);
@@ -534,6 +535,7 @@ void ObjectManager::device_update_object_transform(UpdateObjectTransformState *s
uint32_t hash_asset = util_murmur_hash3(ob->asset_name.c_str(), ob->asset_name.length(), 0);
kobject.cryptomatte_object = util_hash_to_float(hash_name);
kobject.cryptomatte_asset = util_hash_to_float(hash_asset);
+ kobject.shadow_terminator_offset = 1.0f / (1.0f - 0.5f * ob->shadow_terminator_offset);
/* Object flag. */
if (ob->use_holdout) {
diff --git a/intern/cycles/render/object.h b/intern/cycles/render/object.h
index 7c84c2de4fb..ac9b4c331f5 100644
--- a/intern/cycles/render/object.h
+++ b/intern/cycles/render/object.h
@@ -59,6 +59,7 @@ class Object : public Node {
bool hide_on_missing_motion;
bool use_holdout;
bool is_shadow_catcher;
+ float shadow_terminator_offset;
float3 dupli_generated;
float2 dupli_uv;
diff --git a/intern/cycles/util/util_guarded_allocator.h b/intern/cycles/util/util_guarded_allocator.h
index 2d09326d2ca..f78cc5f5da9 100644
--- a/intern/cycles/util/util_guarded_allocator.h
+++ b/intern/cycles/util/util_guarded_allocator.h
@@ -18,6 +18,7 @@
#define __UTIL_GUARDED_ALLOCATOR_H__
#include <cstddef>
+#include <cstdlib>
#include <memory>
#ifdef WITH_BLENDER_GUARDEDALLOC
diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp
index 633451feb85..31110694ea6 100644
--- a/intern/ghost/intern/GHOST_SystemWayland.cpp
+++ b/intern/ghost/intern/GHOST_SystemWayland.cpp
@@ -1527,7 +1527,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
GHOST_TDrawingContextType type,
GHOST_GLSettings glSettings,
const bool exclusive,
- const bool /*is_dialog*/,
+ const bool is_dialog,
const GHOST_IWindow *parentWindow)
{
GHOST_WindowWayland *window = new GHOST_WindowWayland(
@@ -1540,6 +1540,7 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
state,
parentWindow,
type,
+ is_dialog,
((glSettings.flags & GHOST_glStereoVisual) != 0),
exclusive);
diff --git a/intern/ghost/intern/GHOST_WindowWayland.cpp b/intern/ghost/intern/GHOST_WindowWayland.cpp
index 0ea6f5f8ecb..ef02db7abc3 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.cpp
+++ b/intern/ghost/intern/GHOST_WindowWayland.cpp
@@ -39,6 +39,7 @@ struct window_t {
bool is_maximised;
bool is_fullscreen;
bool is_active;
+ bool is_dialog;
int32_t width, height;
};
@@ -144,6 +145,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
GHOST_TWindowState state,
const GHOST_IWindow *parentWindow,
GHOST_TDrawingContextType type,
+ const bool is_dialog,
const bool stereoVisual,
const bool exclusive)
: GHOST_Window(width, height, state, stereoVisual, exclusive),
@@ -155,6 +157,8 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
w->width = int32_t(width);
w->height = int32_t(height);
+ w->is_dialog = is_dialog;
+
/* Window surfaces. */
w->surface = wl_compositor_create_surface(m_system->compositor());
w->egl_window = wl_egl_window_create(w->surface, int(width), int(height));
@@ -376,6 +380,11 @@ GHOST_TSuccess GHOST_WindowWayland::endFullScreen() const
return GHOST_kSuccess;
}
+bool GHOST_WindowWayland::isDialog() const
+{
+ return w->is_dialog;
+}
+
/**
* \param type The type of rendering context create.
* \return Indication of success.
diff --git a/intern/ghost/intern/GHOST_WindowWayland.h b/intern/ghost/intern/GHOST_WindowWayland.h
index 39c35f77d7d..23e55fcd6e4 100644
--- a/intern/ghost/intern/GHOST_WindowWayland.h
+++ b/intern/ghost/intern/GHOST_WindowWayland.h
@@ -42,6 +42,7 @@ class GHOST_WindowWayland : public GHOST_Window {
GHOST_TWindowState state,
const GHOST_IWindow *parentWindow,
GHOST_TDrawingContextType type,
+ const bool is_dialog,
const bool stereoVisual,
const bool exclusive);
@@ -106,6 +107,8 @@ class GHOST_WindowWayland : public GHOST_Window {
GHOST_TSuccess endFullScreen() const override;
+ bool isDialog() const override;
+
private:
GHOST_SystemWayland *m_system;
struct window_t *w;
diff --git a/intern/opencolorio/ocio_impl_glsl.cc b/intern/opencolorio/ocio_impl_glsl.cc
index df6adc8f34b..43416f734c5 100644
--- a/intern/opencolorio/ocio_impl_glsl.cc
+++ b/intern/opencolorio/ocio_impl_glsl.cc
@@ -263,19 +263,20 @@ static void updateGLSLShader(OCIO_GLSLShader *shader,
shader->curve_mapping_loc = glGetUniformLocation(shader->program, "curve_mapping");
glUseProgram(shader->program);
- /* Set texture bind point uniform once. This is saved by the shader. */
- glUniform1i(glGetUniformLocation(shader->program, "image_texture"), 0);
- glUniform1i(glGetUniformLocation(shader->program, "lut3d_texture"), 2);
- glUniform1i(glGetUniformLocation(shader->program, "lut3d_display_texture"), 3);
- glUniform1i(glGetUniformLocation(shader->program, "curve_mapping_texture"), 4);
+
+ /* TODO(fclem) Remove this. Make caller always assume viewport space and
+ * specify texco via vertex attribs. */
+ shader->interface = GPU_shaderinterface_create(shader->program);
/* Set UBO binding location. */
GLuint index = glGetUniformBlockIndex(shader->program, "OCIO_GLSLCurveMappingParameters");
glUniformBlockBinding(shader->program, index, UBO_BIND_LOC);
- /* TODO(fclem) Remove this. Make caller always assume viewport space and
- * specify texco via vertex attribs. */
- shader->interface = GPU_shaderinterface_create(shader->program);
+ /* Set texture bind point uniform once. This is saved by the shader. */
+ glUniform1i(glGetUniformLocation(shader->program, "image_texture"), 0);
+ glUniform1i(glGetUniformLocation(shader->program, "lut3d_texture"), 2);
+ glUniform1i(glGetUniformLocation(shader->program, "lut3d_display_texture"), 3);
+ glUniform1i(glGetUniformLocation(shader->program, "curve_mapping_texture"), 4);
}
shader->cacheId = cache_id;
diff --git a/release/scripts/modules/bl_app_template_utils.py b/release/scripts/modules/bl_app_template_utils.py
index 42467d21580..7db084a9a29 100644
--- a/release/scripts/modules/bl_app_template_utils.py
+++ b/release/scripts/modules/bl_app_template_utils.py
@@ -68,14 +68,15 @@ def _enable(template_id, *, handle_error=None, ignore_not_found=False):
# 1) try import
try:
mod = import_from_id(template_id, ignore_not_found=ignore_not_found)
- if mod is None:
- return None
- mod.__template_enabled__ = False
- _modules[template_id] = mod
except Exception as ex:
handle_error(ex)
return None
+ _modules[template_id] = mod
+ if mod is None:
+ return None
+ mod.__template_enabled__ = False
+
# 2) try run the modules register function
try:
mod.register()
@@ -111,9 +112,12 @@ def _disable(template_id, *, handle_error=None):
import traceback
traceback.print_exc()
- mod = _modules.get(template_id)
+ mod = _modules.get(template_id, False)
- if mod and getattr(mod, "__template_enabled__", False) is not False:
+ if mod is None:
+ # Loaded but has no module, remove since there is no use in keeping it.
+ del _modules[template_id]
+ elif getattr(mod, "__template_enabled__", False) is not False:
mod.__template_enabled__ = False
try:
@@ -124,7 +128,7 @@ def _disable(template_id, *, handle_error=None):
handle_error(ex)
else:
print("\tapp_template_utils.disable: %s not %s." %
- (template_id, "disabled" if mod is None else "loaded"))
+ (template_id, "disabled" if mod is False else "loaded"))
if _bpy.app.debug_python:
print("\tapp_template_utils.disable", template_id)
@@ -170,10 +174,6 @@ def activate(template_id=None):
if template_id_prev:
_disable(template_id_prev)
- # Disable all addons, afterwards caller must reset.
- import addon_utils
- addon_utils.disable_all()
-
# ignore_not_found so modules that don't contain scripts don't raise errors
_mod = _enable(template_id, ignore_not_found=True) if template_id else None
diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 2559a2f1df5..08e81d89c4f 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -2463,7 +2463,7 @@ def km_sequencer(params):
{"properties": [("all", False)]}),
("sequencer.gap_remove", {"type": 'BACK_SPACE', "value": 'PRESS', "shift": True},
{"properties": [("all", True)]}),
- ("sequencer.gap_insert", {"type": 'EQUAL', "value": 'PRESS', "shift": True}, None),
+ ("sequencer.gap_insert", {"type": 'BACK_SPACE', "value": 'PRESS', "ctrl": True}, None),
("sequencer.snap", {"type": 'S', "value": 'PRESS', "shift": True}, None),
("sequencer.swap_inputs", {"type": 'S', "value": 'PRESS', "alt": True}, None),
*(
@@ -2521,6 +2521,15 @@ def km_sequencer(params):
{"properties": [("left_right", 'LEFT'), ("linked_time", True)]}),
("sequencer.select", {"type": 'RIGHT_BRACKET', "value": 'PRESS'},
{"properties": [("left_right", 'RIGHT'), ("linked_time", True)]}),
+ ("sequencer.select", {"type": 'EQUAL', "value": 'PRESS'},
+ {"properties": [("left_right", 'OVERLAP'), ("linked_time", True)]}),
+ ("sequencer.select", {"type": 'LEFT_BRACKET', "value": 'PRESS', "shift": True},
+ {"properties": [("left_right", 'LEFT'), ("linked_time", True), ("extend", True)]}),
+ ("sequencer.select", {"type": 'RIGHT_BRACKET', "value": 'PRESS', "shift": True},
+ {"properties": [("left_right", 'RIGHT'), ("linked_time", True), ("extend", True)]}),
+ ("sequencer.select", {"type": 'EQUAL', "value": 'PRESS', "shift": True},
+ {"properties": [("left_right", 'OVERLAP'), ("linked_time", True), ("extend", True)]}),
+
*_template_items_context_menu("SEQUENCER_MT_context_menu", params.context_menu_event),
])
@@ -6263,6 +6272,16 @@ def km_3d_view_tool_sculpt_mesh_filter(params):
]},
)
+def km_3d_view_tool_sculpt_cloth_filter(params):
+ return (
+ "3D View Tool: Sculpt, Cloth Filter",
+ {"space_type": 'VIEW_3D', "region_type": 'WINDOW'},
+ {"items": [
+ ("sculpt.cloth_filter", {"type": params.tool_tweak, "value": 'ANY'},
+ None)
+ ]},
+ )
+
def km_3d_view_tool_paint_weight_sample_weight(params):
return (
"3D View Tool: Paint Weight, Sample Weight",
@@ -6802,6 +6821,7 @@ def generate_keymaps(params=None):
km_3d_view_tool_sculpt_box_mask(params),
km_3d_view_tool_sculpt_lasso_mask(params),
km_3d_view_tool_sculpt_mesh_filter(params),
+ km_3d_view_tool_sculpt_cloth_filter(params),
km_3d_view_tool_paint_weight_sample_weight(params),
km_3d_view_tool_paint_weight_sample_vertex_group(params),
km_3d_view_tool_paint_weight_gradient(params),
diff --git a/release/scripts/startup/bl_operators/sequencer.py b/release/scripts/startup/bl_operators/sequencer.py
index 206f778195e..af071561232 100644
--- a/release/scripts/startup/bl_operators/sequencer.py
+++ b/release/scripts/startup/bl_operators/sequencer.py
@@ -188,7 +188,7 @@ class SequencerFadesAdd(Operator):
('CURSOR_TO', 'To Playhead', 'Fade from the start of sequences under the time cursor to the current frame'),
),
name="Fade type",
- description="Fade in, out, both in and out, to, or from the playhead. Default is both in and out",
+ description="Fade in, out, both in and out, to, or from the current frame. Default is both in and out",
default='IN_OUT')
@classmethod
diff --git a/release/scripts/startup/bl_ui/properties_output.py b/release/scripts/startup/bl_ui/properties_output.py
index e859798c085..5f0fd3374d2 100644
--- a/release/scripts/startup/bl_ui/properties_output.py
+++ b/release/scripts/startup/bl_ui/properties_output.py
@@ -367,11 +367,11 @@ class RENDER_PT_encoding_video(RenderOutputButtonsPanel, Panel):
# I-frames
layout.prop(ffmpeg, "gopsize")
# B-Frames
- split = layout.split(factor=0.5)
- split.prop(ffmpeg, "use_max_b_frames", text="Max B-frames")
- pbox = split.column()
- pbox.prop(ffmpeg, "max_b_frames", text="")
- pbox.enabled = ffmpeg.use_max_b_frames
+ row = layout.row(align=True, heading="Max B-frames")
+ row.prop(ffmpeg, "use_max_b_frames", text="")
+ sub = row.row(align=True)
+ sub.active = ffmpeg.use_max_b_frames
+ sub.prop(ffmpeg, "max_b_frames", text="")
if not use_crf or ffmpeg.constant_rate_factor == 'NONE':
col = layout.column()
diff --git a/release/scripts/startup/bl_ui/properties_paint_common.py b/release/scripts/startup/bl_ui/properties_paint_common.py
index 5fadb31c83f..1612cce3c51 100644
--- a/release/scripts/startup/bl_ui/properties_paint_common.py
+++ b/release/scripts/startup/bl_ui/properties_paint_common.py
@@ -623,7 +623,7 @@ def brush_settings(layout, context, brush, popover=False):
layout.prop(brush, "pose_origin_type")
layout.prop(brush, "pose_offset")
layout.prop(brush, "pose_smooth_iterations")
- if brush.pose_deform_type == 'ROTATE_TWIST':
+ if brush.pose_deform_type == 'ROTATE_TWIST' and brush.pose_origin_type in ('TOPOLOGY','FACE_SETS'):
layout.prop(brush, "pose_ik_segments")
layout.prop(brush, "use_pose_ik_anchored")
layout.separator()
diff --git a/release/scripts/startup/bl_ui/properties_physics_fluid.py b/release/scripts/startup/bl_ui/properties_physics_fluid.py
index 2c8ed363738..833cd05dd81 100644
--- a/release/scripts/startup/bl_ui/properties_physics_fluid.py
+++ b/release/scripts/startup/bl_ui/properties_physics_fluid.py
@@ -1174,7 +1174,7 @@ class PHYSICS_PT_cache(PhysicButtonsPanel, Panel):
if domain.is_cache_baking_data and not domain.has_cache_baked_data:
split.enabled = False
- split.operator("fluid.pause_bake", text="Baking All - ESC to pause")
+ split.operator("fluid.pause_bake", text="Baking All - ESC to cancel")
elif not domain.has_cache_baked_data and not domain.is_cache_baking_data:
split.operator("fluid.bake_all", text="Bake All")
else:
diff --git a/release/scripts/startup/bl_ui/space_sequencer.py b/release/scripts/startup/bl_ui/space_sequencer.py
index 41c220f7ee4..4f317a97b38 100644
--- a/release/scripts/startup/bl_ui/space_sequencer.py
+++ b/release/scripts/startup/bl_ui/space_sequencer.py
@@ -244,6 +244,20 @@ class SEQUENCER_MT_preview_zoom(Menu):
layout.operator_context = 'INVOKE_DEFAULT'
+class SEQUENCER_MT_proxy(Menu):
+ bl_label = "Proxy"
+
+ def draw(self, context):
+ layout = self.layout
+
+ st = context.space_data
+ col = layout.column()
+ col.operator("sequencer.enable_proxies", text="Setup")
+ col.operator("sequencer.rebuild_proxy", text="Rebuild")
+ col.enabled = selected_sequences_len(context) >= 1
+ layout.prop(st, "proxy_render_size", text="")
+
+
class SEQUENCER_MT_view(Menu):
bl_label = "View"
@@ -291,6 +305,10 @@ class SEQUENCER_MT_view(Menu):
layout.operator("view2d.zoom_border", text="Zoom")
layout.menu("SEQUENCER_MT_preview_zoom")
+ layout.separator()
+
+ layout.menu("SEQUENCER_MT_proxy")
+
layout.operator_context = 'INVOKE_DEFAULT'
if is_sequencer_view:
@@ -376,12 +394,15 @@ class SEQUENCER_MT_select_linked(Menu):
layout.operator("sequencer.select_more", text="More")
-class SEQUENCER_MT_select_playhead(Menu):
- bl_label = "Select Playhead"
+class SEQUENCER_MT_select_side_of_frame(Menu):
+ bl_label = "Side of Current Frame"
def draw(self, _context):
layout = self.layout
+ props = layout.operator("sequencer.select", text="Overlap")
+ props.left_right = 'OVERLAP'
+ props.linked_time = True
props = layout.operator("sequencer.select", text="Left")
props.left_right = 'LEFT'
props.linked_time = True
@@ -408,7 +429,7 @@ class SEQUENCER_MT_select(Menu):
layout.separator()
- layout.menu("SEQUENCER_MT_select_playhead", text="Playhead")
+ layout.menu("SEQUENCER_MT_select_side_of_frame")
layout.menu("SEQUENCER_MT_select_handle", text="Handle")
layout.menu("SEQUENCER_MT_select_channel", text="Channel")
layout.menu("SEQUENCER_MT_select_linked", text="Linked")
@@ -770,9 +791,6 @@ class SEQUENCER_MT_strip(Menu):
layout.separator()
layout.menu("SEQUENCER_MT_strip_input")
- layout.separator()
- layout.operator("sequencer.rebuild_proxy")
-
class SEQUENCER_MT_context_menu(Menu):
bl_label = "Sequencer Context Menu"
@@ -1042,7 +1060,8 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
strip_type = strip.type
if strip_type == 'COLOR':
- layout.prop(strip, "color")
+ layout.template_color_picker(strip, "color", value_slider=True, cubic=True)
+ layout.prop(strip, "color", text="")
elif strip_type == 'WIPE':
col = layout.column()
@@ -1133,9 +1152,13 @@ class SEQUENCER_PT_effect(SequencerButtonsPanel, Panel):
elif strip_type == 'TEXT':
layout = self.layout
- layout.use_property_split = False
- layout.prop(strip, "text", text="")
- layout.use_property_split = True
+ col = layout.column()
+ col.scale_x = 1.3
+ col.scale_y = 1.3
+ col.use_property_split = False
+ col.prop(strip, "text", text="")
+ col.use_property_split = True
+ layout.prop(strip, "wrap_width", text="Wrap Width")
col = layout.column(align=True)
if strip_type == 'SPEED':
@@ -1172,9 +1195,8 @@ class SEQUENCER_PT_effect_text_layout(SequencerButtonsPanel, Panel):
layout.use_property_split = True
col = layout.column()
col.prop(strip, "location", text="Location")
- col.prop(strip, "align_x", text="Alignment X")
+ col.prop(strip, "align_x", text="Anchor X")
col.prop(strip, "align_y", text="Y")
- col.prop(strip, "wrap_width", text="Wrap Width")
class SEQUENCER_PT_effect_text_style(SequencerButtonsPanel, Panel):
@@ -1563,10 +1585,10 @@ class SEQUENCER_PT_time(SequencerButtonsPanel, Panel):
split.alignment = 'RIGHT'
split.label(text="Playhead")
split = split.split(factor=0.8 + max_factor, align=True)
- playhead = frame_current - frame_final_start
- split.label(text="{:>14}".format(smpte_from_frame(playhead)))
+ frame_display = frame_current - frame_final_start
+ split.label(text="{:>14}".format(smpte_from_frame(frame_display)))
split.alignment = 'RIGHT'
- split.label(text=str(playhead) + " ")
+ split.label(text=str(frame_display) + " ")
if strip.type == 'SCENE':
scene = strip.scene
@@ -1664,7 +1686,7 @@ class SEQUENCER_PT_adjust_transform(SequencerButtonsPanel, Panel):
return strip.type in {
'MOVIE', 'IMAGE', 'SCENE', 'MOVIECLIP', 'MASK',
- 'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER',
+ 'META', 'ADD', 'SUBTRACT', 'ALPHA_OVER', 'TEXT',
'ALPHA_UNDER', 'CROSS', 'GAMMA_CROSS', 'MULTIPLY',
'OVER_DROP', 'WIPE', 'GLOW', 'TRANSFORM', 'COLOR',
'MULTICAM', 'SPEED', 'ADJUSTMENT', 'COLORMIX'
@@ -2198,7 +2220,8 @@ classes = (
SEQUENCER_MT_view_cache,
SEQUENCER_MT_view_toggle,
SEQUENCER_MT_preview_zoom,
- SEQUENCER_MT_select_playhead,
+ SEQUENCER_MT_proxy,
+ SEQUENCER_MT_select_side_of_frame,
SEQUENCER_MT_select_handle,
SEQUENCER_MT_select_channel,
SEQUENCER_MT_select_linked,
diff --git a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
index 1aa5dde168b..b4c1ea5163f 100644
--- a/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
+++ b/release/scripts/startup/bl_ui/space_toolsystem_toolbar.py
@@ -1228,6 +1228,25 @@ class _defs_sculpt:
draw_settings=draw_settings,
)
+ @ToolDef.from_fn
+ def cloth_filter():
+ def draw_settings(_context, layout, tool):
+ props = tool.operator_properties("sculpt.cloth_filter")
+ layout.prop(props, "type", expand=False)
+ layout.prop(props, "strength")
+ layout.prop(props, "cloth_mass")
+ layout.prop(props, "cloth_damping")
+ layout.prop(props, "use_face_sets")
+
+ return dict(
+ idname="builtin.cloth_filter",
+ label="Cloth Filter",
+ icon="ops.sculpt.cloth_filter",
+ widget=None,
+ keymap=(),
+ draw_settings=draw_settings,
+ )
+
class _defs_vertex_paint:
@@ -2402,6 +2421,7 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
_defs_sculpt.hide_border,
None,
_defs_sculpt.mesh_filter,
+ _defs_sculpt.cloth_filter,
None,
_defs_transform.translate,
_defs_transform.rotate,
diff --git a/release/scripts/startup/bl_ui/space_userpref.py b/release/scripts/startup/bl_ui/space_userpref.py
index 63fc44aed38..436d866886b 100644
--- a/release/scripts/startup/bl_ui/space_userpref.py
+++ b/release/scripts/startup/bl_ui/space_userpref.py
@@ -1284,12 +1284,12 @@ class USERPREF_PT_saveload_autorun(FilePathsPanel, Panel):
box = layout.box()
row = box.row()
row.label(text="Excluded Paths:")
- row.operator("wm.userpref_autoexec_path_add", text="", icon='ADD', emboss=False)
+ row.operator("preferences.autoexec_path_add", text="", icon='ADD', emboss=False)
for i, path_cmp in enumerate(prefs.autoexec_paths):
row = box.row()
row.prop(path_cmp, "path", text="")
row.prop(path_cmp, "use_glob", text="", icon='FILTER')
- row.operator("wm.userpref_autoexec_path_remove", text="", icon='X', emboss=False).index = i
+ row.operator("preferences.autoexec_path_remove", text="", icon='X', emboss=False).index = i
# -----------------------------------------------------------------------------
diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py
index 6dc21669f32..4795298d2f0 100644
--- a/release/scripts/startup/bl_ui/space_view3d.py
+++ b/release/scripts/startup/bl_ui/space_view3d.py
@@ -1224,6 +1224,7 @@ class VIEW3D_MT_view_cameras(Menu):
layout.operator("view3d.object_as_camera")
layout.operator("view3d.view_camera", text="Active Camera")
+ layout.operator("view3d.view_center_camera")
class VIEW3D_MT_view_viewpoint(Menu):
diff --git a/source/blender/blenkernel/BKE_bvhutils.h b/source/blender/blenkernel/BKE_bvhutils.h
index 458f1ab7a56..5d7e8fe743e 100644
--- a/source/blender/blenkernel/BKE_bvhutils.h
+++ b/source/blender/blenkernel/BKE_bvhutils.h
@@ -25,6 +25,7 @@
#include "BLI_bitmap.h"
#include "BLI_kdopbvh.h"
+#include "BLI_threads.h"
#ifdef __cplusplus
extern "C" {
@@ -39,7 +40,7 @@ struct MFace;
struct MVert;
struct Mesh;
-typedef struct LinkNode BVHCache;
+struct BVHCache;
/**
* Struct that stores basic information about a BVHTree built from a edit-mesh.
@@ -98,6 +99,9 @@ typedef enum BVHCacheType {
BVHTREE_FROM_EM_VERTS,
BVHTREE_FROM_EM_EDGES,
BVHTREE_FROM_EM_LOOPTRI,
+
+ /* Keep `BVHTREE_MAX_ITEM` as last item. */
+ BVHTREE_MAX_ITEM,
} BVHCacheType;
/**
@@ -122,7 +126,8 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -134,7 +139,8 @@ BVHTree *bvhtree_from_mesh_verts_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
@@ -147,7 +153,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -161,7 +168,8 @@ BVHTree *bvhtree_from_mesh_edges_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -175,7 +183,8 @@ BVHTree *bvhtree_from_mesh_faces_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_editmesh_looptri(
BVHTreeFromEditMesh *data, struct BMEditMesh *em, float epsilon, int tree_type, int axis);
@@ -188,7 +197,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
const struct MVert *vert,
@@ -204,7 +214,8 @@ BVHTree *bvhtree_from_mesh_looptri_ex(struct BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
struct Mesh *mesh,
@@ -215,7 +226,8 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const int tree_type,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache);
+ struct BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex);
/**
* Frees data allocated by a call to bvhtree_from_mesh_*.
@@ -244,10 +256,9 @@ float bvhtree_sphereray_tri_intersection(const BVHTreeRay *ray,
/* Using local coordinates */
-bool bvhcache_find(const BVHCache *cache, BVHCacheType type, BVHTree **r_tree);
-bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree);
-void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, BVHCacheType type);
-void bvhcache_free(BVHCache **cache_p);
+bool bvhcache_has_tree(const struct BVHCache *bvh_cache, const BVHTree *tree);
+struct BVHCache *bvhcache_init(void);
+void bvhcache_free(struct BVHCache *bvh_cache);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index a314008f715..f4b56aa152f 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -50,6 +50,10 @@ typedef struct CollectionParent {
struct Collection *BKE_collection_add(struct Main *bmain,
struct Collection *parent,
const char *name);
+void BKE_collection_add_from_object(struct Main *bmain,
+ struct Scene *scene,
+ const struct Object *ob_src,
+ struct Collection *collection_dst);
void BKE_collection_free(struct Collection *collection);
bool BKE_collection_delete(struct Main *bmain, struct Collection *collection, bool hierarchy);
diff --git a/source/blender/blenkernel/BKE_gpencil.h b/source/blender/blenkernel/BKE_gpencil.h
index 2084122929e..24db577322f 100644
--- a/source/blender/blenkernel/BKE_gpencil.h
+++ b/source/blender/blenkernel/BKE_gpencil.h
@@ -41,6 +41,7 @@ struct Object;
struct Scene;
struct SpaceImage;
struct ToolSettings;
+struct ViewLayer;
struct bDeformGroup;
struct bGPDframe;
struct bGPDlayer;
@@ -258,7 +259,8 @@ typedef void (*gpIterCb)(struct bGPDlayer *layer,
struct bGPDstroke *stroke,
void *thunk);
-void BKE_gpencil_visible_stroke_iter(struct Object *ob,
+void BKE_gpencil_visible_stroke_iter(struct ViewLayer *view_layer,
+ struct Object *ob,
gpIterCb layer_cb,
gpIterCb stroke_cb,
void *thunk,
diff --git a/source/blender/blenkernel/BKE_paint.h b/source/blender/blenkernel/BKE_paint.h
index ac292432acc..26ffd1bbfef 100644
--- a/source/blender/blenkernel/BKE_paint.h
+++ b/source/blender/blenkernel/BKE_paint.h
@@ -253,6 +253,7 @@ typedef struct SculptPoseIKChainSegment {
typedef struct SculptPoseIKChain {
SculptPoseIKChainSegment *segments;
int tot_segments;
+ float grab_delta_offset[3];
} SculptPoseIKChain;
/* Cloth Brush */
diff --git a/source/blender/blenkernel/BKE_pbvh.h b/source/blender/blenkernel/BKE_pbvh.h
index 2bf16e38716..8fb6f140822 100644
--- a/source/blender/blenkernel/BKE_pbvh.h
+++ b/source/blender/blenkernel/BKE_pbvh.h
@@ -82,8 +82,8 @@ typedef struct PBVHFrustumPlanes {
int num_planes;
} PBVHFrustumPlanes;
-void BKE_pbvh_set_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes);
-void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes);
+void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
+void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes);
/* Callbacks */
@@ -98,7 +98,7 @@ typedef void (*BKE_pbvh_SearchNearestCallback)(PBVHNode *node, void *data, float
/* Building */
PBVH *BKE_pbvh_new(void);
-void BKE_pbvh_build_mesh(PBVH *bvh,
+void BKE_pbvh_build_mesh(PBVH *pbvh,
const struct Mesh *mesh,
const struct MPoly *mpoly,
const struct MLoop *mloop,
@@ -109,47 +109,47 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
struct CustomData *pdata,
const struct MLoopTri *looptri,
int looptri_num);
-void BKE_pbvh_build_grids(PBVH *bvh,
+void BKE_pbvh_build_grids(PBVH *pbvh,
struct CCGElem **grid_elems,
int totgrid,
struct CCGKey *key,
void **gridfaces,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
-void BKE_pbvh_build_bmesh(PBVH *bvh,
+void BKE_pbvh_build_bmesh(PBVH *pbvh,
struct BMesh *bm,
bool smooth_shading,
struct BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset);
-void BKE_pbvh_free(PBVH *bvh);
+void BKE_pbvh_free(PBVH *pbvh);
/* Hierarchical Search in the BVH, two methods:
* - for each hit calling a callback
* - gather nodes in an array (easy to multithread) */
-void BKE_pbvh_search_callback(PBVH *bvh,
+void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitCallback hcb,
void *hit_data);
void BKE_pbvh_search_gather(
- PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot);
+ PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***array, int *tot);
/* Raycast
* the hit callback is called for all leaf nodes intersecting the ray;
* it's up to the callback to find the primitive within the leaves that is
* hit first */
-void BKE_pbvh_raycast(PBVH *bvh,
+void BKE_pbvh_raycast(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const float ray_start[3],
const float ray_normal[3],
bool original);
-bool BKE_pbvh_node_raycast(PBVH *bvh,
+bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -170,16 +170,16 @@ bool BKE_pbvh_bmesh_node_raycast_detail(PBVHNode *node,
/* for orthographic cameras, project the far away ray segment points to the root node so
* we can have better precision. */
void BKE_pbvh_raycast_project_ray_root(
- PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
+ PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3]);
-void BKE_pbvh_find_nearest_to_ray(PBVH *bvh,
+void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const float ray_start[3],
const float ray_normal[3],
bool original);
-bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
+bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -190,7 +190,7 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
/* Drawing */
-void BKE_pbvh_draw_cb(PBVH *bvh,
+void BKE_pbvh_draw_cb(PBVH *pbvh,
bool update_only_visible,
PBVHFrustumPlanes *update_frustum,
PBVHFrustumPlanes *draw_frustum,
@@ -198,7 +198,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
void *user_data);
void BKE_pbvh_draw_debug_cb(
- PBVH *bvh,
+ PBVH *pbvh,
void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
void *user_data);
@@ -209,26 +209,27 @@ typedef enum {
PBVH_BMESH,
} PBVHType;
-PBVHType BKE_pbvh_type(const PBVH *bvh);
-bool BKE_pbvh_has_faces(const PBVH *bvh);
+PBVHType BKE_pbvh_type(const PBVH *pbvh);
+bool BKE_pbvh_has_faces(const PBVH *pbvh);
/* Get the PBVH root's bounding box */
-void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3]);
+void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3]);
/* multires hidden data, only valid for type == PBVH_GRIDS */
-unsigned int **BKE_pbvh_grid_hidden(const PBVH *bvh);
+unsigned int **BKE_pbvh_grid_hidden(const PBVH *pbvh);
int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
int *grid_indices,
int totgrid,
int gridsize);
-void BKE_pbvh_sync_face_sets_to_grids(PBVH *bvh);
+void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh);
/* multires level, only valid for type == PBVH_GRIDS */
const struct CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh);
struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh);
+BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh);
int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh);
/* Only valid for type == PBVH_BMESH */
@@ -239,7 +240,7 @@ typedef enum {
PBVH_Subdivide = 1,
PBVH_Collapse = 2,
} PBVHTopologyUpdateMode;
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
+bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
@@ -262,15 +263,15 @@ bool BKE_pbvh_node_fully_masked_get(PBVHNode *node);
void BKE_pbvh_node_fully_unmasked_set(PBVHNode *node, int fully_masked);
bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node);
-void BKE_pbvh_node_get_grids(PBVH *bvh,
+void BKE_pbvh_node_get_grids(PBVH *pbvh,
PBVHNode *node,
int **grid_indices,
int *totgrid,
int *maxgrid,
int *gridsize,
struct CCGElem ***grid_elems);
-void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *r_totvert);
-void BKE_pbvh_node_get_verts(PBVH *bvh,
+void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert);
+void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
struct MVert **r_verts);
@@ -289,27 +290,27 @@ struct GSet *BKE_pbvh_bmesh_node_unique_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_other_verts(PBVHNode *node);
struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node);
void BKE_pbvh_bmesh_node_save_orig(struct BMesh *bm, PBVHNode *node);
-void BKE_pbvh_bmesh_after_stroke(PBVH *bvh);
+void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh);
/* Update Bounding Box/Redraw and clear flags */
-void BKE_pbvh_update_bounds(PBVH *bvh, int flags);
-void BKE_pbvh_update_vertex_data(PBVH *bvh, int flags);
-void BKE_pbvh_update_visibility(PBVH *bvh);
-void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg);
-void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3]);
-void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface);
-void BKE_pbvh_grids_update(PBVH *bvh,
+void BKE_pbvh_update_bounds(PBVH *pbvh, int flags);
+void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flags);
+void BKE_pbvh_update_visibility(PBVH *pbvh);
+void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg);
+void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3]);
+void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface);
+void BKE_pbvh_grids_update(PBVH *pbvh,
struct CCGElem **grid_elems,
void **gridfaces,
struct DMFlagMat *flagmats,
unsigned int **grid_hidden);
-void BKE_pbvh_subdiv_cgg_set(PBVH *bvh, struct SubdivCCG *subdiv_ccg);
-void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets);
+void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, struct SubdivCCG *subdiv_ccg);
+void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets);
-void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default);
+void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default);
-void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide);
+void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide);
/* vertex deformer */
float (*BKE_pbvh_vert_coords_alloc(struct PBVH *pbvh))[3];
@@ -370,10 +371,10 @@ typedef struct PBVHVertexIter {
bool visible;
} PBVHVertexIter;
-void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
+void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode);
-#define BKE_pbvh_vertex_iter_begin(bvh, node, vi, mode) \
- pbvh_vertex_iter_init(bvh, node, &vi, mode); \
+#define BKE_pbvh_vertex_iter_begin(pbvh, node, vi, mode) \
+ pbvh_vertex_iter_init(pbvh, node, &vi, mode); \
\
for (vi.i = 0, vi.g = 0; vi.g < vi.totgrid; vi.g++) { \
if (vi.grids) { \
@@ -446,30 +447,30 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
void BKE_pbvh_node_get_proxies(PBVHNode *node, PBVHProxyNode **proxies, int *proxy_count);
void BKE_pbvh_node_free_proxies(PBVHNode *node);
-PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node);
+PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node);
void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***nodes, int *totnode);
void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
int (**r_orco_tris)[3],
int *r_orco_tris_num,
float (**r_orco_coords)[3]);
-bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node);
+bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node);
// void BKE_pbvh_node_BB_reset(PBVHNode *node);
// void BKE_pbvh_node_BB_expand(PBVHNode *node, float co[3]);
-bool pbvh_has_mask(PBVH *bvh);
-void pbvh_show_mask_set(PBVH *bvh, bool show_mask);
+bool pbvh_has_mask(PBVH *pbvh);
+void pbvh_show_mask_set(PBVH *pbvh, bool show_mask);
-bool pbvh_has_face_sets(PBVH *bvh);
-void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets);
+bool pbvh_has_face_sets(PBVH *pbvh);
+void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets);
/* Parallelization */
void BKE_pbvh_parallel_range_settings(struct TaskParallelSettings *settings,
bool use_threading,
int totnode);
-struct MVert *BKE_pbvh_get_verts(const PBVH *bvh);
+struct MVert *BKE_pbvh_get_verts(const PBVH *pbvh);
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/intern/blender.c b/source/blender/blenkernel/intern/blender.c
index 1fb4ca95c93..e8aa13a8beb 100644
--- a/source/blender/blenkernel/intern/blender.c
+++ b/source/blender/blenkernel/intern/blender.c
@@ -102,7 +102,7 @@ void BKE_blender_free(void)
free_nodesystem();
}
-static void blender_version_init()
+static void blender_version_init(void)
{
const char *version_cycle = "";
if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
@@ -130,7 +130,7 @@ static void blender_version_init()
version_cycle);
}
-const char *BKE_blender_version_string()
+const char *BKE_blender_version_string(void)
{
return blender_version_string;
}
diff --git a/source/blender/blenkernel/intern/brush.c b/source/blender/blenkernel/intern/brush.c
index 133917e441c..3241518cae5 100644
--- a/source/blender/blenkernel/intern/brush.c
+++ b/source/blender/blenkernel/intern/brush.c
@@ -520,6 +520,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2);
if (ma == NULL) {
ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
+ ma->gp_style->mode = GP_MATERIAL_MODE_DOT;
}
brush->gpencil_settings->material = ma;
/* Pin the matterial to the brush. */
@@ -744,6 +745,7 @@ void BKE_gpencil_brush_preset_set(Main *bmain, Brush *brush, const short type)
Material *ma = BLI_findstring(&bmain->materials, "Dots Stroke", offsetof(ID, name) + 2);
if (ma == NULL) {
ma = BKE_gpencil_material_add(bmain, "Dots Stroke");
+ ma->gp_style->mode = GP_MATERIAL_MODE_DOT;
}
brush->gpencil_settings->material = ma;
/* Pin the matterial to the brush. */
diff --git a/source/blender/blenkernel/intern/bvhutils.c b/source/blender/blenkernel/intern/bvhutils.c
index cd90ebc2eed..93794eb9709 100644
--- a/source/blender/blenkernel/intern/bvhutils.c
+++ b/source/blender/blenkernel/intern/bvhutils.c
@@ -41,8 +41,126 @@
#include "MEM_guardedalloc.h"
-static ThreadRWMutex cache_rwlock = BLI_RWLOCK_INITIALIZER;
+/* -------------------------------------------------------------------- */
+/** \name BVHCache
+ * \{ */
+
+typedef struct BVHCacheItem {
+ bool is_filled;
+ BVHTree *tree;
+} BVHCacheItem;
+
+typedef struct BVHCache {
+ BVHCacheItem items[BVHTREE_MAX_ITEM];
+ ThreadMutex mutex;
+} BVHCache;
+
+/**
+ * Queries a bvhcache for the cache bvhtree of the request type
+ *
+ * When the `r_locked` is filled and the tree could not be found the caches mutex will be
+ * locked. This mutex can be unlocked by calling `bvhcache_unlock`.
+ *
+ * When `r_locked` is used the `mesh_eval_mutex` must contain the `Mesh_Runtime.eval_mutex`.
+ */
+static bool bvhcache_find(BVHCache **bvh_cache_p,
+ BVHCacheType type,
+ BVHTree **r_tree,
+ bool *r_locked,
+ ThreadMutex *mesh_eval_mutex)
+{
+ bool do_lock = r_locked;
+ if (r_locked) {
+ *r_locked = false;
+ }
+ if (*bvh_cache_p == NULL) {
+ if (!do_lock) {
+ /* Cache does not exist and no lock is requested. */
+ return false;
+ }
+ /* Lazy initialization of the bvh_cache using the `mesh_eval_mutex`. */
+ BLI_mutex_lock(mesh_eval_mutex);
+ if (*bvh_cache_p == NULL) {
+ *bvh_cache_p = bvhcache_init();
+ }
+ BLI_mutex_unlock(mesh_eval_mutex);
+ }
+ BVHCache *bvh_cache = *bvh_cache_p;
+ if (bvh_cache->items[type].is_filled) {
+ *r_tree = bvh_cache->items[type].tree;
+ return true;
+ }
+ if (do_lock) {
+ BLI_mutex_lock(&bvh_cache->mutex);
+ bool in_cache = bvhcache_find(bvh_cache_p, type, r_tree, NULL, NULL);
+ if (in_cache) {
+ BLI_mutex_unlock(&bvh_cache->mutex);
+ return in_cache;
+ }
+ *r_locked = true;
+ }
+ return false;
+}
+
+static void bvhcache_unlock(BVHCache *bvh_cache, bool lock_started)
+{
+ if (lock_started) {
+ BLI_mutex_unlock(&bvh_cache->mutex);
+ }
+}
+
+bool bvhcache_has_tree(const BVHCache *bvh_cache, const BVHTree *tree)
+{
+ if (bvh_cache == NULL) {
+ return false;
+ }
+
+ for (BVHCacheType i = 0; i < BVHTREE_MAX_ITEM; i++) {
+ if (bvh_cache->items[i].tree == tree) {
+ return true;
+ }
+ }
+ return false;
+}
+
+BVHCache *bvhcache_init(void)
+{
+ BVHCache *cache = MEM_callocN(sizeof(BVHCache), __func__);
+ BLI_mutex_init(&cache->mutex);
+ return cache;
+}
+/**
+ * Inserts a BVHTree of the given type under the cache
+ * After that the caller no longer needs to worry when to free the BVHTree
+ * as that will be done when the cache is freed.
+ *
+ * A call to this assumes that there was no previous cached tree of the given type
+ * \warning The #BVHTree can be NULL.
+ */
+static void bvhcache_insert(BVHCache *bvh_cache, BVHTree *tree, BVHCacheType type)
+{
+ BVHCacheItem *item = &bvh_cache->items[type];
+ BLI_assert(!item->is_filled);
+ item->tree = tree;
+ item->is_filled = true;
+}
+
+/**
+ * frees a bvhcache
+ */
+void bvhcache_free(BVHCache *bvh_cache)
+{
+ for (BVHCacheType index = 0; index < BVHTREE_MAX_ITEM; index++) {
+ BVHCacheItem *item = &bvh_cache->items[index];
+ BLI_bvhtree_free(item->tree);
+ item->tree = NULL;
+ }
+ BLI_mutex_end(&bvh_cache->mutex);
+ MEM_freeN(bvh_cache);
+}
+
+/** \} */
/* -------------------------------------------------------------------- */
/** \name Local Callbacks
* \{ */
@@ -518,29 +636,26 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (bvh_cache_p) {
+ bool lock_started = false;
+ data->cached = bvhcache_find(
+ bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
if (data->cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- if (data->cached == false) {
- tree = bvhtree_from_editmesh_verts_create_tree(
- epsilon, tree_type, axis, em, verts_mask, verts_num_active);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- data->cached = true;
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ tree = bvhtree_from_editmesh_verts_create_tree(
+ epsilon, tree_type, axis, em, verts_mask, verts_num_active);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(*bvh_cache_p, tree, bvh_cache_type);
+ data->cached = true;
}
+ bvhcache_unlock(*bvh_cache_p, lock_started);
}
else {
tree = bvhtree_from_editmesh_verts_create_tree(
@@ -553,7 +668,7 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
data->em = em;
data->nearest_callback = NULL;
data->raycast_callback = editmesh_verts_spherecast;
- data->cached = bvh_cache != NULL;
+ data->cached = bvh_cache_p != NULL;
}
return tree;
@@ -562,7 +677,8 @@ BVHTree *bvhtree_from_editmesh_verts_ex(BVHTreeFromEditMesh *data,
BVHTree *bvhtree_from_editmesh_verts(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_verts_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
+ return bvhtree_from_editmesh_verts_ex(
+ data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
}
/**
@@ -582,32 +698,26 @@ BVHTree *bvhtree_from_mesh_verts_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
tree = bvhtree_from_mesh_verts_create_tree(
epsilon, tree_type, axis, vert, verts_num, verts_mask, verts_num_active);
- if (bvh_cache) {
+ if (bvh_cache_p) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
+ BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -735,29 +845,26 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
-
+ if (bvh_cache_p) {
+ bool lock_started = false;
+ data->cached = bvhcache_find(
+ bvh_cache_p, bvh_cache_type, &data->tree, &lock_started, mesh_eval_mutex);
+ BVHCache *bvh_cache = *bvh_cache_p;
if (data->cached == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- data->cached = bvhcache_find(*bvh_cache, bvh_cache_type, &data->tree);
- if (data->cached == false) {
- tree = bvhtree_from_editmesh_edges_create_tree(
- epsilon, tree_type, axis, em, edges_mask, edges_num_active);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- data->cached = true;
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ tree = bvhtree_from_editmesh_edges_create_tree(
+ epsilon, tree_type, axis, em, edges_mask, edges_num_active);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
+ data->cached = true;
}
+ bvhcache_unlock(bvh_cache, lock_started);
}
else {
tree = bvhtree_from_editmesh_edges_create_tree(
@@ -770,7 +877,7 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
data->em = em;
data->nearest_callback = NULL; /* TODO */
data->raycast_callback = NULL; /* TODO */
- data->cached = bvh_cache != NULL;
+ data->cached = bvh_cache_p != NULL;
}
return tree;
@@ -779,7 +886,8 @@ BVHTree *bvhtree_from_editmesh_edges_ex(BVHTreeFromEditMesh *data,
BVHTree *bvhtree_from_editmesh_edges(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_edges_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
+ return bvhtree_from_editmesh_edges_ex(
+ data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
}
/**
@@ -802,32 +910,26 @@ BVHTree *bvhtree_from_mesh_edges_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
tree = bvhtree_from_mesh_edges_create_tree(
vert, edge, edges_num, edges_mask, edges_num_active, epsilon, tree_type, axis);
- if (bvh_cache) {
+ if (bvh_cache_p) {
+ BVHCache *bvh_cache = *bvh_cache_p;
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -937,32 +1039,26 @@ BVHTree *bvhtree_from_mesh_faces_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
tree = bvhtree_from_mesh_faces_create_tree(
epsilon, tree_type, axis, vert, face, numFaces, faces_mask, faces_num_active);
- if (bvh_cache) {
+ if (bvh_cache_p) {
/* Save on cache for later use */
/* printf("BVHTree built and saved on cache\n"); */
+ BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -1113,29 +1209,28 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
/* BMESH specific check that we have tessfaces,
* we _could_ tessellate here but rather not - campbell */
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- bool in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (bvh_cache_p) {
+ bool lock_started = false;
+ bool in_cache = bvhcache_find(
+ bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
+ BVHCache *bvh_cache = *bvh_cache_p;
+
if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache == false) {
- tree = bvhtree_from_editmesh_looptri_create_tree(
- epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
-
- /* Save on cache for later use */
- /* printf("BVHTree built and saved on cache\n"); */
- bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- }
- BLI_rw_mutex_unlock(&cache_rwlock);
+ tree = bvhtree_from_editmesh_looptri_create_tree(
+ epsilon, tree_type, axis, em, looptri_mask, looptri_num_active);
+
+ /* Save on cache for later use */
+ /* printf("BVHTree built and saved on cache\n"); */
+ bvhcache_insert(bvh_cache, tree, bvh_cache_type);
}
+ bvhcache_unlock(bvh_cache, lock_started);
}
else {
tree = bvhtree_from_editmesh_looptri_create_tree(
@@ -1147,7 +1242,7 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
data->nearest_callback = editmesh_looptri_nearest_point;
data->raycast_callback = editmesh_looptri_spherecast;
data->em = em;
- data->cached = bvh_cache != NULL;
+ data->cached = bvh_cache_p != NULL;
}
return tree;
}
@@ -1155,7 +1250,8 @@ BVHTree *bvhtree_from_editmesh_looptri_ex(BVHTreeFromEditMesh *data,
BVHTree *bvhtree_from_editmesh_looptri(
BVHTreeFromEditMesh *data, BMEditMesh *em, float epsilon, int tree_type, int axis)
{
- return bvhtree_from_editmesh_looptri_ex(data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL);
+ return bvhtree_from_editmesh_looptri_ex(
+ data, em, NULL, -1, epsilon, tree_type, axis, 0, NULL, NULL);
}
/**
@@ -1177,21 +1273,14 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
int tree_type,
int axis,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
bool in_cache = false;
+ bool lock_started = false;
BVHTree *tree = NULL;
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
- if (in_cache == false) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_WRITE);
- in_cache = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- if (in_cache) {
- BLI_rw_mutex_unlock(&cache_rwlock);
- }
- }
+ if (bvh_cache_p) {
+ in_cache = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, &lock_started, mesh_eval_mutex);
}
if (in_cache == false) {
@@ -1206,9 +1295,10 @@ BVHTree *bvhtree_from_mesh_looptri_ex(BVHTreeFromMesh *data,
looptri_mask,
looptri_num_active);
- if (bvh_cache) {
+ if (bvh_cache_p) {
+ BVHCache *bvh_cache = *bvh_cache_p;
bvhcache_insert(bvh_cache, tree, bvh_cache_type);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bvhcache_unlock(bvh_cache, lock_started);
in_cache = true;
}
}
@@ -1315,11 +1405,10 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
const int tree_type)
{
BVHTree *tree = NULL;
- BVHCache **bvh_cache = &mesh->runtime.bvh_cache;
+ BVHCache **bvh_cache_p = (BVHCache **)&mesh->runtime.bvh_cache;
+ ThreadMutex *mesh_eval_mutex = (ThreadMutex *)mesh->runtime.eval_mutex;
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- bool is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ bool is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
if (is_cached && tree == NULL) {
memset(data, 0, sizeof(*data));
@@ -1351,7 +1440,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
if (loose_verts_mask != NULL) {
MEM_freeN(loose_verts_mask);
@@ -1386,7 +1476,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
if (loose_edges_mask != NULL) {
MEM_freeN(loose_edges_mask);
@@ -1416,7 +1507,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1452,7 +1544,8 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
tree_type,
6,
bvh_cache_type,
- bvh_cache);
+ bvh_cache_p,
+ mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1464,6 +1557,7 @@ BVHTree *BKE_bvhtree_from_mesh_get(struct BVHTreeFromMesh *data,
case BVHTREE_FROM_EM_VERTS:
case BVHTREE_FROM_EM_EDGES:
case BVHTREE_FROM_EM_LOOPTRI:
+ case BVHTREE_MAX_ITEM:
BLI_assert(false);
break;
}
@@ -1493,17 +1587,16 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
struct BMEditMesh *em,
const int tree_type,
const BVHCacheType bvh_cache_type,
- BVHCache **bvh_cache)
+ BVHCache **bvh_cache_p,
+ ThreadMutex *mesh_eval_mutex)
{
BVHTree *tree = NULL;
bool is_cached = false;
memset(data, 0, sizeof(*data));
- if (bvh_cache) {
- BLI_rw_mutex_lock(&cache_rwlock, THREAD_LOCK_READ);
- is_cached = bvhcache_find(*bvh_cache, bvh_cache_type, &tree);
- BLI_rw_mutex_unlock(&cache_rwlock);
+ if (bvh_cache_p) {
+ is_cached = bvhcache_find(bvh_cache_p, bvh_cache_type, &tree, NULL, NULL);
if (is_cached && tree == NULL) {
return tree;
@@ -1517,7 +1610,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_EM_VERTS:
if (is_cached == false) {
tree = bvhtree_from_editmesh_verts_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
}
else {
data->nearest_callback = NULL;
@@ -1528,7 +1621,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_EM_EDGES:
if (is_cached == false) {
tree = bvhtree_from_editmesh_edges_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1540,7 +1633,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_EM_LOOPTRI:
if (is_cached == false) {
tree = bvhtree_from_editmesh_looptri_ex(
- data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache);
+ data, em, NULL, -1, 0.0f, tree_type, 6, bvh_cache_type, bvh_cache_p, mesh_eval_mutex);
}
else {
/* Setup BVHTreeFromMesh */
@@ -1555,6 +1648,7 @@ BVHTree *BKE_bvhtree_from_editmesh_get(BVHTreeFromEditMesh *data,
case BVHTREE_FROM_LOOPTRI_NO_HIDDEN:
case BVHTREE_FROM_LOOSEVERTS:
case BVHTREE_FROM_LOOSEEDGES:
+ case BVHTREE_MAX_ITEM:
BLI_assert(false);
break;
}
@@ -1615,82 +1709,3 @@ void free_bvhtree_from_mesh(struct BVHTreeFromMesh *data)
memset(data, 0, sizeof(*data));
}
-
-/* -------------------------------------------------------------------- */
-/** \name BVHCache
- * \{ */
-
-typedef struct BVHCacheItem {
- BVHCacheType type;
- BVHTree *tree;
-
-} BVHCacheItem;
-
-/**
- * Queries a bvhcache for the cache bvhtree of the request type
- */
-bool bvhcache_find(const BVHCache *cache, BVHCacheType type, BVHTree **r_tree)
-{
- while (cache) {
- const BVHCacheItem *item = cache->link;
- if (item->type == type) {
- *r_tree = item->tree;
- return true;
- }
- cache = cache->next;
- }
- return false;
-}
-
-bool bvhcache_has_tree(const BVHCache *cache, const BVHTree *tree)
-{
- while (cache) {
- const BVHCacheItem *item = cache->link;
- if (item->tree == tree) {
- return true;
- }
- cache = cache->next;
- }
- return false;
-}
-
-/**
- * Inserts a BVHTree of the given type under the cache
- * After that the caller no longer needs to worry when to free the BVHTree
- * as that will be done when the cache is freed.
- *
- * A call to this assumes that there was no previous cached tree of the given type
- * \warning The #BVHTree can be NULL.
- */
-void bvhcache_insert(BVHCache **cache_p, BVHTree *tree, BVHCacheType type)
-{
- BVHCacheItem *item = NULL;
-
- BLI_assert(bvhcache_find(*cache_p, type, &(BVHTree *){0}) == false);
-
- item = MEM_mallocN(sizeof(BVHCacheItem), "BVHCacheItem");
-
- item->type = type;
- item->tree = tree;
-
- BLI_linklist_prepend(cache_p, item);
-}
-
-/**
- * frees a bvhcache
- */
-static void bvhcacheitem_free(void *_item)
-{
- BVHCacheItem *item = (BVHCacheItem *)_item;
-
- BLI_bvhtree_free(item->tree);
- MEM_freeN(item);
-}
-
-void bvhcache_free(BVHCache **cache_p)
-{
- BLI_linklist_free(*cache_p, (LinkNodeFreeFP)bvhcacheitem_free);
- *cache_p = NULL;
-}
-
-/** \} */
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index a28cc73cb94..1352c0b8a14 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -210,6 +210,34 @@ Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const
return collection;
}
+/**
+ * Add \a collection_dst to all scene collections that reference object \a ob_src is in.
+ * Used to replace an instance object with a collection (library override operator).
+ *
+ * Logic is very similar to #BKE_collection_object_add_from().
+ */
+void BKE_collection_add_from_object(Main *bmain,
+ Scene *scene,
+ const Object *ob_src,
+ Collection *collection_dst)
+{
+ bool is_instantiated = false;
+
+ FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
+ if (!ID_IS_LINKED(collection) && BKE_collection_has_object(collection, ob_src)) {
+ collection_child_add(collection, collection_dst, 0, true);
+ is_instantiated = true;
+ }
+ }
+ FOREACH_SCENE_COLLECTION_END;
+
+ if (!is_instantiated) {
+ collection_child_add(scene->master_collection, collection_dst, 0, true);
+ }
+
+ BKE_main_collection_sync(bmain);
+}
+
/*********************** Free and Delete Collection ****************************/
/** Free (or release) any data used by this collection (does not free the collection itself). */
@@ -761,8 +789,10 @@ bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
}
/**
- * Add object to all scene collections that reference object is in
- * (used to copy objects).
+ * Add \a ob_dst to all scene collections that reference object \a ob_src is in.
+ * Used for copying objects.
+ *
+ * Logic is very similar to #BKE_collection_add_from_object()
*/
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
{
diff --git a/source/blender/blenkernel/intern/gpencil.c b/source/blender/blenkernel/intern/gpencil.c
index 7f65dfc2b51..5ba3bfa0ff7 100644
--- a/source/blender/blenkernel/intern/gpencil.c
+++ b/source/blender/blenkernel/intern/gpencil.c
@@ -1895,8 +1895,13 @@ bool BKE_gpencil_from_image(SpaceImage *sima, bGPDframe *gpf, const float size,
*
* \{ */
-void BKE_gpencil_visible_stroke_iter(
- Object *ob, gpIterCb layer_cb, gpIterCb stroke_cb, void *thunk, bool do_onion, int cfra)
+void BKE_gpencil_visible_stroke_iter(ViewLayer *view_layer,
+ Object *ob,
+ gpIterCb layer_cb,
+ gpIterCb stroke_cb,
+ void *thunk,
+ bool do_onion,
+ int cfra)
{
bGPdata *gpd = (bGPdata *)ob->data;
const bool is_multiedit = GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
@@ -1918,6 +1923,14 @@ void BKE_gpencil_visible_stroke_iter(
continue;
}
+ /* Hide the layer if it's defined a view layer filter. This is used to
+ * generate renders, putting only selected GP layers for each View Layer.
+ * This is used only in final render and never in Viewport. */
+ if ((view_layer != NULL) && (gpl->viewlayername[0] != '\0') &&
+ (!STREQ(view_layer->name, gpl->viewlayername))) {
+ continue;
+ }
+
if (is_multiedit) {
sta_gpf = end_gpf = NULL;
/* Check the whole range and tag the editable frames. */
diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c
index 795390f1940..9426d229e01 100644
--- a/source/blender/blenkernel/intern/lib_override.c
+++ b/source/blender/blenkernel/intern/lib_override.c
@@ -46,6 +46,11 @@
#include "RNA_types.h"
#define OVERRIDE_AUTO_CHECK_DELAY 0.2 /* 200ms between auto-override checks. */
+//#define DEBUG_OVERRIDE_TIMEIT
+
+#ifdef DEBUG_OVERRIDE_TIMEIT
+# include "PIL_time_utildefines.h"
+#endif
static void lib_override_library_property_copy(IDOverrideLibraryProperty *op_dst,
IDOverrideLibraryProperty *op_src);
@@ -1027,7 +1032,7 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
ID *storage_id;
#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_START_AVERAGED(BKE_override_operations_store_start);
+ TIMEIT_START_AVERAGED(BKE_lib_override_library_operations_store_start);
#endif
/* XXX TODO We may also want a specialized handling of things here too, to avoid copying heavy
@@ -1055,12 +1060,13 @@ ID *BKE_lib_override_library_operations_store_start(Main *bmain,
local->override_library->storage = storage_id;
#ifdef DEBUG_OVERRIDE_TIMEIT
- TIMEIT_END_AVERAGED(BKE_override_operations_store_start);
+ TIMEIT_END_AVERAGED(BKE_lib_override_library_operations_store_start);
#endif
return storage_id;
}
-/** Restore given ID modified by \a BKE_override_operations_store_start, to its original state. */
+/** Restore given ID modified by \a BKE_lib_override_library_operations_store_start, to its
+ * original state. */
void BKE_lib_override_library_operations_store_end(
OverrideLibraryStorage *UNUSED(override_storage), ID *local)
{
diff --git a/source/blender/blenkernel/intern/mesh_remap.c b/source/blender/blenkernel/intern/mesh_remap.c
index d09205b5744..404d6a581ae 100644
--- a/source/blender/blenkernel/intern/mesh_remap.c
+++ b/source/blender/blenkernel/intern/mesh_remap.c
@@ -1555,6 +1555,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
2,
6,
0,
+ NULL,
NULL);
}
@@ -1598,6 +1599,7 @@ void BKE_mesh_remap_calc_loops_from_mesh(const int mode,
2,
6,
0,
+ NULL,
NULL);
}
diff --git a/source/blender/blenkernel/intern/mesh_runtime.c b/source/blender/blenkernel/intern/mesh_runtime.c
index aa3586d1e3d..8bce577897b 100644
--- a/source/blender/blenkernel/intern/mesh_runtime.c
+++ b/source/blender/blenkernel/intern/mesh_runtime.c
@@ -53,6 +53,7 @@ void BKE_mesh_runtime_reset(Mesh *mesh)
memset(&mesh->runtime, 0, sizeof(mesh->runtime));
mesh->runtime.eval_mutex = MEM_mallocN(sizeof(ThreadMutex), "mesh runtime eval_mutex");
BLI_mutex_init(mesh->runtime.eval_mutex);
+ mesh->runtime.bvh_cache = NULL;
}
/* Clear all pointers which we don't want to be shared on copying the datablock.
@@ -227,7 +228,10 @@ bool BKE_mesh_runtime_clear_edit_data(Mesh *mesh)
void BKE_mesh_runtime_clear_geometry(Mesh *mesh)
{
- bvhcache_free(&mesh->runtime.bvh_cache);
+ if (mesh->runtime.bvh_cache) {
+ bvhcache_free(mesh->runtime.bvh_cache);
+ mesh->runtime.bvh_cache = NULL;
+ }
MEM_SAFE_FREE(mesh->runtime.looptris.array);
/* TODO(sergey): Does this really belong here? */
if (mesh->runtime.subdiv_ccg != NULL) {
diff --git a/source/blender/blenkernel/intern/pbvh.c b/source/blender/blenkernel/intern/pbvh.c
index e31d2a8e005..19f28047b80 100644
--- a/source/blender/blenkernel/intern/pbvh.c
+++ b/source/blender/blenkernel/intern/pbvh.c
@@ -61,7 +61,7 @@ typedef struct PBVHStack {
} PBVHStack;
typedef struct PBVHIter {
- PBVH *bvh;
+ PBVH *pbvh;
BKE_pbvh_SearchCallback scb;
void *search_data;
@@ -131,7 +131,7 @@ void BBC_update_centroid(BBC *bbc)
}
/* Not recursive */
-static void update_node_vb(PBVH *bvh, PBVHNode *node)
+static void update_node_vb(PBVH *pbvh, PBVHNode *node)
{
BB vb;
@@ -140,15 +140,15 @@ static void update_node_vb(PBVH *bvh, PBVHNode *node)
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
BB_expand(&vb, vd.co);
}
BKE_pbvh_vertex_iter_end;
}
else {
- BB_expand_with_bb(&vb, &bvh->nodes[node->children_offset].vb);
- BB_expand_with_bb(&vb, &bvh->nodes[node->children_offset + 1].vb);
+ BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset].vb);
+ BB_expand_with_bb(&vb, &pbvh->nodes[node->children_offset + 1].vb);
}
node->vb = vb;
@@ -197,24 +197,24 @@ static int partition_indices(int *prim_indices, int lo, int hi, int axis, float
}
/* Returns the index of the first element on the right of the partition */
-static int partition_indices_material(PBVH *bvh, int lo, int hi)
+static int partition_indices_material(PBVH *pbvh, int lo, int hi)
{
- const MPoly *mpoly = bvh->mpoly;
- const MLoopTri *looptri = bvh->looptri;
- const DMFlagMat *flagmats = bvh->grid_flag_mats;
- const int *indices = bvh->prim_indices;
+ const MPoly *mpoly = pbvh->mpoly;
+ const MLoopTri *looptri = pbvh->looptri;
+ const DMFlagMat *flagmats = pbvh->grid_flag_mats;
+ const int *indices = pbvh->prim_indices;
const void *first;
int i = lo, j = hi;
- if (bvh->looptri) {
- first = &mpoly[looptri[bvh->prim_indices[lo]].poly];
+ if (pbvh->looptri) {
+ first = &mpoly[looptri[pbvh->prim_indices[lo]].poly];
}
else {
- first = &flagmats[bvh->prim_indices[lo]];
+ first = &flagmats[pbvh->prim_indices[lo]];
}
for (;;) {
- if (bvh->looptri) {
+ if (pbvh->looptri) {
for (; face_materials_match(first, &mpoly[looptri[indices[i]].poly]); i++) {
/* pass */
}
@@ -235,36 +235,36 @@ static int partition_indices_material(PBVH *bvh, int lo, int hi)
return i;
}
- SWAP(int, bvh->prim_indices[i], bvh->prim_indices[j]);
+ SWAP(int, pbvh->prim_indices[i], pbvh->prim_indices[j]);
i++;
}
}
-void pbvh_grow_nodes(PBVH *bvh, int totnode)
+void pbvh_grow_nodes(PBVH *pbvh, int totnode)
{
- if (UNLIKELY(totnode > bvh->node_mem_count)) {
- bvh->node_mem_count = bvh->node_mem_count + (bvh->node_mem_count / 3);
- if (bvh->node_mem_count < totnode) {
- bvh->node_mem_count = totnode;
+ if (UNLIKELY(totnode > pbvh->node_mem_count)) {
+ pbvh->node_mem_count = pbvh->node_mem_count + (pbvh->node_mem_count / 3);
+ if (pbvh->node_mem_count < totnode) {
+ pbvh->node_mem_count = totnode;
}
- bvh->nodes = MEM_recallocN(bvh->nodes, sizeof(PBVHNode) * bvh->node_mem_count);
+ pbvh->nodes = MEM_recallocN(pbvh->nodes, sizeof(PBVHNode) * pbvh->node_mem_count);
}
- bvh->totnode = totnode;
+ pbvh->totnode = totnode;
}
/* Add a vertex to the map, with a positive value for unique vertices and
* a negative value for additional vertices */
static int map_insert_vert(
- PBVH *bvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex)
+ PBVH *pbvh, GHash *map, unsigned int *face_verts, unsigned int *uniq_verts, int vertex)
{
void *key, **value_p;
key = POINTER_FROM_INT(vertex);
if (!BLI_ghash_ensure_p(map, key, &value_p)) {
int value_i;
- if (BLI_BITMAP_TEST(bvh->vert_bitmap, vertex) == 0) {
- BLI_BITMAP_ENABLE(bvh->vert_bitmap, vertex);
+ if (BLI_BITMAP_TEST(pbvh->vert_bitmap, vertex) == 0) {
+ BLI_BITMAP_ENABLE(pbvh->vert_bitmap, vertex);
value_i = *uniq_verts;
(*uniq_verts)++;
}
@@ -281,7 +281,7 @@ static int map_insert_vert(
}
/* Find vertices used by the faces in this node and update the draw buffers */
-static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
+static void build_mesh_leaf_node(PBVH *pbvh, PBVHNode *node)
{
bool has_visible = false;
@@ -295,19 +295,19 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
node->face_vert_indices = (const int(*)[3])face_vert_indices;
- if (bvh->respect_hide == false) {
+ if (pbvh->respect_hide == false) {
has_visible = true;
}
for (int i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[node->prim_indices[i]];
+ const MLoopTri *lt = &pbvh->looptri[node->prim_indices[i]];
for (int j = 0; j < 3; j++) {
face_vert_indices[i][j] = map_insert_vert(
- bvh, map, &node->face_verts, &node->uniq_verts, bvh->mloop[lt->tri[j]].v);
+ pbvh, map, &node->face_verts, &node->uniq_verts, pbvh->mloop[lt->tri[j]].v);
}
if (has_visible == false) {
- if (!paint_is_face_hidden(lt, bvh->verts, bvh->mloop)) {
+ if (!paint_is_face_hidden(lt, pbvh->verts, pbvh->mloop)) {
has_visible = true;
}
}
@@ -347,11 +347,11 @@ static void build_mesh_leaf_node(PBVH *bvh, PBVHNode *node)
BLI_ghash_free(map, NULL, NULL);
}
-static void update_vb(PBVH *bvh, PBVHNode *node, BBC *prim_bbc, int offset, int count)
+static void update_vb(PBVH *pbvh, PBVHNode *node, BBC *prim_bbc, int offset, int count)
{
BB_reset(&node->vb);
for (int i = offset + count - 1; i >= offset; i--) {
- BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[bvh->prim_indices[i]]));
+ BB_expand_with_bb(&node->vb, (BB *)(&prim_bbc[pbvh->prim_indices[i]]));
}
node->orig_vb = node->vb;
}
@@ -389,77 +389,78 @@ int BKE_pbvh_count_grid_quads(BLI_bitmap **grid_hidden,
return totquad;
}
-void BKE_pbvh_sync_face_sets_to_grids(PBVH *bvh)
+void BKE_pbvh_sync_face_sets_to_grids(PBVH *pbvh)
{
- const int gridsize = bvh->gridkey.grid_size;
- for (int i = 0; i < bvh->totgrid; i++) {
- BLI_bitmap *gh = bvh->grid_hidden[i];
- const int face_index = BKE_subdiv_ccg_grid_to_face_index(bvh->subdiv_ccg, i);
- if (!gh && bvh->face_sets[face_index] < 0) {
- gh = bvh->grid_hidden[i] = BLI_BITMAP_NEW(bvh->gridkey.grid_area, "partialvis_update_grids");
+ const int gridsize = pbvh->gridkey.grid_size;
+ for (int i = 0; i < pbvh->totgrid; i++) {
+ BLI_bitmap *gh = pbvh->grid_hidden[i];
+ const int face_index = BKE_subdiv_ccg_grid_to_face_index(pbvh->subdiv_ccg, i);
+ if (!gh && pbvh->face_sets[face_index] < 0) {
+ gh = pbvh->grid_hidden[i] = BLI_BITMAP_NEW(pbvh->gridkey.grid_area,
+ "partialvis_update_grids");
}
if (gh) {
for (int y = 0; y < gridsize; y++) {
for (int x = 0; x < gridsize; x++) {
- BLI_BITMAP_SET(gh, y * gridsize + x, bvh->face_sets[face_index] < 0);
+ BLI_BITMAP_SET(gh, y * gridsize + x, pbvh->face_sets[face_index] < 0);
}
}
}
}
}
-static void build_grid_leaf_node(PBVH *bvh, PBVHNode *node)
+static void build_grid_leaf_node(PBVH *pbvh, PBVHNode *node)
{
int totquads = BKE_pbvh_count_grid_quads(
- bvh->grid_hidden, node->prim_indices, node->totprim, bvh->gridkey.grid_size);
+ pbvh->grid_hidden, node->prim_indices, node->totprim, pbvh->gridkey.grid_size);
BKE_pbvh_node_fully_hidden_set(node, (totquads == 0));
BKE_pbvh_node_mark_rebuild_draw(node);
}
-static void build_leaf(PBVH *bvh, int node_index, BBC *prim_bbc, int offset, int count)
+static void build_leaf(PBVH *pbvh, int node_index, BBC *prim_bbc, int offset, int count)
{
- bvh->nodes[node_index].flag |= PBVH_Leaf;
+ pbvh->nodes[node_index].flag |= PBVH_Leaf;
- bvh->nodes[node_index].prim_indices = bvh->prim_indices + offset;
- bvh->nodes[node_index].totprim = count;
+ pbvh->nodes[node_index].prim_indices = pbvh->prim_indices + offset;
+ pbvh->nodes[node_index].totprim = count;
/* Still need vb for searches */
- update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
+ update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
- if (bvh->looptri) {
- build_mesh_leaf_node(bvh, bvh->nodes + node_index);
+ if (pbvh->looptri) {
+ build_mesh_leaf_node(pbvh, pbvh->nodes + node_index);
}
else {
- build_grid_leaf_node(bvh, bvh->nodes + node_index);
+ build_grid_leaf_node(pbvh, pbvh->nodes + node_index);
}
}
/* Return zero if all primitives in the node can be drawn with the
* same material (including flat/smooth shading), non-zero otherwise */
-static bool leaf_needs_material_split(PBVH *bvh, int offset, int count)
+static bool leaf_needs_material_split(PBVH *pbvh, int offset, int count)
{
if (count <= 1) {
return false;
}
- if (bvh->looptri) {
- const MLoopTri *first = &bvh->looptri[bvh->prim_indices[offset]];
- const MPoly *mp = &bvh->mpoly[first->poly];
+ if (pbvh->looptri) {
+ const MLoopTri *first = &pbvh->looptri[pbvh->prim_indices[offset]];
+ const MPoly *mp = &pbvh->mpoly[first->poly];
for (int i = offset + count - 1; i > offset; i--) {
- int prim = bvh->prim_indices[i];
- const MPoly *mp_other = &bvh->mpoly[bvh->looptri[prim].poly];
+ int prim = pbvh->prim_indices[i];
+ const MPoly *mp_other = &pbvh->mpoly[pbvh->looptri[prim].poly];
if (!face_materials_match(mp, mp_other)) {
return true;
}
}
}
else {
- const DMFlagMat *first = &bvh->grid_flag_mats[bvh->prim_indices[offset]];
+ const DMFlagMat *first = &pbvh->grid_flag_mats[pbvh->prim_indices[offset]];
for (int i = offset + count - 1; i > offset; i--) {
- int prim = bvh->prim_indices[i];
- if (!grid_materials_match(first, &bvh->grid_flag_mats[prim])) {
+ int prim = pbvh->prim_indices[i];
+ if (!grid_materials_match(first, &pbvh->grid_flag_mats[prim])) {
return true;
}
}
@@ -479,26 +480,26 @@ static bool leaf_needs_material_split(PBVH *bvh, int offset, int count)
* offset and start indicate a range in the array of primitive indices
*/
-static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count)
+static void build_sub(PBVH *pbvh, int node_index, BB *cb, BBC *prim_bbc, int offset, int count)
{
int end;
BB cb_backing;
/* Decide whether this is a leaf or not */
- const bool below_leaf_limit = count <= bvh->leaf_limit;
+ const bool below_leaf_limit = count <= pbvh->leaf_limit;
if (below_leaf_limit) {
- if (!leaf_needs_material_split(bvh, offset, count)) {
- build_leaf(bvh, node_index, prim_bbc, offset, count);
+ if (!leaf_needs_material_split(pbvh, offset, count)) {
+ build_leaf(pbvh, node_index, prim_bbc, offset, count);
return;
}
}
/* Add two child nodes */
- bvh->nodes[node_index].children_offset = bvh->totnode;
- pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh->nodes[node_index].children_offset = pbvh->totnode;
+ pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
/* Update parent node bounding box */
- update_vb(bvh, &bvh->nodes[node_index], prim_bbc, offset, count);
+ update_vb(pbvh, &pbvh->nodes[node_index], prim_bbc, offset, count);
if (!below_leaf_limit) {
/* Find axis with widest range of primitive centroids */
@@ -506,13 +507,13 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offs
cb = &cb_backing;
BB_reset(cb);
for (int i = offset + count - 1; i >= offset; i--) {
- BB_expand(cb, prim_bbc[bvh->prim_indices[i]].bcentroid);
+ BB_expand(cb, prim_bbc[pbvh->prim_indices[i]].bcentroid);
}
}
const int axis = BB_widest_axis(cb);
/* Partition primitives along that axis */
- end = partition_indices(bvh->prim_indices,
+ end = partition_indices(pbvh->prim_indices,
offset,
offset + count - 1,
axis,
@@ -521,38 +522,42 @@ static void build_sub(PBVH *bvh, int node_index, BB *cb, BBC *prim_bbc, int offs
}
else {
/* Partition primitives by material */
- end = partition_indices_material(bvh, offset, offset + count - 1);
+ end = partition_indices_material(pbvh, offset, offset + count - 1);
}
/* Build children */
- build_sub(bvh, bvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset);
- build_sub(
- bvh, bvh->nodes[node_index].children_offset + 1, NULL, prim_bbc, end, offset + count - end);
+ build_sub(pbvh, pbvh->nodes[node_index].children_offset, NULL, prim_bbc, offset, end - offset);
+ build_sub(pbvh,
+ pbvh->nodes[node_index].children_offset + 1,
+ NULL,
+ prim_bbc,
+ end,
+ offset + count - end);
}
-static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
+static void pbvh_build(PBVH *pbvh, BB *cb, BBC *prim_bbc, int totprim)
{
- if (totprim != bvh->totprim) {
- bvh->totprim = totprim;
- if (bvh->nodes) {
- MEM_freeN(bvh->nodes);
+ if (totprim != pbvh->totprim) {
+ pbvh->totprim = totprim;
+ if (pbvh->nodes) {
+ MEM_freeN(pbvh->nodes);
}
- if (bvh->prim_indices) {
- MEM_freeN(bvh->prim_indices);
+ if (pbvh->prim_indices) {
+ MEM_freeN(pbvh->prim_indices);
}
- bvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices");
+ pbvh->prim_indices = MEM_mallocN(sizeof(int) * totprim, "bvh prim indices");
for (int i = 0; i < totprim; i++) {
- bvh->prim_indices[i] = i;
+ pbvh->prim_indices[i] = i;
}
- bvh->totnode = 0;
- if (bvh->node_mem_count < 100) {
- bvh->node_mem_count = 100;
- bvh->nodes = MEM_callocN(sizeof(PBVHNode) * bvh->node_mem_count, "bvh initial nodes");
+ pbvh->totnode = 0;
+ if (pbvh->node_mem_count < 100) {
+ pbvh->node_mem_count = 100;
+ pbvh->nodes = MEM_callocN(sizeof(PBVHNode) * pbvh->node_mem_count, "bvh initial nodes");
}
}
- bvh->totnode = 1;
- build_sub(bvh, 0, cb, prim_bbc, 0, totprim);
+ pbvh->totnode = 1;
+ build_sub(pbvh, 0, cb, prim_bbc, 0, totprim);
}
/**
@@ -561,7 +566,7 @@ static void pbvh_build(PBVH *bvh, BB *cb, BBC *prim_bbc, int totprim)
* \note Unlike mpoly/mloop/verts, looptri is **totally owned** by PBVH
* (which means it may rewrite it if needed, see #BKE_pbvh_vert_coords_apply().
*/
-void BKE_pbvh_build_mesh(PBVH *bvh,
+void BKE_pbvh_build_mesh(PBVH *pbvh,
const Mesh *mesh,
const MPoly *mpoly,
const MLoop *mloop,
@@ -576,21 +581,21 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
BBC *prim_bbc = NULL;
BB cb;
- bvh->mesh = mesh;
- bvh->type = PBVH_FACES;
- bvh->mpoly = mpoly;
- bvh->mloop = mloop;
- bvh->looptri = looptri;
- bvh->verts = verts;
- bvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
- bvh->totvert = totvert;
- bvh->leaf_limit = LEAF_LIMIT;
- bvh->vdata = vdata;
- bvh->ldata = ldata;
- bvh->pdata = pdata;
-
- bvh->face_sets_color_seed = mesh->face_sets_color_seed;
- bvh->face_sets_color_default = mesh->face_sets_color_default;
+ pbvh->mesh = mesh;
+ pbvh->type = PBVH_FACES;
+ pbvh->mpoly = mpoly;
+ pbvh->mloop = mloop;
+ pbvh->looptri = looptri;
+ pbvh->verts = verts;
+ pbvh->vert_bitmap = BLI_BITMAP_NEW(totvert, "bvh->vert_bitmap");
+ pbvh->totvert = totvert;
+ pbvh->leaf_limit = LEAF_LIMIT;
+ pbvh->vdata = vdata;
+ pbvh->ldata = ldata;
+ pbvh->pdata = pdata;
+
+ pbvh->face_sets_color_seed = mesh->face_sets_color_seed;
+ pbvh->face_sets_color_default = mesh->face_sets_color_default;
BB_reset(&cb);
@@ -605,7 +610,7 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
BB_reset((BB *)bbc);
for (int j = 0; j < sides; j++) {
- BB_expand((BB *)bbc, verts[bvh->mloop[lt->tri[j]].v].co);
+ BB_expand((BB *)bbc, verts[pbvh->mloop[lt->tri[j]].v].co);
}
BBC_update_centroid(bbc);
@@ -614,15 +619,15 @@ void BKE_pbvh_build_mesh(PBVH *bvh,
}
if (looptri_num) {
- pbvh_build(bvh, &cb, prim_bbc, looptri_num);
+ pbvh_build(pbvh, &cb, prim_bbc, looptri_num);
}
MEM_freeN(prim_bbc);
- MEM_freeN(bvh->vert_bitmap);
+ MEM_freeN(pbvh->vert_bitmap);
}
/* Do a full rebuild with on Grids data structure */
-void BKE_pbvh_build_grids(PBVH *bvh,
+void BKE_pbvh_build_grids(PBVH *pbvh,
CCGElem **grids,
int totgrid,
CCGKey *key,
@@ -632,14 +637,14 @@ void BKE_pbvh_build_grids(PBVH *bvh,
{
const int gridsize = key->grid_size;
- bvh->type = PBVH_GRIDS;
- bvh->grids = grids;
- bvh->gridfaces = gridfaces;
- bvh->grid_flag_mats = flagmats;
- bvh->totgrid = totgrid;
- bvh->gridkey = *key;
- bvh->grid_hidden = grid_hidden;
- bvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
+ pbvh->type = PBVH_GRIDS;
+ pbvh->grids = grids;
+ pbvh->gridfaces = gridfaces;
+ pbvh->grid_flag_mats = flagmats;
+ pbvh->totgrid = totgrid;
+ pbvh->gridkey = *key;
+ pbvh->grid_hidden = grid_hidden;
+ pbvh->leaf_limit = max_ii(LEAF_LIMIT / ((gridsize - 1) * (gridsize - 1)), 1);
BB cb;
BB_reset(&cb);
@@ -663,7 +668,7 @@ void BKE_pbvh_build_grids(PBVH *bvh,
}
if (totgrid) {
- pbvh_build(bvh, &cb, prim_bbc, totgrid);
+ pbvh_build(pbvh, &cb, prim_bbc, totgrid);
}
MEM_freeN(prim_bbc);
@@ -671,15 +676,15 @@ void BKE_pbvh_build_grids(PBVH *bvh,
PBVH *BKE_pbvh_new(void)
{
- PBVH *bvh = MEM_callocN(sizeof(PBVH), "pbvh");
- bvh->respect_hide = true;
- return bvh;
+ PBVH *pbvh = MEM_callocN(sizeof(PBVH), "pbvh");
+ pbvh->respect_hide = true;
+ return pbvh;
}
-void BKE_pbvh_free(PBVH *bvh)
+void BKE_pbvh_free(PBVH *pbvh)
{
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *node = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *node = &pbvh->nodes[i];
if (node->flag & PBVH_Leaf) {
if (node->draw_buffers) {
@@ -703,42 +708,42 @@ void BKE_pbvh_free(PBVH *bvh)
}
}
- if (bvh->deformed) {
- if (bvh->verts) {
+ if (pbvh->deformed) {
+ if (pbvh->verts) {
/* if pbvh was deformed, new memory was allocated for verts/faces -- free it */
- MEM_freeN((void *)bvh->verts);
+ MEM_freeN((void *)pbvh->verts);
}
}
- if (bvh->looptri) {
- MEM_freeN((void *)bvh->looptri);
+ if (pbvh->looptri) {
+ MEM_freeN((void *)pbvh->looptri);
}
- if (bvh->nodes) {
- MEM_freeN(bvh->nodes);
+ if (pbvh->nodes) {
+ MEM_freeN(pbvh->nodes);
}
- if (bvh->prim_indices) {
- MEM_freeN(bvh->prim_indices);
+ if (pbvh->prim_indices) {
+ MEM_freeN(pbvh->prim_indices);
}
- MEM_freeN(bvh);
+ MEM_freeN(pbvh);
}
static void pbvh_iter_begin(PBVHIter *iter,
- PBVH *bvh,
+ PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data)
{
- iter->bvh = bvh;
+ iter->pbvh = pbvh;
iter->scb = scb;
iter->search_data = search_data;
iter->stack = iter->stackfixed;
iter->stackspace = STACK_FIXED_DEPTH;
- iter->stack[0].node = bvh->nodes;
+ iter->stack[0].node = pbvh->nodes;
iter->stack[0].revisiting = false;
iter->stacksize = 1;
}
@@ -804,8 +809,8 @@ static PBVHNode *pbvh_iter_next(PBVHIter *iter)
pbvh_stack_push(iter, node, true);
/* push two child nodes on the stack */
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false);
}
}
@@ -834,8 +839,8 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
return node;
}
else {
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset + 1, false);
- pbvh_stack_push(iter, iter->bvh->nodes + node->children_offset, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset + 1, false);
+ pbvh_stack_push(iter, iter->pbvh->nodes + node->children_offset, false);
}
}
@@ -843,13 +848,13 @@ static PBVHNode *pbvh_iter_next_occluded(PBVHIter *iter)
}
void BKE_pbvh_search_gather(
- PBVH *bvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot)
+ PBVH *pbvh, BKE_pbvh_SearchCallback scb, void *search_data, PBVHNode ***r_array, int *r_tot)
{
PBVHIter iter;
PBVHNode **array = NULL, *node;
int tot = 0, space = 0;
- pbvh_iter_begin(&iter, bvh, scb, search_data);
+ pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_Leaf) {
@@ -875,7 +880,7 @@ void BKE_pbvh_search_gather(
*r_tot = tot;
}
-void BKE_pbvh_search_callback(PBVH *bvh,
+void BKE_pbvh_search_callback(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitCallback hcb,
@@ -884,7 +889,7 @@ void BKE_pbvh_search_callback(PBVH *bvh,
PBVHIter iter;
PBVHNode *node;
- pbvh_iter_begin(&iter, bvh, scb, search_data);
+ pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_Leaf) {
@@ -958,7 +963,7 @@ float BKE_pbvh_node_get_tmin(PBVHNode *node)
return node->tmin;
}
-static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
+static void BKE_pbvh_search_callback_occluded(PBVH *pbvh,
BKE_pbvh_SearchCallback scb,
void *search_data,
BKE_pbvh_HitOccludedCallback hcb,
@@ -968,7 +973,7 @@ static void BKE_pbvh_search_callback_occluded(PBVH *bvh,
PBVHNode *node;
node_tree *tree = NULL;
- pbvh_iter_begin(&iter, bvh, scb, search_data);
+ pbvh_iter_begin(&iter, pbvh, scb, search_data);
while ((node = pbvh_iter_next_occluded(&iter))) {
if (node->flag & PBVH_Leaf) {
@@ -1009,7 +1014,7 @@ static bool update_search_cb(PBVHNode *node, void *data_v)
}
typedef struct PBVHUpdateData {
- PBVH *bvh;
+ PBVH *pbvh;
PBVHNode **nodes;
int totnode;
@@ -1024,7 +1029,7 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
float(*vnors)[3] = data->vnors;
@@ -1036,25 +1041,25 @@ static void pbvh_update_normals_accum_task_cb(void *__restrict userdata,
const int totface = node->totprim;
for (int i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const MLoopTri *lt = &pbvh->looptri[faces[i]];
const unsigned int vtri[3] = {
- bvh->mloop[lt->tri[0]].v,
- bvh->mloop[lt->tri[1]].v,
- bvh->mloop[lt->tri[2]].v,
+ pbvh->mloop[lt->tri[0]].v,
+ pbvh->mloop[lt->tri[1]].v,
+ pbvh->mloop[lt->tri[2]].v,
};
const int sides = 3;
/* Face normal and mask */
if (lt->poly != mpoly_prev) {
- const MPoly *mp = &bvh->mpoly[lt->poly];
- BKE_mesh_calc_poly_normal(mp, &bvh->mloop[mp->loopstart], bvh->verts, fn);
+ const MPoly *mp = &pbvh->mpoly[lt->poly];
+ BKE_mesh_calc_poly_normal(mp, &pbvh->mloop[mp->loopstart], pbvh->verts, fn);
mpoly_prev = lt->poly;
}
for (int j = sides; j--;) {
const int v = vtri[j];
- if (bvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
+ if (pbvh->verts[v].flag & ME_VERT_PBVH_UPDATE) {
/* Note: This avoids `lock, add_v3_v3, unlock`
* and is five to ten times quicker than a spin-lock.
* Not exact equivalent though, since atomicity is only ensured for one component
@@ -1073,7 +1078,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
float(*vnors)[3] = data->vnors;
@@ -1083,7 +1088,7 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- MVert *mvert = &bvh->verts[v];
+ MVert *mvert = &pbvh->verts[v];
/* No atomics necessary because we are iterating over uniq_verts only,
* so we know only this thread will handle this vertex. */
@@ -1098,11 +1103,11 @@ static void pbvh_update_normals_store_task_cb(void *__restrict userdata,
}
}
-static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode)
+static void pbvh_faces_update_normals(PBVH *pbvh, PBVHNode **nodes, int totnode)
{
/* could be per node to save some memory, but also means
* we have to store for each vertex which node it is in */
- float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * bvh->totvert, __func__);
+ float(*vnors)[3] = MEM_callocN(sizeof(*vnors) * pbvh->totvert, __func__);
/* subtle assumptions:
* - We know that for all edited vertices, the nodes with faces
@@ -1115,7 +1120,7 @@ static void pbvh_faces_update_normals(PBVH *bvh, PBVHNode **nodes, int totnode)
*/
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.vnors = vnors,
};
@@ -1135,7 +1140,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateMask) {
@@ -1144,7 +1149,7 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
if (vd.mask && *vd.mask < 1.0f) {
has_unmasked = true;
@@ -1166,10 +1171,10 @@ static void pbvh_update_mask_redraw_task_cb(void *__restrict userdata,
}
}
-static void pbvh_update_mask_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+static void pbvh_update_mask_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
{
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.flag = flag,
};
@@ -1185,14 +1190,14 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateVisibility) {
node->flag &= ~PBVH_UpdateVisibility;
BKE_pbvh_node_fully_hidden_set(node, true);
if (node->flag & PBVH_Leaf) {
PBVHVertexIter vd;
- BKE_pbvh_vertex_iter_begin(bvh, node, vd, PBVH_ITER_ALL)
+ BKE_pbvh_vertex_iter_begin(pbvh, node, vd, PBVH_ITER_ALL)
{
if (vd.visible) {
BKE_pbvh_node_fully_hidden_set(node, false);
@@ -1204,10 +1209,10 @@ static void pbvh_update_visibility_redraw_task_cb(void *__restrict userdata,
}
}
-static void pbvh_update_visibility_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+static void pbvh_update_visibility_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
{
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.flag = flag,
};
@@ -1222,14 +1227,14 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
const TaskParallelTLS *__restrict UNUSED(tls))
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
const int flag = data->flag;
if ((flag & PBVH_UpdateBB) && (node->flag & PBVH_UpdateBB)) {
/* don't clear flag yet, leave it for flushing later */
/* Note that bvh usage is read-only here, so no need to thread-protect it. */
- update_node_vb(bvh, node);
+ update_node_vb(pbvh, node);
}
if ((flag & PBVH_UpdateOriginalBB) && (node->flag & PBVH_UpdateOriginalBB)) {
@@ -1241,11 +1246,11 @@ static void pbvh_update_BB_redraw_task_cb(void *__restrict userdata,
}
}
-void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
+void pbvh_update_BB_redraw(PBVH *pbvh, PBVHNode **nodes, int totnode, int flag)
{
/* update BB, redraw flag */
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
.flag = flag,
};
@@ -1255,7 +1260,7 @@ void pbvh_update_BB_redraw(PBVH *bvh, PBVHNode **nodes, int totnode, int flag)
BLI_task_parallel_range(0, totnode, &data, pbvh_update_BB_redraw_task_cb, &settings);
}
-static int pbvh_get_buffers_update_flags(PBVH *UNUSED(bvh))
+static int pbvh_get_buffers_update_flags(PBVH *UNUSED(pbvh))
{
int update_flags = GPU_PBVH_BUFFERS_SHOW_VCOL | GPU_PBVH_BUFFERS_SHOW_MASK |
GPU_PBVH_BUFFERS_SHOW_SCULPT_FACE_SETS;
@@ -1270,61 +1275,61 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
* do any OpenGL calls. Flags are not cleared immediately, that happens
* after GPU_pbvh_buffer_flush() which does the final OpenGL calls. */
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_RebuildDrawBuffers) {
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, bvh->grid_hidden);
+ node->draw_buffers = GPU_pbvh_grid_buffers_build(node->totprim, pbvh->grid_hidden);
break;
case PBVH_FACES:
node->draw_buffers = GPU_pbvh_mesh_buffers_build(
- bvh->mpoly,
- bvh->mloop,
- bvh->looptri,
- bvh->verts,
+ pbvh->mpoly,
+ pbvh->mloop,
+ pbvh->looptri,
+ pbvh->verts,
node->prim_indices,
- CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS),
+ CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
node->totprim,
- bvh->mesh);
+ pbvh->mesh);
break;
case PBVH_BMESH:
- node->draw_buffers = GPU_pbvh_bmesh_buffers_build(bvh->flags &
+ node->draw_buffers = GPU_pbvh_bmesh_buffers_build(pbvh->flags &
PBVH_DYNTOPO_SMOOTH_SHADING);
break;
}
}
if (node->flag & PBVH_UpdateDrawBuffers) {
- const int update_flags = pbvh_get_buffers_update_flags(bvh);
- switch (bvh->type) {
+ const int update_flags = pbvh_get_buffers_update_flags(pbvh);
+ switch (pbvh->type) {
case PBVH_GRIDS:
GPU_pbvh_grid_buffers_update(node->draw_buffers,
- bvh->subdiv_ccg,
- bvh->grids,
- bvh->grid_flag_mats,
+ pbvh->subdiv_ccg,
+ pbvh->grids,
+ pbvh->grid_flag_mats,
node->prim_indices,
node->totprim,
- bvh->face_sets,
- bvh->face_sets_color_seed,
- bvh->face_sets_color_default,
- &bvh->gridkey,
+ pbvh->face_sets,
+ pbvh->face_sets_color_seed,
+ pbvh->face_sets_color_default,
+ &pbvh->gridkey,
update_flags);
break;
case PBVH_FACES:
GPU_pbvh_mesh_buffers_update(node->draw_buffers,
- bvh->verts,
- CustomData_get_layer(bvh->vdata, CD_PAINT_MASK),
- CustomData_get_layer(bvh->ldata, CD_MLOOPCOL),
- CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS),
- bvh->face_sets_color_seed,
- bvh->face_sets_color_default,
+ pbvh->verts,
+ CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK),
+ CustomData_get_layer(pbvh->ldata, CD_MLOOPCOL),
+ CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS),
+ pbvh->face_sets_color_seed,
+ pbvh->face_sets_color_default,
update_flags);
break;
case PBVH_BMESH:
GPU_pbvh_bmesh_buffers_update(node->draw_buffers,
- bvh->bm,
+ pbvh->bm,
node->bm_faces,
node->bm_unique_verts,
node->bm_other_verts,
@@ -1334,9 +1339,9 @@ static void pbvh_update_draw_buffer_cb(void *__restrict userdata,
}
}
-static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, int update_flag)
+static void pbvh_update_draw_buffers(PBVH *pbvh, PBVHNode **nodes, int totnode, int update_flag)
{
- if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(bvh->type, PBVH_GRIDS, PBVH_BMESH)) {
+ if ((update_flag & PBVH_RebuildDrawBuffers) || ELEM(pbvh->type, PBVH_GRIDS, PBVH_BMESH)) {
/* Free buffers uses OpenGL, so not in parallel. */
for (int n = 0; n < totnode; n++) {
PBVHNode *node = nodes[n];
@@ -1345,11 +1350,11 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
node->draw_buffers = NULL;
}
else if ((node->flag & PBVH_UpdateDrawBuffers) && node->draw_buffers) {
- if (bvh->type == PBVH_GRIDS) {
+ if (pbvh->type == PBVH_GRIDS) {
GPU_pbvh_grid_buffers_update_free(
- node->draw_buffers, bvh->grid_flag_mats, node->prim_indices);
+ node->draw_buffers, pbvh->grid_flag_mats, node->prim_indices);
}
- else if (bvh->type == PBVH_BMESH) {
+ else if (pbvh->type == PBVH_BMESH) {
GPU_pbvh_bmesh_buffers_update_free(node->draw_buffers);
}
}
@@ -1358,7 +1363,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
/* Parallel creation and update of draw buffers. */
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
};
@@ -1367,7 +1372,7 @@ static void pbvh_update_draw_buffers(PBVH *bvh, PBVHNode **nodes, int totnode, i
BLI_task_parallel_range(0, totnode, &data, pbvh_update_draw_buffer_cb, &settings);
}
-static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
+static int pbvh_flush_bb(PBVH *pbvh, PBVHNode *node, int flag)
{
int update = 0;
@@ -1386,11 +1391,11 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
return update;
}
else {
- update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset, flag);
- update |= pbvh_flush_bb(bvh, bvh->nodes + node->children_offset + 1, flag);
+ update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset, flag);
+ update |= pbvh_flush_bb(pbvh, pbvh->nodes + node->children_offset + 1, flag);
if (update & PBVH_UpdateBB) {
- update_node_vb(bvh, node);
+ update_node_vb(pbvh, node);
}
if (update & PBVH_UpdateOriginalBB) {
node->orig_vb = node->vb;
@@ -1400,45 +1405,45 @@ static int pbvh_flush_bb(PBVH *bvh, PBVHNode *node, int flag)
return update;
}
-void BKE_pbvh_update_bounds(PBVH *bvh, int flag)
+void BKE_pbvh_update_bounds(PBVH *pbvh, int flag)
{
- if (!bvh->nodes) {
+ if (!pbvh->nodes) {
return;
}
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB | PBVH_UpdateRedraw)) {
- pbvh_update_BB_redraw(bvh, nodes, totnode, flag);
+ pbvh_update_BB_redraw(pbvh, nodes, totnode, flag);
}
if (flag & (PBVH_UpdateBB | PBVH_UpdateOriginalBB)) {
- pbvh_flush_bb(bvh, bvh->nodes, flag);
+ pbvh_flush_bb(pbvh, pbvh->nodes, flag);
}
MEM_SAFE_FREE(nodes);
}
-void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag)
+void BKE_pbvh_update_vertex_data(PBVH *pbvh, int flag)
{
- if (!bvh->nodes) {
+ if (!pbvh->nodes) {
return;
}
PBVHNode **nodes;
int totnode;
- BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, update_search_cb, POINTER_FROM_INT(flag), &nodes, &totnode);
if (flag & (PBVH_UpdateMask)) {
- pbvh_update_mask_redraw(bvh, nodes, totnode, flag);
+ pbvh_update_mask_redraw(pbvh, nodes, totnode, flag);
}
if (flag & (PBVH_UpdateVisibility)) {
- pbvh_update_visibility_redraw(bvh, nodes, totnode, flag);
+ pbvh_update_visibility_redraw(pbvh, nodes, totnode, flag);
}
if (nodes) {
@@ -1446,13 +1451,13 @@ void BKE_pbvh_update_vertex_data(PBVH *bvh, int flag)
}
}
-static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node)
+static void pbvh_faces_node_visibility_update(PBVH *pbvh, PBVHNode *node)
{
MVert *mvert;
const int *vert_indices;
int totvert, i;
- BKE_pbvh_node_num_verts(bvh, node, NULL, &totvert);
- BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &mvert);
+ BKE_pbvh_node_num_verts(pbvh, node, NULL, &totvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &mvert);
for (i = 0; i < totvert; i++) {
MVert *v = &mvert[vert_indices[i]];
@@ -1465,15 +1470,15 @@ static void pbvh_faces_node_visibility_update(PBVH *bvh, PBVHNode *node)
BKE_pbvh_node_fully_hidden_set(node, true);
}
-static void pbvh_grids_node_visibility_update(PBVH *bvh, PBVHNode *node)
+static void pbvh_grids_node_visibility_update(PBVH *pbvh, PBVHNode *node)
{
CCGElem **grids;
BLI_bitmap **grid_hidden;
int *grid_indices, totgrid, i;
- BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
- grid_hidden = BKE_pbvh_grid_hidden(bvh);
- CCGKey key = *BKE_pbvh_get_grid_key(bvh);
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, NULL, &grids);
+ grid_hidden = BKE_pbvh_grid_hidden(pbvh);
+ CCGKey key = *BKE_pbvh_get_grid_key(pbvh);
for (i = 0; i < totgrid; i++) {
int g = grid_indices[i], x, y;
@@ -1530,15 +1535,15 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata,
{
PBVHUpdateData *data = userdata;
- PBVH *bvh = data->bvh;
+ PBVH *pbvh = data->pbvh;
PBVHNode *node = data->nodes[n];
if (node->flag & PBVH_UpdateMask) {
- switch (BKE_pbvh_type(bvh)) {
+ switch (BKE_pbvh_type(pbvh)) {
case PBVH_FACES:
- pbvh_faces_node_visibility_update(bvh, node);
+ pbvh_faces_node_visibility_update(pbvh, node);
break;
case PBVH_GRIDS:
- pbvh_grids_node_visibility_update(bvh, node);
+ pbvh_grids_node_visibility_update(pbvh, node);
break;
case PBVH_BMESH:
pbvh_bmesh_node_visibility_update(node);
@@ -1548,10 +1553,10 @@ static void pbvh_update_visibility_task_cb(void *__restrict userdata,
}
}
-static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode)
+static void pbvh_update_visibility(PBVH *pbvh, PBVHNode **nodes, int totnode)
{
PBVHUpdateData data = {
- .bvh = bvh,
+ .pbvh = pbvh,
.nodes = nodes,
};
@@ -1560,9 +1565,9 @@ static void pbvh_update_visibility(PBVH *bvh, PBVHNode **nodes, int totnode)
BLI_task_parallel_range(0, totnode, &data, pbvh_update_visibility_task_cb, &settings);
}
-void BKE_pbvh_update_visibility(PBVH *bvh)
+void BKE_pbvh_update_visibility(PBVH *pbvh)
{
- if (!bvh->nodes) {
+ if (!pbvh->nodes) {
return;
}
@@ -1570,15 +1575,15 @@ void BKE_pbvh_update_visibility(PBVH *bvh)
int totnode;
BKE_pbvh_search_gather(
- bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
- pbvh_update_visibility(bvh, nodes, totnode);
+ pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateVisibility), &nodes, &totnode);
+ pbvh_update_visibility(pbvh, nodes, totnode);
if (nodes) {
MEM_freeN(nodes);
}
}
-void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
+void BKE_pbvh_redraw_BB(PBVH *pbvh, float bb_min[3], float bb_max[3])
{
PBVHIter iter;
PBVHNode *node;
@@ -1586,7 +1591,7 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
BB_reset(&bb);
- pbvh_iter_begin(&iter, bvh, NULL, NULL);
+ pbvh_iter_begin(&iter, pbvh, NULL, NULL);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_UpdateRedraw) {
@@ -1600,18 +1605,18 @@ void BKE_pbvh_redraw_BB(PBVH *bvh, float bb_min[3], float bb_max[3])
copy_v3_v3(bb_max, bb.bmax);
}
-void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *r_totface)
+void BKE_pbvh_get_grid_updates(PBVH *pbvh, bool clear, void ***r_gridfaces, int *r_totface)
{
GSet *face_set = BLI_gset_ptr_new(__func__);
PBVHNode *node;
PBVHIter iter;
- pbvh_iter_begin(&iter, bvh, NULL, NULL);
+ pbvh_iter_begin(&iter, pbvh, NULL, NULL);
while ((node = pbvh_iter_next(&iter))) {
if (node->flag & PBVH_UpdateNormals) {
for (uint i = 0; i < node->totprim; i++) {
- void *face = bvh->gridfaces[node->prim_indices[i]];
+ void *face = pbvh->gridfaces[node->prim_indices[i]];
BLI_gset_add(face_set, face);
}
@@ -1647,25 +1652,25 @@ void BKE_pbvh_get_grid_updates(PBVH *bvh, bool clear, void ***r_gridfaces, int *
/***************************** PBVH Access ***********************************/
-PBVHType BKE_pbvh_type(const PBVH *bvh)
+PBVHType BKE_pbvh_type(const PBVH *pbvh)
{
- return bvh->type;
+ return pbvh->type;
}
-bool BKE_pbvh_has_faces(const PBVH *bvh)
+bool BKE_pbvh_has_faces(const PBVH *pbvh)
{
- if (bvh->type == PBVH_BMESH) {
- return (bvh->bm->totface != 0);
+ if (pbvh->type == PBVH_BMESH) {
+ return (pbvh->bm->totface != 0);
}
else {
- return (bvh->totprim != 0);
+ return (pbvh->totprim != 0);
}
}
-void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
+void BKE_pbvh_bounding_box(const PBVH *pbvh, float min[3], float max[3])
{
- if (bvh->totnode) {
- const BB *bb = &bvh->nodes[0].vb;
+ if (pbvh->totnode) {
+ const BB *bb = &pbvh->nodes[0].vb;
copy_v3_v3(min, bb->bmin);
copy_v3_v3(max, bb->bmax);
}
@@ -1675,34 +1680,40 @@ void BKE_pbvh_bounding_box(const PBVH *bvh, float min[3], float max[3])
}
}
-BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *bvh)
+BLI_bitmap **BKE_pbvh_grid_hidden(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return bvh->grid_hidden;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->grid_hidden;
}
-const CCGKey *BKE_pbvh_get_grid_key(const PBVH *bvh)
+const CCGKey *BKE_pbvh_get_grid_key(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return &bvh->gridkey;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return &pbvh->gridkey;
}
-struct CCGElem **BKE_pbvh_get_grids(const PBVH *bvh)
+struct CCGElem **BKE_pbvh_get_grids(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return bvh->grids;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->grids;
}
-int BKE_pbvh_get_grid_num_vertices(const PBVH *bvh)
+BLI_bitmap **BKE_pbvh_get_grid_visibility(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_GRIDS);
- return bvh->totgrid * bvh->gridkey.grid_area;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->grid_hidden;
}
-BMesh *BKE_pbvh_get_bmesh(PBVH *bvh)
+int BKE_pbvh_get_grid_num_vertices(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_BMESH);
- return bvh->bm;
+ BLI_assert(pbvh->type == PBVH_GRIDS);
+ return pbvh->totgrid * pbvh->gridkey.grid_area;
+}
+
+BMesh *BKE_pbvh_get_bmesh(PBVH *pbvh)
+{
+ BLI_assert(pbvh->type == PBVH_BMESH);
+ return pbvh->bm;
}
/***************************** Node Access ***********************************/
@@ -1785,7 +1796,7 @@ bool BKE_pbvh_node_fully_unmasked_get(PBVHNode *node)
return (node->flag & PBVH_Leaf) && (node->flag & PBVH_FullyUnmasked);
}
-void BKE_pbvh_node_get_verts(PBVH *bvh,
+void BKE_pbvh_node_get_verts(PBVH *pbvh,
PBVHNode *node,
const int **r_vert_indices,
MVert **r_verts)
@@ -1795,17 +1806,17 @@ void BKE_pbvh_node_get_verts(PBVH *bvh,
}
if (r_verts) {
- *r_verts = bvh->verts;
+ *r_verts = pbvh->verts;
}
}
-void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *r_totvert)
+void BKE_pbvh_node_num_verts(PBVH *pbvh, PBVHNode *node, int *r_uniquevert, int *r_totvert)
{
int tot;
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- tot = node->totprim * bvh->gridkey.grid_area;
+ tot = node->totprim * pbvh->gridkey.grid_area;
if (r_totvert) {
*r_totvert = tot;
}
@@ -1833,7 +1844,7 @@ void BKE_pbvh_node_num_verts(PBVH *bvh, PBVHNode *node, int *r_uniquevert, int *
}
}
-void BKE_pbvh_node_get_grids(PBVH *bvh,
+void BKE_pbvh_node_get_grids(PBVH *pbvh,
PBVHNode *node,
int **r_grid_indices,
int *r_totgrid,
@@ -1841,7 +1852,7 @@ void BKE_pbvh_node_get_grids(PBVH *bvh,
int *r_gridsize,
CCGElem ***r_griddata)
{
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
if (r_grid_indices) {
*r_grid_indices = node->prim_indices;
@@ -1850,13 +1861,13 @@ void BKE_pbvh_node_get_grids(PBVH *bvh,
*r_totgrid = node->totprim;
}
if (r_maxgrid) {
- *r_maxgrid = bvh->totgrid;
+ *r_maxgrid = pbvh->totgrid;
}
if (r_gridsize) {
- *r_gridsize = bvh->gridkey.grid_size;
+ *r_gridsize = pbvh->gridkey.grid_size;
}
if (r_griddata) {
- *r_griddata = bvh->grids;
+ *r_griddata = pbvh->grids;
}
break;
case PBVH_FACES:
@@ -1927,15 +1938,15 @@ void BKE_pbvh_node_get_bm_orco_data(PBVHNode *node,
* however this is important to avoid having to recalculate bound-box & sync the buffers to the
* GPU (which is far more expensive!) See: T47232.
*/
-bool BKE_pbvh_node_vert_update_check_any(PBVH *bvh, PBVHNode *node)
+bool BKE_pbvh_node_vert_update_check_any(PBVH *pbvh, PBVHNode *node)
{
- BLI_assert(bvh->type == PBVH_FACES);
+ BLI_assert(pbvh->type == PBVH_FACES);
const int *verts = node->vert_indices;
const int totvert = node->uniq_verts + node->face_verts;
for (int i = 0; i < totvert; i++) {
const int v = verts[i];
- const MVert *mvert = &bvh->verts[v];
+ const MVert *mvert = &pbvh->verts[v];
if (mvert->flag & ME_VERT_PBVH_UPDATE) {
return true;
@@ -1971,7 +1982,7 @@ static bool ray_aabb_intersect(PBVHNode *node, void *data_v)
return isect_ray_aabb_v3(&rcd->ray, bb_min, bb_max, &node->tmin);
}
-void BKE_pbvh_raycast(PBVH *bvh,
+void BKE_pbvh_raycast(PBVH *pbvh,
BKE_pbvh_HitOccludedCallback cb,
void *data,
const float ray_start[3],
@@ -1983,7 +1994,7 @@ void BKE_pbvh_raycast(PBVH *bvh,
isect_ray_aabb_v3_precalc(&rcd.ray, ray_start, ray_normal);
rcd.original = original;
- BKE_pbvh_search_callback_occluded(bvh, ray_aabb_intersect, &rcd, cb, data);
+ BKE_pbvh_search_callback_occluded(pbvh, ray_aabb_intersect, &rcd, cb, data);
}
bool ray_face_intersection_quad(const float ray_start[3],
@@ -2101,7 +2112,7 @@ bool ray_face_nearest_tri(const float ray_start[3],
}
}
-static bool pbvh_faces_node_raycast(PBVH *bvh,
+static bool pbvh_faces_node_raycast(PBVH *pbvh,
const PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2112,18 +2123,18 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
int *r_active_face_index,
float *r_face_normal)
{
- const MVert *vert = bvh->verts;
- const MLoop *mloop = bvh->mloop;
+ const MVert *vert = pbvh->verts;
+ const MLoop *mloop = pbvh->mloop;
const int *faces = node->prim_indices;
int totface = node->totprim;
bool hit = false;
float nearest_vertex_co[3] = {0.0f};
for (int i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
+ if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
continue;
}
@@ -2169,7 +2180,7 @@ static bool pbvh_faces_node_raycast(PBVH *bvh,
return hit;
}
-static bool pbvh_grids_node_raycast(PBVH *bvh,
+static bool pbvh_grids_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2181,21 +2192,21 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
float *r_face_normal)
{
const int totgrid = node->totprim;
- const int gridsize = bvh->gridkey.grid_size;
+ const int gridsize = pbvh->gridkey.grid_size;
bool hit = false;
float nearest_vertex_co[3] = {0.0};
- const CCGKey *gridkey = &bvh->gridkey;
+ const CCGKey *gridkey = &pbvh->gridkey;
for (int i = 0; i < totgrid; i++) {
const int grid_index = node->prim_indices[i];
- CCGElem *grid = bvh->grids[grid_index];
+ CCGElem *grid = pbvh->grids[grid_index];
BLI_bitmap *gh;
if (!grid) {
continue;
}
- gh = bvh->grid_hidden[grid_index];
+ gh = pbvh->grid_hidden[grid_index];
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
@@ -2263,7 +2274,7 @@ static bool pbvh_grids_node_raycast(PBVH *bvh,
return hit;
}
-bool BKE_pbvh_node_raycast(PBVH *bvh,
+bool BKE_pbvh_node_raycast(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -2281,9 +2292,9 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
return false;
}
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_FACES:
- hit |= pbvh_faces_node_raycast(bvh,
+ hit |= pbvh_faces_node_raycast(pbvh,
node,
origco,
ray_start,
@@ -2295,7 +2306,7 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
face_normal);
break;
case PBVH_GRIDS:
- hit |= pbvh_grids_node_raycast(bvh,
+ hit |= pbvh_grids_node_raycast(pbvh,
node,
origco,
ray_start,
@@ -2307,7 +2318,7 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
face_normal);
break;
case PBVH_BMESH:
- BM_mesh_elem_index_ensure(bvh->bm, BM_VERT);
+ BM_mesh_elem_index_ensure(pbvh->bm, BM_VERT);
hit = pbvh_bmesh_node_raycast(node,
ray_start,
ray_normal,
@@ -2323,9 +2334,9 @@ bool BKE_pbvh_node_raycast(PBVH *bvh,
}
void BKE_pbvh_raycast_project_ray_root(
- PBVH *bvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
+ PBVH *pbvh, bool original, float ray_start[3], float ray_end[3], float ray_normal[3])
{
- if (bvh->nodes) {
+ if (pbvh->nodes) {
float rootmin_start, rootmin_end;
float bb_min_root[3], bb_max_root[3], bb_center[3], bb_diff[3];
struct IsectRayAABB_Precalc ray;
@@ -2334,10 +2345,10 @@ void BKE_pbvh_raycast_project_ray_root(
float offset_vec[3] = {1e-3f, 1e-3f, 1e-3f};
if (original) {
- BKE_pbvh_node_get_original_BB(bvh->nodes, bb_min_root, bb_max_root);
+ BKE_pbvh_node_get_original_BB(pbvh->nodes, bb_min_root, bb_max_root);
}
else {
- BKE_pbvh_node_get_BB(bvh->nodes, bb_min_root, bb_max_root);
+ BKE_pbvh_node_get_BB(pbvh->nodes, bb_min_root, bb_max_root);
}
/* Slightly offset min and max in case we have a zero width node
@@ -2399,7 +2410,7 @@ static bool nearest_to_ray_aabb_dist_sq(PBVHNode *node, void *data_v)
return depth > 0.0f;
}
-void BKE_pbvh_find_nearest_to_ray(PBVH *bvh,
+void BKE_pbvh_find_nearest_to_ray(PBVH *pbvh,
BKE_pbvh_SearchNearestCallback cb,
void *data,
const float ray_start[3],
@@ -2411,10 +2422,10 @@ void BKE_pbvh_find_nearest_to_ray(PBVH *bvh,
dist_squared_ray_to_aabb_v3_precalc(&ncd.dist_ray_to_aabb_precalc, ray_start, ray_normal);
ncd.original = original;
- BKE_pbvh_search_callback_occluded(bvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data);
+ BKE_pbvh_search_callback_occluded(pbvh, nearest_to_ray_aabb_dist_sq, &ncd, cb, data);
}
-static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh,
+static bool pbvh_faces_node_nearest_to_ray(PBVH *pbvh,
const PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2422,17 +2433,17 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh,
float *depth,
float *dist_sq)
{
- const MVert *vert = bvh->verts;
- const MLoop *mloop = bvh->mloop;
+ const MVert *vert = pbvh->verts;
+ const MLoop *mloop = pbvh->mloop;
const int *faces = node->prim_indices;
int i, totface = node->totprim;
bool hit = false;
for (i = 0; i < totface; i++) {
- const MLoopTri *lt = &bvh->looptri[faces[i]];
+ const MLoopTri *lt = &pbvh->looptri[faces[i]];
const int *face_verts = node->face_vert_indices[i];
- if (bvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
+ if (pbvh->respect_hide && paint_is_face_hidden(lt, vert, mloop)) {
continue;
}
@@ -2461,7 +2472,7 @@ static bool pbvh_faces_node_nearest_to_ray(PBVH *bvh,
return hit;
}
-static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
+static bool pbvh_grids_node_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
const float ray_start[3],
@@ -2470,18 +2481,18 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
float *dist_sq)
{
const int totgrid = node->totprim;
- const int gridsize = bvh->gridkey.grid_size;
+ const int gridsize = pbvh->gridkey.grid_size;
bool hit = false;
for (int i = 0; i < totgrid; i++) {
- CCGElem *grid = bvh->grids[node->prim_indices[i]];
+ CCGElem *grid = pbvh->grids[node->prim_indices[i]];
BLI_bitmap *gh;
if (!grid) {
continue;
}
- gh = bvh->grid_hidden[node->prim_indices[i]];
+ gh = pbvh->grid_hidden[node->prim_indices[i]];
for (int y = 0; y < gridsize - 1; y++) {
for (int x = 0; x < gridsize - 1; x++) {
@@ -2505,10 +2516,10 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
else {
hit |= ray_face_nearest_quad(ray_start,
ray_normal,
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y),
- CCG_grid_elem_co(&bvh->gridkey, grid, x + 1, y + 1),
- CCG_grid_elem_co(&bvh->gridkey, grid, x, y + 1),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x, y),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x + 1, y + 1),
+ CCG_grid_elem_co(&pbvh->gridkey, grid, x, y + 1),
depth,
dist_sq);
}
@@ -2523,7 +2534,7 @@ static bool pbvh_grids_node_nearest_to_ray(PBVH *bvh,
return hit;
}
-bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
+bool BKE_pbvh_node_find_nearest_to_ray(PBVH *pbvh,
PBVHNode *node,
float (*origco)[3],
bool use_origco,
@@ -2538,14 +2549,14 @@ bool BKE_pbvh_node_find_nearest_to_ray(PBVH *bvh,
return false;
}
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_FACES:
hit |= pbvh_faces_node_nearest_to_ray(
- bvh, node, origco, ray_start, ray_normal, depth, dist_sq);
+ pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
break;
case PBVH_GRIDS:
hit |= pbvh_grids_node_nearest_to_ray(
- bvh, node, origco, ray_start, ray_normal, depth, dist_sq);
+ pbvh, node, origco, ray_start, ray_normal, depth, dist_sq);
break;
case PBVH_BMESH:
hit = pbvh_bmesh_node_nearest_to_ray(
@@ -2619,26 +2630,26 @@ bool BKE_pbvh_node_frustum_exclude_AABB(PBVHNode *node, void *data)
return test_frustum_aabb(bb_min, bb_max, data) != ISECT_INSIDE;
}
-void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
+void BKE_pbvh_update_normals(PBVH *pbvh, struct SubdivCCG *subdiv_ccg)
{
/* Update normals */
PBVHNode **nodes;
int totnode;
BKE_pbvh_search_gather(
- bvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);
+ pbvh, update_search_cb, POINTER_FROM_INT(PBVH_UpdateNormals), &nodes, &totnode);
if (totnode > 0) {
- if (bvh->type == PBVH_BMESH) {
+ if (pbvh->type == PBVH_BMESH) {
pbvh_bmesh_normals_update(nodes, totnode);
}
- else if (bvh->type == PBVH_FACES) {
- pbvh_faces_update_normals(bvh, nodes, totnode);
+ else if (pbvh->type == PBVH_FACES) {
+ pbvh_faces_update_normals(pbvh, nodes, totnode);
}
- else if (bvh->type == PBVH_GRIDS) {
+ else if (pbvh->type == PBVH_GRIDS) {
struct CCGFace **faces;
int num_faces;
- BKE_pbvh_get_grid_updates(bvh, true, (void ***)&faces, &num_faces);
+ BKE_pbvh_get_grid_updates(pbvh, true, (void ***)&faces, &num_faces);
if (num_faces > 0) {
BKE_subdiv_ccg_update_normals(subdiv_ccg, faces, num_faces);
MEM_freeN(faces);
@@ -2649,10 +2660,10 @@ void BKE_pbvh_update_normals(PBVH *bvh, struct SubdivCCG *subdiv_ccg)
MEM_SAFE_FREE(nodes);
}
-void BKE_pbvh_face_sets_color_set(PBVH *bvh, int seed, int color_default)
+void BKE_pbvh_face_sets_color_set(PBVH *pbvh, int seed, int color_default)
{
- bvh->face_sets_color_seed = seed;
- bvh->face_sets_color_default = color_default;
+ pbvh->face_sets_color_seed = seed;
+ pbvh->face_sets_color_default = color_default;
}
/**
@@ -2675,7 +2686,7 @@ static bool pbvh_draw_search_cb(PBVHNode *node, void *data_v)
return true;
}
-void BKE_pbvh_draw_cb(PBVH *bvh,
+void BKE_pbvh_draw_cb(PBVH *pbvh,
bool update_only_visible,
PBVHFrustumPlanes *update_frustum,
PBVHFrustumPlanes *draw_frustum,
@@ -2689,10 +2700,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
if (!update_only_visible) {
/* Update all draw buffers, also those outside the view. */
- BKE_pbvh_search_gather(bvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode);
+ BKE_pbvh_search_gather(
+ pbvh, update_search_cb, POINTER_FROM_INT(update_flag), &nodes, &totnode);
if (totnode) {
- pbvh_update_draw_buffers(bvh, nodes, totnode, update_flag);
+ pbvh_update_draw_buffers(pbvh, nodes, totnode, update_flag);
}
MEM_SAFE_FREE(nodes);
@@ -2700,11 +2712,11 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
/* Gather visible nodes. */
PBVHDrawSearchData data = {.frustum = update_frustum, .accum_update_flag = 0};
- BKE_pbvh_search_gather(bvh, pbvh_draw_search_cb, &data, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &data, &nodes, &totnode);
if (update_only_visible && (data.accum_update_flag & update_flag)) {
/* Update draw buffers in visible nodes. */
- pbvh_update_draw_buffers(bvh, nodes, totnode, data.accum_update_flag);
+ pbvh_update_draw_buffers(pbvh, nodes, totnode, data.accum_update_flag);
}
/* Draw. */
@@ -2722,7 +2734,7 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
MEM_SAFE_FREE(nodes);
PBVHDrawSearchData draw_data = {.frustum = draw_frustum, .accum_update_flag = 0};
- BKE_pbvh_search_gather(bvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode);
+ BKE_pbvh_search_gather(pbvh, pbvh_draw_search_cb, &draw_data, &nodes, &totnode);
for (int a = 0; a < totnode; a++) {
PBVHNode *node = nodes[a];
@@ -2735,29 +2747,29 @@ void BKE_pbvh_draw_cb(PBVH *bvh,
}
void BKE_pbvh_draw_debug_cb(
- PBVH *bvh,
+ PBVH *pbvh,
void (*draw_fn)(void *user_data, const float bmin[3], const float bmax[3], PBVHNodeFlags flag),
void *user_data)
{
- for (int a = 0; a < bvh->totnode; a++) {
- PBVHNode *node = &bvh->nodes[a];
+ for (int a = 0; a < pbvh->totnode; a++) {
+ PBVHNode *node = &pbvh->nodes[a];
draw_fn(user_data, node->vb.bmin, node->vb.bmax, node->flag);
}
}
void BKE_pbvh_grids_update(
- PBVH *bvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
+ PBVH *pbvh, CCGElem **grids, void **gridfaces, DMFlagMat *flagmats, BLI_bitmap **grid_hidden)
{
- bvh->grids = grids;
- bvh->gridfaces = gridfaces;
+ pbvh->grids = grids;
+ pbvh->gridfaces = gridfaces;
- if (flagmats != bvh->grid_flag_mats || bvh->grid_hidden != grid_hidden) {
- bvh->grid_flag_mats = flagmats;
- bvh->grid_hidden = grid_hidden;
+ if (flagmats != pbvh->grid_flag_mats || pbvh->grid_hidden != grid_hidden) {
+ pbvh->grid_flag_mats = flagmats;
+ pbvh->grid_hidden = grid_hidden;
- for (int a = 0; a < bvh->totnode; a++) {
- BKE_pbvh_node_mark_rebuild_draw(&bvh->nodes[a]);
+ for (int a = 0; a < pbvh->totnode; a++) {
+ BKE_pbvh_node_mark_rebuild_draw(&pbvh->nodes[a]);
}
}
}
@@ -2830,7 +2842,7 @@ bool BKE_pbvh_is_deformed(PBVH *pbvh)
}
/* Proxies */
-PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
+PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *pbvh, PBVHNode *node)
{
int index, totverts;
@@ -2845,7 +2857,7 @@ PBVHProxyNode *BKE_pbvh_node_add_proxy(PBVH *bvh, PBVHNode *node)
node->proxies = MEM_mallocN(sizeof(PBVHProxyNode), "PBVHNodeProxy");
}
- BKE_pbvh_node_num_verts(bvh, node, &totverts, NULL);
+ BKE_pbvh_node_num_verts(pbvh, node, &totverts, NULL);
node->proxies[index].co = MEM_callocN(sizeof(float[3]) * totverts, "PBVHNodeProxy.co");
return node->proxies + index;
@@ -2893,7 +2905,7 @@ void BKE_pbvh_gather_proxies(PBVH *pbvh, PBVHNode ***r_array, int *r_tot)
*r_tot = tot;
}
-void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
+void pbvh_vertex_iter_init(PBVH *pbvh, PBVHNode *node, PBVHVertexIter *vi, int mode)
{
struct CCGElem **grids;
struct MVert *verts;
@@ -2906,16 +2918,16 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
vi->fno = NULL;
vi->mvert = NULL;
- vi->respect_hide = bvh->respect_hide;
- if (bvh->respect_hide == false) {
+ vi->respect_hide = pbvh->respect_hide;
+ if (pbvh->respect_hide == false) {
/* The same value for all vertices. */
vi->visible = true;
}
- BKE_pbvh_node_get_grids(bvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
- BKE_pbvh_node_num_verts(bvh, node, &uniq_verts, &totvert);
- BKE_pbvh_node_get_verts(bvh, node, &vert_indices, &verts);
- vi->key = bvh->gridkey;
+ BKE_pbvh_node_get_grids(pbvh, node, &grid_indices, &totgrid, NULL, &gridsize, &grids);
+ BKE_pbvh_node_num_verts(pbvh, node, &uniq_verts, &totvert);
+ BKE_pbvh_node_get_verts(pbvh, node, &vert_indices, &verts);
+ vi->key = pbvh->gridkey;
vi->grids = grids;
vi->grid_indices = grid_indices;
@@ -2931,45 +2943,45 @@ void pbvh_vertex_iter_init(PBVH *bvh, PBVHNode *node, PBVHVertexIter *vi, int mo
vi->vert_indices = vert_indices;
vi->mverts = verts;
- if (bvh->type == PBVH_BMESH) {
+ if (pbvh->type == PBVH_BMESH) {
BLI_gsetIterator_init(&vi->bm_unique_verts, node->bm_unique_verts);
BLI_gsetIterator_init(&vi->bm_other_verts, node->bm_other_verts);
- vi->bm_vdata = &bvh->bm->vdata;
+ vi->bm_vdata = &pbvh->bm->vdata;
vi->cd_vert_mask_offset = CustomData_get_offset(vi->bm_vdata, CD_PAINT_MASK);
}
vi->gh = NULL;
if (vi->grids && mode == PBVH_ITER_UNIQUE) {
- vi->grid_hidden = bvh->grid_hidden;
+ vi->grid_hidden = pbvh->grid_hidden;
}
vi->mask = NULL;
- if (bvh->type == PBVH_FACES) {
- vi->vmask = CustomData_get_layer(bvh->vdata, CD_PAINT_MASK);
+ if (pbvh->type == PBVH_FACES) {
+ vi->vmask = CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK);
}
}
-bool pbvh_has_mask(PBVH *bvh)
+bool pbvh_has_mask(PBVH *pbvh)
{
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- return (bvh->gridkey.has_mask != 0);
+ return (pbvh->gridkey.has_mask != 0);
case PBVH_FACES:
- return (bvh->vdata && CustomData_get_layer(bvh->vdata, CD_PAINT_MASK));
+ return (pbvh->vdata && CustomData_get_layer(pbvh->vdata, CD_PAINT_MASK));
case PBVH_BMESH:
- return (bvh->bm && (CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK) != -1));
+ return (pbvh->bm && (CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK) != -1));
}
return false;
}
-bool pbvh_has_face_sets(PBVH *bvh)
+bool pbvh_has_face_sets(PBVH *pbvh)
{
- switch (bvh->type) {
+ switch (pbvh->type) {
case PBVH_GRIDS:
- return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS));
+ return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
case PBVH_FACES:
- return (bvh->pdata && CustomData_get_layer(bvh->pdata, CD_SCULPT_FACE_SETS));
+ return (pbvh->pdata && CustomData_get_layer(pbvh->pdata, CD_SCULPT_FACE_SETS));
case PBVH_BMESH:
return false;
}
@@ -2977,29 +2989,29 @@ bool pbvh_has_face_sets(PBVH *bvh)
return false;
}
-void pbvh_show_mask_set(PBVH *bvh, bool show_mask)
+void pbvh_show_mask_set(PBVH *pbvh, bool show_mask)
{
- bvh->show_mask = show_mask;
+ pbvh->show_mask = show_mask;
}
-void pbvh_show_face_sets_set(PBVH *bvh, bool show_face_sets)
+void pbvh_show_face_sets_set(PBVH *pbvh, bool show_face_sets)
{
- bvh->show_face_sets = show_face_sets;
+ pbvh->show_face_sets = show_face_sets;
}
-void BKE_pbvh_set_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes)
+void BKE_pbvh_set_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
{
- bvh->num_planes = planes->num_planes;
- for (int i = 0; i < bvh->num_planes; i++) {
- copy_v4_v4(bvh->planes[i], planes->planes[i]);
+ pbvh->num_planes = planes->num_planes;
+ for (int i = 0; i < pbvh->num_planes; i++) {
+ copy_v4_v4(pbvh->planes[i], planes->planes[i]);
}
}
-void BKE_pbvh_get_frustum_planes(PBVH *bvh, PBVHFrustumPlanes *planes)
+void BKE_pbvh_get_frustum_planes(PBVH *pbvh, PBVHFrustumPlanes *planes)
{
- planes->num_planes = bvh->num_planes;
+ planes->num_planes = pbvh->num_planes;
for (int i = 0; i < planes->num_planes; i++) {
- copy_v4_v4(planes->planes[i], bvh->planes[i]);
+ copy_v4_v4(planes->planes[i], pbvh->planes[i]);
}
}
@@ -3011,23 +3023,23 @@ void BKE_pbvh_parallel_range_settings(TaskParallelSettings *settings,
settings->use_threading = use_threading && totnode > 1;
}
-MVert *BKE_pbvh_get_verts(const PBVH *bvh)
+MVert *BKE_pbvh_get_verts(const PBVH *pbvh)
{
- BLI_assert(bvh->type == PBVH_FACES);
- return bvh->verts;
+ BLI_assert(pbvh->type == PBVH_FACES);
+ return pbvh->verts;
}
-void BKE_pbvh_subdiv_cgg_set(PBVH *bvh, SubdivCCG *subdiv_ccg)
+void BKE_pbvh_subdiv_cgg_set(PBVH *pbvh, SubdivCCG *subdiv_ccg)
{
- bvh->subdiv_ccg = subdiv_ccg;
+ pbvh->subdiv_ccg = subdiv_ccg;
}
-void BKE_pbvh_face_sets_set(PBVH *bvh, int *face_sets)
+void BKE_pbvh_face_sets_set(PBVH *pbvh, int *face_sets)
{
- bvh->face_sets = face_sets;
+ pbvh->face_sets = face_sets;
}
-void BKE_pbvh_respect_hide_set(PBVH *bvh, bool respect_hide)
+void BKE_pbvh_respect_hide_set(PBVH *pbvh, bool respect_hide)
{
- bvh->respect_hide = respect_hide;
+ pbvh->respect_hide = respect_hide;
}
diff --git a/source/blender/blenkernel/intern/pbvh_bmesh.c b/source/blender/blenkernel/intern/pbvh_bmesh.c
index 73042222436..e87c7c8d46d 100644
--- a/source/blender/blenkernel/intern/pbvh_bmesh.c
+++ b/source/blender/blenkernel/intern/pbvh_bmesh.c
@@ -62,7 +62,7 @@
// #define USE_VERIFY
#ifdef USE_VERIFY
-static void pbvh_bmesh_verify(PBVH *bvh);
+static void pbvh_bmesh_verify(PBVH *pbvh);
#endif
/** \name BMesh Utility API
@@ -200,13 +200,13 @@ static BMVert *bm_vert_hash_lookup_chain(GHash *deleted_verts, BMVert *v)
/****************************** Building ******************************/
/* Update node data after splitting */
-static void pbvh_bmesh_node_finalize(PBVH *bvh,
+static void pbvh_bmesh_node_finalize(PBVH *pbvh,
const int node_index,
const int cd_vert_node_offset,
const int cd_face_node_offset)
{
GSetIterator gs_iter;
- PBVHNode *n = &bvh->nodes[node_index];
+ PBVHNode *n = &pbvh->nodes[node_index];
bool has_visible = false;
/* Create vert hash sets */
@@ -258,15 +258,15 @@ static void pbvh_bmesh_node_finalize(PBVH *bvh,
}
/* Recursively split the node if it exceeds the leaf_limit */
-static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_index)
+static void pbvh_bmesh_node_split(PBVH *pbvh, const BBC *bbc_array, int node_index)
{
- const int cd_vert_node_offset = bvh->cd_vert_node_offset;
- const int cd_face_node_offset = bvh->cd_face_node_offset;
- PBVHNode *n = &bvh->nodes[node_index];
+ const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
+ const int cd_face_node_offset = pbvh->cd_face_node_offset;
+ PBVHNode *n = &pbvh->nodes[node_index];
- if (BLI_gset_len(n->bm_faces) <= bvh->leaf_limit) {
+ if (BLI_gset_len(n->bm_faces) <= pbvh->leaf_limit) {
/* Node limit not exceeded */
- pbvh_bmesh_node_finalize(bvh, node_index, cd_vert_node_offset, cd_face_node_offset);
+ pbvh_bmesh_node_finalize(pbvh, node_index, cd_vert_node_offset, cd_face_node_offset);
return;
}
@@ -286,15 +286,15 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
const float mid = (cb.bmax[axis] + cb.bmin[axis]) * 0.5f;
/* Add two new child nodes */
- const int children = bvh->totnode;
+ const int children = pbvh->totnode;
n->children_offset = children;
- pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
/* Array reallocated, update current node pointer */
- n = &bvh->nodes[node_index];
+ n = &pbvh->nodes[node_index];
/* Initialize children */
- PBVHNode *c1 = &bvh->nodes[children], *c2 = &bvh->nodes[children + 1];
+ PBVHNode *c1 = &pbvh->nodes[children], *c2 = &pbvh->nodes[children + 1];
c1->flag |= PBVH_Leaf;
c2->flag |= PBVH_Leaf;
c1->bm_faces = BLI_gset_ptr_new_ex("bm_faces", BLI_gset_len(n->bm_faces) / 2);
@@ -370,25 +370,25 @@ static void pbvh_bmesh_node_split(PBVH *bvh, const BBC *bbc_array, int node_inde
n->flag &= ~PBVH_Leaf;
/* Recurse */
- pbvh_bmesh_node_split(bvh, bbc_array, children);
- pbvh_bmesh_node_split(bvh, bbc_array, children + 1);
+ pbvh_bmesh_node_split(pbvh, bbc_array, children);
+ pbvh_bmesh_node_split(pbvh, bbc_array, children + 1);
/* Array maybe reallocated, update current node pointer */
- n = &bvh->nodes[node_index];
+ n = &pbvh->nodes[node_index];
/* Update bounding box */
BB_reset(&n->vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset + 1].vb);
n->orig_vb = n->vb;
}
/* Recursively split the node if it exceeds the leaf_limit */
-static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
+static bool pbvh_bmesh_node_limit_ensure(PBVH *pbvh, int node_index)
{
- GSet *bm_faces = bvh->nodes[node_index].bm_faces;
+ GSet *bm_faces = pbvh->nodes[node_index].bm_faces;
const int bm_faces_size = BLI_gset_len(bm_faces);
- if (bm_faces_size <= bvh->leaf_limit) {
+ if (bm_faces_size <= pbvh->leaf_limit) {
/* Node limit not exceeded */
return false;
}
@@ -414,9 +414,9 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
BM_elem_index_set(f, i); /* set_dirty! */
}
/* Likely this is already dirty. */
- bvh->bm->elem_index_dirty |= BM_FACE;
+ pbvh->bm->elem_index_dirty |= BM_FACE;
- pbvh_bmesh_node_split(bvh, bbc_array, node_index);
+ pbvh_bmesh_node_split(pbvh, bbc_array, node_index);
MEM_freeN(bbc_array);
@@ -426,88 +426,91 @@ static bool pbvh_bmesh_node_limit_ensure(PBVH *bvh, int node_index)
/**********************************************************************/
#if 0
-static int pbvh_bmesh_node_offset_from_elem(PBVH *bvh, BMElem *ele)
+static int pbvh_bmesh_node_offset_from_elem(PBVH *pbvh, BMElem *ele)
{
switch (ele->head.htype) {
case BM_VERT:
- return bvh->cd_vert_node_offset;
+ return pbvh->cd_vert_node_offset;
default:
BLI_assert(ele->head.htype == BM_FACE);
- return bvh->cd_face_node_offset;
+ return pbvh->cd_face_node_offset;
}
}
-static int pbvh_bmesh_node_index_from_elem(PBVH *bvh, void *key)
+static int pbvh_bmesh_node_index_from_elem(PBVH *pbvh, void *key)
{
- const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(bvh, key);
+ const int cd_node_offset = pbvh_bmesh_node_offset_from_elem(pbvh, key);
const int node_index = BM_ELEM_CD_GET_INT((BMElem *)key, cd_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
- BLI_assert(node_index < bvh->totnode);
- (void)bvh;
+ BLI_assert(node_index < pbvh->totnode);
+ (void)pbvh;
return node_index;
}
-static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *bvh, void *key)
+static PBVHNode *pbvh_bmesh_node_from_elem(PBVH *pbvh, void *key)
{
- return &bvh->nodes[pbvh_bmesh_node_index_from_elem(bvh, key)];
+ return &pbvh->nodes[pbvh_bmesh_node_index_from_elem(pbvh, key)];
}
/* typecheck */
-# define pbvh_bmesh_node_index_from_elem(bvh, key) \
- (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_index_from_elem(bvh, key))
-# define pbvh_bmesh_node_from_elem(bvh, key) \
- (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_from_elem(bvh, key))
+# define pbvh_bmesh_node_index_from_elem(pbvh, key) \
+ (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_index_from_elem(pbvh, key))
+# define pbvh_bmesh_node_from_elem(pbvh, key) \
+ (CHECK_TYPE_ANY(key, BMFace *, BMVert *), pbvh_bmesh_node_from_elem(pbvh, key))
#endif
-BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *bvh, const BMVert *key)
+BLI_INLINE int pbvh_bmesh_node_index_from_vert(PBVH *pbvh, const BMVert *key)
{
- const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_vert_node_offset);
+ const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_vert_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
- BLI_assert(node_index < bvh->totnode);
+ BLI_assert(node_index < pbvh->totnode);
return node_index;
}
-BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *bvh, const BMFace *key)
+BLI_INLINE int pbvh_bmesh_node_index_from_face(PBVH *pbvh, const BMFace *key)
{
- const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, bvh->cd_face_node_offset);
+ const int node_index = BM_ELEM_CD_GET_INT((const BMElem *)key, pbvh->cd_face_node_offset);
BLI_assert(node_index != DYNTOPO_NODE_NONE);
- BLI_assert(node_index < bvh->totnode);
+ BLI_assert(node_index < pbvh->totnode);
return node_index;
}
-BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *bvh, const BMVert *key)
+BLI_INLINE PBVHNode *pbvh_bmesh_node_from_vert(PBVH *pbvh, const BMVert *key)
{
- return &bvh->nodes[pbvh_bmesh_node_index_from_vert(bvh, key)];
+ return &pbvh->nodes[pbvh_bmesh_node_index_from_vert(pbvh, key)];
}
-BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *bvh, const BMFace *key)
+BLI_INLINE PBVHNode *pbvh_bmesh_node_from_face(PBVH *pbvh, const BMFace *key)
{
- return &bvh->nodes[pbvh_bmesh_node_index_from_face(bvh, key)];
+ return &pbvh->nodes[pbvh_bmesh_node_index_from_face(pbvh, key)];
}
-static BMVert *pbvh_bmesh_vert_create(
- PBVH *bvh, int node_index, const float co[3], const float no[3], const int cd_vert_mask_offset)
+static BMVert *pbvh_bmesh_vert_create(PBVH *pbvh,
+ int node_index,
+ const float co[3],
+ const float no[3],
+ const int cd_vert_mask_offset)
{
- PBVHNode *node = &bvh->nodes[node_index];
+ PBVHNode *node = &pbvh->nodes[node_index];
- BLI_assert((bvh->totnode == 1 || node_index) && node_index <= bvh->totnode);
+ BLI_assert((pbvh->totnode == 1 || node_index) && node_index <= pbvh->totnode);
/* avoid initializing customdata because its quite involved */
- BMVert *v = BM_vert_create(bvh->bm, co, NULL, BM_CREATE_SKIP_CD);
- CustomData_bmesh_set_default(&bvh->bm->vdata, &v->head.data);
+ BMVert *v = BM_vert_create(pbvh->bm, co, NULL, BM_CREATE_SKIP_CD);
+ CustomData_bmesh_set_default(&pbvh->bm->vdata, &v->head.data);
/* This value is logged below */
copy_v3_v3(v->no, no);
BLI_gset_insert(node->bm_unique_verts, v);
- BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, node_index);
+ BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, node_index);
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
/* Log the new vertex */
- BM_log_vert_added(bvh->bm_log, v, cd_vert_mask_offset);
+ BM_log_vert_added(pbvh->bm_log, v, cd_vert_mask_offset);
return v;
}
@@ -516,38 +519,38 @@ static BMVert *pbvh_bmesh_vert_create(
* \note Callers are responsible for checking if the face exists before adding.
*/
static BMFace *pbvh_bmesh_face_create(
- PBVH *bvh, int node_index, BMVert *v_tri[3], BMEdge *e_tri[3], const BMFace *f_example)
+ PBVH *pbvh, int node_index, BMVert *v_tri[3], BMEdge *e_tri[3], const BMFace *f_example)
{
- PBVHNode *node = &bvh->nodes[node_index];
+ PBVHNode *node = &pbvh->nodes[node_index];
/* ensure we never add existing face */
BLI_assert(!BM_face_exists(v_tri, 3));
- BMFace *f = BM_face_create(bvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
+ BMFace *f = BM_face_create(pbvh->bm, v_tri, e_tri, 3, f_example, BM_CREATE_NOP);
f->head.hflag = f_example->head.hflag;
BLI_gset_insert(node->bm_faces, f);
- BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, node_index);
+ BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, node_index);
/* mark node for update */
node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
node->flag &= ~PBVH_FullyHidden;
/* Log the new face */
- BM_log_face_added(bvh->bm_log, f);
+ BM_log_face_added(pbvh->bm_log, f);
return f;
}
/* Return the number of faces in 'node' that use vertex 'v' */
#if 0
-static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
+static int pbvh_bmesh_node_vert_use_count(PBVH *pbvh, PBVHNode *node, BMVert *v)
{
BMFace *f;
int count = 0;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
if (f_node == node) {
count++;
}
@@ -558,10 +561,10 @@ static int pbvh_bmesh_node_vert_use_count(PBVH *bvh, PBVHNode *node, BMVert *v)
}
#endif
-#define pbvh_bmesh_node_vert_use_count_is_equal(bvh, node, v, n) \
- (pbvh_bmesh_node_vert_use_count_at_most(bvh, node, v, (n) + 1) == n)
+#define pbvh_bmesh_node_vert_use_count_is_equal(pbvh, node, v, n) \
+ (pbvh_bmesh_node_vert_use_count_at_most(pbvh, node, v, (n) + 1) == n)
-static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh,
+static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *pbvh,
PBVHNode *node,
BMVert *v,
const int count_max)
@@ -570,7 +573,7 @@ static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh,
BMFace *f;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
if (f_node == node) {
count++;
if (count == count_max) {
@@ -584,13 +587,13 @@ static int pbvh_bmesh_node_vert_use_count_at_most(PBVH *bvh,
}
/* Return a node that uses vertex 'v' other than its current owner */
-static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
+static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *pbvh, BMVert *v)
{
- PBVHNode *current_node = pbvh_bmesh_node_from_vert(bvh, v);
+ PBVHNode *current_node = pbvh_bmesh_node_from_vert(pbvh, v);
BMFace *f;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
if (f_node != current_node) {
return f_node;
@@ -601,9 +604,9 @@ static PBVHNode *pbvh_bmesh_vert_other_node_find(PBVH *bvh, BMVert *v)
return NULL;
}
-static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, BMVert *v)
+static void pbvh_bmesh_vert_ownership_transfer(PBVH *pbvh, PBVHNode *new_owner, BMVert *v)
{
- PBVHNode *current_owner = pbvh_bmesh_node_from_vert(bvh, v);
+ PBVHNode *current_owner = pbvh_bmesh_node_from_vert(pbvh, v);
/* mark node for update */
current_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
@@ -613,7 +616,7 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, B
BLI_gset_remove(current_owner->bm_unique_verts, v, NULL);
/* Set new ownership */
- BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, new_owner - bvh->nodes);
+ BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, new_owner - pbvh->nodes);
BLI_gset_insert(new_owner->bm_unique_verts, v);
BLI_gset_remove(new_owner->bm_other_verts, v, NULL);
BLI_assert(!BLI_gset_haskey(new_owner->bm_other_verts, v));
@@ -622,26 +625,26 @@ static void pbvh_bmesh_vert_ownership_transfer(PBVH *bvh, PBVHNode *new_owner, B
new_owner->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
}
-static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
+static void pbvh_bmesh_vert_remove(PBVH *pbvh, BMVert *v)
{
/* never match for first time */
int f_node_index_prev = DYNTOPO_NODE_NONE;
- PBVHNode *v_node = pbvh_bmesh_node_from_vert(bvh, v);
+ PBVHNode *v_node = pbvh_bmesh_node_from_vert(pbvh, v);
BLI_gset_remove(v_node->bm_unique_verts, v, NULL);
- BM_ELEM_CD_SET_INT(v, bvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
+ BM_ELEM_CD_SET_INT(v, pbvh->cd_vert_node_offset, DYNTOPO_NODE_NONE);
/* Have to check each neighboring face's node */
BMFace *f;
BM_FACES_OF_VERT_ITER_BEGIN (f, v) {
- const int f_node_index = pbvh_bmesh_node_index_from_face(bvh, f);
+ const int f_node_index = pbvh_bmesh_node_index_from_face(pbvh, f);
/* faces often share the same node,
* quick check to avoid redundant #BLI_gset_remove calls */
if (f_node_index_prev != f_node_index) {
f_node_index_prev = f_node_index;
- PBVHNode *f_node = &bvh->nodes[f_node_index];
+ PBVHNode *f_node = &pbvh->nodes[f_node_index];
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateBB;
/* Remove current ownership */
@@ -654,9 +657,9 @@ static void pbvh_bmesh_vert_remove(PBVH *bvh, BMVert *v)
BM_FACES_OF_VERT_ITER_END;
}
-static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
+static void pbvh_bmesh_face_remove(PBVH *pbvh, BMFace *f)
{
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, f);
/* Check if any of this face's vertices need to be removed
* from the node */
@@ -664,16 +667,16 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
BMLoop *l_iter = l_first;
do {
BMVert *v = l_iter->v;
- if (pbvh_bmesh_node_vert_use_count_is_equal(bvh, f_node, v, 1)) {
+ if (pbvh_bmesh_node_vert_use_count_is_equal(pbvh, f_node, v, 1)) {
if (BLI_gset_haskey(f_node->bm_unique_verts, v)) {
/* Find a different node that uses 'v' */
PBVHNode *new_node;
- new_node = pbvh_bmesh_vert_other_node_find(bvh, v);
+ new_node = pbvh_bmesh_vert_other_node_find(pbvh, v);
BLI_assert(new_node || BM_vert_face_count_is_equal(v, 1));
if (new_node) {
- pbvh_bmesh_vert_ownership_transfer(bvh, new_node, v);
+ pbvh_bmesh_vert_ownership_transfer(pbvh, new_node, v);
}
}
else {
@@ -685,10 +688,10 @@ static void pbvh_bmesh_face_remove(PBVH *bvh, BMFace *f)
/* Remove face from node and top level */
BLI_gset_remove(f_node->bm_faces, f, NULL);
- BM_ELEM_CD_SET_INT(f, bvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
+ BM_ELEM_CD_SET_INT(f, pbvh->cd_face_node_offset, DYNTOPO_NODE_NONE);
/* Log removed face */
- BM_log_face_removed(bvh->bm_log, f);
+ BM_log_face_removed(pbvh->bm_log, f);
/* mark node for update */
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals;
@@ -766,10 +769,10 @@ typedef struct {
#ifdef USE_EDGEQUEUE_TAG_VERIFY
/* simply check no edges are tagged
* (it's a requirement that edges enter and leave a clean tag state) */
-static void pbvh_bmesh_edge_tag_verify(PBVH *bvh)
+static void pbvh_bmesh_edge_tag_verify(PBVH *pbvh)
{
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
if (node->bm_faces) {
GSetIterator gs_iter;
GSET_ITER (gs_iter, node->bm_faces) {
@@ -999,7 +1002,7 @@ static void short_edge_queue_face_add(EdgeQueueContext *eq_ctx, BMFace *f)
* The highest priority (lowest number) is given to the longest edge.
*/
static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
const float center[3],
const float view_normal[3],
float radius,
@@ -1009,9 +1012,9 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->heap = BLI_heapsimple_new();
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
- eq_ctx->q->limit_len_squared = bvh->bm_max_edge_len * bvh->bm_max_edge_len;
+ eq_ctx->q->limit_len_squared = pbvh->bm_max_edge_len * pbvh->bm_max_edge_len;
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
- eq_ctx->q->limit_len = bvh->bm_max_edge_len;
+ eq_ctx->q->limit_len = pbvh->bm_max_edge_len;
#endif
eq_ctx->q->view_normal = view_normal;
@@ -1031,11 +1034,11 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
}
#ifdef USE_EDGEQUEUE_TAG_VERIFY
- pbvh_bmesh_edge_tag_verify(bvh);
+ pbvh_bmesh_edge_tag_verify(pbvh);
#endif
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
/* Check leaf nodes marked for topology update */
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
@@ -1062,7 +1065,7 @@ static void long_edge_queue_create(EdgeQueueContext *eq_ctx,
* The highest priority (lowest number) is given to the shortest edge.
*/
static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
const float center[3],
const float view_normal[3],
float radius,
@@ -1072,9 +1075,9 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->heap = BLI_heapsimple_new();
eq_ctx->q->center = center;
eq_ctx->q->radius_squared = radius * radius;
- eq_ctx->q->limit_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+ eq_ctx->q->limit_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
#ifdef USE_EDGEQUEUE_EVEN_SUBDIV
- eq_ctx->q->limit_len = bvh->bm_min_edge_len;
+ eq_ctx->q->limit_len = pbvh->bm_min_edge_len;
#endif
eq_ctx->q->view_normal = view_normal;
@@ -1093,8 +1096,8 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
eq_ctx->q->edge_queue_tri_in_range = edge_queue_tri_in_sphere;
}
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
/* Check leaf nodes marked for topology update */
if ((node->flag & PBVH_Leaf) && (node->flag & PBVH_UpdateTopology) &&
@@ -1114,7 +1117,7 @@ static void short_edge_queue_create(EdgeQueueContext *eq_ctx,
/*************************** Topology update **************************/
static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
BMEdge *e,
BLI_Buffer *edge_loops)
{
@@ -1130,7 +1133,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
int node_index = BM_ELEM_CD_GET_INT(e->v1, eq_ctx->cd_vert_node_offset);
BMVert *v_new = pbvh_bmesh_vert_create(
- bvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
+ pbvh, node_index, co_mid, no_mid, eq_ctx->cd_vert_mask_offset);
/* update paint mask */
if (eq_ctx->cd_vert_mask_offset != -1) {
@@ -1163,7 +1166,7 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
v2 = l_adj->next->v;
if (ni != node_index && i == 0) {
- pbvh_bmesh_vert_ownership_transfer(bvh, &bvh->nodes[ni], v_new);
+ pbvh_bmesh_vert_ownership_transfer(pbvh, &pbvh->nodes[ni], v_new);
}
/**
@@ -1196,26 +1199,26 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
v_tri[0] = v1;
v_tri[1] = v_new;
v_tri[2] = v_opp;
- bm_edges_from_tri(bvh->bm, v_tri, e_tri);
- f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
+ bm_edges_from_tri(pbvh->bm, v_tri, e_tri);
+ f_new = pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f_adj);
long_edge_queue_face_add(eq_ctx, f_new);
v_tri[0] = v_new;
v_tri[1] = v2;
/* v_tri[2] = v_opp; */ /* unchanged */
- e_tri[0] = BM_edge_create(bvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
+ e_tri[0] = BM_edge_create(pbvh->bm, v_tri[0], v_tri[1], NULL, BM_CREATE_NO_DOUBLE);
e_tri[2] = e_tri[1]; /* switched */
- e_tri[1] = BM_edge_create(bvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
- f_new = pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f_adj);
+ e_tri[1] = BM_edge_create(pbvh->bm, v_tri[1], v_tri[2], NULL, BM_CREATE_NO_DOUBLE);
+ f_new = pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f_adj);
long_edge_queue_face_add(eq_ctx, f_new);
/* Delete original */
- pbvh_bmesh_face_remove(bvh, f_adj);
- BM_face_kill(bvh->bm, f_adj);
+ pbvh_bmesh_face_remove(pbvh, f_adj);
+ BM_face_kill(pbvh->bm, f_adj);
/* Ensure new vertex is in the node */
- if (!BLI_gset_haskey(bvh->nodes[ni].bm_unique_verts, v_new)) {
- BLI_gset_add(bvh->nodes[ni].bm_other_verts, v_new);
+ if (!BLI_gset_haskey(pbvh->nodes[ni].bm_unique_verts, v_new)) {
+ BLI_gset_add(pbvh->nodes[ni].bm_other_verts, v_new);
}
if (BM_vert_edge_count_is_over(v_opp, 8)) {
@@ -1228,11 +1231,11 @@ static void pbvh_bmesh_split_edge(EdgeQueueContext *eq_ctx,
}
}
- BM_edge_kill(bvh->bm, e);
+ BM_edge_kill(pbvh->bm, e);
}
static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
BLI_Buffer *edge_loops)
{
bool any_subdivided = false;
@@ -1274,17 +1277,17 @@ static bool pbvh_bmesh_subdivide_long_edges(EdgeQueueContext *eq_ctx,
any_subdivided = true;
- pbvh_bmesh_split_edge(eq_ctx, bvh, e, edge_loops);
+ pbvh_bmesh_split_edge(eq_ctx, pbvh, e, edge_loops);
}
#ifdef USE_EDGEQUEUE_TAG_VERIFY
- pbvh_bmesh_edge_tag_verify(bvh);
+ pbvh_bmesh_edge_tag_verify(pbvh);
#endif
return any_subdivided;
}
-static void pbvh_bmesh_collapse_edge(PBVH *bvh,
+static void pbvh_bmesh_collapse_edge(PBVH *pbvh,
BMEdge *e,
BMVert *v1,
BMVert *v2,
@@ -1306,20 +1309,20 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
}
/* Remove the merge vertex from the PBVH */
- pbvh_bmesh_vert_remove(bvh, v_del);
+ pbvh_bmesh_vert_remove(pbvh, v_del);
/* Remove all faces adjacent to the edge */
BMLoop *l_adj;
while ((l_adj = e->l)) {
BMFace *f_adj = l_adj->f;
- pbvh_bmesh_face_remove(bvh, f_adj);
- BM_face_kill(bvh->bm, f_adj);
+ pbvh_bmesh_face_remove(pbvh, f_adj);
+ BM_face_kill(pbvh->bm, f_adj);
}
/* Kill the edge */
BLI_assert(BM_edge_is_wire(e));
- BM_edge_kill(bvh->bm, e);
+ BM_edge_kill(pbvh->bm, e);
/* For all remaining faces of v_del, create a new face that is the
* same except it uses v_conn instead of v_del */
@@ -1364,10 +1367,10 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
BLI_assert(!BM_face_exists(v_tri, 3));
BMEdge *e_tri[3];
- PBVHNode *n = pbvh_bmesh_node_from_face(bvh, f);
- int ni = n - bvh->nodes;
- bm_edges_from_tri(bvh->bm, v_tri, e_tri);
- pbvh_bmesh_face_create(bvh, ni, v_tri, e_tri, f);
+ PBVHNode *n = pbvh_bmesh_node_from_face(pbvh, f);
+ int ni = n - pbvh->nodes;
+ bm_edges_from_tri(pbvh->bm, v_tri, e_tri);
+ pbvh_bmesh_face_create(pbvh, ni, v_tri, e_tri, f);
/* Ensure that v_conn is in the new face's node */
if (!BLI_gset_haskey(n->bm_unique_verts, v_conn)) {
@@ -1398,14 +1401,14 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
e_tri[2] = l_iter->e;
/* Remove the face */
- pbvh_bmesh_face_remove(bvh, f_del);
- BM_face_kill(bvh->bm, f_del);
+ pbvh_bmesh_face_remove(pbvh, f_del);
+ BM_face_kill(pbvh->bm, f_del);
/* Check if any of the face's edges are now unused by any
* face, if so delete them */
for (int j = 0; j < 3; j++) {
if (BM_edge_is_wire(e_tri[j])) {
- BM_edge_kill(bvh->bm, e_tri[j]);
+ BM_edge_kill(pbvh->bm, e_tri[j]);
}
}
@@ -1413,15 +1416,15 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
* remove them from the PBVH */
for (int j = 0; j < 3; j++) {
if ((v_tri[j] != v_del) && (v_tri[j]->e == NULL)) {
- pbvh_bmesh_vert_remove(bvh, v_tri[j]);
+ pbvh_bmesh_vert_remove(pbvh, v_tri[j]);
- BM_log_vert_removed(bvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
+ BM_log_vert_removed(pbvh->bm_log, v_tri[j], eq_ctx->cd_vert_mask_offset);
if (v_tri[j] == v_conn) {
v_conn = NULL;
}
BLI_ghash_insert(deleted_verts, v_tri[j], NULL);
- BM_vert_kill(bvh->bm, v_tri[j]);
+ BM_vert_kill(pbvh->bm, v_tri[j]);
}
}
}
@@ -1429,7 +1432,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
/* Move v_conn to the midpoint of v_conn and v_del (if v_conn still exists, it
* may have been deleted above) */
if (v_conn != NULL) {
- BM_log_vert_before_modified(bvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset);
+ BM_log_vert_before_modified(pbvh->bm_log, v_conn, eq_ctx->cd_vert_mask_offset);
mid_v3_v3v3(v_conn->co, v_conn->co, v_del->co);
add_v3_v3(v_conn->no, v_del->no);
normalize_v3(v_conn->no);
@@ -1437,7 +1440,7 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
/* update boundboxes attached to the connected vertex
* note that we can often get-away without this but causes T48779 */
BM_LOOPS_OF_VERT_ITER_BEGIN (l, v_conn) {
- PBVHNode *f_node = pbvh_bmesh_node_from_face(bvh, l->f);
+ PBVHNode *f_node = pbvh_bmesh_node_from_face(pbvh, l->f);
f_node->flag |= PBVH_UpdateDrawBuffers | PBVH_UpdateNormals | PBVH_UpdateBB;
}
BM_LOOPS_OF_VERT_ITER_END;
@@ -1445,17 +1448,17 @@ static void pbvh_bmesh_collapse_edge(PBVH *bvh,
/* Delete v_del */
BLI_assert(!BM_vert_face_check(v_del));
- BM_log_vert_removed(bvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset);
+ BM_log_vert_removed(pbvh->bm_log, v_del, eq_ctx->cd_vert_mask_offset);
/* v_conn == NULL is OK */
BLI_ghash_insert(deleted_verts, v_del, v_conn);
- BM_vert_kill(bvh->bm, v_del);
+ BM_vert_kill(pbvh->bm, v_del);
}
static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
- PBVH *bvh,
+ PBVH *pbvh,
BLI_Buffer *deleted_faces)
{
- const float min_len_squared = bvh->bm_min_edge_len * bvh->bm_min_edge_len;
+ const float min_len_squared = pbvh->bm_min_edge_len * pbvh->bm_min_edge_len;
bool any_collapsed = false;
/* deleted verts point to vertices they were merged into, or NULL when removed. */
GHash *deleted_verts = BLI_ghash_ptr_new("deleted_verts");
@@ -1496,7 +1499,7 @@ static bool pbvh_bmesh_collapse_short_edges(EdgeQueueContext *eq_ctx,
any_collapsed = true;
- pbvh_bmesh_collapse_edge(bvh, e, v1, v2, deleted_verts, deleted_faces, eq_ctx);
+ pbvh_bmesh_collapse_edge(pbvh, e, v1, v2, deleted_verts, deleted_faces, eq_ctx);
}
BLI_ghash_free(deleted_verts, NULL, NULL);
@@ -1691,11 +1694,11 @@ struct FastNodeBuildInfo {
* to a sub part of the arrays.
*/
static void pbvh_bmesh_node_limit_ensure_fast(
- PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, MemArena *arena)
+ PBVH *pbvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, MemArena *arena)
{
struct FastNodeBuildInfo *child1, *child2;
- if (node->totface <= bvh->leaf_limit) {
+ if (node->totface <= pbvh->leaf_limit) {
return;
}
@@ -1782,38 +1785,38 @@ static void pbvh_bmesh_node_limit_ensure_fast(
child2->start = node->start + num_child1;
child1->child1 = child1->child2 = child2->child1 = child2->child2 = NULL;
- pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child1, arena);
- pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, child2, arena);
+ pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, child1, arena);
+ pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, child2, arena);
}
static void pbvh_bmesh_create_nodes_fast_recursive(
- PBVH *bvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, int node_index)
+ PBVH *pbvh, BMFace **nodeinfo, BBC *bbc_array, struct FastNodeBuildInfo *node, int node_index)
{
- PBVHNode *n = bvh->nodes + node_index;
+ PBVHNode *n = pbvh->nodes + node_index;
/* two cases, node does not have children or does have children */
if (node->child1) {
- int children_offset = bvh->totnode;
+ int children_offset = pbvh->totnode;
n->children_offset = children_offset;
- pbvh_grow_nodes(bvh, bvh->totnode + 2);
+ pbvh_grow_nodes(pbvh, pbvh->totnode + 2);
pbvh_bmesh_create_nodes_fast_recursive(
- bvh, nodeinfo, bbc_array, node->child1, children_offset);
+ pbvh, nodeinfo, bbc_array, node->child1, children_offset);
pbvh_bmesh_create_nodes_fast_recursive(
- bvh, nodeinfo, bbc_array, node->child2, children_offset + 1);
+ pbvh, nodeinfo, bbc_array, node->child2, children_offset + 1);
- n = &bvh->nodes[node_index];
+ n = &pbvh->nodes[node_index];
/* Update bounding box */
BB_reset(&n->vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset].vb);
- BB_expand_with_bb(&n->vb, &bvh->nodes[n->children_offset + 1].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset].vb);
+ BB_expand_with_bb(&n->vb, &pbvh->nodes[n->children_offset + 1].vb);
n->orig_vb = n->vb;
}
else {
/* node does not have children so it's a leaf node, populate with faces and tag accordingly
* this is an expensive part but it's not so easily thread-able due to vertex node indices */
- const int cd_vert_node_offset = bvh->cd_vert_node_offset;
- const int cd_face_node_offset = bvh->cd_face_node_offset;
+ const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
+ const int cd_face_node_offset = pbvh->cd_face_node_offset;
bool has_visible = false;
@@ -1876,27 +1879,27 @@ static void pbvh_bmesh_create_nodes_fast_recursive(
/***************************** Public API *****************************/
/* Build a PBVH from a BMesh */
-void BKE_pbvh_build_bmesh(PBVH *bvh,
+void BKE_pbvh_build_bmesh(PBVH *pbvh,
BMesh *bm,
bool smooth_shading,
BMLog *log,
const int cd_vert_node_offset,
const int cd_face_node_offset)
{
- bvh->cd_vert_node_offset = cd_vert_node_offset;
- bvh->cd_face_node_offset = cd_face_node_offset;
- bvh->bm = bm;
+ pbvh->cd_vert_node_offset = cd_vert_node_offset;
+ pbvh->cd_face_node_offset = cd_face_node_offset;
+ pbvh->bm = bm;
- BKE_pbvh_bmesh_detail_size_set(bvh, 0.75);
+ BKE_pbvh_bmesh_detail_size_set(pbvh, 0.75);
- bvh->type = PBVH_BMESH;
- bvh->bm_log = log;
+ pbvh->type = PBVH_BMESH;
+ pbvh->bm_log = log;
/* TODO: choose leaf limit better */
- bvh->leaf_limit = 100;
+ pbvh->leaf_limit = 100;
if (smooth_shading) {
- bvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
+ pbvh->flags |= PBVH_DYNTOPO_SMOOTH_SHADING;
}
/* bounding box array of all faces, no need to recalculate every time */
@@ -1936,17 +1939,17 @@ void BKE_pbvh_build_bmesh(PBVH *bvh,
rootnode.totface = bm->totface;
/* start recursion, assign faces to nodes accordingly */
- pbvh_bmesh_node_limit_ensure_fast(bvh, nodeinfo, bbc_array, &rootnode, arena);
+ pbvh_bmesh_node_limit_ensure_fast(pbvh, nodeinfo, bbc_array, &rootnode, arena);
/* We now have all faces assigned to a node,
* next we need to assign those to the gsets of the nodes. */
/* Start with all faces in the root node */
- bvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
- bvh->totnode = 1;
+ pbvh->nodes = MEM_callocN(sizeof(PBVHNode), "PBVHNode");
+ pbvh->totnode = 1;
/* take root node and visit and populate children recursively */
- pbvh_bmesh_create_nodes_fast_recursive(bvh, nodeinfo, bbc_array, &rootnode, 0);
+ pbvh_bmesh_create_nodes_fast_recursive(pbvh, nodeinfo, bbc_array, &rootnode, 0);
BLI_memarena_free(arena);
MEM_freeN(bbc_array);
@@ -1954,7 +1957,7 @@ void BKE_pbvh_build_bmesh(PBVH *bvh,
}
/* Collapse short edges, subdivide long edges */
-bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
+bool BKE_pbvh_bmesh_update_topology(PBVH *pbvh,
PBVHTopologyUpdateMode mode,
const float center[3],
const float view_normal[3],
@@ -1965,9 +1968,9 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
/* 2 is enough for edge faces - manifold edge */
BLI_buffer_declare_static(BMLoop *, edge_loops, BLI_BUFFER_NOP, 2);
BLI_buffer_declare_static(BMFace *, deleted_faces, BLI_BUFFER_NOP, 32);
- const int cd_vert_mask_offset = CustomData_get_offset(&bvh->bm->vdata, CD_PAINT_MASK);
- const int cd_vert_node_offset = bvh->cd_vert_node_offset;
- const int cd_face_node_offset = bvh->cd_face_node_offset;
+ const int cd_vert_mask_offset = CustomData_get_offset(&pbvh->bm->vdata, CD_PAINT_MASK);
+ const int cd_vert_node_offset = pbvh->cd_vert_node_offset;
+ const int cd_face_node_offset = pbvh->cd_face_node_offset;
bool modified = false;
@@ -1981,15 +1984,15 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
EdgeQueueContext eq_ctx = {
&q,
queue_pool,
- bvh->bm,
+ pbvh->bm,
cd_vert_mask_offset,
cd_vert_node_offset,
cd_face_node_offset,
};
short_edge_queue_create(
- &eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected);
- modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, bvh, &deleted_faces);
+ &eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
+ modified |= pbvh_bmesh_collapse_short_edges(&eq_ctx, pbvh, &deleted_faces);
BLI_heapsimple_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
@@ -2000,22 +2003,22 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
EdgeQueueContext eq_ctx = {
&q,
queue_pool,
- bvh->bm,
+ pbvh->bm,
cd_vert_mask_offset,
cd_vert_node_offset,
cd_face_node_offset,
};
long_edge_queue_create(
- &eq_ctx, bvh, center, view_normal, radius, use_frontface, use_projected);
- modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, bvh, &edge_loops);
+ &eq_ctx, pbvh, center, view_normal, radius, use_frontface, use_projected);
+ modified |= pbvh_bmesh_subdivide_long_edges(&eq_ctx, pbvh, &edge_loops);
BLI_heapsimple_free(q.heap, NULL);
BLI_mempool_destroy(queue_pool);
}
/* Unmark nodes */
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
if (node->flag & PBVH_Leaf && node->flag & PBVH_UpdateTopology) {
node->flag &= ~PBVH_UpdateTopology;
@@ -2025,7 +2028,7 @@ bool BKE_pbvh_bmesh_update_topology(PBVH *bvh,
BLI_buffer_free(&deleted_faces);
#ifdef USE_VERIFY
- pbvh_bmesh_verify(bvh);
+ pbvh_bmesh_verify(pbvh);
#endif
return modified;
@@ -2092,25 +2095,25 @@ void BKE_pbvh_bmesh_node_save_orig(BMesh *bm, PBVHNode *node)
node->bm_tot_ortri = i;
}
-void BKE_pbvh_bmesh_after_stroke(PBVH *bvh)
+void BKE_pbvh_bmesh_after_stroke(PBVH *pbvh)
{
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
if (n->flag & PBVH_Leaf) {
/* Free orco/ortri data */
pbvh_bmesh_node_drop_orig(n);
/* Recursively split nodes that have gotten too many
* elements */
- pbvh_bmesh_node_limit_ensure(bvh, i);
+ pbvh_bmesh_node_limit_ensure(pbvh, i);
}
}
}
-void BKE_pbvh_bmesh_detail_size_set(PBVH *bvh, float detail_size)
+void BKE_pbvh_bmesh_detail_size_set(PBVH *pbvh, float detail_size)
{
- bvh->bm_max_edge_len = detail_size;
- bvh->bm_min_edge_len = bvh->bm_max_edge_len * 0.4f;
+ pbvh->bm_max_edge_len = detail_size;
+ pbvh->bm_min_edge_len = pbvh->bm_max_edge_len * 0.4f;
}
void BKE_pbvh_node_mark_topology_update(PBVHNode *node)
@@ -2137,25 +2140,25 @@ struct GSet *BKE_pbvh_bmesh_node_faces(PBVHNode *node)
#if 0
-static void pbvh_bmesh_print(PBVH *bvh)
+static void pbvh_bmesh_print(PBVH *pbvh)
{
- fprintf(stderr, "\npbvh=%p\n", bvh);
+ fprintf(stderr, "\npbvh=%p\n", pbvh);
fprintf(stderr, "bm_face_to_node:\n");
BMIter iter;
BMFace *f;
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(bvh, f));
+ BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
+ fprintf(stderr, " %d -> %d\n", BM_elem_index_get(f), pbvh_bmesh_node_index_from_face(pbvh, f));
}
fprintf(stderr, "bm_vert_to_node:\n");
BMVert *v;
- BM_ITER_MESH (v, &iter, bvh->bm, BM_FACES_OF_MESH) {
- fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(bvh, v));
+ BM_ITER_MESH (v, &iter, pbvh->bm, BM_FACES_OF_MESH) {
+ fprintf(stderr, " %d -> %d\n", BM_elem_index_get(v), pbvh_bmesh_node_index_from_vert(pbvh, v));
}
- for (int n = 0; n < bvh->totnode; n++) {
- PBVHNode *node = &bvh->nodes[n];
+ for (int n = 0; n < pbvh->totnode; n++) {
+ PBVHNode *node = &pbvh->nodes[n];
if (!(node->flag & PBVH_Leaf)) {
continue;
}
@@ -2186,25 +2189,25 @@ static void print_flag_factors(int flag)
#ifdef USE_VERIFY
-static void pbvh_bmesh_verify(PBVH *bvh)
+static void pbvh_bmesh_verify(PBVH *pbvh)
{
/* build list of faces & verts to lookup */
- GSet *faces_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totface);
+ GSet *faces_all = BLI_gset_ptr_new_ex(__func__, pbvh->bm->totface);
BMIter iter;
{
BMFace *f;
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
- BLI_assert(BM_ELEM_CD_GET_INT(f, bvh->cd_face_node_offset) != DYNTOPO_NODE_NONE);
+ BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
+ BLI_assert(BM_ELEM_CD_GET_INT(f, pbvh->cd_face_node_offset) != DYNTOPO_NODE_NONE);
BLI_gset_insert(faces_all, f);
}
}
- GSet *verts_all = BLI_gset_ptr_new_ex(__func__, bvh->bm->totvert);
+ GSet *verts_all = BLI_gset_ptr_new_ex(__func__, pbvh->bm->totvert);
{
BMVert *v;
- BM_ITER_MESH (v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
- if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
+ BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
+ if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) != DYNTOPO_NODE_NONE) {
BLI_gset_insert(verts_all, v);
}
}
@@ -2213,8 +2216,8 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check vert/face counts */
{
int totface = 0, totvert = 0;
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
totface += n->bm_faces ? BLI_gset_len(n->bm_faces) : 0;
totvert += n->bm_unique_verts ? BLI_gset_len(n->bm_unique_verts) : 0;
}
@@ -2225,10 +2228,10 @@ static void pbvh_bmesh_verify(PBVH *bvh)
{
BMFace *f;
- BM_ITER_MESH (f, &iter, bvh->bm, BM_FACES_OF_MESH) {
+ BM_ITER_MESH (f, &iter, pbvh->bm, BM_FACES_OF_MESH) {
BMIter bm_iter;
BMVert *v;
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *n = pbvh_bmesh_node_lookup(pbvh, f);
/* Check that the face's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -2244,7 +2247,7 @@ static void pbvh_bmesh_verify(PBVH *bvh)
BLI_assert(BLI_gset_haskey(n->bm_unique_verts, v) ^ BLI_gset_haskey(n->bm_other_verts, v));
/* Check that the vertex has a node owner */
- nv = pbvh_bmesh_node_lookup(bvh, v);
+ nv = pbvh_bmesh_node_lookup(pbvh, v);
/* Check that the vertex's node knows it owns the vert */
BLI_assert(BLI_gset_haskey(nv->bm_unique_verts, v));
@@ -2258,13 +2261,13 @@ static void pbvh_bmesh_verify(PBVH *bvh)
/* Check verts */
{
BMVert *v;
- BM_ITER_MESH (v, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (v, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
/* vertex isn't tracked */
- if (BM_ELEM_CD_GET_INT(v, bvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
+ if (BM_ELEM_CD_GET_INT(v, pbvh->cd_vert_node_offset) == DYNTOPO_NODE_NONE) {
continue;
}
- PBVHNode *n = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *n = pbvh_bmesh_node_lookup(pbvh, v);
/* Check that the vert's node is a leaf */
BLI_assert(n->flag & PBVH_Leaf);
@@ -2281,7 +2284,7 @@ static void pbvh_bmesh_verify(PBVH *bvh)
BMIter bm_iter;
BMFace *f = NULL;
BM_ITER_ELEM (f, &bm_iter, v, BM_FACES_OF_VERT) {
- if (pbvh_bmesh_node_lookup(bvh, f) == n) {
+ if (pbvh_bmesh_node_lookup(pbvh, f) == n) {
found = true;
break;
}
@@ -2291,8 +2294,8 @@ static void pbvh_bmesh_verify(PBVH *bvh)
# if 1
/* total freak stuff, check if node exists somewhere else */
/* Slow */
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n_other = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n_other = &pbvh->nodes[i];
if ((n != n_other) && (n_other->bm_unique_verts)) {
BLI_assert(!BLI_gset_haskey(n_other->bm_unique_verts, v));
}
@@ -2304,10 +2307,10 @@ static void pbvh_bmesh_verify(PBVH *bvh)
# if 0
/* check that every vert belongs somewhere */
/* Slow */
- BM_ITER_MESH (vi, &iter, bvh->bm, BM_VERTS_OF_MESH) {
+ BM_ITER_MESH (vi, &iter, pbvh->bm, BM_VERTS_OF_MESH) {
bool has_unique = false;
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
if ((n->bm_unique_verts != NULL) && BLI_gset_haskey(n->bm_unique_verts, vi)) {
has_unique = true;
}
@@ -2317,25 +2320,25 @@ static void pbvh_bmesh_verify(PBVH *bvh)
}
/* if totvert differs from number of verts inside the hash. hash-totvert is checked above */
- BLI_assert(vert_count == bvh->bm->totvert);
+ BLI_assert(vert_count == pbvh->bm->totvert);
# endif
/* Check that node elements are recorded in the top level */
- for (int i = 0; i < bvh->totnode; i++) {
- PBVHNode *n = &bvh->nodes[i];
+ for (int i = 0; i < pbvh->totnode; i++) {
+ PBVHNode *n = &pbvh->nodes[i];
if (n->flag & PBVH_Leaf) {
GSetIterator gs_iter;
GSET_ITER (gs_iter, n->bm_faces) {
BMFace *f = BLI_gsetIterator_getKey(&gs_iter);
- PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, f);
+ PBVHNode *n_other = pbvh_bmesh_node_lookup(pbvh, f);
BLI_assert(n == n_other);
BLI_assert(BLI_gset_haskey(faces_all, f));
}
GSET_ITER (gs_iter, n->bm_unique_verts) {
BMVert *v = BLI_gsetIterator_getKey(&gs_iter);
- PBVHNode *n_other = pbvh_bmesh_node_lookup(bvh, v);
+ PBVHNode *n_other = pbvh_bmesh_node_lookup(pbvh, v);
BLI_assert(!BLI_gset_haskey(n->bm_other_verts, v));
BLI_assert(n == n_other);
BLI_assert(BLI_gset_haskey(verts_all, v));
diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c
index 7d60d21a496..bb7ec0adc19 100644
--- a/source/blender/blenkernel/intern/scene.c
+++ b/source/blender/blenkernel/intern/scene.c
@@ -672,7 +672,6 @@ ToolSettings *BKE_toolsettings_copy(ToolSettings *toolsettings, const int flag)
}
BKE_paint_copy(&ts->imapaint.paint, &ts->imapaint.paint, flag);
- ts->imapaint.paintcursor = NULL;
ts->particle.paintcursor = NULL;
ts->particle.scene = NULL;
ts->particle.object = NULL;
diff --git a/source/blender/blenkernel/intern/seqprefetch.c b/source/blender/blenkernel/intern/seqprefetch.c
index dc75e2b9098..30a371b5b28 100644
--- a/source/blender/blenkernel/intern/seqprefetch.c
+++ b/source/blender/blenkernel/intern/seqprefetch.c
@@ -435,11 +435,8 @@ static void *seq_prefetch_frames(void *job)
seq_prefetch_update_depsgraph(pfjob);
AnimData *adt = BKE_animdata_from_id(&pfjob->context_cpy.scene->id);
- BKE_animsys_evaluate_animdata(&pfjob->context_cpy.scene->id,
- adt,
- seq_prefetch_cfra(pfjob),
- ADT_RECALC_ALL,
- false);
+ BKE_animsys_evaluate_animdata(
+ &pfjob->context_cpy.scene->id, adt, seq_prefetch_cfra(pfjob), ADT_RECALC_ALL, false);
/* This is quite hacky solution:
* We need cross-reference original scene with copy for cache.
diff --git a/source/blender/blenkernel/intern/studiolight.c b/source/blender/blenkernel/intern/studiolight.c
index aef274f7d91..4892e8d6ede 100644
--- a/source/blender/blenkernel/intern/studiolight.c
+++ b/source/blender/blenkernel/intern/studiolight.c
@@ -503,10 +503,8 @@ static void studiolight_create_equirect_radiance_gputexture(StudioLight *sl)
sl->equirect_radiance_gputexture = GPU_texture_create_2d(
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
GPUTexture *tex = sl->equirect_radiance_gputexture;
- GPU_texture_bind(tex, 0);
GPU_texture_filter_mode(tex, true);
GPU_texture_wrap_mode(tex, true, true);
- GPU_texture_unbind(tex);
}
sl->flag |= STUDIOLIGHT_EQUIRECT_RADIANCE_GPUTEXTURE;
}
@@ -567,10 +565,8 @@ static void studiolight_create_equirect_irradiance_gputexture(StudioLight *sl)
sl->equirect_irradiance_gputexture = GPU_texture_create_2d(
ibuf->x, ibuf->y, GPU_RGBA16F, ibuf->rect_float, NULL);
GPUTexture *tex = sl->equirect_irradiance_gputexture;
- GPU_texture_bind(tex, 0);
GPU_texture_filter_mode(tex, true);
GPU_texture_wrap_mode(tex, true, true);
- GPU_texture_unbind(tex);
}
sl->flag |= STUDIOLIGHT_EQUIRECT_IRRADIANCE_GPUTEXTURE;
}
diff --git a/source/blender/blenkernel/intern/unit.c b/source/blender/blenkernel/intern/unit.c
index 3f44c13ba19..a8136dd7932 100644
--- a/source/blender/blenkernel/intern/unit.c
+++ b/source/blender/blenkernel/intern/unit.c
@@ -713,6 +713,113 @@ static bool ch_is_op(char op)
}
}
+/**
+ * Helper function for #unit_distribute_negatives to find the next negative to distribute.
+ *
+ * \note This unecessarily skips the next space if it comes right after the "-"
+ * just to make a more predictable output.
+ */
+static char *find_next_negative(const char *str, const char *remaining_str)
+{
+ char *str_found = strstr(remaining_str, "-");
+
+ if (str_found == NULL) {
+ return NULL;
+ }
+
+ /* Don't use the "-" from scientific notation, but make sure we can look backwards first. */
+ if ((str_found != str) && ELEM(*(str_found - 1), 'e', 'E')) {
+ return find_next_negative(str, str_found + 1);
+ }
+
+ if (*(str_found + 1) == ' ') {
+ str_found++;
+ }
+
+ return str_found + 1;
+}
+
+/**
+ * Helper function for #unit_distribute_negatives to find the next operation, including "-".
+ *
+ * \note This unecessarily skips the space before the operation character
+ * just to make a more predictable output.
+ */
+static char *find_next_op(const char *str, char *remaining_str, int len_max)
+{
+ int i;
+ bool scientific_notation = false;
+ for (i = 0; i < len_max; i++) {
+ if (remaining_str[i] == '\0') {
+ return remaining_str + i;
+ }
+
+ if (ch_is_op(remaining_str[i])) {
+ if (scientific_notation) {
+ scientific_notation = false;
+ continue;
+ }
+
+ /* Make sure we don't look backwards before the start of the string. */
+ if (remaining_str != str && i != 0) {
+ /* Check for scientific notation. */
+ if (remaining_str[i - 1] == 'e' || remaining_str[i - 1] == 'E') {
+ scientific_notation = true;
+ continue;
+ }
+
+ /* Return position before a space character. */
+ if (remaining_str[i - 1] == ' ') {
+ i--;
+ }
+ }
+
+ return remaining_str + i;
+ }
+ }
+ BLI_assert(!"String should be NULL terminated");
+ return remaining_str + i;
+}
+
+/**
+ * Put parentheses around blocks of values after negative signs to get rid of an implied "+"
+ * between numbers without an operation between them. For example:
+ *
+ * "-1m50cm + 1 - 2m50cm" -> "-(1m50cm) + 1 - (2m50cm)"
+ */
+static bool unit_distribute_negatives(char *str, const int len_max)
+{
+ bool changed = false;
+
+ char *remaining_str = str;
+ int remaining_str_len = len_max;
+ while ((remaining_str = find_next_negative(str, remaining_str)) != NULL) {
+ /* Exit early in the unlikely situation that we've run out of length to add the parentheses. */
+ remaining_str_len = len_max - (int)(remaining_str - str);
+ if (remaining_str_len <= 2) {
+ return changed;
+ }
+
+ changed = true;
+
+ /* Add '(', shift the following characters to the right to make space. */
+ memmove(remaining_str + 1, remaining_str, remaining_str_len - 2);
+ *remaining_str = '(';
+
+ /* Add the ')' before the next operation or at the end. */
+ remaining_str = find_next_op(str, remaining_str + 1, remaining_str_len);
+ remaining_str_len = len_max - (int)(remaining_str - str);
+ memmove(remaining_str + 1, remaining_str, remaining_str_len - 2);
+ *remaining_str = ')';
+
+ /* Only move forward by 1 even though we added two characters. Minus signs need to be able to
+ * apply to the next block of values too. */
+ remaining_str += 1;
+ }
+
+ return changed;
+}
+
static int unit_scale_str(char *str,
int len_max,
char *str_tmp,
@@ -896,6 +1003,10 @@ bool bUnit_ReplaceString(
char str_tmp[TEMP_STR_SIZE];
bool changed = false;
+ /* Fix cases like "-1m50cm" which would evaluate to -0.5m without this. */
+ changed |= unit_distribute_negatives(str, len_max);
+ printf("%s\n", str);
+
/* Try to find a default unit from current or previous string. */
default_unit = unit_detect_from_str(usys, str, str_prev);
diff --git a/source/blender/blenloader/BLO_undofile.h b/source/blender/blenloader/BLO_undofile.h
index f280b8f3b9c..175aa4ab9d0 100644
--- a/source/blender/blenloader/BLO_undofile.h
+++ b/source/blender/blenloader/BLO_undofile.h
@@ -26,6 +26,7 @@
*/
struct Scene;
+struct GHash;
typedef struct {
void *next, *prev;
@@ -38,6 +39,9 @@ typedef struct {
* detect unchanged IDs).
* Defined when writing the next step (i.e. last undo step has those always false). */
bool is_identical_future;
+ /** Session uuid of the ID being curently written (MAIN_ID_SESSION_UUID_UNSET when not writing
+ * ID-related data). Used to find matching chunks in previous memundo step. */
+ uint id_session_uuid;
} MemFileChunk;
typedef struct MemFile {
@@ -45,6 +49,17 @@ typedef struct MemFile {
size_t size;
} MemFile;
+typedef struct MemFileWriteData {
+ MemFile *written_memfile;
+ MemFile *reference_memfile;
+
+ uint current_id_session_uuid;
+ MemFileChunk *reference_current_chunk;
+
+ /** Maps an ID session uuid to its first reference MemFileChunk, if existing. */
+ struct GHash *id_session_uuid_mapping;
+} MemFileWriteData;
+
typedef struct MemFileUndoData {
char filename[1024]; /* FILE_MAX */
MemFile memfile;
@@ -52,10 +67,13 @@ typedef struct MemFileUndoData {
} MemFileUndoData;
/* actually only used writefile.c */
-extern void memfile_chunk_add(MemFile *memfile,
- const char *buf,
- unsigned int size,
- MemFileChunk **compchunk_step);
+
+void BLO_memfile_write_init(MemFileWriteData *mem_data,
+ MemFile *written_memfile,
+ MemFile *reference_memfile);
+void BLO_memfile_write_finalize(MemFileWriteData *mem_data);
+
+void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, unsigned int size);
/* exports */
extern void BLO_memfile_free(MemFile *memfile);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index db63091ce36..c9027eae296 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6984,7 +6984,6 @@ static void direct_link_scene(FileData *fd, Scene *sce)
direct_link_paint(fd, sce, &sce->toolsettings->imapaint.paint);
- sce->toolsettings->imapaint.paintcursor = NULL;
sce->toolsettings->particle.paintcursor = NULL;
sce->toolsettings->particle.scene = NULL;
sce->toolsettings->particle.object = NULL;
diff --git a/source/blender/blenloader/intern/undofile.c b/source/blender/blenloader/intern/undofile.c
index c7057883f88..28b37c4a737 100644
--- a/source/blender/blenloader/intern/undofile.c
+++ b/source/blender/blenloader/intern/undofile.c
@@ -41,10 +41,12 @@
#include "DNA_listBase.h"
#include "BLI_blenlib.h"
+#include "BLI_ghash.h"
#include "BLO_readfile.h"
#include "BLO_undofile.h"
+#include "BKE_lib_id.h"
#include "BKE_main.h"
/* keep last */
@@ -100,8 +102,52 @@ void BLO_memfile_clear_future(MemFile *memfile)
}
}
-void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChunk **compchunk_step)
+void BLO_memfile_write_init(MemFileWriteData *mem_data,
+ MemFile *written_memfile,
+ MemFile *reference_memfile)
{
+ mem_data->written_memfile = written_memfile;
+ mem_data->reference_memfile = reference_memfile;
+ mem_data->reference_current_chunk = reference_memfile ? reference_memfile->chunks.first : NULL;
+
+ /* If we have a reference memfile, we generate a mapping between the session_uuid's of the IDs
+ * stored in that previous undo step, and its first matching memchunk.
+ * This will allow us to easily find the existing undo memory storage of IDs even when some
+ * re-ordering in current Main data-base broke the order matching with the memchunks from
+ * previous step. */
+ if (reference_memfile != NULL) {
+ mem_data->id_session_uuid_mapping = BLI_ghash_new(
+ BLI_ghashutil_inthash_p_simple, BLI_ghashutil_intcmp, __func__);
+ uint current_session_uuid = MAIN_ID_SESSION_UUID_UNSET;
+ LISTBASE_FOREACH (MemFileChunk *, mem_chunk, &reference_memfile->chunks) {
+ if (!ELEM(mem_chunk->id_session_uuid, MAIN_ID_SESSION_UUID_UNSET, current_session_uuid)) {
+ current_session_uuid = mem_chunk->id_session_uuid;
+ void **entry;
+ if (!BLI_ghash_ensure_p(mem_data->id_session_uuid_mapping,
+ POINTER_FROM_UINT(current_session_uuid),
+ &entry)) {
+ *entry = mem_chunk;
+ }
+ else {
+ BLI_assert(0);
+ }
+ }
+ }
+ }
+}
+
+void BLO_memfile_write_finalize(MemFileWriteData *mem_data)
+{
+ if (mem_data->id_session_uuid_mapping != NULL) {
+ BLI_ghash_free(mem_data->id_session_uuid_mapping, NULL, NULL);
+ }
+}
+
+void BLO_memfile_chunk_add(MemFileWriteData *mem_data, const char *buf, uint size)
+{
+ MemFile *memfile = mem_data->written_memfile;
+ MemFileChunk **compchunk_step = &mem_data->reference_current_chunk;
+
MemFileChunk *curchunk = MEM_mallocN(sizeof(MemFileChunk), "MemFileChunk");
curchunk->size = size;
curchunk->buf = NULL;
@@ -110,6 +156,7 @@ void memfile_chunk_add(MemFile *memfile, const char *buf, uint size, MemFileChun
* perform an undo push may make changes after the last undo push that
* will then not be undo. Though it's not entirely clear that is wrong behavior. */
curchunk->is_identical_future = true;
+ curchunk->id_session_uuid = mem_data->current_id_session_uuid;
BLI_addtail(&memfile->chunks, curchunk);
/* we compare compchunk with buf */
diff --git a/source/blender/blenloader/intern/versioning_290.c b/source/blender/blenloader/intern/versioning_290.c
index 6574c983b09..1aa569d8336 100644
--- a/source/blender/blenloader/intern/versioning_290.c
+++ b/source/blender/blenloader/intern/versioning_290.c
@@ -249,7 +249,7 @@ void blo_do_versions_290(FileData *fd, Library *UNUSED(lib), Main *bmain)
LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
LISTBASE_FOREACH (ModifierData *, md, &ob->modifiers) {
if (md->type == eModifierType_WeightVGEdit) {
- md->flag &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE;
+ ((WeightVGEditModifierData *)md)->edit_flags &= ~MOD_WVG_EDIT_WEIGHTS_NORMALIZE;
}
}
}
diff --git a/source/blender/blenloader/intern/versioning_defaults.c b/source/blender/blenloader/intern/versioning_defaults.c
index 57c9ca16693..91d89254c90 100644
--- a/source/blender/blenloader/intern/versioning_defaults.c
+++ b/source/blender/blenloader/intern/versioning_defaults.c
@@ -465,6 +465,9 @@ void BLO_update_defaults_startup_blend(Main *bmain, const char *app_template)
/* Reset all grease pencil brushes. */
Scene *scene = bmain->scenes.first;
BKE_brush_gpencil_paint_presets(bmain, scene->toolsettings, true);
+ BKE_brush_gpencil_sculpt_presets(bmain, scene->toolsettings, true);
+ BKE_brush_gpencil_vertex_presets(bmain, scene->toolsettings, true);
+ BKE_brush_gpencil_weight_presets(bmain, scene->toolsettings, true);
/* Ensure new Paint modes. */
BKE_paint_ensure_from_paintmode(scene, PAINT_MODE_VERTEX_GPENCIL);
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index c7d9fbf7268..bc36497dd9f 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -164,6 +164,7 @@
#include "BKE_gpencil_modifier.h"
#include "BKE_idtype.h"
#include "BKE_layer.h"
+#include "BKE_lib_id.h"
#include "BKE_lib_override.h"
#include "BKE_main.h"
#include "BKE_modifier.h"
@@ -328,12 +329,7 @@ typedef struct {
bool error;
/** #MemFile writing (used for undo). */
- struct {
- MemFile *current;
- MemFile *compare;
- /** Use to de-duplicate chunks when writing. */
- MemFileChunk *compare_chunk;
- } mem;
+ MemFileWriteData mem;
/** When true, write to #WriteData.current, could also call 'is_undo'. */
bool use_memfile;
@@ -372,7 +368,7 @@ static void writedata_do_write(WriteData *wd, const void *mem, int memlen)
/* memory based save */
if (wd->use_memfile) {
- memfile_chunk_add(wd->mem.current, mem, memlen, &wd->mem.compare_chunk);
+ BLO_memfile_chunk_add(&wd->mem, mem, memlen);
}
else {
if (wd->ww->write(wd->ww, mem, memlen) != memlen) {
@@ -473,9 +469,7 @@ static WriteData *mywrite_begin(WriteWrap *ww, MemFile *compare, MemFile *curren
WriteData *wd = writedata_new(ww);
if (current != NULL) {
- wd->mem.current = current;
- wd->mem.compare = compare;
- wd->mem.compare_chunk = compare ? compare->chunks.first : NULL;
+ BLO_memfile_write_init(&wd->mem, current, compare);
wd->use_memfile = true;
}
@@ -495,12 +489,58 @@ static bool mywrite_end(WriteData *wd)
wd->buf_used_len = 0;
}
+ if (wd->use_memfile) {
+ BLO_memfile_write_finalize(&wd->mem);
+ }
+
const bool err = wd->error;
writedata_free(wd);
return err;
}
+/**
+ * Start writing of data related to a single ID.
+ *
+ * Only does something when storing an undo step.
+ */
+static void mywrite_id_begin(WriteData *wd, ID *id)
+{
+ if (wd->use_memfile) {
+ wd->mem.current_id_session_uuid = id->session_uuid;
+
+ /* If current next memchunk does not match the ID we are about to write, try to find the
+ * correct memchunk in the mapping using ID's session_uuid. */
+ if (wd->mem.id_session_uuid_mapping != NULL &&
+ (wd->mem.reference_current_chunk == NULL ||
+ wd->mem.reference_current_chunk->id_session_uuid != id->session_uuid)) {
+ void *ref = BLI_ghash_lookup(wd->mem.id_session_uuid_mapping,
+ POINTER_FROM_UINT(id->session_uuid));
+ if (ref != NULL) {
+ wd->mem.reference_current_chunk = ref;
+ }
+ /* Else, no existing memchunk found, i.e. this is supposed to be a new ID. */
+ }
+ /* Otherwise, we try with the current memchunk in any case, whether it is matching current
+ * ID's session_uuid or not. */
+ }
+}
+
+/**
+ * Start writing of data related to a single ID.
+ *
+ * Only does something when storing an undo step.
+ */
+static void mywrite_id_end(WriteData *wd, ID *UNUSED(id))
+{
+ if (wd->use_memfile) {
+ /* Very important to do it after every ID write now, otherwise we cannot know whether a
+ * specific ID changed or not. */
+ mywrite_flush(wd);
+ wd->mem.current_id_session_uuid = MAIN_ID_SESSION_UUID_UNSET;
+ }
+}
+
/** \} */
/* -------------------------------------------------------------------- */
@@ -4149,6 +4189,8 @@ static bool write_file_handle(Main *mainvar,
}
}
+ mywrite_id_begin(wd, id);
+
memcpy(id_buffer, id, idtype_struct_size);
((ID *)id_buffer)->tag = 0;
@@ -4290,11 +4332,7 @@ static bool write_file_handle(Main *mainvar,
BKE_lib_override_library_operations_store_end(override_storage, id);
}
- if (wd->use_memfile) {
- /* Very important to do it after every ID write now, otherwise we cannot know whether a
- * specific ID changed or not. */
- mywrite_flush(wd);
- }
+ mywrite_id_end(wd, id);
}
if (id_buffer != id_buffer_static) {
diff --git a/source/blender/bmesh/intern/bmesh_marking.c b/source/blender/bmesh/intern/bmesh_marking.c
index 1bf419f4461..177599656b6 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -1021,7 +1021,7 @@ void BM_select_history_validate(BMesh *bm)
bool BM_select_history_active_get(BMesh *bm, BMEditSelection *ese)
{
BMEditSelection *ese_last = bm->selected.last;
- BMFace *efa = BM_mesh_active_face_get(bm, false, false);
+ BMFace *efa = BM_mesh_active_face_get(bm, false, true);
ese->next = ese->prev = NULL;
diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
index c98aab51654..f5a131a1731 100644
--- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
+++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc
@@ -1500,7 +1500,10 @@ void DepsgraphRelationBuilder::build_driver_data(ID *id, FCurve *fcu)
}
}
if (property_entry_key.prop != nullptr && RNA_property_is_idprop(property_entry_key.prop)) {
- RNAPathKey property_exit_key(id, rna_path, RNAPointerSource::EXIT);
+ RNAPathKey property_exit_key(property_entry_key.id,
+ property_entry_key.ptr,
+ property_entry_key.prop,
+ RNAPointerSource::EXIT);
OperationKey parameters_key(id, NodeType::PARAMETERS, OperationCode::PARAMETERS_EVAL);
add_relation(property_exit_key, parameters_key, "Driven Property -> Properties");
}
@@ -2889,6 +2892,9 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node)
DriverGroupMap driver_groups;
LISTBASE_FOREACH (FCurve *, fcu, &adt->drivers) {
+ if (fcu->rna_path == nullptr) {
+ continue;
+ }
// Get the RNA path except the part after the last dot.
char *last_dot = strrchr(fcu->rna_path, '.');
string rna_prefix;
@@ -2939,7 +2945,7 @@ void DepsgraphRelationBuilder::build_driver_relations(IDNode *id_node)
}
}
}
-}
+} // namespace DEG
/* **** ID traversal callbacks functions **** */
diff --git a/source/blender/draw/CMakeLists.txt b/source/blender/draw/CMakeLists.txt
index d9f7a3acae0..aeecb452217 100644
--- a/source/blender/draw/CMakeLists.txt
+++ b/source/blender/draw/CMakeLists.txt
@@ -34,6 +34,7 @@ set(INC
../imbuf
../makesdna
../makesrna
+ ../nodes
../render/extern/include
../render/intern/include
../windowmanager
@@ -317,8 +318,8 @@ data_to_c_simple(engines/select/shaders/selection_id_3D_vert.glsl SRC)
data_to_c_simple(engines/select/shaders/selection_id_frag.glsl SRC)
data_to_c_simple(engines/basic/shaders/conservative_depth_geom.glsl SRC)
-data_to_c_simple(engines/basic/shaders/conservative_depth_vert.glsl SRC)
-data_to_c_simple(engines/basic/shaders/conservative_depth_frag.glsl SRC)
+data_to_c_simple(engines/basic/shaders/depth_vert.glsl SRC)
+data_to_c_simple(engines/basic/shaders/depth_frag.glsl SRC)
if(WITH_LANPR)
data_to_c_simple(engines/lanpr/shaders/lanpr_dpix_preview_geom.glsl SRC)
diff --git a/source/blender/draw/engines/basic/basic_engine.c b/source/blender/draw/engines/basic/basic_engine.c
index 6658fea7825..bbc3c407f14 100644
--- a/source/blender/draw/engines/basic/basic_engine.c
+++ b/source/blender/draw/engines/basic/basic_engine.c
@@ -37,8 +37,8 @@
#define BASIC_ENGINE "BLENDER_BASIC"
-extern char datatoc_conservative_depth_frag_glsl[];
-extern char datatoc_conservative_depth_vert_glsl[];
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
extern char datatoc_conservative_depth_geom_glsl[];
extern char datatoc_common_view_lib_glsl[];
@@ -91,22 +91,28 @@ static void basic_engine_init(void *UNUSED(vedata))
/* Depth prepass */
if (!sh_data->depth) {
- sh_data->depth = DRW_shader_create_3d_depth_only(draw_ctx->sh_cfg);
-
const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[draw_ctx->sh_cfg];
+
+ sh_data->depth = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
+
sh_data->depth_conservative = GPU_shader_create_from_arrays({
.vert = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_vert_glsl,
+ datatoc_depth_vert_glsl,
NULL},
.geom = (const char *[]){sh_cfg->lib,
datatoc_common_view_lib_glsl,
datatoc_conservative_depth_geom_glsl,
NULL},
- .frag = (const char *[]){datatoc_common_view_lib_glsl,
- datatoc_conservative_depth_frag_glsl,
- NULL},
- .defs = (const char *[]){sh_cfg->def, NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, "#define CONSERVATIVE_RASTER\n", NULL},
});
}
}
@@ -233,6 +239,7 @@ static void basic_engine_free(void)
{
for (int i = 0; i < GPU_SHADER_CFG_LEN; i++) {
BASIC_Shaders *sh_data = &e_data.sh_data[i];
+ DRW_SHADER_FREE_SAFE(sh_data->depth);
DRW_SHADER_FREE_SAFE(sh_data->depth_conservative);
}
}
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl b/source/blender/draw/engines/basic/shaders/depth_frag.glsl
index ff4a015c335..ff4a015c335 100644
--- a/source/blender/draw/engines/basic/shaders/conservative_depth_frag.glsl
+++ b/source/blender/draw/engines/basic/shaders/depth_frag.glsl
diff --git a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl b/source/blender/draw/engines/basic/shaders/depth_vert.glsl
index c55a3211ff2..318d0acef6f 100644
--- a/source/blender/draw/engines/basic/shaders/conservative_depth_vert.glsl
+++ b/source/blender/draw/engines/basic/shaders/depth_vert.glsl
@@ -1,12 +1,16 @@
+#ifdef CONSERVATIVE_RASTER
RESOURCE_ID_VARYING
+#endif
in vec3 pos;
void main()
{
GPU_INTEL_VERTEX_SHADER_WORKAROUND
+#ifdef CONSERVATIVE_RASTER
PASS_RESOURCE_ID
+#endif
vec3 world_pos = point_object_to_world(pos);
gl_Position = point_world_to_ndc(world_pos);
diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index 6874947de55..a19af77124f 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -24,6 +24,8 @@
#include "DRW_render.h"
+#include "BLI_memblock.h"
+
#include "eevee_lightcache.h"
#include "eevee_private.h"
@@ -54,8 +56,17 @@ void EEVEE_view_layer_data_free(void *storage)
DRW_UBO_FREE_SAFE(sldata->grid_ubo);
DRW_UBO_FREE_SAFE(sldata->planar_ubo);
DRW_UBO_FREE_SAFE(sldata->common_ubo);
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- DRW_UBO_FREE_SAFE(sldata->renderpass_ubo[i]);
+
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.combined);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.diff_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_color);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.spec_light);
+ DRW_UBO_FREE_SAFE(sldata->renderpass_ubo.emit);
+
+ if (sldata->material_cache) {
+ BLI_memblock_destroy(sldata->material_cache, NULL);
+ sldata->material_cache = NULL;
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_depth_of_field.c b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
index ec6770e4549..4a3cc36ddef 100644
--- a/source/blender/draw/engines/eevee/eevee_depth_of_field.c
+++ b/source/blender/draw/engines/eevee/eevee_depth_of_field.c
@@ -31,6 +31,8 @@
#include "BKE_camera.h"
+#include "BLI_string_utils.h"
+
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_query.h"
@@ -48,24 +50,28 @@ static struct {
extern char datatoc_effect_dof_vert_glsl[];
extern char datatoc_effect_dof_frag_glsl[];
+extern char datatoc_common_view_lib_glsl[];
+
static void eevee_create_shader_depth_of_field(const bool use_alpha)
{
+ char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl, datatoc_effect_dof_frag_glsl);
e_data.dof_downsample_sh[use_alpha] = DRW_shader_create_fullscreen(
- datatoc_effect_dof_frag_glsl,
+ frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_DOWNSAMPLE\n" :
"#define STEP_DOWNSAMPLE\n");
e_data.dof_scatter_sh[use_alpha] = DRW_shader_create(datatoc_effect_dof_vert_glsl,
NULL,
- datatoc_effect_dof_frag_glsl,
+ frag,
use_alpha ? "#define USE_ALPHA_DOF\n"
"#define STEP_SCATTER\n" :
"#define STEP_SCATTER\n");
- e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(datatoc_effect_dof_frag_glsl,
+ e_data.dof_resolve_sh[use_alpha] = DRW_shader_create_fullscreen(frag,
use_alpha ?
"#define USE_ALPHA_DOF\n"
"#define STEP_RESOLVE\n" :
"#define STEP_RESOLVE\n");
+ MEM_freeN(frag);
}
int EEVEE_depth_of_field_init(EEVEE_ViewLayerData *UNUSED(sldata),
diff --git a/source/blender/draw/engines/eevee/eevee_effects.c b/source/blender/draw/engines/eevee/eevee_effects.c
index 05b18da4374..ab846fe0f11 100644
--- a/source/blender/draw/engines/eevee/eevee_effects.c
+++ b/source/blender/draw/engines/eevee/eevee_effects.c
@@ -333,8 +333,7 @@ void EEVEE_effects_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
grp = DRW_shgroup_create(EEVEE_shaders_velocity_resolve_sh_get(), psl->velocity_resolve);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_mat4(grp, "currPersinv", effects->velocity_curr_persinv);
DRW_shgroup_uniform_mat4(grp, "pastPersmat", effects->velocity_past_persmat);
DRW_shgroup_call(grp, quad, NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_engine.c b/source/blender/draw/engines/eevee/eevee_engine.c
index a1112eb92df..b698574f9d7 100644
--- a/source/blender/draw/engines/eevee/eevee_engine.c
+++ b/source/blender/draw/engines/eevee/eevee_engine.c
@@ -88,7 +88,7 @@ static void eevee_engine_init(void *ved)
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, camera, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
}
@@ -230,7 +230,7 @@ static void eevee_draw_scene(void *vedata)
BLI_halton_3d(primes, offset, samp, r);
EEVEE_update_noise(psl, fbl, r);
EEVEE_volumes_set_jitter(sldata, samp - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
}
/* Copy previous persmat to UBO data */
copy_m4_m4(sldata->common_data.prev_persmat, stl->effects->prev_persmat);
@@ -274,8 +274,7 @@ static void eevee_draw_scene(void *vedata)
/* Depth prepass */
DRW_stats_group_start("Prepass");
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_stats_group_end();
/* Create minmax texture */
@@ -289,9 +288,9 @@ static void eevee_draw_scene(void *vedata)
/* Shading pass */
DRW_stats_group_start("Shading");
if (DRW_state_draw_background()) {
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
}
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
DRW_stats_group_end();
@@ -306,9 +305,8 @@ static void eevee_draw_scene(void *vedata)
/* Opaque refraction */
DRW_stats_group_start("Opaque Refraction");
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
DRW_stats_group_end();
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c
index 614c749b9aa..4cdd166f09c 100644
--- a/source/blender/draw/engines/eevee/eevee_lightcache.c
+++ b/source/blender/draw/engines/eevee/eevee_lightcache.c
@@ -379,9 +379,7 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
0,
false,
NULL);
- GPU_texture_bind(lcache->grid_tx.tex, 0);
GPU_texture_filter_mode(lcache->grid_tx.tex, true);
- GPU_texture_unbind(lcache->grid_tx.tex);
}
if (lcache->cube_tx.tex == NULL) {
@@ -406,13 +404,11 @@ static bool eevee_lightcache_static_load(LightCache *lcache)
NULL);
}
- GPU_texture_bind(lcache->cube_tx.tex, 0);
- GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
for (int mip = 0; mip < lcache->mips_len; mip++) {
GPU_texture_add_mipmap(
lcache->cube_tx.tex, GPU_DATA_10_11_11_REV, mip + 1, lcache->cube_mips[mip].data);
}
- GPU_texture_unbind(lcache->cube_tx.tex);
+ GPU_texture_mipmap_mode(lcache->cube_tx.tex, true, true);
}
return true;
}
@@ -822,7 +818,7 @@ static void eevee_lightbake_cache_create(EEVEE_Data *vedata, EEVEE_LightBake *lb
DRW_render_viewport_size_set(viewport_size);
EEVEE_effects_init(sldata, vedata, NULL, true);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_lightprobes.c b/source/blender/draw/engines/eevee/eevee_lightprobes.c
index 3350c512b17..83b2a9bb6d4 100644
--- a/source/blender/draw/engines/eevee/eevee_lightprobes.c
+++ b/source/blender/draw/engines/eevee/eevee_lightprobes.c
@@ -248,8 +248,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
// DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call_instances(grp, NULL, geom, 6);
@@ -271,8 +270,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_float(grp, "intensityFac", &pinfo->intensity_fac, 1);
DRW_shgroup_uniform_texture(grp, "probeHdr", rt_color);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -293,8 +291,7 @@ void EEVEE_lightbake_cache_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
DRW_shgroup_uniform_texture(grp, "probeDepth", rt_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRW_shgroup_call(grp, geom, NULL);
@@ -337,51 +334,29 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
/* LookDev */
EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->probe_background, wo, pinfo);
- /* END */
+
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float queue_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_lightprobe_get(scene, wo);
-
- eGPUMaterialStatus status = GPU_material_status(gpumat);
-
- switch (status) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
- DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- stl->g_data->queued_shaders_count++;
- col = queue_col;
- break;
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_PROBE);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->probe_background);
+ DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
grp = DRW_shgroup_create(EEVEE_shaders_probe_default_sh_get(), psl->probe_background);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float_copy(grp, "backgroundAlpha", 1.0f);
DRW_shgroup_call(grp, geom, NULL);
}
@@ -408,8 +383,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
/* TODO (fclem) get rid of those UBO. */
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, cube_len * 2);
}
@@ -436,8 +410,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(shgrp, "renderpass_block", sldata->renderpass_ubo.combined);
int tri_count = egrid->resolution[0] * egrid->resolution[1] * egrid->resolution[2] * 2;
DRW_shgroup_call_procedural_triangles(shgrp, NULL, tri_count);
}
@@ -455,8 +428,7 @@ void EEVEE_lightprobes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
DRWShadingGroup *grp = DRW_shgroup_create(EEVEE_shaders_probe_planar_display_sh_get(),
psl->probe_display);
DRW_shgroup_uniform_texture_ref(grp, "probePlanars", &txl->planar_pool);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
stl->g_data->planar_display_shgrp = DRW_shgroup_call_buffer_instance(
grp, e_data.format_probe_display_planar, DRW_cache_quad_get());
@@ -923,12 +895,10 @@ static void lightbake_render_scene_face(int face, EEVEE_BakeRenderData *user_dat
GPU_framebuffer_bind(face_fb[face]);
GPU_framebuffer_clear_depth(face_fb[face], 1.0f);
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
DRW_draw_pass(psl->probe_background);
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
DRW_draw_pass(psl->transparent_pass);
}
@@ -987,10 +957,8 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
/* Slight modification: we handle refraction as normal
* shading and don't do SSRefraction. */
- DRW_draw_pass(psl->depth_pass_clip);
- DRW_draw_pass(psl->depth_pass_clip_cull);
- DRW_draw_pass(psl->refract_depth_pass_clip);
- DRW_draw_pass(psl->refract_depth_pass_clip_cull);
+ DRW_draw_pass(psl->depth_ps);
+ DRW_draw_pass(psl->depth_refract_ps);
DRW_draw_pass(psl->probe_background);
EEVEE_create_minmax_buffer(vedata, tmp_planar_depth, layer);
@@ -999,10 +967,9 @@ static void lightbake_render_scene_reflected(int layer, EEVEE_BakeRenderData *us
GPU_framebuffer_bind(fbl->planarref_fb);
/* Shading pass */
- EEVEE_materials_draw_opaque(sldata, psl);
- DRW_draw_pass(psl->sss_pass); /* Only output standard pass */
- DRW_draw_pass(psl->sss_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->material_ps);
+ DRW_draw_pass(psl->material_sss_ps); /* Only output standard pass */
+ DRW_draw_pass(psl->material_refract_ps);
/* Transparent */
if (DRW_state_is_image_render()) {
diff --git a/source/blender/draw/engines/eevee/eevee_lookdev.c b/source/blender/draw/engines/eevee/eevee_lookdev.c
index b33be750d80..18365d69514 100644
--- a/source/blender/draw/engines/eevee/eevee_lookdev.c
+++ b/source/blender/draw/engines/eevee/eevee_lookdev.c
@@ -34,6 +34,8 @@
#include "ED_screen.h"
+#include "GPU_material.h"
+
#include "UI_resources.h"
#include "eevee_lightcache.h"
@@ -56,6 +58,43 @@ static void eevee_lookdev_lightcache_delete(EEVEE_Data *vedata)
g_data->studiolight_rot_z = 0.0f;
}
+static void eevee_lookdev_hdri_preview_init(EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata)
+{
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
+ DRWShadingGroup *grp;
+
+ struct GPUBatch *sphere = DRW_cache_sphere_get();
+ int mat_options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
+ DRW_STATE_CULL_BACK;
+
+ {
+ Material *ma = EEVEE_material_default_diffuse_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_diffuse_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+ {
+ Material *ma = EEVEE_material_default_glossy_get();
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
+ grp = DRW_shgroup_create(sh, psl->lookdev_glossy_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
+ DRW_shgroup_add_material_resources(grp, gpumat);
+ DRW_shgroup_call(grp, sphere, NULL);
+ }
+}
+
void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
DRWShadingGroup **r_grp,
@@ -106,6 +145,8 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
effects->anchor[1] = rect->ymin;
EEVEE_temporal_sampling_reset(vedata);
}
+
+ eevee_lookdev_hdri_preview_init(vedata, sldata);
}
if (LOOK_DEV_STUDIO_LIGHT_ENABLED(v3d)) {
@@ -176,8 +217,7 @@ void EEVEE_lookdev_cache_init(EEVEE_Data *vedata,
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
diff --git a/source/blender/draw/engines/eevee/eevee_lut_gen.c b/source/blender/draw/engines/eevee/eevee_lut_gen.c
new file mode 100644
index 00000000000..5f20d6fbfb8
--- /dev/null
+++ b/source/blender/draw/engines/eevee/eevee_lut_gen.c
@@ -0,0 +1,198 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Copyright 2020, Blender Foundation.
+ */
+
+/** \file
+ * \ingroup draw_engine
+ *
+ * EEVEE LUT generation:
+ *
+ * Routine to generate the LUT used by eevee stored in eevee_lut.h
+ * Theses functions are not to be used in the final executable.
+ */
+
+#include "DRW_render.h"
+
+#include "BLI_alloca.h"
+#include "BLI_rand.h"
+#include "BLI_string_utils.h"
+
+extern char datatoc_bsdf_lut_frag_glsl[];
+extern char datatoc_btdf_lut_frag_glsl[];
+extern char datatoc_bsdf_common_lib_glsl[];
+extern char datatoc_bsdf_sampling_lib_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+
+static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
+{
+ struct GPUTexture *tex;
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
+ datatoc_lightprobe_geom_glsl,
+ datatoc_bsdf_lut_frag_glsl,
+ lib_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n");
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
+ DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+ DRW_draw_pass(pass);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
+ glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
+
+ printf("{");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, ", data[i], data[i + 1]);
+ i += 3;
+ printf("%ff, %ff, \n", data[i], data[i + 1]);
+ }
+ printf("}");
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+}
+
+static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
+{
+ struct GPUTexture *tex;
+ struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
+ struct GPUFrameBuffer *fb = NULL;
+ static float samples_len = 8192.0f;
+ static float a2 = 0.0f;
+ static float inv_samples_len = 1.0f / 8192.0f;
+
+ char *frag_str = BLI_string_joinN(
+ datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
+
+ struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
+ "#define HAMMERSLEY_SIZE 8192\n"
+ "#define BRDF_LUT_SIZE 64\n"
+ "#define NOISE_SIZE 64\n"
+ "#define LUT_SIZE 64\n");
+
+ MEM_freeN(frag_str);
+
+ DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
+ DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
+ DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
+ DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
+ DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
+ DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
+
+ struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
+ DRW_shgroup_call(grp, geom, NULL);
+
+ float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
+
+ tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
+
+ DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
+ GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
+
+ GPU_framebuffer_bind(fb);
+
+ float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
+
+ float inc = 1.0f / 31.0f;
+ float roughness = 1e-8f - inc;
+ FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
+ fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
+ do {
+ roughness += inc;
+ CLAMP(roughness, 1e-4f, 1.0f);
+ a2 = powf(roughness, 4.0f);
+ DRW_draw_pass(pass);
+
+ GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
+
+#if 1
+ fprintf(f, "\t{\n\t\t");
+ for (int i = 0; i < w * h * 3; i += 3) {
+ fprintf(f, "%ff,", data[i]);
+ if (((i / 3) + 1) % 12 == 0) {
+ fprintf(f, "\n\t\t");
+ }
+ else {
+ fprintf(f, " ");
+ }
+ }
+ fprintf(f, "\n\t},\n");
+#else
+ for (int i = 0; i < w * h * 3; i += 3) {
+ if (data[i] < 0.01) {
+ printf(" ");
+ }
+ else if (data[i] < 0.3) {
+ printf(".");
+ }
+ else if (data[i] < 0.6) {
+ printf("+");
+ }
+ else if (data[i] < 0.9) {
+ printf("%%");
+ }
+ else {
+ printf("#");
+ }
+ if ((i / 3 + 1) % 64 == 0) {
+ printf("\n");
+ }
+ }
+#endif
+
+ } while (roughness < 1.0f);
+ fprintf(f, "\n};\n");
+
+ fclose(f);
+
+ MEM_freeN(texels);
+ MEM_freeN(data);
+
+ return tex;
+} \ No newline at end of file
diff --git a/source/blender/draw/engines/eevee/eevee_materials.c b/source/blender/draw/engines/eevee/eevee_materials.c
index 03cdb02a48a..0f10fb0ef53 100644
--- a/source/blender/draw/engines/eevee/eevee_materials.c
+++ b/source/blender/draw/engines/eevee/eevee_materials.c
@@ -23,10 +23,10 @@
#include "DRW_render.h"
#include "BLI_alloca.h"
-#include "BLI_dynstr.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
#include "BLI_math_bits.h"
+#include "BLI_memblock.h"
#include "BLI_rand.h"
#include "BLI_string_utils.h"
@@ -48,29 +48,11 @@
/* *********** STATIC *********** */
static struct {
- char *frag_shader_lib;
- char *vert_shader_str;
- char *vert_shadow_shader_str;
- char *vert_background_shader_str;
- char *vert_volume_shader_str;
- char *geom_volume_shader_str;
- char *volume_shader_lib;
-
- struct GPUShader *default_prepass_sh;
- struct GPUShader *default_prepass_clip_sh;
- struct GPUShader *default_hair_prepass_sh;
- struct GPUShader *default_hair_prepass_clip_sh;
- struct GPUShader *default_lit[VAR_MAT_MAX];
- struct GPUShader *default_background;
- struct GPUShader *update_noise_sh;
-
/* 64*64 array texture containing all LUTs and other utilitarian arrays.
* Packing enables us to same precious textures slots. */
struct GPUTexture *util_tex;
struct GPUTexture *noise_tex;
- uint sss_count;
-
float noise_offsets[3];
} e_data = {NULL}; /* Engine data */
@@ -82,8 +64,6 @@ extern char datatoc_prepass_vert_glsl[];
extern char datatoc_default_frag_glsl[];
extern char datatoc_default_world_frag_glsl[];
extern char datatoc_ltc_lib_glsl[];
-extern char datatoc_bsdf_lut_frag_glsl[];
-extern char datatoc_btdf_lut_frag_glsl[];
extern char datatoc_bsdf_common_lib_glsl[];
extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
@@ -107,320 +87,45 @@ extern char datatoc_volumetric_frag_glsl[];
extern char datatoc_volumetric_lib_glsl[];
extern char datatoc_gpu_shader_uniform_color_frag_glsl[];
-#define DEFAULT_RENDER_PASS_FLAG 0xefffffff
-
-/* Iterator for render passes. This iteration will only do the material based render passes. it
- * will ignore `EEVEE_RENDER_PASS_ENVIRONMENT`.
- *
- * parameters:
- * - `render_passes_` is a bitflag for render_passes that needs to be iterated over.
- * - `render_pass_index_` is a parameter name where the index of the render_pass will be available
- * during iteration. This index can be used to select the right pass in the `psl`.
- * - `render_pass_` is the bitflag of the render_pass of the current iteration.
- *
- * The `render_pass_index_` parameter needs to be the same for the `RENDER_PASS_ITER_BEGIN` and
- * `RENDER_PASS_ITER_END`.
- */
-#define RENDER_PASS_ITER_BEGIN(render_passes_, render_pass_index_, render_pass_) \
- const eViewLayerEEVEEPassType __filtered_##render_pass_index_ = render_passes_ & \
- EEVEE_RENDERPASSES_MATERIAL & \
- ~EEVEE_RENDER_PASS_ENVIRONMENT; \
- if (__filtered_##render_pass_index_ != 0) { \
- int render_pass_index_ = 1; \
- for (int bit_##render_pass_ = 0; bit_##render_pass_ < EEVEE_RENDER_PASS_MAX_BIT; \
- bit_##render_pass_++) { \
- eViewLayerEEVEEPassType render_pass_ = (1 << bit_##render_pass_); \
- if ((__filtered_##render_pass_index_ & render_pass_) != 0) {
-#define RENDER_PASS_ITER_END(render_pass_index_) \
- render_pass_index_ += 1; \
- } \
- } \
- } \
- ((void)0)
+typedef struct EeveeMaterialCache {
+ struct DRWShadingGroup *depth_grp;
+ struct DRWShadingGroup *shading_grp;
+ struct DRWShadingGroup *shadow_grp;
+ struct GPUMaterial *shading_gpumat;
+ /* Meh, Used by hair to ensure draw order when calling DRW_shgroup_create_sub.
+ * Pointers to ghash values. */
+ struct DRWShadingGroup **depth_grp_p;
+ struct DRWShadingGroup **shading_grp_p;
+ struct DRWShadingGroup **shadow_grp_p;
+} EeveeMaterialCache;
/* *********** FUNCTIONS *********** */
-#if 0 /* Used only to generate the LUT values */
-static struct GPUTexture *create_ggx_lut_texture(int UNUSED(w), int UNUSED(h))
-{
- struct GPUTexture *tex;
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *lib_str = BLI_string_joinN(datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl);
-
- struct GPUShader *sh = DRW_shader_create_with_lib(datatoc_lightprobe_vert_glsl,
- datatoc_lightprobe_geom_glsl,
- datatoc_bsdf_lut_frag_glsl,
- lib_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n");
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", e_data.hammersley);
- DRW_shgroup_uniform_texture(grp, "texJitter", e_data.jitter);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_RG16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_RG16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
- DRW_draw_pass(pass);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
- glReadBuffer(GL_COLOR_ATTACHMENT0);
- glReadPixels(0, 0, w, h, GL_RGB, GL_FLOAT, data);
-
- printf("{");
- for (int i = 0; i < w * h * 3; i += 3) {
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, ", data[i], data[i + 1]);
- i += 3;
- printf("%ff, %ff, \n", data[i], data[i + 1]);
- }
- printf("}");
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-
-static struct GPUTexture *create_ggx_refraction_lut_texture(int w, int h)
-{
- struct GPUTexture *tex;
- struct GPUTexture *hammersley = create_hammersley_sample_texture(8192);
- struct GPUFrameBuffer *fb = NULL;
- static float samples_len = 8192.0f;
- static float a2 = 0.0f;
- static float inv_samples_len = 1.0f / 8192.0f;
-
- char *frag_str = BLI_string_joinN(
- datatoc_bsdf_common_lib_glsl, datatoc_bsdf_sampling_lib_glsl, datatoc_btdf_lut_frag_glsl);
-
- struct GPUShader *sh = DRW_shader_create_fullscreen(frag_str,
- "#define HAMMERSLEY_SIZE 8192\n"
- "#define BRDF_LUT_SIZE 64\n"
- "#define NOISE_SIZE 64\n"
- "#define LUT_SIZE 64\n");
-
- MEM_freeN(frag_str);
-
- DRWPass *pass = DRW_pass_create("LightProbe Filtering", DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_float(grp, "a2", &a2, 1);
- DRW_shgroup_uniform_float(grp, "sampleCount", &samples_len, 1);
- DRW_shgroup_uniform_float(grp, "invSampleCount", &inv_samples_len, 1);
- DRW_shgroup_uniform_texture(grp, "texHammersley", hammersley);
- DRW_shgroup_uniform_texture(grp, "utilTex", e_data.util_tex);
-
- struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
- DRW_shgroup_call(grp, geom, NULL);
-
- float *texels = MEM_mallocN(sizeof(float[2]) * w * h, "lut");
-
- tex = DRW_texture_create_2d(w, h, GPU_R16F, DRW_TEX_FILTER, (float *)texels);
-
- DRWFboTexture tex_filter = {&tex, GPU_R16F, DRW_TEX_FILTER};
- GPU_framebuffer_init(&fb, &draw_engine_eevee_type, w, h, &tex_filter, 1);
-
- GPU_framebuffer_bind(fb);
-
- float *data = MEM_mallocN(sizeof(float[3]) * w * h, "lut");
-
- float inc = 1.0f / 31.0f;
- float roughness = 1e-8f - inc;
- FILE *f = BLI_fopen("btdf_split_sum_ggx.h", "w");
- fprintf(f, "static float btdf_split_sum_ggx[32][64 * 64] = {\n");
- do {
- roughness += inc;
- CLAMP(roughness, 1e-4f, 1.0f);
- a2 = powf(roughness, 4.0f);
- DRW_draw_pass(pass);
-
- GPU_framebuffer_read_data(0, 0, w, h, 3, 0, data);
-
-# if 1
- fprintf(f, "\t{\n\t\t");
- for (int i = 0; i < w * h * 3; i += 3) {
- fprintf(f, "%ff,", data[i]);
- if (((i / 3) + 1) % 12 == 0) {
- fprintf(f, "\n\t\t");
- }
- else {
- fprintf(f, " ");
- }
- }
- fprintf(f, "\n\t},\n");
-# else
- for (int i = 0; i < w * h * 3; i += 3) {
- if (data[i] < 0.01) {
- printf(" ");
- }
- else if (data[i] < 0.3) {
- printf(".");
- }
- else if (data[i] < 0.6) {
- printf("+");
- }
- else if (data[i] < 0.9) {
- printf("%%");
- }
- else {
- printf("#");
- }
- if ((i / 3 + 1) % 64 == 0) {
- printf("\n");
- }
- }
-# endif
-
- } while (roughness < 1.0f);
- fprintf(f, "\n};\n");
-
- fclose(f);
-
- MEM_freeN(texels);
- MEM_freeN(data);
-
- return tex;
-}
-#endif
/* XXX TODO define all shared resources in a shared place without duplication */
struct GPUTexture *EEVEE_materials_get_util_tex(void)
{
return e_data.util_tex;
}
-static char *eevee_get_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
-
- if ((options & VAR_MAT_MESH) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
- if ((options & VAR_MAT_HAIR) != 0) {
- BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
- }
- if ((options & VAR_MAT_PROBE) != 0) {
- BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
- }
- if ((options & VAR_MAT_CLIP) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_CLIP\n");
- }
- if ((options & VAR_MAT_SHADOW) != 0) {
- BLI_dynstr_append(ds, "#define SHADOW_SHADER\n");
- }
- if ((options & VAR_MAT_HASH) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
- }
- if ((options & VAR_MAT_BLEND) != 0) {
- BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
- }
- if ((options & VAR_MAT_MULT) != 0) {
- BLI_dynstr_append(ds, "#define USE_MULTIPLY\n");
- }
- if ((options & VAR_MAT_REFRACT) != 0) {
- BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
- }
- if ((options & VAR_MAT_LOOKDEV) != 0) {
- BLI_dynstr_append(ds, "#define LOOKDEV\n");
- }
- if ((options & VAR_MAT_HOLDOUT) != 0) {
- BLI_dynstr_append(ds, "#define HOLDOUT\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-static char *eevee_get_volume_defines(int options)
-{
- char *str = NULL;
-
- DynStr *ds = BLI_dynstr_new();
- BLI_dynstr_append(ds, SHADER_DEFINES);
- BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
-
- if ((options & VAR_MAT_VOLUME) != 0) {
- BLI_dynstr_append(ds, "#define MESH_SHADER\n");
- }
-
- str = BLI_dynstr_get_cstring(ds);
- BLI_dynstr_free(ds);
-
- return str;
-}
-
-/* Get the default render pass ubo. This is a ubo that enables all bsdf render passes. */
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata)
-{
- return sldata->renderpass_ubo[0];
-}
-
-/* Get the render pass ubo for rendering the given render_pass. */
-static struct GPUUniformBuffer *get_render_pass_ubo(EEVEE_ViewLayerData *sldata,
- eViewLayerEEVEEPassType render_pass)
-{
- int index;
- switch (render_pass) {
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- index = 1;
- break;
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- index = 2;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- index = 3;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- index = 4;
- break;
- case EEVEE_RENDER_PASS_EMIT:
- index = 5;
- break;
- default:
- index = 0;
- break;
- }
- return sldata->renderpass_ubo[index];
-}
/**
* ssr_id can be null to disable ssr contribution.
*/
-static void add_standard_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- int *ssr_id,
- float *refract_depth,
- bool use_diffuse,
- bool use_glossy,
- bool use_refract,
- bool use_ssrefraction,
- bool use_alpha_blend,
- eViewLayerEEVEEPassType render_pass)
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend)
{
+ bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
+ bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
+ bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
+
LightCache *lcache = vedata->stl->g_data->light_cache;
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
@@ -428,11 +133,11 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "renderpass_block", get_render_pass_ubo(sldata, render_pass));
+ DRW_shgroup_uniform_block_ref(shgrp, "renderpass_block", &pd->renderpass_ubo);
DRW_shgroup_uniform_int_copy(shgrp, "outputSssId", 1);
+ DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
if (use_diffuse || use_glossy || use_refract) {
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
DRW_shgroup_uniform_texture_ref(shgrp, "maxzBuffer", &vedata->txl->maxzbuffer);
@@ -463,36 +168,6 @@ static void add_standard_uniforms(DRWShadingGroup *shgrp,
}
}
-/* Add the uniforms for the background shader to `shgrp`. */
-static void add_background_uniforms(DRWShadingGroup *shgrp,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata)
-{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- DRW_shgroup_uniform_float(shgrp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
- /* TODO (fclem): remove those (need to clean the GLSL files). */
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
-}
-
-static void create_default_shader(int options)
-{
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_default_frag_glsl);
-
- char *defines = eevee_get_defines(options);
-
- e_data.default_lit[options] = DRW_shader_create(e_data.vert_shader_str, NULL, frag_str, defines);
-
- MEM_freeN(defines);
- MEM_freeN(frag_str);
-}
-
static void eevee_init_noise_texture(void)
{
e_data.noise_tex = DRW_texture_create_2d(64, 64, GPU_RGBA16F, 0, (float *)blue_noise);
@@ -559,8 +234,6 @@ void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const d
e_data.noise_offsets[1] = offsets[1];
e_data.noise_offsets[2] = offsets[2];
- /* Attach & detach because we don't currently support multiple FB per texture,
- * and this would be the case for multiple viewport. */
GPU_framebuffer_bind(fbl->update_noise_fb);
DRW_draw_pass(psl->update_noise_pass);
}
@@ -606,94 +279,15 @@ void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_vi
}
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_PrivateData *g_data = stl->g_data;
- if (!e_data.frag_shader_lib) {
- /* Shaders */
- e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_bsdf_sampling_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_raytrace_lib_glsl,
- datatoc_ssr_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- /* Add one for each Closure */
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_lit_surface_frag_glsl,
- datatoc_volumetric_lib_glsl);
-
- e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_common_uniforms_lib_glsl,
- datatoc_bsdf_common_lib_glsl,
- datatoc_ambient_occlusion_lib_glsl,
- datatoc_octahedron_lib_glsl,
- datatoc_cubemap_lib_glsl,
- datatoc_irradiance_lib_glsl,
- datatoc_lightprobe_lib_glsl,
- datatoc_ltc_lib_glsl,
- datatoc_lights_lib_glsl,
- datatoc_volumetric_lib_glsl,
- datatoc_volumetric_frag_glsl);
-
- e_data.vert_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
-
- e_data.vert_shadow_shader_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
-
- e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_background_vert_glsl);
-
- e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_vert_glsl);
-
- e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
- datatoc_volumetric_geom_glsl);
-
- e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
- NULL,
- datatoc_default_world_frag_glsl,
- datatoc_common_view_lib_glsl,
- NULL);
-
- char *vert_str = BLI_string_joinN(
- datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_prepass_vert_glsl);
-
- e_data.default_prepass_sh = DRW_shader_create(vert_str, NULL, datatoc_prepass_frag_glsl, NULL);
-
- e_data.default_prepass_clip_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define CLIP_PLANES\n");
-
- e_data.default_hair_prepass_sh = DRW_shader_create(
- vert_str, NULL, datatoc_prepass_frag_glsl, "#define HAIR_SHADER\n");
-
- e_data.default_hair_prepass_clip_sh = DRW_shader_create(vert_str,
- NULL,
- datatoc_prepass_frag_glsl,
- "#define HAIR_SHADER\n"
- "#define CLIP_PLANES\n");
- MEM_freeN(vert_str);
-
- e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ if (!e_data.util_tex) {
+ EEVEE_shaders_material_shaders_init();
eevee_init_util_texture();
eevee_init_noise_texture();
@@ -728,33 +322,36 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
{
/* Create RenderPass UBO */
- if (sldata->renderpass_ubo[0] == NULL) {
- /* EEVEE_RENDER_PASS_COMBINED */
- sldata->renderpass_data[0] = (const EEVEE_RenderPassData){
- true, true, true, true, true, false};
- /* EEVEE_RENDER_PASS_DIFFUSE_COLOR */
- sldata->renderpass_data[1] = (const EEVEE_RenderPassData){
- true, false, false, false, false, true};
- /* EEVEE_RENDER_PASS_DIFFUSE_LIGHT */
- sldata->renderpass_data[2] = (const EEVEE_RenderPassData){
- true, true, false, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_COLOR */
- sldata->renderpass_data[3] = (const EEVEE_RenderPassData){
- false, false, true, false, false, false};
- /* EEVEE_RENDER_PASS_SPECULAR_LIGHT */
- sldata->renderpass_data[4] = (const EEVEE_RenderPassData){
- false, false, true, true, false, false};
- /* EEVEE_RENDER_PASS_EMIT */
- sldata->renderpass_data[5] = (const EEVEE_RenderPassData){
- false, false, false, false, true, false};
-
- for (int i = 0; i < MAX_MATERIAL_RENDER_PASSES_UBO; i++) {
- sldata->renderpass_ubo[i] = DRW_uniformbuffer_create(sizeof(EEVEE_RenderPassData),
- &sldata->renderpass_data[i]);
- }
+ if (sldata->renderpass_ubo.combined == NULL) {
+ sldata->renderpass_ubo.combined = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, true, true, true, false});
+
+ sldata->renderpass_ubo.diff_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, false, false, false, false, true});
+
+ sldata->renderpass_ubo.diff_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){true, true, false, false, false, false});
+
+ sldata->renderpass_ubo.spec_color = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, false, false, false});
+
+ sldata->renderpass_ubo.spec_light = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, true, true, false, false});
+
+ sldata->renderpass_ubo.emit = DRW_uniformbuffer_create(
+ sizeof(EEVEE_RenderPassData),
+ &(const EEVEE_RenderPassData){false, false, false, false, true, false});
}
- /* HACK: EEVEE_material_world_background_get can create a new context. This can only be
+ /* Used combined pass by default. */
+ g_data->renderpass_ubo = sldata->renderpass_ubo.combined;
+
+ /* HACK: EEVEE_material_get can create a new context. This can only be
* done when there is no active framebuffer. We do this here otherwise
* `EEVEE_renderpasses_output_init` will fail. It cannot be done in
* `EEVEE_renderpasses_init` as the `e_data.vertcode` can be uninitialized.
@@ -763,414 +360,12 @@ void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
struct Scene *scene = draw_ctx->scene;
struct World *wo = scene->world;
if (wo && wo->use_nodes) {
- EEVEE_material_world_background_get(scene, wo);
+ EEVEE_material_get(vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
}
}
}
}
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- const int options = VAR_WORLD_PROBE;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, false);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define PROBE_CAPTURE\n",
- false);
-}
-
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_BACKGROUND;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
- return DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- false,
- e_data.vert_background_shader_str,
- NULL,
- e_data.frag_shader_lib,
- SHADER_DEFINES "#define WORLD_BACKGROUND\n",
- true);
-}
-
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, World *wo)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_WORLD_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_world(wo, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_world(scene,
- wo,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_get(struct Scene *scene,
- Material *ma,
- EEVEE_Data *UNUSED(vedata),
- bool use_blend,
- bool use_refract)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
- SET_FLAG_FROM_TEST(options, use_refract, VAR_MAT_REFRACT);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_VOLUME;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat != NULL) {
- return mat;
- }
-
- char *defines = eevee_get_volume_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- true,
- e_data.vert_volume_shader_str,
- e_data.geom_volume_shader_str,
- e_data.volume_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- true);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-static struct GPUMaterial *EEVEE_material_hair_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- SET_FLAG_FROM_TEST(options, use_hashed_alpha, VAR_MAT_HASH);
- SET_FLAG_FROM_TEST(options, !use_hashed_alpha, VAR_MAT_CLIP);
- SET_FLAG_FROM_TEST(options, is_shadow, VAR_MAT_SHADOW);
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- char *frag_str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- (is_shadow) ? e_data.vert_shadow_shader_str :
- e_data.vert_shader_str,
- NULL,
- frag_str,
- defines,
- false);
-
- MEM_freeN(frag_str);
- MEM_freeN(defines);
-
- return mat;
-}
-
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma)
-{
- const void *engine = &DRW_engine_viewport_eevee_type;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- GPUMaterial *mat = DRW_shader_find_from_material(ma, engine, options, true);
- if (mat) {
- return mat;
- }
-
- char *defines = eevee_get_defines(options);
-
- mat = DRW_shader_create_from_material(scene,
- ma,
- engine,
- options,
- false,
- e_data.vert_shader_str,
- NULL,
- e_data.frag_shader_lib,
- defines,
- true);
-
- MEM_freeN(defines);
-
- return mat;
-}
-
-/**
- * Create a default shading group inside the given pass.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_create(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- DRWPass *pass,
- bool is_hair,
- bool use_blend,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, use_blend, VAR_MAT_BLEND);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
-
- return shgrp;
-}
-
-/**
- * Create a default shading group inside the default pass without standard uniforms.
- */
-static struct DRWShadingGroup *EEVEE_default_shading_group_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool is_hair,
- bool holdout,
- bool use_ssr)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- EEVEE_PassList *psl = vedata->psl;
-
- BLI_assert(!is_hair || (ob && ((psys && md) || ob->type == OB_HAIR)));
-
- SET_FLAG_FROM_TEST(options, is_hair, VAR_MAT_HAIR);
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- if (psl->default_pass[options] == NULL) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->default_pass[options], state);
-
- /* XXX / WATCH: This creates non persistent binds for the ubos and textures.
- * But it's currently OK because the following shgroups does not add any bind.
- * EDIT: THIS IS NOT THE CASE FOR HAIRS !!! DUMMY!!! */
- if (!is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options],
- psl->default_pass[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- }
- }
-
- if (is_hair) {
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, vedata->psl->default_pass[options], e_data.default_lit[options]);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- return shgrp;
- }
- else {
- return DRW_shgroup_create(e_data.default_lit[options], vedata->psl->default_pass[options]);
- }
-}
-
-static struct DRWShadingGroup *EEVEE_default_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH;
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_create(e_data.default_lit[options], pass);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
-static struct DRWShadingGroup *EEVEE_default_hair_render_pass_shading_group_get(
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- Object *ob,
- ParticleSystem *psys,
- ModifierData *md,
- bool holdout,
- bool use_ssr,
- DRWPass *pass,
- eViewLayerEEVEEPassType render_pass_flag)
-{
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- int options = VAR_MAT_MESH | VAR_MAT_HAIR;
-
- BLI_assert((ob && psys && md));
-
- SET_FLAG_FROM_TEST(options, holdout, VAR_MAT_HOLDOUT);
-
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
- }
-
- DRWShadingGroup *shgrp = DRW_shgroup_hair_create(
- ob, psys, md, pass, e_data.default_lit[options]);
- add_standard_uniforms(
- shgrp, sldata, vedata, &ssr_id, NULL, true, true, false, false, false, render_pass_flag);
- return shgrp;
-}
-
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
@@ -1180,10 +375,17 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* Create Material Ghash */
{
stl->g_data->material_hash = BLI_ghash_ptr_new("Eevee_material ghash");
+
+ if (sldata->material_cache == NULL) {
+ sldata->material_cache = BLI_memblock_create(sizeof(EeveeMaterialCache));
+ }
+ else {
+ BLI_memblock_clear(sldata->material_cache, NULL);
+ }
}
{
- DRW_PASS_CREATE(psl->background_pass, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
+ DRW_PASS_CREATE(psl->background_ps, DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL);
struct GPUBatch *geom = DRW_cache_fullscreen_quad_get();
DRWShadingGroup *grp = NULL;
@@ -1191,485 +393,297 @@ void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
Scene *scene = draw_ctx->scene;
World *wo = scene->world;
- const float *col = G_draw.block.colorBackground;
-
- EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_pass, wo, NULL);
+ EEVEE_lookdev_cache_init(vedata, sldata, &grp, psl->background_ps, wo, NULL);
if (!grp && wo) {
- col = &wo->horr;
-
- if (wo->use_nodes && wo->nodetree) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
-
- switch (GPU_material_status(gpumat)) {
- case GPU_MAT_SUCCESS:
- grp = DRW_shgroup_material_create(gpumat, psl->background_pass);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, geom, NULL);
- break;
- case GPU_MAT_QUEUED:
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- col = compile_col;
- break;
- case GPU_MAT_FAILED:
- default:
- col = error_col;
- break;
- }
- }
+ struct GPUMaterial *gpumat = EEVEE_material_get(
+ vedata, scene, NULL, wo, VAR_WORLD_BACKGROUND);
+
+ grp = DRW_shgroup_material_create(gpumat, psl->background_ps);
+ DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
+ /* TODO (fclem): remove those (need to clean the GLSL files). */
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
+ DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
+ DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_call(grp, geom, NULL);
}
/* Fallback if shader fails or if not using nodetree. */
if (grp == NULL) {
- grp = DRW_shgroup_create(e_data.default_background, psl->background_pass);
- DRW_shgroup_uniform_vec3(grp, "color", col, 1);
+ GPUShader *sh = EEVEE_shaders_default_background_sh_get();
+ grp = DRW_shgroup_create(sh, psl->background_ps);
+ DRW_shgroup_uniform_vec3(grp, "color", G_draw.block.colorBackground, 1);
DRW_shgroup_uniform_float(grp, "backgroundAlpha", &stl->g_data->background_alpha, 1);
DRW_shgroup_call(grp, geom, NULL);
}
}
- {
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->depth_pass, state);
- stl->g_data->depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh, psl->depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_cull, state);
- stl->g_data->depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->depth_pass_clip, state);
- stl->g_data->depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->depth_pass_clip_cull, state);
- stl->g_data->depth_shgrp_clip_cull = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->depth_pass_clip_cull);
- }
+#define EEVEE_PASS_CREATE(pass, state) \
+ do { \
+ DRW_PASS_CREATE(psl->pass##_ps, state); \
+ DRW_PASS_CREATE(psl->pass##_cull_ps, state | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_ps, psl->pass##_cull_ps); \
+ } while (0)
- {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->material_pass, state);
- DRW_PASS_CREATE(psl->material_pass_cull, state | DRW_STATE_CULL_BACK);
- }
+#define EEVEE_CLIP_PASS_CREATE(pass, state) \
+ do { \
+ DRWState st = state | DRW_STATE_CLIP_PLANES; \
+ DRW_PASS_INSTANCE_CREATE(psl->pass##_clip_ps, psl->pass##_ps, st); \
+ DRW_PASS_INSTANCE_CREATE( \
+ psl->pass##_clip_cull_ps, psl->pass##_cull_ps, st | DRW_STATE_CULL_BACK); \
+ DRW_pass_link(psl->pass##_clip_ps, psl->pass##_clip_cull_ps); \
+ } while (0)
{
- DRWState state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
- DRW_PASS_CREATE(psl->refract_depth_pass, state);
- stl->g_data->refract_depth_shgrp = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_cull, state);
- stl->g_data->refract_depth_shgrp_cull = DRW_shgroup_create(e_data.default_prepass_sh,
- psl->refract_depth_pass_cull);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip, state);
- stl->g_data->refract_depth_shgrp_clip = DRW_shgroup_create(e_data.default_prepass_clip_sh,
- psl->refract_depth_pass_clip);
-
- state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_CULL_BACK;
- DRW_PASS_CREATE(psl->refract_depth_pass_clip_cull, state);
- stl->g_data->refract_depth_shgrp_clip_cull = DRW_shgroup_create(
- e_data.default_prepass_clip_sh, psl->refract_depth_pass_clip_cull);
- }
+ DRWState state_depth = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
+ DRWState state_shading = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES;
+ DRWState state_sss = DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS;
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES);
- DRW_PASS_CREATE(psl->refract_pass, state);
- }
+ EEVEE_PASS_CREATE(depth, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth, state_depth);
- {
- DRWState state = (DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_CLIP_PLANES |
- DRW_STATE_WRITE_STENCIL | DRW_STATE_STENCIL_ALWAYS);
- DRW_PASS_CREATE(psl->sss_pass, state);
- DRW_PASS_CREATE(psl->sss_pass_cull, state | DRW_STATE_CULL_BACK);
- e_data.sss_count = 0;
+ EEVEE_PASS_CREATE(depth_refract, state_depth);
+ EEVEE_CLIP_PASS_CREATE(depth_refract, state_depth);
+
+ EEVEE_PASS_CREATE(material, state_shading);
+ EEVEE_PASS_CREATE(material_refract, state_shading);
+ EEVEE_PASS_CREATE(material_sss, state_shading | state_sss);
}
+ {
+ /* Renderpass accumulation. */
+ DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
+ /* Create an instance of each of theses passes and link them together. */
+ DRWPass *passes[] = {
+ psl->material_ps,
+ psl->material_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ };
+ DRWPass *first = NULL, *last = NULL;
+ for (int i = 0; i < ARRAY_SIZE(passes); i++) {
+ DRWPass *pass = DRW_pass_create_instance("Renderpass Accumulation", passes[i], state);
+ if (first == NULL) {
+ first = last = pass;
+ }
+ else {
+ DRW_pass_link(last, pass);
+ last = pass;
+ }
+ }
+ psl->material_accum_ps = first;
+ /* Same for background */
+ DRW_PASS_INSTANCE_CREATE(psl->background_accum_ps, psl->background_ps, state);
+ }
{
DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CLIP_PLANES;
DRW_PASS_CREATE(psl->transparent_pass, state);
}
-
{
DRW_PASS_CREATE(psl->update_noise_pass, DRW_STATE_WRITE_COLOR);
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.update_noise_sh, psl->update_noise_pass);
+ GPUShader *sh = EEVEE_shaders_update_noise_sh_get();
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->update_noise_pass);
DRW_shgroup_uniform_texture(grp, "blueNoise", e_data.noise_tex);
DRW_shgroup_uniform_vec3(grp, "offsets", e_data.noise_offsets, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
+}
- if (eevee_hdri_preview_overlay_enabled(draw_ctx->v3d)) {
- DRWShadingGroup *shgrp;
-
- struct GPUBatch *sphere = DRW_cache_sphere_get();
- static float color_chrome[3] = {1.0f, 1.0f, 1.0f};
- static float color_diffuse[3] = {0.8f, 0.8f, 0.8f};
- int options = VAR_MAT_MESH | VAR_MAT_LOOKDEV;
+BLI_INLINE void material_shadow(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ bool is_hair,
+ EeveeMaterialCache *emc)
+{
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
+ const DRWContextState *draw_ctx = DRW_context_state_get();
+ Scene *scene = draw_ctx->scene;
- if (e_data.default_lit[options] == NULL) {
- create_default_shader(options);
+ if (ma->blend_shadow != MA_BS_NONE) {
+ /* Shadow Pass */
+ const bool use_shadow_shader = ma->use_nodes && ma->nodetree &&
+ ELEM(ma->blend_shadow, MA_BS_CLIP, MA_BS_HASHED);
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_shadow_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_shadow_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ /* Avoid possible confusion with depth pre-pass options. */
+ int option = KEY_SHADOW;
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
+ }
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, psl->shadow_pass);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_ALWAYS |
- DRW_STATE_CULL_BACK;
-
- DRW_PASS_CREATE(psl->lookdev_diffuse_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_diffuse_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_diffuse, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 0.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "specular", 0.5f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 1.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
-
- DRW_PASS_CREATE(psl->lookdev_glossy_pass, state);
- shgrp = DRW_shgroup_create(e_data.default_lit[options], psl->lookdev_glossy_pass);
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- true,
- true,
- false,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_chrome, 1);
- DRW_shgroup_uniform_float_copy(shgrp, "metallic", 1.0f);
- DRW_shgroup_uniform_float_copy(shgrp, "roughness", 0.0f);
- DRW_shgroup_call(shgrp, sphere, NULL);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- {
- memset(psl->material_accum_pass, 0, sizeof(psl->material_accum_pass));
- for (int pass_index = 0; pass_index < stl->g_data->render_passes_material_count;
- pass_index++) {
- DRWState state = DRW_STATE_WRITE_COLOR | DRW_STATE_DEPTH_EQUAL | DRW_STATE_BLEND_ADD_FULL;
- DRW_PASS_CREATE(psl->material_accum_pass[pass_index], state);
- }
+ emc->shadow_grp = grp;
+ emc->shadow_grp_p = grp_p;
+ }
+ else {
+ emc->shadow_grp = NULL;
+ emc->shadow_grp_p = NULL;
}
}
-#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
- do { \
- if (oedata) { \
- DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
- } \
- else { \
- DRW_shgroup_call(shgrp, geom, ob); \
- } \
- } while (0)
-
-#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
- do { \
- if (shgrp) { \
- ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
- } \
- } while (0)
-
-typedef struct EeveeMaterialShadingGroups {
- struct DRWShadingGroup *shading_grp;
- struct DRWShadingGroup *depth_grp;
- struct DRWShadingGroup *depth_clip_grp;
- struct DRWShadingGroup *material_accum_grp[MAX_MATERIAL_RENDER_PASSES];
-} EeveeMaterialShadingGroups;
-
-static void material_opaque(Material *ma,
- GHash *material_hash,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct GPUMaterial **gpumat_depth,
- struct EeveeMaterialShadingGroups *shgrps,
- bool holdout)
+static EeveeMaterialCache material_opaque(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma,
+ const bool is_hair)
{
EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_PassList *psl = vedata->psl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
- bool use_diffuse, use_glossy, use_refract;
- bool store_material = true;
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
- const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
- const bool use_gpumat = (ma->use_nodes && ma->nodetree && !holdout);
+ const bool do_cull = !is_hair && (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
+ const bool use_gpumat = (ma->use_nodes && ma->nodetree);
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
((effects->enabled_effects & EFFECT_REFRACT) != 0);
- const bool use_translucency = ((ma->blend_flag & MA_BL_TRANSLUCENCY) != 0);
+ const bool use_depth_shader = use_gpumat && ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED);
- EeveeMaterialShadingGroups *emsg = BLI_ghash_lookup(material_hash, (const void *)ma);
-
- if (emsg) {
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
-
- /* This will have been created already, just perform a lookup. */
- *gpumat = (use_gpumat) ? EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract) :
- NULL;
- *gpumat_depth = (use_gpumat) ? EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false) :
- NULL;
- return;
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */
+ void *key = (char *)ma + is_hair;
+ /* Search for other material instances (sharing the same Material datablock). */
+ EeveeMaterialCache **emc_p, *emc;
+ if (BLI_ghash_ensure_p(pd->material_hash, key, (void ***)&emc_p)) {
+ return **emc_p;
+ }
+ else {
+ *emc_p = emc = BLI_memblock_alloc(sldata->material_cache);
}
- emsg = MEM_callocN(sizeof(EeveeMaterialShadingGroups), "EeveeMaterialShadingGroups");
- if (use_gpumat) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- static float half = 0.5f;
-
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, false, use_ssrefract);
-
- eGPUMaterialStatus status_mat_surface = GPU_material_status(*gpumat);
-
- /* Alpha CLipped : Discard pixel from depth pass, then
- * fail the depth test for shading. */
- if (ELEM(ma->blend_method, MA_BM_CLIP, MA_BM_HASHED)) {
- *gpumat_depth = EEVEE_material_mesh_depth_get(
- scene, ma, (ma->blend_method == MA_BM_HASHED), false);
+ material_shadow(vedata, sldata, ma, is_hair, emc);
- eGPUMaterialStatus status_mat_depth = GPU_material_status(*gpumat_depth);
- if (status_mat_depth != GPU_MAT_SUCCESS) {
- /* Mixing both flags. If depth shader fails, show it to the user by not using
- * the surface shader. */
- status_mat_surface = status_mat_depth;
- }
- else if (use_ssrefract) {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->refract_depth_pass_cull : psl->refract_depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth,
- (do_cull) ? psl->refract_depth_pass_clip_cull : psl->refract_depth_pass_clip);
- }
- else {
- emsg->depth_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_cull : psl->depth_pass);
- emsg->depth_clip_grp = DRW_shgroup_material_create(
- *gpumat_depth, (do_cull) ? psl->depth_pass_clip_cull : psl->depth_pass_clip);
- }
-
- if (emsg->depth_grp != NULL) {
- use_diffuse = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat_depth, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(emsg->depth_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
- add_standard_uniforms(emsg->depth_clip_grp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (ma->blend_method == MA_BM_CLIP) {
- DRW_shgroup_uniform_float(emsg->depth_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- DRW_shgroup_uniform_float(
- emsg->depth_clip_grp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
+ {
+ /* Depth Pass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, use_depth_shader, VAR_MAT_HASH);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = (use_depth_shader) ?
+ EEVEE_material_get(vedata, scene, ma, NULL, mat_options) :
+ EEVEE_material_default_get(scene, ma, mat_options);
+
+ int option = 0;
+ SET_FLAG_FROM_TEST(option, do_cull, KEY_CULL);
+ SET_FLAG_FROM_TEST(option, use_ssrefract, KEY_REFRACT);
+ DRWPass *depth_ps = (DRWPass *[]){
+ psl->depth_ps,
+ psl->depth_cull_ps,
+ psl->depth_refract_ps,
+ psl->depth_refract_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key. */
+ SET_FLAG_FROM_TEST(option, is_hair, KEY_HAIR);
+
+ /* Search for the same shaders usage in the pass. */
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- static int no_ssr = 0;
- static int first_ssr = 1;
- int *ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ?
- &first_ssr :
- &no_ssr;
- const bool use_sss = GPU_material_flag_get(*gpumat, GPU_MATFLAG_SSS);
- use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- emsg->shading_grp = DRW_shgroup_material_create(
- *gpumat,
- (use_ssrefract) ?
- psl->refract_pass :
- (use_sss) ? ((do_cull) ? psl->sss_pass_cull : psl->sss_pass) :
- ((do_cull) ? psl->material_pass_cull : psl->material_pass));
-
- add_standard_uniforms(emsg->shading_grp,
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- if (use_sss) {
- struct GPUTexture *sss_tex_profile = NULL;
- struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
- *gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-
- if (sss_profile) {
- /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
- if (e_data.sss_count < 254) {
- int sss_id = e_data.sss_count + 1;
- DRW_shgroup_stencil_mask(emsg->shading_grp, sss_id);
- EEVEE_subsurface_add_pass(sldata, vedata, sss_id, sss_profile);
- if (use_translucency) {
- EEVEE_subsurface_translucency_add_pass(
- sldata, vedata, sss_id, sss_profile, sss_tex_profile);
- }
- e_data.sss_count++;
- }
- else {
- /* TODO : display message. */
- printf("Error: Too many different Subsurface shader in the scene.\n");
- }
- }
- }
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- emsg->material_accum_grp[render_pass_index] = DRW_shgroup_material_create(
- *gpumat, psl->material_accum_pass[render_pass_index]);
- add_standard_uniforms(emsg->material_accum_grp[render_pass_index],
- sldata,
- vedata,
- ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- store_material = false;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
+ else {
+ *grp_p = grp = DRW_shgroup_create(sh, depth_ps);
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, false);
}
- }
- /* Fallback to default shader */
- if (emsg->shading_grp == NULL) {
- bool use_ssr = ((effects->enabled_effects & EFFECT_SSR) != 0);
- emsg->shading_grp = EEVEE_default_shading_group_get(
- sldata, vedata, NULL, NULL, NULL, false, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(emsg->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(emsg->shading_grp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- DRWShadingGroup *shgrp = EEVEE_default_render_pass_shading_group_get(
- sldata,
- vedata,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
- emsg->material_accum_grp[render_pass_index] = shgrp;
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback default depth prepass */
- if (emsg->depth_grp == NULL) {
- if (use_ssrefract) {
- emsg->depth_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_cull :
- stl->g_data->refract_depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->refract_depth_shgrp_clip_cull :
- stl->g_data->refract_depth_shgrp_clip;
+ emc->depth_grp = grp;
+ emc->depth_grp_p = grp_p;
+ }
+ {
+ /* Shading Pass */
+ int mat_options = VAR_MAT_MESH;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ SET_FLAG_FROM_TEST(mat_options, is_hair, VAR_MAT_HAIR);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ const bool use_sss = GPU_material_flag_get(gpumat, GPU_MATFLAG_SSS);
+
+ int ssr_id = (((effects->enabled_effects & EFFECT_SSR) != 0) && !use_ssrefract) ? 1 : 0;
+ int option = (use_ssrefract ? 0 : (use_sss ? 1 : 2)) * 2 + do_cull;
+ DRWPass *shading_pass = (DRWPass *[]){
+ psl->material_refract_ps,
+ psl->material_refract_cull_ps,
+ psl->material_sss_ps,
+ psl->material_sss_cull_ps,
+ psl->material_ps,
+ psl->material_cull_ps,
+ }[option];
+ /* Hair are rendered inside the non-cull pass but needs to have a separate cache key */
+ option = option * 2 + is_hair;
+
+ /* Search for the same shaders usage in the pass. */
+ /* HACK: Assume the struct will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing. */
+ BLI_assert(option <= 16);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+ void *cache_key = (char *)sh + option;
+ DRWShadingGroup *grp, **grp_p;
+
+ if (BLI_ghash_ensure_p(pd->material_hash, cache_key, (void ***)&grp_p)) {
+ /* This GPUShader has already been used by another material.
+ * Add new shading group just after to avoid shader switching cost. */
+ grp = DRW_shgroup_create_sub(*grp_p);
}
else {
- emsg->depth_grp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
- emsg->depth_clip_grp = (do_cull) ? stl->g_data->depth_shgrp_clip_cull :
- stl->g_data->depth_shgrp_clip;
+ *grp_p = grp = DRW_shgroup_create(sh, shading_pass);
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, false);
}
- }
+ DRW_shgroup_add_material_resources(grp, gpumat);
- memcpy(shgrps, emsg, sizeof(EeveeMaterialShadingGroups));
- if (store_material) {
- BLI_ghash_insert(material_hash, ma, emsg);
- }
- else {
- MEM_freeN(emsg);
+ if (use_sss) {
+ EEVEE_subsurface_add_pass(sldata, vedata, ma, grp, gpumat);
+ }
+
+ emc->shading_grp = grp;
+ emc->shading_grp_p = grp_p;
+ emc->shading_gpumat = gpumat;
}
+ return *emc;
}
-static void material_transparent(Material *ma,
- EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- struct GPUMaterial **gpumat,
- struct EeveeMaterialShadingGroups *shgrps)
+static EeveeMaterialCache material_transparent(EEVEE_Data *vedata,
+ EEVEE_ViewLayerData *sldata,
+ Material *ma)
{
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
- EEVEE_PassList *psl = ((EEVEE_Data *)vedata)->psl;
+ EEVEE_PassList *psl = vedata->psl;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
+ EeveeMaterialCache emc = {0};
const bool do_cull = (ma->blend_flag & MA_BL_CULL_BACKFACE) != 0;
const bool use_gpumat = ma->use_nodes && ma->nodetree;
const bool use_ssrefract = use_gpumat && ((ma->blend_flag & MA_BL_SS_REFRACTION) != 0) &&
- ((stl->effects->enabled_effects & EFFECT_REFRACT) != 0);
- const float *color_p = &ma->r;
- const float *metal_p = &ma->metallic;
- const float *spec_p = &ma->spec;
- const float *rough_p = &ma->roughness;
-
+ ((effects->enabled_effects & EFFECT_REFRACT) != 0);
const bool use_prepass = ((ma->blend_flag & MA_BL_HIDE_BACKFACE) != 0);
DRWState cur_state;
@@ -1677,81 +691,53 @@ static void material_transparent(Material *ma,
DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_DEPTH_EQUAL |
DRW_STATE_BLEND_CUSTOM);
- /* Depth prepass */
+ material_shadow(vedata, sldata, ma, false, &emc);
+
if (use_prepass) {
- shgrps->depth_grp = DRW_shgroup_create(e_data.default_prepass_clip_sh, psl->transparent_pass);
+ /* Depth prepass */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_DEPTH;
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
+ struct GPUShader *sh = GPU_material_get_shader(gpumat);
+
+ DRWShadingGroup *grp = DRW_shgroup_create(sh, psl->transparent_pass);
+
+ EEVEE_material_bind_resources(grp, gpumat, sldata, vedata, NULL, NULL, false, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
cur_state = DRW_STATE_WRITE_DEPTH | DRW_STATE_DEPTH_LESS_EQUAL;
cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- DRW_shgroup_state_disable(shgrps->depth_grp, all_state);
- DRW_shgroup_state_enable(shgrps->depth_grp, cur_state);
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
+
+ emc.depth_grp = grp;
}
+ {
+ /* Shading */
+ int ssr_id = -1; /* TODO transparent SSR */
+ int mat_options = VAR_MAT_MESH | VAR_MAT_BLEND;
+ SET_FLAG_FROM_TEST(mat_options, use_ssrefract, VAR_MAT_REFRACT);
+ GPUMaterial *gpumat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
- if (use_gpumat) {
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
- static float half = 0.5f;
+ DRWShadingGroup *grp = DRW_shgroup_create(GPU_material_get_shader(gpumat),
+ psl->transparent_pass);
- /* Shading */
- *gpumat = EEVEE_material_mesh_get(scene, ma, vedata, true, use_ssrefract);
-
- switch (GPU_material_status(*gpumat)) {
- case GPU_MAT_SUCCESS: {
- static int ssr_id = -1; /* TODO transparent SSR */
-
- shgrps->shading_grp = DRW_shgroup_material_create(*gpumat, psl->transparent_pass);
-
- bool use_blend = true;
- bool use_diffuse = GPU_material_flag_get(*gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(*gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(*gpumat, GPU_MATFLAG_REFRACT);
-
- add_standard_uniforms(shgrps->shading_grp,
- sldata,
- vedata,
- &ssr_id,
- &ma->refract_depth,
- use_diffuse,
- use_glossy,
- use_refract,
- use_ssrefract,
- use_blend,
- DEFAULT_RENDER_PASS_FLAG);
- break;
- }
- case GPU_MAT_QUEUED: {
- /* TODO Bypass probe compilation. */
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- }
+ EEVEE_material_bind_resources(
+ grp, gpumat, sldata, vedata, &ssr_id, &ma->refract_depth, use_ssrefract, true);
+ DRW_shgroup_add_material_resources(grp, gpumat);
- /* Fallback to default shader */
- if (shgrps->shading_grp == NULL) {
- shgrps->shading_grp = EEVEE_default_shading_group_create(
- sldata, vedata, psl->transparent_pass, false, true, false);
- DRW_shgroup_uniform_vec3(shgrps->shading_grp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrps->shading_grp, "roughness", rough_p, 1);
- }
+ cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
+ cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
+ cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
- cur_state = DRW_STATE_WRITE_COLOR | DRW_STATE_BLEND_CUSTOM;
- cur_state |= (use_prepass) ? DRW_STATE_DEPTH_EQUAL : DRW_STATE_DEPTH_LESS_EQUAL;
- cur_state |= (do_cull) ? DRW_STATE_CULL_BACK : 0;
+ /* Disable other blend modes and use the one we want. */
+ DRW_shgroup_state_disable(grp, all_state);
+ DRW_shgroup_state_enable(grp, cur_state);
- /* Disable other blend modes and use the one we want. */
- DRW_shgroup_state_disable(shgrps->shading_grp, all_state);
- DRW_shgroup_state_enable(shgrps->shading_grp, cur_state);
+ emc.shading_grp = grp;
+ emc.shading_gpumat = gpumat;
+ }
+ return emc;
}
/* Return correct material or empty default material if slot is empty. */
@@ -1766,12 +752,35 @@ BLI_INLINE Material *eevee_object_material_get(Object *ob, int slot, bool holdou
ma = BKE_material_default_volume();
}
else {
- ma = BKE_material_default_empty();
+ ma = BKE_material_default_surface();
}
}
return ma;
}
+BLI_INLINE EeveeMaterialCache eevee_material_cache_get(
+ EEVEE_Data *vedata, EEVEE_ViewLayerData *sldata, Object *ob, int slot, bool is_hair)
+{
+ const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
+ EeveeMaterialCache matcache;
+ Material *ma = eevee_object_material_get(ob, slot, holdout);
+ switch (ma->blend_method) {
+ case MA_BM_BLEND:
+ if (!is_hair) {
+ matcache = material_transparent(vedata, sldata, ma);
+ break;
+ }
+ ATTR_FALLTHROUGH;
+ case MA_BM_SOLID:
+ case MA_BM_CLIP:
+ case MA_BM_HASHED:
+ default:
+ matcache = material_opaque(vedata, sldata, ma, is_hair);
+ break;
+ }
+ return matcache;
+}
+
static void eevee_hair_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
@@ -1780,240 +789,49 @@ static void eevee_hair_cache_populate(EEVEE_Data *vedata,
int matnr,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- const DRWContextState *draw_ctx = DRW_context_state_get();
- Scene *scene = draw_ctx->scene;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
-
- DRWShadingGroup *shgrp = NULL;
- Material *ma = eevee_object_material_get(ob, matnr - 1, holdout);
- const bool use_gpumat = ma->use_nodes && ma->nodetree && !holdout;
- const bool use_alpha_hash = (ma->blend_method == MA_BM_HASHED);
- const bool use_alpha_clip = (ma->blend_method == MA_BM_CLIP);
- const bool use_ssr = ((stl->effects->enabled_effects & EFFECT_SSR) != 0);
+ EeveeMaterialCache matcache = eevee_material_cache_get(vedata, sldata, ob, matnr - 1, true);
- GPUMaterial *gpumat = use_gpumat ? EEVEE_material_hair_get(scene, ma) : NULL;
- eGPUMaterialStatus status_mat_surface = gpumat ? GPU_material_status(gpumat) : GPU_MAT_SUCCESS;
-
- float *color_p = &ma->r;
- float *metal_p = &ma->metallic;
- float *spec_p = &ma->spec;
- float *rough_p = &ma->roughness;
-
- /* Depth prepass. */
- if (use_gpumat && (use_alpha_clip || use_alpha_hash)) {
- GPUMaterial *gpumat_depth = EEVEE_material_hair_depth_get(scene, ma, use_alpha_hash, false);
-
- eGPUMaterialStatus status_mat_depth = GPU_material_status(gpumat_depth);
-
- if (status_mat_depth != GPU_MAT_SUCCESS) {
- /* Mixing both flags. If depth shader fails, show it to the user by not using
- * the surface shader. */
- status_mat_surface = status_mat_depth;
- }
- else {
- const bool use_diffuse = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_DIFFUSE);
- const bool use_glossy = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_GLOSSY);
- const bool use_refract = GPU_material_flag_get(gpumat_depth, GPU_MATFLAG_REFRACT);
-
- for (int i = 0; i < 2; i++) {
- DRWPass *pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, pass, gpumat_depth);
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- NULL,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (use_alpha_clip) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- }
- }
+ if (matcache.depth_grp) {
+ *matcache.depth_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.depth_grp);
}
-
- /* Fallback to default shader */
- if (shgrp == NULL) {
- for (int i = 0; i < 2; i++) {
- DRWPass *depth_pass = (i == 0) ? psl->depth_pass : psl->depth_pass_clip;
- struct GPUShader *depth_sh = (i == 0) ? e_data.default_hair_prepass_sh :
- e_data.default_hair_prepass_clip_sh;
- DRW_shgroup_hair_create(ob, psys, md, depth_pass, depth_sh);
- }
+ if (matcache.shading_grp) {
+ *matcache.shading_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shading_grp);
}
-
- shgrp = NULL;
-
- if (gpumat) {
- static int ssr_id;
- ssr_id = (use_ssr) ? 1 : -1;
- static float half = 0.5f;
- static float error_col[3] = {1.0f, 0.0f, 1.0f};
- static float compile_col[3] = {0.5f, 0.5f, 0.5f};
-
- switch (status_mat_surface) {
- case GPU_MAT_SUCCESS: {
- bool use_diffuse = GPU_material_flag_get(gpumat, GPU_MATFLAG_DIFFUSE);
- bool use_glossy = GPU_material_flag_get(gpumat, GPU_MATFLAG_GLOSSY);
- bool use_refract = GPU_material_flag_get(gpumat, GPU_MATFLAG_REFRACT);
-
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->material_pass, gpumat);
-
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* HACK: Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs are present.
- * This binds utilTex even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- DEFAULT_RENDER_PASS_FLAG);
-
- /* Add the hair to all the render_passes that are enabled */
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = DRW_shgroup_material_hair_create(
- ob, psys, md, psl->material_accum_pass[render_pass_index], gpumat);
- if (!use_diffuse && !use_glossy && !use_refract) {
- /* Small hack to avoid issue when utilTex is needed for
- * world_normals_get and none of the bsdfs that need it are present.
- * This binds `utilTex` even if not needed. */
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
- }
-
- add_standard_uniforms(shgrp,
- sldata,
- vedata,
- &ssr_id,
- NULL,
- use_diffuse,
- use_glossy,
- use_refract,
- false,
- false,
- render_pass_flag);
- }
- RENDER_PASS_ITER_END(render_pass_index);
-
- break;
- }
- case GPU_MAT_QUEUED: {
- stl->g_data->queued_shaders_count++;
- color_p = compile_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
- case GPU_MAT_FAILED:
- default:
- color_p = error_col;
- metal_p = spec_p = rough_p = &half;
- break;
- }
+ if (matcache.shadow_grp) {
+ *matcache.shadow_grp_p = DRW_shgroup_hair_create_sub(ob, psys, md, matcache.shadow_grp);
+ *cast_shadow = true;
}
+}
- /* Fallback to default shader */
- if (shgrp == NULL) {
- shgrp = EEVEE_default_shading_group_get(sldata, vedata, ob, psys, md, true, holdout, use_ssr);
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
-
- RENDER_PASS_ITER_BEGIN (stl->g_data->render_passes, render_pass_index, render_pass_flag) {
- shgrp = EEVEE_default_hair_render_pass_shading_group_get(
- sldata,
- vedata,
- ob,
- psys,
- md,
- holdout,
- use_ssr,
- psl->material_accum_pass[render_pass_index],
- render_pass_flag);
-
- DRW_shgroup_uniform_vec3(shgrp, "basecol", color_p, 1);
- DRW_shgroup_uniform_float(shgrp, "metallic", metal_p, 1);
- DRW_shgroup_uniform_float(shgrp, "specular", spec_p, 1);
- DRW_shgroup_uniform_float(shgrp, "roughness", rough_p, 1);
- }
- RENDER_PASS_ITER_END(render_pass_index);
- }
+#define ADD_SHGROUP_CALL(shgrp, ob, geom, oedata) \
+ do { \
+ if (oedata) { \
+ DRW_shgroup_call_with_callback(shgrp, geom, ob, oedata); \
+ } \
+ else { \
+ DRW_shgroup_call(shgrp, geom, ob); \
+ } \
+ } while (0)
- /* Shadows */
- char blend_shadow = use_gpumat ? ma->blend_shadow : MA_BS_SOLID;
- const bool shadow_alpha_hash = (blend_shadow == MA_BS_HASHED);
- switch (blend_shadow) {
- case MA_BS_SOLID:
- DRW_shgroup_hair_create(ob, psys, md, psl->shadow_pass, e_data.default_hair_prepass_sh);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- case MA_BS_HASHED:
- gpumat = EEVEE_material_hair_depth_get(scene, ma, shadow_alpha_hash, true);
- shgrp = DRW_shgroup_material_hair_create(ob, psys, md, psl->shadow_pass, gpumat);
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(shgrp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(shgrp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(shgrp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(shgrp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(shgrp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- shgrp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(shgrp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_texture(shgrp, "utilTex", e_data.util_tex);
-
- if (!shadow_alpha_hash) {
- DRW_shgroup_uniform_float(shgrp, "alphaThreshold", &ma->alpha_threshold, 1);
- }
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+#define ADD_SHGROUP_CALL_SAFE(shgrp, ob, geom, oedata) \
+ do { \
+ if (shgrp) { \
+ ADD_SHGROUP_CALL(shgrp, ob, geom, oedata); \
+ } \
+ } while (0)
+
+#define MATCACHE_AS_ARRAY(matcache, member, materials_len, output_array) \
+ for (int i = 0; i < materials_len; i++) { \
+ output_array[i] = matcache[i].member; \
}
-}
void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
EEVEE_ViewLayerData *sldata,
Object *ob,
bool *cast_shadow)
{
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
const DRWContextState *draw_ctx = DRW_context_state_get();
Scene *scene = draw_ctx->scene;
- GHash *material_hash = stl->g_data->material_hash;
- const bool holdout = (ob->base_flag & BASE_HOLDOUT) != 0;
bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
!DRW_state_is_image_render();
@@ -2022,139 +840,64 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
const int materials_len = DRW_cache_object_material_count_get(ob);
- struct EeveeMaterialShadingGroups *shgrps_array = BLI_array_alloca(shgrps_array,
- materials_len);
-
- struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
- struct GPUMaterial **gpumat_depth_array = BLI_array_alloca(gpumat_array, materials_len);
- struct Material **ma_array = BLI_array_alloca(ma_array, materials_len);
-
+ EeveeMaterialCache *matcache = BLI_array_alloca(matcache, materials_len);
for (int i = 0; i < materials_len; i++) {
- ma_array[i] = eevee_object_material_get(ob, i, holdout);
- memset(&shgrps_array[i], 0, sizeof(EeveeMaterialShadingGroups));
- gpumat_array[i] = NULL;
- gpumat_depth_array[i] = NULL;
-
- switch (ma_array[i]->blend_method) {
- case MA_BM_SOLID:
- case MA_BM_CLIP:
- case MA_BM_HASHED:
- material_opaque(ma_array[i],
- material_hash,
- sldata,
- vedata,
- &gpumat_array[i],
- &gpumat_depth_array[i],
- &shgrps_array[i],
- holdout);
- break;
- case MA_BM_BLEND:
- material_transparent(ma_array[i], sldata, vedata, &gpumat_array[i], &shgrps_array[i]);
- break;
- default:
- BLI_assert(0);
- break;
- }
+ matcache[i] = eevee_material_cache_get(vedata, sldata, ob, i, false);
}
/* Only support single volume material for now. */
/* XXX We rely on the previously compiled surface shader
* to know if the material has a "volume nodetree".
*/
- bool use_volume_material = (gpumat_array[0] &&
- GPU_material_has_volume_output(gpumat_array[0]));
+ bool use_volume_material = (matcache[0].shading_gpumat &&
+ GPU_material_has_volume_output(matcache[0].shading_gpumat));
if ((ob->dt >= OB_SOLID) || DRW_state_is_image_render()) {
- /* Get per-material split surface */
- struct GPUBatch **mat_geom = NULL;
-
- if (!use_sculpt_pbvh) {
- mat_geom = DRW_cache_object_surface_material_get(ob, gpumat_array, materials_len);
- }
-
if (use_sculpt_pbvh) {
- struct DRWShadingGroup **sculpt_shgrps_array = BLI_array_alloca(sculpt_shgrps_array,
- materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].shading_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ struct DRWShadingGroup **shgrps_array = BLI_array_alloca(shgrps_array, materials_len);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].depth_clip_grp;
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
+ MATCACHE_AS_ARRAY(matcache, shading_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- for (int i = 0; i < materials_len; i++) {
- sculpt_shgrps_array[i] = shgrps_array[i].material_accum_grp[renderpass_index];
- }
- DRW_shgroup_call_sculpt_with_materials(sculpt_shgrps_array, materials_len, ob);
- }
+ MATCACHE_AS_ARRAY(matcache, depth_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
- /* TODO(fclem): Support shadows in sculpt mode. */
+ MATCACHE_AS_ARRAY(matcache, shadow_grp, materials_len, shgrps_array);
+ DRW_shgroup_call_sculpt_with_materials(shgrps_array, materials_len, ob);
}
- else if (mat_geom) {
- for (int i = 0; i < materials_len; i++) {
- if (mat_geom[i] == NULL) {
- continue;
- }
+ else {
+ struct GPUMaterial **gpumat_array = BLI_array_alloca(gpumat_array, materials_len);
+ MATCACHE_AS_ARRAY(matcache, shading_gpumat, materials_len, gpumat_array);
+ /* Get per-material split surface */
+ struct GPUBatch **mat_geom = DRW_cache_object_surface_material_get(
+ ob, gpumat_array, materials_len);
- /* Do not render surface if we are rendering a volume object
- * and do not have a surface closure. */
- if (use_volume_material &&
- (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
- continue;
- }
+ if (mat_geom) {
+ for (int i = 0; i < materials_len; i++) {
+ if (mat_geom[i] == NULL) {
+ continue;
+ }
- /* XXX TODO rewrite this to include the dupli objects.
- * This means we cannot exclude dupli objects from reflections!!! */
- EEVEE_ObjectEngineData *oedata = NULL;
- if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
- oedata = EEVEE_object_data_ensure(ob);
- oedata->ob = ob;
- oedata->test_data = &sldata->probes->vis_data;
- }
- EeveeMaterialShadingGroups *shgrps = &shgrps_array[i];
- ADD_SHGROUP_CALL(shgrps->shading_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_grp, ob, mat_geom[i], oedata);
- ADD_SHGROUP_CALL_SAFE(shgrps->depth_clip_grp, ob, mat_geom[i], oedata);
- for (int renderpass_index = 0;
- renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- ADD_SHGROUP_CALL_SAFE(
- shgrps->material_accum_grp[renderpass_index], ob, mat_geom[i], oedata);
- }
+ /* Do not render surface if we are rendering a volume object
+ * and do not have a surface closure. */
+ if (use_volume_material &&
+ (gpumat_array[i] && !GPU_material_has_surface_output(gpumat_array[i]))) {
+ continue;
+ }
+
+ /* XXX TODO rewrite this to include the dupli objects.
+ * This means we cannot exclude dupli objects from reflections!!! */
+ EEVEE_ObjectEngineData *oedata = NULL;
+ if ((ob->base_flag & BASE_FROM_DUPLI) == 0) {
+ oedata = EEVEE_object_data_ensure(ob);
+ oedata->ob = ob;
+ oedata->test_data = &sldata->probes->vis_data;
+ }
- /* Shadow Pass */
- struct GPUMaterial *gpumat;
- const bool use_gpumat = (ma_array[i]->use_nodes && ma_array[i]->nodetree);
- char blend_shadow = use_gpumat ? ma_array[i]->blend_shadow : MA_BS_SOLID;
- switch (blend_shadow) {
- case MA_BS_SOLID:
- EEVEE_shadows_caster_add(sldata, stl, mat_geom[i], ob);
- *cast_shadow = true;
- break;
- case MA_BS_CLIP:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], false, true);
- EEVEE_shadows_caster_material_add(
- sldata, psl, gpumat, mat_geom[i], ob, &ma_array[i]->alpha_threshold);
- *cast_shadow = true;
- break;
- case MA_BS_HASHED:
- gpumat = EEVEE_material_mesh_depth_get(scene, ma_array[i], true, true);
- EEVEE_shadows_caster_material_add(sldata, psl, gpumat, mat_geom[i], ob, NULL);
- *cast_shadow = true;
- break;
- case MA_BS_NONE:
- default:
- break;
+ ADD_SHGROUP_CALL(matcache[i].shading_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].depth_grp, ob, mat_geom[i], oedata);
+ ADD_SHGROUP_CALL_SAFE(matcache[i].shadow_grp, ob, mat_geom[i], oedata);
+ *cast_shadow = (matcache[i].shadow_grp != NULL);
}
}
}
@@ -2205,11 +948,12 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = ((EEVEE_Data *)vedata)->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
- BLI_ghash_free(stl->g_data->material_hash, NULL, MEM_freeN);
+ BLI_ghash_free(pd->material_hash, NULL, NULL);
- SET_FLAG_FROM_TEST(stl->effects->enabled_effects, e_data.sss_count > 0, EFFECT_SSS);
+ SET_FLAG_FROM_TEST(effects->enabled_effects, effects->sss_surface_count > 0, EFFECT_SSS);
/* TODO(fclem) this is not really clean. Init should not be done in cache finish. */
EEVEE_subsurface_draw_init(sldata, vedata);
@@ -2217,38 +961,10 @@ void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedat
void EEVEE_materials_free(void)
{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- DRW_SHADER_FREE_SAFE(e_data.default_lit[i]);
- }
- MEM_SAFE_FREE(e_data.frag_shader_lib);
- MEM_SAFE_FREE(e_data.vert_shader_str);
- MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
- MEM_SAFE_FREE(e_data.vert_background_shader_str);
- MEM_SAFE_FREE(e_data.vert_volume_shader_str);
- MEM_SAFE_FREE(e_data.geom_volume_shader_str);
- MEM_SAFE_FREE(e_data.volume_shader_lib);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_hair_prepass_clip_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_prepass_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_prepass_clip_sh);
- DRW_SHADER_FREE_SAFE(e_data.default_background);
- DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_TEXTURE_FREE_SAFE(e_data.util_tex);
DRW_TEXTURE_FREE_SAFE(e_data.noise_tex);
}
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_PassList *psl)
-{
- for (int i = 0; i < VAR_MAT_MAX; i++) {
- if (psl->default_pass[i]) {
- DRW_draw_pass(psl->default_pass[i]);
- }
- }
-
- DRW_draw_pass(psl->material_pass);
- DRW_draw_pass(psl->material_pass_cull);
-}
-
/* -------------------------------------------------------------------- */
/** \name Render Passes
@@ -2256,172 +972,140 @@ void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Pass
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata)
{
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PrivateData *g_data = stl->g_data;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
/* For diffuse and glossy we calculate the final light + color buffer where we extract the
* light from by dividing by the color buffer. When one the light is requested we also tag
* the color buffer to do the extraction. */
- if (g_data->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_DIFFUSE_COLOR;
}
- if (g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
- g_data->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ pd->render_passes |= EEVEE_RENDER_PASS_SPECULAR_COLOR;
}
+}
- /* Calculate the number of material based render passes */
- uint num_render_passes = count_bits_i(stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL);
- if ((num_render_passes != 0 && stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) ==
- 0) {
- num_render_passes += 1;
+static void material_renderpass_init(EEVEE_FramebufferList *fbl,
+ GPUTexture **output_tx,
+ const eGPUTextureFormat format,
+ const bool do_clear)
+{
+ DRW_texture_ensure_fullscreen_2d(output_tx, format, 0);
+ /* Clear texture. */
+ if (do_clear) {
+ float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* TODO(fclem) replace by GPU_texture_clear once it is fast. */
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, *output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
+ GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
+ GPU_framebuffer_bind(fbl->main_fb);
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, *output_tx);
}
- stl->g_data->render_passes_material_count = num_render_passes;
}
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples)
{
- const DRWContextState *draw_ctx = DRW_context_state_get();
EEVEE_FramebufferList *fbl = vedata->fbl;
DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_TextureList *txl = vedata->txl;
EEVEE_StorageList *stl = vedata->stl;
- EEVEE_PassList *psl = vedata->psl;
EEVEE_EffectsInfo *effects = stl->effects;
+ EEVEE_PrivateData *pd = stl->g_data;
- float clear[4] = {0.0f, 0.0f, 0.0f, 0.0f};
+ /* Should be enough precision for many samples. */
+ const eGPUTextureFormat texture_format = (tot_samples > 128) ? GPU_RGBA32F : GPU_RGBA16F;
+ const bool do_clear = DRW_state_is_image_render() || (effects->taa_current_sample == 1);
/* Create FrameBuffer. */
+ GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
+ {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- /* Should be enough precision for many samples. */
- const eGPUTextureFormat texture_format_material_accum = (tot_samples > 128) ? GPU_RGBA32F :
- GPU_RGBA16F;
- const eViewLayerEEVEEPassType render_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL;
- if (render_passes != 0) {
- GPU_framebuffer_ensure_config(&fbl->material_accum_fb,
- {GPU_ATTACHMENT_TEXTURE(dtxl->depth), GPU_ATTACHMENT_LEAVE});
- int render_pass_index = ((render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) != 0) ? 0 : 1;
- for (int bit = 0; bit < 32; bit++) {
- eViewLayerEEVEEPassType bitflag = (1 << bit);
- if ((render_passes & bitflag) != 0) {
-
- DRW_texture_ensure_fullscreen_2d(
- &txl->material_accum[render_pass_index], texture_format_material_accum, 0);
-
- /* Clear texture. */
- if (DRW_state_is_image_render() || effects->taa_current_sample == 1) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[render_pass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- GPU_framebuffer_clear_color(fbl->material_accum_fb, clear);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[render_pass_index]);
- }
- render_pass_index++;
- }
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_init(fbl, &txl->env_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_init(fbl, &txl->emit_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_init(fbl, &txl->diff_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_init(fbl, &txl->diff_light_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_init(fbl, &txl->spec_color_accum, texture_format, do_clear);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_init(fbl, &txl->spec_light_accum, texture_format, do_clear);
- if ((render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (effects->enabled_effects & EFFECT_SSR)) {
+ if (effects->enabled_effects & EFFECT_SSR) {
EEVEE_reflection_output_init(sldata, vedata, tot_samples);
}
+ }
+}
- if (render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
- Scene *scene = draw_ctx->scene;
- World *wo = scene->world;
+static void material_renderpass_accumulate(EEVEE_FramebufferList *fbl,
+ DRWPass *renderpass,
+ EEVEE_PrivateData *pd,
+ GPUTexture *output_tx,
+ struct GPUUniformBuffer *renderpass_option_ubo)
+{
+ GPU_framebuffer_texture_attach(fbl->material_accum_fb, output_tx, 0, 0);
+ GPU_framebuffer_bind(fbl->material_accum_fb);
- if (wo && wo->use_nodes && wo->nodetree) {
- struct GPUMaterial *gpumat = EEVEE_material_world_background_get(scene, wo);
- if (GPU_material_status(gpumat) == GPU_MAT_SUCCESS) {
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->material_accum_pass[0]);
- add_background_uniforms(grp, sldata, vedata);
- DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
- }
- }
- }
- }
+ pd->renderpass_ubo = renderpass_option_ubo;
+ DRW_draw_pass(renderpass);
+
+ GPU_framebuffer_texture_detach(fbl->material_accum_fb, output_tx);
}
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
{
EEVEE_FramebufferList *fbl = vedata->fbl;
EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
+ EEVEE_PrivateData *pd = vedata->stl->g_data;
+ EEVEE_EffectsInfo *effects = vedata->stl->effects;
EEVEE_TextureList *txl = vedata->txl;
if (fbl->material_accum_fb != NULL) {
- for (int renderpass_index = 0; renderpass_index < stl->g_data->render_passes_material_count;
- renderpass_index++) {
- if (txl->material_accum[renderpass_index] != NULL) {
- GPU_framebuffer_texture_attach(
- fbl->material_accum_fb, txl->material_accum[renderpass_index], 0, 0);
- GPU_framebuffer_bind(fbl->material_accum_fb);
- DRW_draw_pass(psl->material_accum_pass[renderpass_index]);
- GPU_framebuffer_bind(fbl->main_fb);
- GPU_framebuffer_texture_detach(fbl->material_accum_fb,
- txl->material_accum[renderpass_index]);
- }
+ DRWPass *material_accum_ps = psl->material_accum_ps;
+ if (pd->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT) {
+ material_renderpass_accumulate(
+ fbl, psl->background_accum_ps, pd, txl->env_accum, sldata->renderpass_ubo.combined);
}
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) &&
- (stl->effects->enabled_effects & EFFECT_SSR)) {
- EEVEE_reflection_output_accumulate(sldata, vedata);
+ if (pd->render_passes & EEVEE_RENDER_PASS_EMIT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->emit_accum, sldata->renderpass_ubo.emit);
}
- }
-}
-
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- EEVEE_StorageList *stl = vedata->stl;
-
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL) != 0);
- BLI_assert((stl->g_data->render_passes & EEVEE_RENDERPASSES_MATERIAL & renderpass_type) != 0);
-
- /* pass_index 0 is reserved for the environment pass. */
- if ((stl->g_data->render_passes & EEVEE_RENDER_PASS_ENVIRONMENT & renderpass_type) != 0) {
- return 0;
- }
-
- /* pass_index 0 is reserved for the environment pass. Other passes start from index 1 */
- int index = 1;
- eViewLayerEEVEEPassType active_material_passes = stl->g_data->render_passes &
- EEVEE_RENDERPASSES_MATERIAL &
- ~EEVEE_RENDER_PASS_ENVIRONMENT;
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_color_accum, sldata->renderpass_ubo.diff_color);
+ }
+ if (pd->render_passes & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->diff_light_accum, sldata->renderpass_ubo.diff_light);
- for (int bitshift = 0; bitshift < 32; bitshift++) {
- eViewLayerEEVEEPassType pass_flag = (1 << bitshift);
- if (pass_flag == renderpass_type) {
- break;
+ if (effects->enabled_effects & EFFECT_SSS) {
+ EEVEE_subsurface_output_accumulate(sldata, vedata);
+ }
}
- if (active_material_passes & pass_flag) {
- index++;
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_COLOR) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_color_accum, sldata->renderpass_ubo.spec_color);
}
- }
+ if (pd->render_passes & EEVEE_RENDER_PASS_SPECULAR_LIGHT) {
+ material_renderpass_accumulate(
+ fbl, material_accum_ps, pd, txl->spec_light_accum, sldata->renderpass_ubo.spec_light);
- return index;
-}
+ if (effects->enabled_effects & EFFECT_SSR) {
+ EEVEE_reflection_output_accumulate(sldata, vedata);
+ }
+ }
-/* Get the pass index that contains the color pass for the given renderpass_type. */
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type)
-{
- BLI_assert(
- ELEM(renderpass_type, EEVEE_RENDER_PASS_DIFFUSE_LIGHT, EEVEE_RENDER_PASS_SPECULAR_LIGHT));
- eViewLayerEEVEEPassType color_pass_type;
- switch (renderpass_type) {
- case EEVEE_RENDER_PASS_DIFFUSE_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_DIFFUSE_COLOR;
- break;
- case EEVEE_RENDER_PASS_SPECULAR_LIGHT:
- color_pass_type = EEVEE_RENDER_PASS_SPECULAR_COLOR;
- break;
- default:
- color_pass_type = 0;
- BLI_assert(false);
+ /* Restore default. */
+ pd->renderpass_ubo = sldata->renderpass_ubo.combined;
+ GPU_framebuffer_bind(fbl->main_fb);
}
- return EEVEE_material_output_pass_index_get(sldata, vedata, color_pass_type);
}
+
/* \} */
diff --git a/source/blender/draw/engines/eevee/eevee_mist.c b/source/blender/draw/engines/eevee/eevee_mist.c
index cdcfd64d995..7b942784ee9 100644
--- a/source/blender/draw/engines/eevee/eevee_mist.c
+++ b/source/blender/draw/engines/eevee/eevee_mist.c
@@ -114,8 +114,7 @@ void EEVEE_mist_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRWShadingGroup *grp = DRW_shgroup_create(e_data.mist_sh, psl->mist_accum_ps);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_vec3(grp, "mistSettings", &g_data->mist_start, 1);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
diff --git a/source/blender/draw/engines/eevee/eevee_occlusion.c b/source/blender/draw/engines/eevee/eevee_occlusion.c
index be4dfd07ce1..f5ebbe08dd1 100644
--- a/source/blender/draw/engines/eevee/eevee_occlusion.c
+++ b/source/blender/draw/engines/eevee/eevee_occlusion.c
@@ -170,8 +170,7 @@ void EEVEE_occlusion_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, DRW_cache_fullscreen_quad_get(), NULL);
}
else {
@@ -209,8 +208,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
DRW_PASS_CREATE(psl->ao_horizon_search_layer, DRW_STATE_WRITE_COLOR);
@@ -219,8 +217,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "maxzBuffer", &txl->maxzbuffer);
DRW_shgroup_uniform_texture_ref(grp, "depthBufferLayered", &effects->ao_src_depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "layer", &stl->effects->ao_depth_layer, 1);
DRW_shgroup_call(grp, quad, NULL);
@@ -233,8 +230,7 @@ void EEVEE_occlusion_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "normalBuffer", &effects->ssr_normal_input);
DRW_shgroup_uniform_texture_ref(grp, "horizonBuffer", &effects->gtao_horizons);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call(grp, quad, NULL);
}
}
diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h
index 264f301e52c..dbe2adef789 100644
--- a/source/blender/draw/engines/eevee/eevee_private.h
+++ b/source/blender/draw/engines/eevee/eevee_private.h
@@ -158,35 +158,34 @@ BLI_INLINE bool eevee_hdri_preview_overlay_enabled(const View3D *v3d)
(EEVEE_RENDER_PASS_EMIT | EEVEE_RENDER_PASS_DIFFUSE_COLOR | EEVEE_RENDER_PASS_DIFFUSE_LIGHT | \
EEVEE_RENDER_PASS_SPECULAR_COLOR | EEVEE_RENDER_PASS_SPECULAR_LIGHT | \
EEVEE_RENDER_PASS_ENVIRONMENT)
-#define MAX_MATERIAL_RENDER_PASSES 6
-#define MAX_MATERIAL_RENDER_PASSES_UBO 6
-/* World shader variations */
-enum {
- VAR_WORLD_BACKGROUND = 0,
- VAR_WORLD_PROBE = 1,
- VAR_WORLD_VOLUME = 2,
-};
/* Material shader variations */
enum {
VAR_MAT_MESH = (1 << 0),
- VAR_MAT_PROBE = (1 << 1),
+ VAR_MAT_VOLUME = (1 << 1),
VAR_MAT_HAIR = (1 << 2),
- VAR_MAT_BLEND = (1 << 3),
- VAR_MAT_VOLUME = (1 << 4),
+ VAR_MAT_PROBE = (1 << 3),
+ VAR_MAT_BLEND = (1 << 4),
VAR_MAT_LOOKDEV = (1 << 5),
VAR_MAT_HOLDOUT = (1 << 6),
- /* Max number of variation */
- /* IMPORTANT : Leave it last and set
- * it's value accordingly. */
- VAR_MAT_MAX = (1 << 7),
- /* These are options that are not counted in VAR_MAT_MAX
- * because they are not cumulative with the others above. */
- VAR_MAT_CLIP = (1 << 9),
- VAR_MAT_HASH = (1 << 10),
- VAR_MAT_MULT = (1 << 11),
- VAR_MAT_SHADOW = (1 << 12),
- VAR_MAT_REFRACT = (1 << 13),
+ VAR_MAT_HASH = (1 << 7),
+ VAR_MAT_DEPTH = (1 << 8),
+ VAR_MAT_REFRACT = (1 << 9),
+ VAR_WORLD_BACKGROUND = (1 << 10),
+ VAR_WORLD_PROBE = (1 << 11),
+ VAR_WORLD_VOLUME = (1 << 12),
+ VAR_DEFAULT = (1 << 13),
+};
+
+/* Material shader cache keys */
+enum {
+ /* HACK: This assumes the struct GPUShader will never be smaller than our variations.
+ * This allow us to only keep one ghash and avoid bigger keys comparissons/hashing.
+ * We combine the GPUShader pointer with the key. */
+ KEY_CULL = (1 << 0),
+ KEY_REFRACT = (1 << 1),
+ KEY_HAIR = (1 << 2),
+ KEY_SHADOW = (1 << 3),
};
/* ************ PROBE UBO ************* */
@@ -272,23 +271,26 @@ typedef struct EEVEE_PassList {
struct DRWPass *maxz_copydepth_ps;
struct DRWPass *maxz_copydepth_layer_ps;
- struct DRWPass *depth_pass;
- struct DRWPass *depth_pass_cull;
- struct DRWPass *depth_pass_clip;
- struct DRWPass *depth_pass_clip_cull;
- struct DRWPass *refract_depth_pass;
- struct DRWPass *refract_depth_pass_cull;
- struct DRWPass *refract_depth_pass_clip;
- struct DRWPass *refract_depth_pass_clip_cull;
- struct DRWPass *default_pass[VAR_MAT_MAX];
- struct DRWPass *sss_pass;
- struct DRWPass *sss_pass_cull;
- struct DRWPass *material_pass;
- struct DRWPass *material_pass_cull;
- struct DRWPass *material_accum_pass[MAX_MATERIAL_RENDER_PASSES];
- struct DRWPass *refract_pass;
+ /* Renderpass Accumulation. */
+ struct DRWPass *material_accum_ps;
+ struct DRWPass *background_accum_ps;
+
+ struct DRWPass *depth_ps;
+ struct DRWPass *depth_cull_ps;
+ struct DRWPass *depth_clip_ps;
+ struct DRWPass *depth_clip_cull_ps;
+ struct DRWPass *depth_refract_ps;
+ struct DRWPass *depth_refract_cull_ps;
+ struct DRWPass *depth_refract_clip_ps;
+ struct DRWPass *depth_refract_clip_cull_ps;
+ struct DRWPass *material_ps;
+ struct DRWPass *material_cull_ps;
+ struct DRWPass *material_refract_ps;
+ struct DRWPass *material_refract_cull_ps;
+ struct DRWPass *material_sss_ps;
+ struct DRWPass *material_sss_cull_ps;
struct DRWPass *transparent_pass;
- struct DRWPass *background_pass;
+ struct DRWPass *background_ps;
struct DRWPass *update_noise_pass;
struct DRWPass *lookdev_glossy_pass;
struct DRWPass *lookdev_diffuse_pass;
@@ -348,7 +350,12 @@ typedef struct EEVEE_TextureList {
struct GPUTexture *mist_accum;
struct GPUTexture *ao_accum;
struct GPUTexture *sss_accum;
- struct GPUTexture *material_accum[MAX_MATERIAL_RENDER_PASSES];
+ struct GPUTexture *env_accum;
+ struct GPUTexture *diff_color_accum;
+ struct GPUTexture *diff_light_accum;
+ struct GPUTexture *spec_color_accum;
+ struct GPUTexture *spec_light_accum;
+ struct GPUTexture *emit_accum;
struct GPUTexture *bloom_accum;
struct GPUTexture *ssr_accum;
struct GPUTexture *shadow_accum;
@@ -574,6 +581,7 @@ typedef struct EEVEE_EffectsInfo {
bool swap_double_buffer;
/* SSSS */
int sss_sample_count;
+ int sss_surface_count;
struct GPUTexture *sss_irradiance; /* Textures from pool */
struct GPUTexture *sss_radius;
struct GPUTexture *sss_albedo;
@@ -754,14 +762,22 @@ typedef struct EEVEE_ViewLayerData {
struct GPUUniformBuffer *planar_ubo;
/* Material Render passes */
- struct EEVEE_RenderPassData renderpass_data[MAX_MATERIAL_RENDER_PASSES_UBO];
- struct GPUUniformBuffer *renderpass_ubo[MAX_MATERIAL_RENDER_PASSES_UBO];
+ struct {
+ struct GPUUniformBuffer *combined;
+ struct GPUUniformBuffer *diff_color;
+ struct GPUUniformBuffer *diff_light;
+ struct GPUUniformBuffer *spec_color;
+ struct GPUUniformBuffer *spec_light;
+ struct GPUUniformBuffer *emit;
+ } renderpass_ubo;
/* Common Uniform Buffer */
struct EEVEE_CommonUniformBuffer common_data;
struct GPUUniformBuffer *common_ubo;
struct LightCache *fallback_lightcache;
+
+ struct BLI_memblock *material_cache;
} EEVEE_ViewLayerData;
/* ************ OBJECT DATA ************ */
@@ -809,14 +825,6 @@ typedef struct EEVEE_Data {
typedef struct EEVEE_PrivateData {
struct DRWShadingGroup *shadow_shgrp;
struct DRWShadingGroup *shadow_accum_shgrp;
- struct DRWShadingGroup *depth_shgrp;
- struct DRWShadingGroup *depth_shgrp_cull;
- struct DRWShadingGroup *depth_shgrp_clip;
- struct DRWShadingGroup *depth_shgrp_clip_cull;
- struct DRWShadingGroup *refract_depth_shgrp;
- struct DRWShadingGroup *refract_depth_shgrp_cull;
- struct DRWShadingGroup *refract_depth_shgrp_clip;
- struct DRWShadingGroup *refract_depth_shgrp_clip_cull;
struct DRWCallBuffer *planar_display_shgrp;
struct GHash *material_hash;
float background_alpha; /* TODO find a better place for this. */
@@ -862,9 +870,8 @@ typedef struct EEVEE_PrivateData {
GPUTexture *renderpass_input;
GPUTexture *renderpass_col_input;
GPUTexture *renderpass_light_input;
- /* The number of active material based render passes */
- uint render_passes_material_count;
-
+ /* Renderpass ubo reference used by material pass. */
+ struct GPUUniformBuffer *renderpass_ubo;
/** For rendering shadows. */
struct DRWView *cube_views[6];
/** For rendering probes. */
@@ -892,6 +899,7 @@ EEVEE_WorldEngineData *EEVEE_world_data_ensure(World *wo);
/* eevee_materials.c */
struct GPUTexture *EEVEE_materials_get_util_tex(void); /* XXX */
void EEVEE_materials_init(EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
EEVEE_StorageList *stl,
EEVEE_FramebufferList *fbl);
void EEVEE_materials_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -908,31 +916,20 @@ void EEVEE_object_hair_cache_populate(EEVEE_Data *vedata,
Object *ob,
bool *cast_shadow);
void EEVEE_materials_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-struct GPUMaterial *EEVEE_material_world_lightprobe_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_background_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_world_volume_get(struct Scene *scene, struct World *wo);
-struct GPUMaterial *EEVEE_material_mesh_get(
- struct Scene *scene, Material *ma, EEVEE_Data *vedata, bool use_blend, bool use_refract);
-struct GPUMaterial *EEVEE_material_mesh_volume_get(struct Scene *scene, Material *ma);
-struct GPUMaterial *EEVEE_material_mesh_depth_get(struct Scene *scene,
- Material *ma,
- bool use_hashed_alpha,
- bool is_shadow);
-struct GPUMaterial *EEVEE_material_hair_get(struct Scene *scene, Material *ma);
-struct GPUUniformBuffer *EEVEE_material_default_render_pass_ubo_get(EEVEE_ViewLayerData *sldata);
void EEVEE_materials_free(void);
-void EEVEE_materials_draw_opaque(EEVEE_ViewLayerData *sldata, EEVEE_PassList *psl);
void EEVEE_update_noise(EEVEE_PassList *psl, EEVEE_FramebufferList *fbl, const double offsets[3]);
void EEVEE_update_viewvecs(float invproj[4][4], float winmat[4][4], float (*r_viewvecs)[4]);
void EEVEE_material_renderpasses_init(EEVEE_Data *vedata);
void EEVEE_material_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata, uint tot_samples);
void EEVEE_material_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-int EEVEE_material_output_pass_index_get(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
-int EEVEE_material_output_color_pass_index_get(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- eViewLayerEEVEEPassType renderpass_type);
+void EEVEE_material_bind_resources(DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat,
+ EEVEE_ViewLayerData *sldata,
+ EEVEE_Data *vedata,
+ int *ssr_id,
+ float *refract_depth,
+ bool use_ssrefraction,
+ bool use_alpha_blend);
/* eevee_lights.c */
void eevee_light_matrix_get(const EEVEE_Light *evli, float r_mat[4][4]);
void EEVEE_lights_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
@@ -943,16 +940,6 @@ void EEVEE_lights_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void eevee_contact_shadow_setup(const Light *la, EEVEE_Shadow *evsh);
void EEVEE_shadows_init(EEVEE_ViewLayerData *sldata);
void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *sldata,
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob);
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold);
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, struct Object *ob);
void EEVEE_shadows_update(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_shadows_cube_add(EEVEE_LightsInfo *linfo, EEVEE_Light *evli, struct Object *ob);
@@ -986,6 +973,7 @@ void EEVEE_random_rotation_m4(int sample_ofs, float scale, float r_mat[4][4]);
/* eevee_shaders.c */
void EEVEE_shaders_lightprobe_shaders_init(void);
+void EEVEE_shaders_material_shaders_init(void);
struct GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_default_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_filter_diffuse_sh_get(void);
@@ -993,12 +981,22 @@ struct GPUShader *EEVEE_shaders_probe_filter_visibility_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_fill_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_downsample_sh_get(void);
struct GPUShader *EEVEE_shaders_default_studiolight_sh_get(void);
+struct GPUShader *EEVEE_shaders_default_background_sh_get(void);
struct GPUShader *EEVEE_shaders_background_studiolight_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_cube_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_grid_display_sh_get(void);
struct GPUShader *EEVEE_shaders_probe_planar_display_sh_get(void);
+struct GPUShader *EEVEE_shaders_update_noise_sh_get(void);
struct GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void);
struct GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects);
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma);
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo);
+Material *EEVEE_material_default_diffuse_get(void);
+Material *EEVEE_material_default_glossy_get(void);
+Material *EEVEE_material_default_error_get(void);
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options);
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options);
void EEVEE_shaders_free(void);
/* eevee_lightprobes.c */
@@ -1105,13 +1103,9 @@ void EEVEE_subsurface_output_init(EEVEE_ViewLayerData *sldata,
uint tot_samples);
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- struct GPUTexture *sss_tex_profile);
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat);
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
void EEVEE_subsurface_output_accumulate(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata);
diff --git a/source/blender/draw/engines/eevee/eevee_render.c b/source/blender/draw/engines/eevee/eevee_render.c
index 076738dcbdf..89a5ad2198a 100644
--- a/source/blender/draw/engines/eevee/eevee_render.c
+++ b/source/blender/draw/engines/eevee/eevee_render.c
@@ -151,7 +151,7 @@ bool EEVEE_render_init(EEVEE_Data *ved, RenderEngine *engine, struct Depsgraph *
* `EEVEE_effects_init` needs to go second for TAA. */
EEVEE_renderpasses_init(vedata);
EEVEE_effects_init(sldata, vedata, ob_camera_eval, false);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
EEVEE_shadows_init(sldata);
EEVEE_lightprobes_init(sldata, vedata);
@@ -463,7 +463,7 @@ static void eevee_render_draw_background(EEVEE_Data *vedata)
GPU_ATTACHMENT_NONE});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->background_pass);
+ DRW_draw_pass(psl->background_ps);
GPU_framebuffer_ensure_config(&fbl->main_fb,
{GPU_ATTACHMENT_LEAVE,
@@ -556,7 +556,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
EEVEE_update_noise(psl, fbl, r);
EEVEE_temporal_sampling_matrices_calc(stl->effects, r);
EEVEE_volumes_set_jitter(sldata, stl->effects->taa_current_sample - 1);
- EEVEE_materials_init(sldata, stl, fbl);
+ EEVEE_materials_init(sldata, vedata, stl, fbl);
/* Refresh Probes
* Shadows needs to be updated for correct probes */
@@ -578,8 +578,7 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
GPU_framebuffer_bind(fbl->main_fb);
GPU_framebuffer_clear_color_depth_stencil(fbl->main_fb, clear_col, clear_depth, clear_stencil);
/* Depth prepass */
- DRW_draw_pass(psl->depth_pass);
- DRW_draw_pass(psl->depth_pass_cull);
+ DRW_draw_pass(psl->depth_ps);
/* Create minmax texture */
EEVEE_create_minmax_buffer(vedata, dtxl->depth, -1);
EEVEE_occlusion_compute(sldata, vedata, dtxl->depth, -1);
@@ -587,16 +586,15 @@ void EEVEE_render_draw(EEVEE_Data *vedata, RenderEngine *engine, RenderLayer *rl
/* Shading pass */
eevee_render_draw_background(vedata);
GPU_framebuffer_bind(fbl->main_fb);
- EEVEE_materials_draw_opaque(sldata, psl);
+ DRW_draw_pass(psl->material_ps);
EEVEE_subsurface_data_render(sldata, vedata);
/* Effects pre-transparency */
EEVEE_subsurface_compute(sldata, vedata);
EEVEE_reflection_compute(sldata, vedata);
EEVEE_refraction_compute(sldata, vedata);
/* Opaque refraction */
- DRW_draw_pass(psl->refract_depth_pass);
- DRW_draw_pass(psl->refract_depth_pass_cull);
- DRW_draw_pass(psl->refract_pass);
+ DRW_draw_pass(psl->depth_refract_ps);
+ DRW_draw_pass(psl->material_refract_ps);
/* Result NORMAL */
eevee_render_result_normal(rl, viewname, rect, vedata, sldata);
/* Volumetrics Resolve Opaque */
diff --git a/source/blender/draw/engines/eevee/eevee_renderpasses.c b/source/blender/draw/engines/eevee/eevee_renderpasses.c
index 9112e14dcf5..4a1880caf7d 100644
--- a/source/blender/draw/engines/eevee/eevee_renderpasses.c
+++ b/source/blender/draw/engines/eevee/eevee_renderpasses.c
@@ -201,8 +201,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
grp, "inputSecondLightBuffer", &g_data->renderpass_light_input);
DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", &dtxl->depth);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "currentSample", &g_data->renderpass_current_sample, 1);
DRW_shgroup_uniform_int(grp, "renderpassType", &g_data->renderpass_type, 1);
DRW_shgroup_uniform_int(grp, "postProcessType", &g_data->renderpass_postprocess, 1);
@@ -225,7 +224,7 @@ void EEVEE_renderpasses_output_init(EEVEE_ViewLayerData *sldata,
* Only invoke this function for passes that need post-processing.
*
* After invoking this function the active framebuffer is set to `vedata->fbl->renderpass_fb`. */
-void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
+void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *UNUSED(sldata),
EEVEE_Data *vedata,
eViewLayerEEVEEPassType renderpass_type)
{
@@ -276,22 +275,30 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
g_data->renderpass_input = txl->shadow_accum;
break;
}
- case EEVEE_RENDER_PASS_DIFFUSE_COLOR:
- case EEVEE_RENDER_PASS_SPECULAR_COLOR:
- case EEVEE_RENDER_PASS_ENVIRONMENT:
+ case EEVEE_RENDER_PASS_DIFFUSE_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->diff_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_SPECULAR_COLOR: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->spec_color_accum;
+ break;
+ }
+ case EEVEE_RENDER_PASS_ENVIRONMENT: {
+ g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
+ g_data->renderpass_input = txl->env_accum;
+ break;
+ }
case EEVEE_RENDER_PASS_EMIT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_COLOR;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
+ g_data->renderpass_input = txl->emit_accum;
break;
}
case EEVEE_RENDER_PASS_SPECULAR_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->spec_light_accum;
+ g_data->renderpass_col_input = txl->spec_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSR) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->ssr_accum;
@@ -303,11 +310,8 @@ void EEVEE_renderpasses_postprocess(EEVEE_ViewLayerData *sldata,
}
case EEVEE_RENDER_PASS_DIFFUSE_LIGHT: {
g_data->renderpass_postprocess = PASS_POST_ACCUMULATED_LIGHT;
- int renderpass_index = EEVEE_material_output_pass_index_get(sldata, vedata, renderpass_type);
- int renderpass_index_color = EEVEE_material_output_color_pass_index_get(
- sldata, vedata, renderpass_type);
- g_data->renderpass_input = txl->material_accum[renderpass_index];
- g_data->renderpass_col_input = txl->material_accum[renderpass_index_color];
+ g_data->renderpass_input = txl->diff_light_accum;
+ g_data->renderpass_col_input = txl->diff_color_accum;
if ((stl->effects->enabled_effects & EFFECT_SSS) != 0) {
g_data->renderpass_postprocess = PASS_POST_TWO_LIGHT_BUFFERS;
g_data->renderpass_light_input = txl->sss_accum;
@@ -343,10 +347,6 @@ void EEVEE_renderpasses_output_accumulate(EEVEE_ViewLayerData *sldata,
if ((render_pass & EEVEE_RENDER_PASS_MIST) != 0) {
EEVEE_mist_output_accumulate(sldata, vedata);
}
- if ((render_pass & EEVEE_RENDER_PASS_DIFFUSE_LIGHT) != 0 &&
- (effects->enabled_effects & EFFECT_SSS) != 0) {
- EEVEE_subsurface_output_accumulate(sldata, vedata);
- }
if ((render_pass & EEVEE_RENDER_PASS_AO) != 0) {
EEVEE_occlusion_output_accumulate(sldata, vedata);
}
diff --git a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
index 2e467fe8535..cece67334c5 100644
--- a/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
+++ b/source/blender/draw/engines/eevee/eevee_screen_raytrace.c
@@ -237,8 +237,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (!effects->reflection_trace_full) {
DRW_shgroup_uniform_ivec2(grp, "halfresOffset", effects->ssr_halfres_ofs, 1);
}
@@ -259,8 +258,7 @@ void EEVEE_screen_raytrace_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *v
DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_int(grp, "neighborOffset", &effects->ssr_neighbor_ofs, 1);
if ((effects->enabled_effects & EFFECT_GTAO) != 0) {
DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
diff --git a/source/blender/draw/engines/eevee/eevee_shaders.c b/source/blender/draw/engines/eevee/eevee_shaders.c
index 50b7c5c5f97..4d25f62a317 100644
--- a/source/blender/draw/engines/eevee/eevee_shaders.c
+++ b/source/blender/draw/engines/eevee/eevee_shaders.c
@@ -22,12 +22,20 @@
#include "DRW_render.h"
+#include "BKE_lib_id.h"
+#include "BKE_node.h"
+
+#include "BLI_dynstr.h"
#include "BLI_string_utils.h"
#include "MEM_guardedalloc.h"
+#include "GPU_material.h"
#include "GPU_shader.h"
+#include "NOD_shader.h"
+
+#include "eevee_engine.h"
#include "eevee_private.h"
static const char *filter_defines = "#define HAMMERSLEY_SIZE " STRINGIFY(HAMMERSLEY_SIZE) "\n"
@@ -61,6 +69,38 @@ static struct {
struct GPUShader *taa_resolve_sh;
struct GPUShader *taa_resolve_reproject_sh;
+ /* General purpose Shaders. */
+ struct GPUShader *default_background;
+ struct GPUShader *update_noise_sh;
+
+ /* Shader strings */
+ char *frag_shader_lib;
+ char *vert_shader_str;
+ char *vert_shadow_shader_str;
+ char *vert_background_shader_str;
+ char *vert_volume_shader_str;
+ char *geom_volume_shader_str;
+ char *volume_shader_lib;
+
+ /* LookDev Materials */
+ Material *glossy_mat;
+ Material *diffuse_mat;
+
+ Material *error_mat;
+
+ /* Default Material */
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ bNodeSocketValueFloat *metallic_socket;
+ bNodeSocketValueFloat *roughness_socket;
+ bNodeSocketValueFloat *specular_socket;
+ } surface;
+
+ struct {
+ bNodeTree *ntree;
+ bNodeSocketValueRGBA *color_socket;
+ } world;
} e_data = {NULL}; /* Engine data */
extern char datatoc_bsdf_common_lib_glsl[];
@@ -68,27 +108,42 @@ extern char datatoc_bsdf_sampling_lib_glsl[];
extern char datatoc_common_uniforms_lib_glsl[];
extern char datatoc_common_view_lib_glsl[];
+extern char datatoc_ambient_occlusion_lib_glsl[];
extern char datatoc_background_vert_glsl[];
+extern char datatoc_common_hair_lib_glsl[];
+extern char datatoc_cubemap_lib_glsl[];
extern char datatoc_default_world_frag_glsl[];
-extern char datatoc_lightprobe_geom_glsl[];
-extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_irradiance_lib_glsl[];
extern char datatoc_lightprobe_cube_display_frag_glsl[];
extern char datatoc_lightprobe_cube_display_vert_glsl[];
extern char datatoc_lightprobe_filter_diffuse_frag_glsl[];
extern char datatoc_lightprobe_filter_glossy_frag_glsl[];
extern char datatoc_lightprobe_filter_visibility_frag_glsl[];
+extern char datatoc_lightprobe_geom_glsl[];
extern char datatoc_lightprobe_grid_display_frag_glsl[];
extern char datatoc_lightprobe_grid_display_vert_glsl[];
extern char datatoc_lightprobe_grid_fill_frag_glsl[];
+extern char datatoc_lightprobe_lib_glsl[];
extern char datatoc_lightprobe_planar_display_frag_glsl[];
extern char datatoc_lightprobe_planar_display_vert_glsl[];
extern char datatoc_lightprobe_planar_downsample_frag_glsl[];
extern char datatoc_lightprobe_planar_downsample_geom_glsl[];
extern char datatoc_lightprobe_planar_downsample_vert_glsl[];
-extern char datatoc_irradiance_lib_glsl[];
-extern char datatoc_lightprobe_lib_glsl[];
+extern char datatoc_lightprobe_vert_glsl[];
+extern char datatoc_lights_lib_glsl[];
+extern char datatoc_lit_surface_frag_glsl[];
+extern char datatoc_lit_surface_vert_glsl[];
+extern char datatoc_ltc_lib_glsl[];
extern char datatoc_octahedron_lib_glsl[];
-extern char datatoc_cubemap_lib_glsl[];
+extern char datatoc_prepass_frag_glsl[];
+extern char datatoc_raytrace_lib_glsl[];
+extern char datatoc_shadow_vert_glsl[];
+extern char datatoc_ssr_lib_glsl[];
+extern char datatoc_update_noise_frag_glsl[];
+extern char datatoc_volumetric_frag_glsl[];
+extern char datatoc_volumetric_geom_glsl[];
+extern char datatoc_volumetric_lib_glsl[];
+extern char datatoc_volumetric_vert_glsl[];
/* Velocity Resolve */
extern char datatoc_effect_velocity_resolve_frag_glsl[];
@@ -150,6 +205,64 @@ void EEVEE_shaders_lightprobe_shaders_init(void)
NULL);
}
+void EEVEE_shaders_material_shaders_init(void)
+{
+ e_data.frag_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_bsdf_sampling_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_raytrace_lib_glsl,
+ datatoc_ssr_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ /* Add one for each Closure */
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_lit_surface_frag_glsl,
+ datatoc_volumetric_lib_glsl);
+
+ e_data.volume_shader_lib = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_common_uniforms_lib_glsl,
+ datatoc_bsdf_common_lib_glsl,
+ datatoc_ambient_occlusion_lib_glsl,
+ datatoc_octahedron_lib_glsl,
+ datatoc_cubemap_lib_glsl,
+ datatoc_irradiance_lib_glsl,
+ datatoc_lightprobe_lib_glsl,
+ datatoc_ltc_lib_glsl,
+ datatoc_lights_lib_glsl,
+ datatoc_volumetric_lib_glsl,
+ datatoc_volumetric_frag_glsl);
+
+ e_data.vert_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_lit_surface_vert_glsl);
+
+ e_data.vert_shadow_shader_str = BLI_string_joinN(
+ datatoc_common_view_lib_glsl, datatoc_common_hair_lib_glsl, datatoc_shadow_vert_glsl);
+
+ e_data.vert_background_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_background_vert_glsl);
+
+ e_data.vert_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_vert_glsl);
+
+ e_data.geom_volume_shader_str = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_volumetric_geom_glsl);
+}
+
GPUShader *EEVEE_shaders_probe_filter_glossy_sh_get(void)
{
return e_data.probe_filter_glossy_sh;
@@ -292,6 +405,26 @@ GPUShader *EEVEE_shaders_velocity_resolve_sh_get(void)
return e_data.velocity_resolve_sh;
}
+GPUShader *EEVEE_shaders_default_background_sh_get(void)
+{
+ if (e_data.default_background == NULL) {
+ e_data.default_background = DRW_shader_create_with_lib(datatoc_background_vert_glsl,
+ NULL,
+ datatoc_default_world_frag_glsl,
+ datatoc_common_view_lib_glsl,
+ NULL);
+ }
+ return e_data.default_background;
+}
+
+GPUShader *EEVEE_shaders_update_noise_sh_get(void)
+{
+ if (e_data.update_noise_sh == NULL) {
+ e_data.update_noise_sh = DRW_shader_create_fullscreen(datatoc_update_noise_frag_glsl, NULL);
+ }
+ return e_data.update_noise_sh;
+}
+
GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
{
GPUShader **sh;
@@ -316,8 +449,330 @@ GPUShader *EEVEE_shaders_taa_resolve_sh_get(EEVEE_EffectsFlag enabled_effects)
return *sh;
}
+Material *EEVEE_material_default_diffuse_get(void)
+{
+ if (!e_data.diffuse_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default diffuse");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_DIFFUSE);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 0.8f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.diffuse_mat = ma;
+ }
+ return e_data.diffuse_mat;
+}
+
+Material *EEVEE_material_default_glossy_get(void)
+{
+ if (!e_data.glossy_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_GLOSSY);
+ bNodeSocket *base_color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl(((bNodeSocketValueRGBA *)base_color->default_value)->value, 1.0f);
+ bNodeSocket *roughness = nodeFindSocket(bsdf, SOCK_IN, "Roughness");
+ ((bNodeSocketValueFloat *)roughness->default_value)->value = 0.0f;
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "BSDF"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.glossy_mat = ma;
+ }
+ return e_data.glossy_mat;
+}
+
+Material *EEVEE_material_default_error_get(void)
+{
+ if (!e_data.error_mat) {
+ Material *ma = BKE_id_new_nomain(ID_MA, "EEVEEE default metal");
+
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ ma->nodetree = ntree;
+ ma->use_nodes = true;
+
+ /* Use emission and output material to be compatible with both World and Material. */
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_EMISSION);
+ bNodeSocket *color = nodeFindSocket(bsdf, SOCK_IN, "Color");
+ copy_v3_fl3(((bNodeSocketValueRGBA *)color->default_value)->value, 1.0f, 0.0f, 1.0f);
+
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+
+ nodeAddLink(ntree,
+ bsdf,
+ nodeFindSocket(bsdf, SOCK_OUT, "Emission"),
+ output,
+ nodeFindSocket(output, SOCK_IN, "Surface"));
+
+ nodeSetActive(ntree, output);
+ e_data.error_mat = ma;
+ }
+ return e_data.error_mat;
+}
+
+/* Configure a default nodetree with the given material. */
+struct bNodeTree *EEVEE_shader_default_surface_nodetree(Material *ma)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.surface.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bsdf = nodeAddStaticNode(NULL, ntree, SH_NODE_BSDF_PRINCIPLED);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_MATERIAL);
+ bNodeSocket *bsdf_out = nodeFindSocket(bsdf, SOCK_OUT, "BSDF");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bsdf, bsdf_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.surface.color_socket = nodeFindSocket(bsdf, SOCK_IN, "Base Color")->default_value;
+ e_data.surface.metallic_socket = nodeFindSocket(bsdf, SOCK_IN, "Metallic")->default_value;
+ e_data.surface.roughness_socket = nodeFindSocket(bsdf, SOCK_IN, "Roughness")->default_value;
+ e_data.surface.specular_socket = nodeFindSocket(bsdf, SOCK_IN, "Specular")->default_value;
+ e_data.surface.ntree = ntree;
+ }
+ /* Update */
+ copy_v3_fl3(e_data.surface.color_socket->value, ma->r, ma->g, ma->b);
+ e_data.surface.metallic_socket->value = ma->metallic;
+ e_data.surface.roughness_socket->value = ma->roughness;
+ e_data.surface.specular_socket->value = ma->spec;
+
+ return e_data.surface.ntree;
+}
+
+/* Configure a default nodetree with the given world. */
+struct bNodeTree *EEVEE_shader_default_world_nodetree(World *wo)
+{
+ /* WARNING: This function is not threadsafe. Which is not a problem for the moment. */
+ if (!e_data.world.ntree) {
+ bNodeTree *ntree = ntreeAddTree(NULL, "Shader Nodetree", ntreeType_Shader->idname);
+ bNode *bg = nodeAddStaticNode(NULL, ntree, SH_NODE_BACKGROUND);
+ bNode *output = nodeAddStaticNode(NULL, ntree, SH_NODE_OUTPUT_WORLD);
+ bNodeSocket *bg_out = nodeFindSocket(bg, SOCK_OUT, "Background");
+ bNodeSocket *output_in = nodeFindSocket(output, SOCK_IN, "Surface");
+ nodeAddLink(ntree, bg, bg_out, output, output_in);
+ nodeSetActive(ntree, output);
+
+ e_data.world.color_socket = nodeFindSocket(bg, SOCK_IN, "Color")->default_value;
+ e_data.world.ntree = ntree;
+ }
+
+ copy_v3_fl3(e_data.world.color_socket->value, wo->horr, wo->horg, wo->horb);
+
+ return e_data.world.ntree;
+}
+
+static char *eevee_get_defines(int options)
+{
+ char *str = NULL;
+
+ DynStr *ds = BLI_dynstr_new();
+ BLI_dynstr_append(ds, SHADER_DEFINES);
+
+ if ((options & VAR_WORLD_BACKGROUND) != 0) {
+ BLI_dynstr_append(ds, "#define WORLD_BACKGROUND\n");
+ }
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ BLI_dynstr_append(ds, "#define VOLUMETRICS\n");
+ }
+ if ((options & VAR_MAT_MESH) != 0) {
+ BLI_dynstr_append(ds, "#define MESH_SHADER\n");
+ }
+ if ((options & VAR_MAT_DEPTH) != 0) {
+ BLI_dynstr_append(ds, "#define DEPTH_SHADER\n");
+ }
+ if ((options & VAR_MAT_HAIR) != 0) {
+ BLI_dynstr_append(ds, "#define HAIR_SHADER\n");
+ }
+ if ((options & (VAR_MAT_PROBE | VAR_WORLD_PROBE)) != 0) {
+ BLI_dynstr_append(ds, "#define PROBE_CAPTURE\n");
+ }
+ if ((options & VAR_MAT_HASH) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_HASH\n");
+ }
+ if ((options & VAR_MAT_BLEND) != 0) {
+ BLI_dynstr_append(ds, "#define USE_ALPHA_BLEND\n");
+ }
+ if ((options & VAR_MAT_REFRACT) != 0) {
+ BLI_dynstr_append(ds, "#define USE_REFRACTION\n");
+ }
+ if ((options & VAR_MAT_LOOKDEV) != 0) {
+ BLI_dynstr_append(ds, "#define LOOKDEV\n");
+ }
+ if ((options & VAR_MAT_HOLDOUT) != 0) {
+ BLI_dynstr_append(ds, "#define HOLDOUT\n");
+ }
+
+ str = BLI_dynstr_get_cstring(ds);
+ BLI_dynstr_free(ds);
+
+ return str;
+}
+
+static char *eevee_get_vert(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.vert_volume_shader_str);
+ }
+ else if ((options & (VAR_WORLD_PROBE | VAR_WORLD_BACKGROUND)) != 0) {
+ str = BLI_strdup(e_data.vert_background_shader_str);
+ }
+ else {
+ str = BLI_strdup(e_data.vert_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_geom(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.geom_volume_shader_str);
+ }
+
+ return str;
+}
+
+static char *eevee_get_frag(int options)
+{
+ char *str = NULL;
+
+ if ((options & VAR_MAT_VOLUME) != 0) {
+ str = BLI_strdup(e_data.volume_shader_lib);
+ }
+ else if ((options & VAR_MAT_DEPTH) != 0) {
+ str = BLI_string_joinN(e_data.frag_shader_lib, datatoc_prepass_frag_glsl);
+ }
+ else {
+ str = BLI_strdup(e_data.frag_shader_lib);
+ }
+
+ return str;
+}
+
+static struct GPUMaterial *eevee_material_get_ex(
+ struct Scene *scene, Material *ma, World *wo, int options, bool deferred)
+{
+ BLI_assert(ma || wo);
+ const bool is_volume = (options & VAR_MAT_VOLUME) != 0;
+ const bool is_default = (options & VAR_DEFAULT) != 0;
+ const void *engine = &DRW_engine_viewport_eevee_type;
+
+ GPUMaterial *mat = NULL;
+
+ if (ma) {
+ mat = DRW_shader_find_from_material(ma, engine, options, deferred);
+ }
+ else {
+ mat = DRW_shader_find_from_world(wo, engine, options, deferred);
+ }
+
+ if (mat) {
+ return mat;
+ }
+
+ char *defines = eevee_get_defines(options);
+ char *vert = eevee_get_vert(options);
+ char *geom = eevee_get_geom(options);
+ char *frag = eevee_get_frag(options);
+
+ if (ma) {
+ bNodeTree *ntree = !is_default ? ma->nodetree : EEVEE_shader_default_surface_nodetree(ma);
+ mat = DRW_shader_create_from_material(
+ scene, ma, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+ else {
+ bNodeTree *ntree = !is_default ? wo->nodetree : EEVEE_shader_default_world_nodetree(wo);
+ mat = DRW_shader_create_from_world(
+ scene, wo, ntree, engine, options, is_volume, vert, geom, frag, defines, deferred);
+ }
+
+ MEM_SAFE_FREE(defines);
+ MEM_SAFE_FREE(vert);
+ MEM_SAFE_FREE(geom);
+ MEM_SAFE_FREE(frag);
+
+ return mat;
+}
+
+/* Note: Compilation is not deferred. */
+struct GPUMaterial *EEVEE_material_default_get(struct Scene *scene, Material *ma, int options)
+{
+ Material *def_ma = (ma && (options & VAR_MAT_VOLUME)) ? BKE_material_default_volume() :
+ BKE_material_default_surface();
+ BLI_assert(def_ma->use_nodes && def_ma->nodetree);
+
+ return eevee_material_get_ex(scene, def_ma, NULL, options, false);
+}
+
+struct GPUMaterial *EEVEE_material_get(
+ EEVEE_Data *vedata, struct Scene *scene, Material *ma, World *wo, int options)
+{
+ if ((ma && (!ma->use_nodes || !ma->nodetree)) || (wo && (!wo->use_nodes || !wo->nodetree))) {
+ options |= VAR_DEFAULT;
+ }
+
+ /* Meh, implicit option. World probe cannot be deferred because they need
+ * to be rendered immediatly. */
+ const bool deferred = (options & VAR_WORLD_PROBE) == 0;
+
+ GPUMaterial *mat = eevee_material_get_ex(scene, ma, wo, options, deferred);
+
+ int status = GPU_material_status(mat);
+ switch (status) {
+ case GPU_MAT_SUCCESS:
+ break;
+ case GPU_MAT_QUEUED:
+ vedata->stl->g_data->queued_shaders_count++;
+ mat = EEVEE_material_default_get(scene, ma, options);
+ break;
+ case GPU_MAT_FAILED:
+ default:
+ ma = EEVEE_material_default_error_get();
+ mat = eevee_material_get_ex(scene, ma, NULL, options, false);
+ break;
+ }
+ /* Returned material should be ready to be drawn. */
+ BLI_assert(GPU_material_status(mat) == GPU_MAT_SUCCESS);
+ return mat;
+}
+
void EEVEE_shaders_free(void)
{
+ MEM_SAFE_FREE(e_data.frag_shader_lib);
+ MEM_SAFE_FREE(e_data.vert_shader_str);
+ MEM_SAFE_FREE(e_data.vert_shadow_shader_str);
+ MEM_SAFE_FREE(e_data.vert_background_shader_str);
+ MEM_SAFE_FREE(e_data.vert_volume_shader_str);
+ MEM_SAFE_FREE(e_data.geom_volume_shader_str);
+ MEM_SAFE_FREE(e_data.volume_shader_lib);
+ DRW_SHADER_FREE_SAFE(e_data.default_background);
+ DRW_SHADER_FREE_SAFE(e_data.update_noise_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_default_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_glossy_sh);
DRW_SHADER_FREE_SAFE(e_data.probe_filter_diffuse_sh);
@@ -332,4 +787,27 @@ void EEVEE_shaders_free(void)
DRW_SHADER_FREE_SAFE(e_data.velocity_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_sh);
DRW_SHADER_FREE_SAFE(e_data.taa_resolve_reproject_sh);
+
+ if (e_data.glossy_mat) {
+ BKE_id_free(NULL, e_data.glossy_mat);
+ e_data.glossy_mat = NULL;
+ }
+ if (e_data.diffuse_mat) {
+ BKE_id_free(NULL, e_data.diffuse_mat);
+ e_data.diffuse_mat = NULL;
+ }
+ if (e_data.error_mat) {
+ BKE_id_free(NULL, e_data.error_mat);
+ e_data.error_mat = NULL;
+ }
+ if (e_data.surface.ntree) {
+ ntreeFreeEmbeddedTree(e_data.surface.ntree);
+ MEM_freeN(e_data.surface.ntree);
+ e_data.surface.ntree = NULL;
+ }
+ if (e_data.world.ntree) {
+ ntreeFreeEmbeddedTree(e_data.world.ntree);
+ MEM_freeN(e_data.world.ntree);
+ e_data.world.ntree = NULL;
+ }
}
diff --git a/source/blender/draw/engines/eevee/eevee_shadows.c b/source/blender/draw/engines/eevee/eevee_shadows.c
index fb338d85fde..84c50a22ae6 100644
--- a/source/blender/draw/engines/eevee/eevee_shadows.c
+++ b/source/blender/draw/engines/eevee/eevee_shadows.c
@@ -159,47 +159,6 @@ void EEVEE_shadows_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
}
}
-/* Add a shadow caster to the shadowpasses */
-void EEVEE_shadows_caster_add(EEVEE_ViewLayerData *UNUSED(sldata),
- EEVEE_StorageList *stl,
- struct GPUBatch *geom,
- Object *ob)
-{
- DRW_shgroup_call(stl->g_data->shadow_shgrp, geom, ob);
-}
-
-void EEVEE_shadows_caster_material_add(EEVEE_ViewLayerData *sldata,
- EEVEE_PassList *psl,
- struct GPUMaterial *gpumat,
- struct GPUBatch *geom,
- struct Object *ob,
- const float *alpha_threshold)
-{
- /* TODO / PERF : reuse the same shading group for objects with the same material */
- DRWShadingGroup *grp = DRW_shgroup_material_create(gpumat, psl->shadow_pass);
-
- if (grp == NULL) {
- return;
- }
-
- /* Unfortunately needed for correctness but not 99% of the time not needed.
- * TODO detect when needed? */
- DRW_shgroup_uniform_block(grp, "probe_block", sldata->probe_ubo);
- DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
-
- if (alpha_threshold != NULL) {
- DRW_shgroup_uniform_float(grp, "alphaThreshold", alpha_threshold, 1);
- }
-
- DRW_shgroup_call(grp, geom, ob);
-}
-
/* Make that object update shadow casting lights inside its influence bounding box. */
void EEVEE_shadows_caster_register(EEVEE_ViewLayerData *sldata, Object *ob)
{
@@ -470,8 +429,7 @@ void EEVEE_shadow_output_init(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_texture_ref(grp, "shadowCubeTexture", &sldata->shadow_cube_pool);
DRW_shgroup_uniform_texture_ref(grp, "shadowCascadeTexture", &sldata->shadow_cascade_pool);
diff --git a/source/blender/draw/engines/eevee/eevee_subsurface.c b/source/blender/draw/engines/eevee/eevee_subsurface.c
index 4f334812a8e..7674148f76a 100644
--- a/source/blender/draw/engines/eevee/eevee_subsurface.c
+++ b/source/blender/draw/engines/eevee/eevee_subsurface.c
@@ -29,7 +29,9 @@
#include "DEG_depsgraph_query.h"
#include "GPU_extensions.h"
+#include "GPU_material.h"
#include "GPU_texture.h"
+
#include "eevee_private.h"
static struct {
@@ -83,6 +85,7 @@ void EEVEE_subsurface_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
const Scene *scene_eval = DEG_get_evaluated_scene(draw_ctx->depsgraph);
effects->sss_sample_count = 1 + scene_eval->eevee.sss_samples * 2;
+ effects->sss_surface_count = 0;
common_data->sss_jitter_threshold = scene_eval->eevee.sss_jitter_threshold;
}
@@ -221,70 +224,77 @@ void EEVEE_subsurface_cache_init(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data
void EEVEE_subsurface_add_pass(EEVEE_ViewLayerData *sldata,
EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile)
+ Material *ma,
+ DRWShadingGroup *shgrp,
+ struct GPUMaterial *gpumat)
{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
EEVEE_PassList *psl = vedata->psl;
EEVEE_StorageList *stl = vedata->stl;
EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
+ DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-
- grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
- DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
-}
+ struct GPUTexture *sss_tex_profile = NULL;
+ struct GPUUniformBuffer *sss_profile = GPU_material_sss_profile_get(
+ gpumat, stl->effects->sss_sample_count, &sss_tex_profile);
-void EEVEE_subsurface_translucency_add_pass(EEVEE_ViewLayerData *sldata,
- EEVEE_Data *vedata,
- uint sss_id,
- struct GPUUniformBuffer *sss_profile,
- GPUTexture *sss_tex_profile)
-{
- DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
- EEVEE_PassList *psl = vedata->psl;
- EEVEE_StorageList *stl = vedata->stl;
- EEVEE_EffectsInfo *effects = stl->effects;
- struct GPUBatch *quad = DRW_cache_fullscreen_quad_get();
- GPUTexture **depth_src = GPU_depth_blitting_workaround() ? &effects->sss_stencil : &dtxl->depth;
+ if (!sss_profile) {
+ BLI_assert(0 && "SSS pass requested but no SSS data was found");
+ return;
+ }
+
+ /* Limit of 8 bit stencil buffer. ID 255 is refraction. */
+ if (effects->sss_surface_count >= 254) {
+ /* TODO : display message. */
+ printf("Error: Too many different Subsurface shader in the scene.\n");
+ return;
+ }
+
+ int sss_id = ++(effects->sss_surface_count);
+ /* Make main pass output stencil mask. */
+ DRW_shgroup_stencil_mask(shgrp, sss_id);
+
+ {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[0], psl->sss_blur_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_irradiance);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+
+ grp = DRW_shgroup_create(e_data.sss_sh[1], psl->sss_resolve_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssIrradiance", &effects->sss_blur);
+ DRW_shgroup_uniform_texture_ref(grp, "sssAlbedo", &effects->sss_albedo);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
- DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
- DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
- DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
- DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
- DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
- DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
- DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
- DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
- DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
- DRW_shgroup_stencil_mask(grp, sss_id);
- DRW_shgroup_call(grp, quad, NULL);
+ if (ma->blend_flag & MA_BL_TRANSLUCENCY) {
+ DRWShadingGroup *grp = DRW_shgroup_create(e_data.sss_sh[2], psl->sss_translucency_ps);
+ DRW_shgroup_uniform_texture(grp, "utilTex", EEVEE_materials_get_util_tex());
+ DRW_shgroup_uniform_texture(grp, "sssTexProfile", sss_tex_profile);
+ DRW_shgroup_uniform_texture_ref(grp, "depthBuffer", depth_src);
+ DRW_shgroup_uniform_texture_ref(grp, "sssRadius", &effects->sss_radius);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCubes", &sldata->shadow_cube_pool);
+ DRW_shgroup_uniform_texture_ref(grp, "sssShadowCascades", &sldata->shadow_cascade_pool);
+ DRW_shgroup_uniform_block(grp, "sssProfile", sss_profile);
+ DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
+ DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
+ DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
+ DRW_shgroup_stencil_mask(grp, sss_id);
+ DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
+ }
}
void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Data *vedata)
@@ -310,8 +320,7 @@ void EEVEE_subsurface_data_render(EEVEE_ViewLayerData *UNUSED(sldata), EEVEE_Dat
GPU_ATTACHMENT_TEXTURE(effects->sss_albedo)});
GPU_framebuffer_bind(fbl->main_fb);
- DRW_draw_pass(psl->sss_pass);
- DRW_draw_pass(psl->sss_pass_cull);
+ DRW_draw_pass(psl->material_sss_ps);
/* Restore */
GPU_framebuffer_ensure_config(&fbl->main_fb,
@@ -350,23 +359,15 @@ void EEVEE_subsurface_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
if (!DRW_pass_is_empty(psl->sss_translucency_ps)) {
/* We sample the shadow-maps using normal sampler. We need to disable Comparison mode.
* TODO(fclem) avoid this by using sampler objects.*/
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, false);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, false);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
GPU_framebuffer_bind(fbl->sss_translucency_fb);
DRW_draw_pass(psl->sss_translucency_ps);
/* Reset original state. */
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
}
/* 1. horizontal pass */
diff --git a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
index b70d872c4af..d57048f2c4e 100644
--- a/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
+++ b/source/blender/draw/engines/eevee/eevee_temporal_sampling.c
@@ -292,8 +292,7 @@ void EEVEE_temporal_sampling_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data
DRW_shgroup_uniform_texture_ref(grp, "colorHistoryBuffer", &txl->taa_history);
DRW_shgroup_uniform_texture_ref(grp, "colorBuffer", &effects->source_buffer);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
if (effects->enabled_effects & EFFECT_TAA_REPROJECT) {
// DefaultTextureList *dtxl = DRW_viewport_texture_list_get();
diff --git a/source/blender/draw/engines/eevee/eevee_volumes.c b/source/blender/draw/engines/eevee/eevee_volumes.c
index 83bd4fcf8d2..90860e94270 100644
--- a/source/blender/draw/engines/eevee/eevee_volumes.c
+++ b/source/blender/draw/engines/eevee/eevee_volumes.c
@@ -355,7 +355,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
struct World *wo = scene->world;
if (wo != NULL && wo->use_nodes && wo->nodetree &&
!LOOK_DEV_STUDIO_LIGHT_ENABLED(draw_ctx->v3d)) {
- struct GPUMaterial *mat = EEVEE_material_world_volume_get(scene, wo);
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, NULL, wo, VAR_MAT_VOLUME);
if (GPU_material_has_volume_output(mat)) {
grp = DRW_shgroup_material_create(mat, psl->volumetric_world_ps);
@@ -369,8 +369,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "planar_block", sldata->planar_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
/* Fix principle volumetric not working with world materials. */
ListBase gpu_grids = GPU_material_volume_grids(mat);
@@ -388,8 +387,7 @@ void EEVEE_volumes_cache_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* If no world or volume material is present just clear the buffer with this drawcall */
grp = DRW_shgroup_create(e_data.volumetric_clear_sh, psl->volumetric_world_ps);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
}
@@ -590,12 +588,10 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
return;
}
- struct GPUMaterial *mat = EEVEE_material_mesh_volume_get(scene, ma);
+ int mat_options = VAR_MAT_VOLUME | VAR_MAT_MESH;
+ struct GPUMaterial *mat = EEVEE_material_get(vedata, scene, ma, NULL, mat_options);
eGPUMaterialStatus status = GPU_material_status(mat);
- if (status == GPU_MAT_QUEUED) {
- vedata->stl->g_data->queued_shaders_count++;
- }
/* If shader failed to compile or is currently compiling. */
if (status != GPU_MAT_SUCCESS) {
return;
@@ -609,8 +605,7 @@ void EEVEE_volumes_cache_object_add(EEVEE_ViewLayerData *sldata,
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "grid_block", sldata->grid_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
@@ -661,8 +656,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_block(grp, "light_block", sldata->light_ubo);
DRW_shgroup_uniform_block(grp, "shadow_block", sldata->shadow_ubo);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, common_data->vol_tex_size[2]);
@@ -671,8 +665,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "volumeScattering", &txl->volume_scatter);
DRW_shgroup_uniform_texture_ref(grp, "volumeExtinction", &txl->volume_transmit);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(
grp, NULL, USE_VOLUME_OPTI ? 1 : common_data->vol_tex_size[2]);
@@ -683,8 +676,7 @@ void EEVEE_volumes_cache_finish(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
}
@@ -775,12 +767,8 @@ void EEVEE_volumes_compute(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata)
/* We sample the shadow-maps using shadow sampler. We need to enable Comparison mode.
* TODO(fclem) avoid this by using sampler objects.*/
- GPU_texture_bind(sldata->shadow_cube_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cube_pool, true);
- GPU_texture_unbind(sldata->shadow_cube_pool);
- GPU_texture_bind(sldata->shadow_cascade_pool, 0);
GPU_texture_compare_mode(sldata->shadow_cascade_pool, true);
- GPU_texture_unbind(sldata->shadow_cascade_pool);
GPU_framebuffer_bind(fbl->volumetric_fb);
DRW_draw_pass(psl->volumetric_world_ps);
@@ -920,8 +908,7 @@ void EEVEE_volumes_output_init(EEVEE_ViewLayerData *sldata, EEVEE_Data *vedata,
DRW_shgroup_uniform_texture_ref(grp, "inTransmittance", &txl->volume_transmit);
DRW_shgroup_uniform_texture_ref(grp, "inSceneDepth", &e_data.depth_src);
DRW_shgroup_uniform_block(grp, "common_block", sldata->common_ubo);
- DRW_shgroup_uniform_block(
- grp, "renderpass_block", EEVEE_material_default_render_pass_ubo_get(sldata));
+ DRW_shgroup_uniform_block(grp, "renderpass_block", sldata->renderpass_ubo.combined);
}
else {
/* There is no volumetrics in the scene. Use a shader to fill the accum textures with a default
diff --git a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
index 8662c0ecb6a..57b16418696 100644
--- a/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/ambient_occlusion_lib.glsl
@@ -6,13 +6,9 @@
#if defined(MESH_SHADER)
# if !defined(USE_ALPHA_HASH)
-# if !defined(USE_ALPHA_CLIP)
-# if !defined(SHADOW_SHADER)
-# if !defined(USE_MULTIPLY)
-# if !defined(USE_ALPHA_BLEND)
-# define ENABLE_DEFERED_AO
-# endif
-# endif
+# if !defined(DEPTH_SHADER)
+# if !defined(USE_ALPHA_BLEND)
+# define ENABLE_DEFERED_AO
# endif
# endif
# endif
diff --git a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
index c3518198805..402d306df45 100644
--- a/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
+++ b/source/blender/draw/engines/eevee/shaders/bsdf_common_lib.glsl
@@ -928,7 +928,7 @@ Closure closure_emission(vec3 rgb)
/* Breaking this across multiple lines causes issues for some older GLSL compilers. */
/* clang-format off */
-# if defined(MESH_SHADER) && !defined(USE_ALPHA_HASH) && !defined(USE_ALPHA_CLIP) && !defined(SHADOW_SHADER)
+# if defined(MESH_SHADER) && !defined(DEPTH_SHADER)
/* clang-format on */
# ifndef USE_ALPHA_BLEND
layout(location = 0) out vec4 outRadiance;
@@ -1001,6 +1001,10 @@ void main()
outRadiance.rgb += cl.sss_irradiance.rgb * cl.sss_albedo.rgb * fac;
# endif
+# ifdef LOOKDEV
+ gl_FragDepth = 0.0;
+# endif
+
# ifndef USE_ALPHA_BLEND
float alpha_div = 1.0 / max(1e-8, alpha);
outRadiance.rgb *= alpha_div;
@@ -1011,6 +1015,6 @@ void main()
# endif
}
-# endif /* MESH_SHADER && !SHADOW_SHADER */
+# endif /* MESH_SHADER */
#endif /* VOLUMETRICS */
diff --git a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
index 5277bfa32bb..d56890769a7 100644
--- a/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/effect_dof_frag.glsl
@@ -1,6 +1,4 @@
-uniform mat4 ProjectionMatrix;
-
uniform sampler2D colorBuffer;
uniform sampler2D depthBuffer;
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
index 8c2619650b9..bc7879763c3 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_frag.glsl
@@ -177,7 +177,7 @@ void CLOSURE_NAME(vec3 N
out_refr = vec3(0.0);
#endif
-#if defined(SHADOW_SHADER) || defined(WORLD_BACKGROUND)
+#if defined(DEPTH_SHADER) || defined(WORLD_BACKGROUND)
/* This makes shader resources become unused and avoid issues with samplers. (see T59747) */
return;
#else
diff --git a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
index cf20b3ff5b9..1b94fc2bee1 100644
--- a/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
+++ b/source/blender/draw/engines/eevee/shaders/lit_surface_vert.glsl
@@ -4,11 +4,12 @@ in vec3 pos;
in vec3 nor;
#endif
+#ifdef MESH_SHADER
out vec3 worldPosition;
out vec3 viewPosition;
-
out vec3 worldNormal;
out vec3 viewNormal;
+#endif
#ifdef HAIR_SHADER
out vec3 hairTangent;
@@ -41,22 +42,28 @@ void main()
hairThickness,
hairThickTime);
worldNormal = cross(hairTangent, binor);
- worldPosition = pos;
+ vec3 world_pos = pos;
#else
- worldPosition = point_object_to_world(pos);
- worldNormal = normalize(normal_object_to_world(nor));
+ vec3 world_pos = point_object_to_world(pos);
#endif
- /* No need to normalize since this is just a rotation. */
- viewNormal = normal_world_to_view(worldNormal);
+ gl_Position = point_world_to_ndc(world_pos);
+ /* Used for planar reflections */
+ gl_ClipDistance[0] = dot(vec4(world_pos, 1.0), clipPlanes[0]);
+
+#ifdef MESH_SHADER
+ worldPosition = world_pos;
viewPosition = point_world_to_view(worldPosition);
- gl_Position = point_world_to_ndc(worldPosition);
- /* Used for planar reflections */
- gl_ClipDistance[0] = dot(vec4(worldPosition, 1.0), clipPlanes[0]);
+# ifndef HAIR_SHADER
+ worldNormal = normalize(normal_object_to_world(nor));
+# endif
-#ifdef USE_ATTR
+ /* No need to normalize since this is just a rotation. */
+ viewNormal = normal_world_to_view(worldNormal);
+# ifdef USE_ATTR
pass_attr(pos);
+# endif
#endif
}
diff --git a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
index b49dbfceba2..9acd8f998f6 100644
--- a/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
+++ b/source/blender/draw/engines/eevee/shaders/prepass_frag.glsl
@@ -45,26 +45,22 @@ float hashed_alpha_threshold(vec3 co)
/* Find our final, uniformly distributed alpha threshold. */
float threshold = (x < one_a) ? ((x < a) ? cases.x : cases.y) : cases.z;
+ /* Jitter the threshold for TAA accumulation. */
+ threshold = fract(threshold + alphaHashOffset);
+
/* Avoids threshold == 0. */
threshold = clamp(threshold, 1.0e-6, 1.0);
- /* Jitter the threshold for TAA accumulation. */
- return fract(threshold + alphaHashOffset);
+ return threshold;
}
#endif
-#ifdef USE_ALPHA_CLIP
-uniform float alphaThreshold;
-#endif
+#define NODETREE_EXEC
void main()
{
- /* For now do nothing.
- * In the future, output object motion blur. */
-
-#if defined(USE_ALPHA_HASH) || defined(USE_ALPHA_CLIP)
-# define NODETREE_EXEC
+#if defined(USE_ALPHA_HASH)
Closure cl = nodetree_exec();
@@ -75,11 +71,6 @@ void main()
if (opacity < hashed_alpha_threshold(worldPosition)) {
discard;
}
-# elif defined(USE_ALPHA_CLIP)
- /* Alpha clip */
- if (opacity <= alphaThreshold) {
- discard;
- }
# endif
#endif
}
diff --git a/source/blender/draw/engines/external/external_engine.c b/source/blender/draw/engines/external/external_engine.c
index 6e636e4dc93..2f448b784ed 100644
--- a/source/blender/draw/engines/external/external_engine.c
+++ b/source/blender/draw/engines/external/external_engine.c
@@ -44,6 +44,11 @@
#define EXTERNAL_ENGINE "BLENDER_EXTERNAL"
+extern char datatoc_depth_frag_glsl[];
+extern char datatoc_depth_vert_glsl[];
+
+extern char datatoc_common_view_lib_glsl[];
+
/* *********** LISTS *********** */
/* GPUViewport.storage
@@ -106,7 +111,16 @@ static void external_engine_init(void *vedata)
/* Depth prepass */
if (!e_data.depth_sh) {
- e_data.depth_sh = DRW_shader_create_3d_depth_only(GPU_SHADER_CFG_DEFAULT);
+ const GPUShaderConfigData *sh_cfg = &GPU_shader_cfg_data[GPU_SHADER_CFG_DEFAULT];
+
+ e_data.depth_sh = GPU_shader_create_from_arrays({
+ .vert = (const char *[]){sh_cfg->lib,
+ datatoc_common_view_lib_glsl,
+ datatoc_depth_vert_glsl,
+ NULL},
+ .frag = (const char *[]){datatoc_depth_frag_glsl, NULL},
+ .defs = (const char *[]){sh_cfg->def, NULL},
+ });
}
if (!stl->g_data) {
@@ -277,7 +291,7 @@ static void external_draw_scene(void *vedata)
static void external_engine_free(void)
{
- /* All shaders are builtin. */
+ DRW_SHADER_FREE_SAFE(e_data.depth_sh);
}
static const DrawEngineDataSize external_data_size = DRW_VIEWPORT_DATA_SIZE(EXTERNAL_Data);
diff --git a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
index 4dd5e3b2da1..8955240c549 100644
--- a/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
+++ b/source/blender/draw/engines/gpencil/gpencil_antialiasing.c
@@ -78,13 +78,8 @@ void GPENCIL_antialiasing_init(struct GPENCIL_Data *vedata)
false,
NULL);
- GPU_texture_bind(txl->smaa_search_tx, 0);
GPU_texture_filter_mode(txl->smaa_search_tx, true);
- GPU_texture_unbind(txl->smaa_search_tx);
-
- GPU_texture_bind(txl->smaa_area_tx, 0);
GPU_texture_filter_mode(txl->smaa_area_tx, true);
- GPU_texture_unbind(txl->smaa_area_tx);
}
{
diff --git a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
index 1344b649dff..2b811f1d52e 100644
--- a/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
+++ b/source/blender/draw/engines/gpencil/gpencil_cache_utils.c
@@ -381,7 +381,7 @@ GPENCIL_tLayer *gpencil_layer_cache_add(GPENCIL_PrivateData *pd,
struct GPUShader *sh = GPENCIL_shader_geometry_get();
DRWShadingGroup *grp = tgp_layer->base_shgrp = DRW_shgroup_create(sh, tgp_layer->geom_ps);
- DRW_shgroup_uniform_texture_persistent(grp, "gpSceneDepthTexture", depth_tex);
+ DRW_shgroup_uniform_texture(grp, "gpSceneDepthTexture", depth_tex);
DRW_shgroup_uniform_texture_ref(grp, "gpMaskTexture", mask_tex);
DRW_shgroup_uniform_vec3_copy(grp, "gpNormal", tgp_ob->plane_normal);
DRW_shgroup_uniform_bool_copy(grp, "strokeOrder3d", tgp_ob->is_drawmode3d);
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index 4f586a1e9f3..495de7ef10b 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -91,6 +91,7 @@ void GPENCIL_engine_init(void *ved)
stl->pd->gp_object_pool = vldata->gp_object_pool;
stl->pd->gp_layer_pool = vldata->gp_layer_pool;
stl->pd->gp_vfx_pool = vldata->gp_vfx_pool;
+ stl->pd->view_layer = ctx->view_layer;
stl->pd->scene = ctx->scene;
stl->pd->v3d = ctx->v3d;
stl->pd->last_light_pool = NULL;
@@ -468,7 +469,7 @@ static void gpencil_layer_cache_populate(bGPDlayer *gpl,
/* Iterator dependent uniforms. */
DRWShadingGroup *grp = iter->grp = tgp_layer->base_shgrp;
- DRW_shgroup_uniform_block_persistent(grp, "gpLightBlock", iter->ubo_lights);
+ DRW_shgroup_uniform_block(grp, "gpLightBlock", iter->ubo_lights);
DRW_shgroup_uniform_block(grp, "gpMaterialBlock", iter->ubo_mat);
DRW_shgroup_uniform_texture(grp, "gpFillTexture", iter->tex_fill);
DRW_shgroup_uniform_texture(grp, "gpStrokeTexture", iter->tex_stroke);
@@ -598,6 +599,7 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
GPENCIL_Data *vedata = (GPENCIL_Data *)ved;
GPENCIL_PrivateData *pd = vedata->stl->pd;
GPENCIL_TextureList *txl = vedata->txl;
+ const bool is_final_render = DRW_state_is_image_render();
/* object must be visible */
if (!(DRW_object_visibility_in_active_context(ob) & OB_VISIBLE_SELF)) {
@@ -617,7 +619,8 @@ void GPENCIL_cache_populate(void *ved, Object *ob)
bGPdata *gpd = (bGPdata *)ob->data;
bool do_onion = (!pd->is_render) ? pd->do_onion : (gpd->onion_flag & GP_ONION_GHOST_ALWAYS);
- BKE_gpencil_visible_stroke_iter(ob,
+ BKE_gpencil_visible_stroke_iter(is_final_render ? pd->view_layer : NULL,
+ ob,
gpencil_layer_cache_populate,
gpencil_stroke_cache_populate,
&iter,
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index f765dcf73de..cedd75af813 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -307,6 +307,8 @@ typedef struct GPENCIL_PrivateData {
float dof_params[2];
/* Used for DoF Setup. */
Object *camera;
+ /* Copy of draw_ctx->view_layer for convenience. */
+ struct ViewLayer *view_layer;
/* Copy of draw_ctx->scene for convenience. */
struct Scene *scene;
/* Copy of draw_ctx->vie3d for convenience. */
diff --git a/source/blender/draw/engines/overlay/overlay_armature.c b/source/blender/draw/engines/overlay/overlay_armature.c
index a538b7ffd5f..95fd918f8c1 100644
--- a/source/blender/draw/engines/overlay/overlay_armature.c
+++ b/source/blender/draw/engines/overlay/overlay_armature.c
@@ -184,7 +184,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->point_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_point_get());
@@ -196,7 +196,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_shape(false);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->custom_solid = grp;
cb->box_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_box_get());
@@ -212,29 +212,29 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_sphere(true);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->point_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_point_wire_outline_get());
sh = OVERLAY_shader_armature_shape(true);
cb->custom_outline = grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->box_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_box_wire_get());
cb->octa_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_octahedral_wire_get());
sh = OVERLAY_shader_armature_shape_wire();
cb->custom_wire = grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
format = formats->instance_extra;
sh = OVERLAY_shader_armature_degrees_of_freedom();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_lines = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_lines_get());
grp = DRW_shgroup_create(sh, armature_transp_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->dof_sphere = BUF_INSTANCE(grp, format, DRW_cache_bone_dof_sphere_get());
}
{
@@ -242,7 +242,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_stick();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->stick = BUF_INSTANCE(grp, format, DRW_cache_bone_stick_get());
}
{
@@ -251,7 +251,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_ps);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_BACK);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", false);
DRW_shgroup_uniform_float_copy(grp, "alpha", 1.0f);
cb->envelope_solid = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -266,14 +266,14 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_envelope(true);
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->envelope_outline = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_outline_get());
format = formats->instance_bone_envelope_distance;
sh = OVERLAY_shader_armature_envelope(false);
grp = DRW_shgroup_create(sh, armature_transp_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isDistance", true);
DRW_shgroup_state_enable(grp, DRW_STATE_CULL_FRONT);
cb->envelope_distance = BUF_INSTANCE(grp, format, DRW_cache_bone_envelope_solid_get());
@@ -283,7 +283,7 @@ void OVERLAY_armature_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_armature_wire();
grp = DRW_shgroup_create(sh, armature_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->wire = BUF_LINE(grp, format);
}
}
diff --git a/source/blender/draw/engines/overlay/overlay_extra.c b/source/blender/draw/engines/overlay/overlay_extra.c
index 71efc6b8d03..859f3f93b1d 100644
--- a/source/blender/draw/engines/overlay/overlay_extra.c
+++ b/source/blender/draw/engines/overlay/overlay_extra.c
@@ -81,8 +81,8 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
struct GPUTexture *tex = DRW_state_is_fbo() ? dtxl->depth : txl->dummy_depth_tx;
pd->extra_grid_grp = grp = DRW_shgroup_create(sh, psl->extra_grid_ps);
- DRW_shgroup_uniform_texture_persistent(grp, "depthBuffer", tex);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "depthBuffer", tex);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_bool_copy(grp, "isTransform", (G.moving & G_TRANSFORM_OBJ) != 0);
}
@@ -112,7 +112,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra(is_select);
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
cb->camera_distances = BUF_INSTANCE(grp_sub, format, DRW_cache_camera_distances_get());
@@ -157,7 +157,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
{
format = formats->instance_extra;
grp = DRW_shgroup_create(sh, psl->extra_blend_ps); /* NOTE: not the same pass! */
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
DRW_shgroup_state_enable(grp_sub, DRW_STATE_DEPTH_LESS_EQUAL | DRW_STATE_CULL_BACK);
@@ -174,7 +174,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_groundline();
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_state_enable(grp, DRW_STATE_BLEND_ALPHA);
cb->groundline = BUF_INSTANCE(grp, format, DRW_cache_groundline_get());
@@ -183,7 +183,7 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_wire(false, is_select);
grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
cb->extra_dashed_lines = BUF_LINE(grp, formats->pos_color);
cb->extra_lines = BUF_LINE(grp, formats->wire_extra);
@@ -192,20 +192,20 @@ void OVERLAY_extra_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_extra_wire(true, is_select);
cb->extra_wire = grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
sh = OVERLAY_shader_extra_loose_point();
cb->extra_loose_points = grp = DRW_shgroup_create(sh, extra_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
{
format = formats->pos;
sh = OVERLAY_shader_extra_point();
grp = DRW_shgroup_create(sh, psl->extra_centers_ps); /* NOTE: not the same pass! */
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
grp_sub = DRW_shgroup_create_sub(grp);
DRW_shgroup_uniform_vec4_copy(grp_sub, "color", G_draw.block.colorActive);
@@ -1371,9 +1371,9 @@ static void OVERLAY_volume_extra(OVERLAY_ExtraCallBuffers *cb,
madd_v3fl_v3fl_v3fl_v3i(min, mds->p0, mds->cell_size, mds->res_min);
float voxel_cubemat[4][4] = {{0.0f}};
/* scale small cube to voxel size */
- voxel_cubemat[0][0] = 1.0f / (float)mds->base_res[0];
- voxel_cubemat[1][1] = 1.0f / (float)mds->base_res[1];
- voxel_cubemat[2][2] = 1.0f / (float)mds->base_res[2];
+ voxel_cubemat[0][0] = mds->cell_size[0] / 2.0f;
+ voxel_cubemat[1][1] = mds->cell_size[1] / 2.0f;
+ voxel_cubemat[2][2] = mds->cell_size[2] / 2.0f;
voxel_cubemat[3][3] = 1.0f;
/* translate small cube to corner */
copy_v3_v3(voxel_cubemat[3], min);
diff --git a/source/blender/draw/engines/overlay/overlay_facing.c b/source/blender/draw/engines/overlay/overlay_facing.c
index 9216ae61b3e..4eb4b8ae85b 100644
--- a/source/blender/draw/engines/overlay/overlay_facing.c
+++ b/source/blender/draw/engines/overlay/overlay_facing.c
@@ -41,7 +41,7 @@ void OVERLAY_facing_cache_init(OVERLAY_Data *vedata)
GPUShader *sh = OVERLAY_shader_facing();
pd->facing_grp[i] = DRW_shgroup_create(sh, psl->facing_ps[i]);
- DRW_shgroup_uniform_block_persistent(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(pd->facing_grp[i], "globalsBlock", G_draw.block_ubo);
}
if (!pd->use_in_front) {
diff --git a/source/blender/draw/engines/overlay/overlay_gpencil.c b/source/blender/draw/engines/overlay/overlay_gpencil.c
index 1397ef7b4b2..ccc914e0422 100644
--- a/source/blender/draw/engines/overlay/overlay_gpencil.c
+++ b/source/blender/draw/engines/overlay/overlay_gpencil.c
@@ -361,7 +361,7 @@ static void OVERLAY_gpencil_color_names(Object *ob)
int cfra = DEG_get_ctime(draw_ctx->depsgraph);
BKE_gpencil_visible_stroke_iter(
- ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
+ NULL, ob, NULL, overlay_gpencil_draw_stroke_color_name, ob, false, cfra);
}
void OVERLAY_gpencil_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_motion_path.c b/source/blender/draw/engines/overlay/overlay_motion_path.c
index 531e1faf715..168f6f8a17f 100644
--- a/source/blender/draw/engines/overlay/overlay_motion_path.c
+++ b/source/blender/draw/engines/overlay/overlay_motion_path.c
@@ -49,11 +49,11 @@ void OVERLAY_motion_path_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_motion_path_line();
pd->motion_path_lines_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
sh = OVERLAY_shader_motion_path_vert();
pd->motion_path_points_grp = grp = DRW_shgroup_create(sh, psl->motion_paths_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
/* Just convert the CPU cache to GPU cache. */
diff --git a/source/blender/draw/engines/overlay/overlay_outline.c b/source/blender/draw/engines/overlay/overlay_outline.c
index 142421f58d8..99d22fc380f 100644
--- a/source/blender/draw/engines/overlay/overlay_outline.c
+++ b/source/blender/draw/engines/overlay/overlay_outline.c
@@ -259,7 +259,7 @@ static void OVERLAY_outline_gpencil(OVERLAY_PrivateData *pd, Object *ob)
}
BKE_gpencil_visible_stroke_iter(
- ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
+ NULL, ob, gp_layer_cache_populate, gp_stroke_cache_populate, &iter, false, pd->cfra);
}
void OVERLAY_outline_cache_populate(OVERLAY_Data *vedata,
diff --git a/source/blender/draw/engines/overlay/overlay_particle.c b/source/blender/draw/engines/overlay/overlay_particle.c
index 98bc62ae66a..b891bb4ce4c 100644
--- a/source/blender/draw/engines/overlay/overlay_particle.c
+++ b/source/blender/draw/engines/overlay/overlay_particle.c
@@ -152,13 +152,13 @@ void OVERLAY_particle_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_particle_dot();
pd->particle_dots_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp);
sh = OVERLAY_shader_particle_shape();
pd->particle_shapes_grp = grp = DRW_shgroup_create(sh, psl->particle_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "weightTex", G_draw.ramp);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_texture(grp, "weightTex", G_draw.ramp);
}
void OVERLAY_particle_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_pointcloud.c b/source/blender/draw/engines/overlay/overlay_pointcloud.c
index a0de7aac1f1..b2a2d44bf73 100644
--- a/source/blender/draw/engines/overlay/overlay_pointcloud.c
+++ b/source/blender/draw/engines/overlay/overlay_pointcloud.c
@@ -46,7 +46,7 @@ void OVERLAY_pointcloud_cache_init(OVERLAY_Data *vedata)
sh = OVERLAY_shader_pointcloud_dot();
pd->pointcloud_dots_grp = grp = DRW_shgroup_create(sh, psl->pointcloud_ps);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
}
void OVERLAY_pointcloud_cache_populate(OVERLAY_Data *vedata, Object *ob)
diff --git a/source/blender/draw/engines/overlay/overlay_wireframe.c b/source/blender/draw/engines/overlay/overlay_wireframe.c
index cb36f0ed326..eebfc88fdce 100644
--- a/source/blender/draw/engines/overlay/overlay_wireframe.c
+++ b/source/blender/draw/engines/overlay/overlay_wireframe.c
@@ -91,7 +91,7 @@ void OVERLAY_wireframe_cache_init(OVERLAY_Data *vedata)
for (int use_coloring = 0; use_coloring < 2; use_coloring++) {
pd->wires_grp[xray][use_coloring] = grp = DRW_shgroup_create(wires_sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "globalsBlock", G_draw.block_ubo);
+ DRW_shgroup_uniform_block(grp, "globalsBlock", G_draw.block_ubo);
DRW_shgroup_uniform_texture_ref(grp, "depthTex", depth_tx);
DRW_shgroup_uniform_float_copy(grp, "wireStepParam", pd->shdata.wire_step_param);
DRW_shgroup_uniform_bool_copy(grp, "useColoring", use_coloring);
@@ -197,13 +197,15 @@ void OVERLAY_wireframe_cache_populate(OVERLAY_Data *vedata,
struct GPUBatch *geom = NULL;
switch (ob->type) {
case OB_CURVE:
- if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
+ if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
+ BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
break;
}
geom = DRW_cache_curve_edge_wire_get(ob);
break;
case OB_FONT:
- if (ob->runtime.curve_cache && BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
+ if (!pd->wireframe_mode && !use_wire && ob->runtime.curve_cache &&
+ BKE_displist_has_faces(&ob->runtime.curve_cache->disp)) {
break;
}
geom = DRW_cache_text_loose_edges_get(ob);
diff --git a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
index 0efcfb35929..51007a9f246 100644
--- a/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
+++ b/source/blender/draw/engines/workbench/shaders/workbench_effect_dof_frag.glsl
@@ -4,7 +4,6 @@
* Converted and adapted from HLSL to GLSL by Clément Foucault
*/
-uniform mat4 ProjectionMatrix;
uniform vec2 invertedViewportSize;
uniform vec2 nearFar;
uniform vec3 dofParams;
diff --git a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
index cb8eb7d1e92..0e896c4b7bb 100644
--- a/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
+++ b/source/blender/draw/engines/workbench/workbench_effect_antialiasing.c
@@ -266,13 +266,8 @@ void workbench_antialiasing_engine_init(WORKBENCH_Data *vedata)
false,
NULL);
- GPU_texture_bind(txl->smaa_search_tx, 0);
GPU_texture_filter_mode(txl->smaa_search_tx, true);
- GPU_texture_unbind(txl->smaa_search_tx);
-
- GPU_texture_bind(txl->smaa_area_tx, 0);
GPU_texture_filter_mode(txl->smaa_area_tx, true);
- GPU_texture_unbind(txl->smaa_area_tx);
}
}
else {
diff --git a/source/blender/draw/engines/workbench/workbench_materials.c b/source/blender/draw/engines/workbench/workbench_materials.c
index 0b7d313342b..b36a4a3a494 100644
--- a/source/blender/draw/engines/workbench/workbench_materials.c
+++ b/source/blender/draw/engines/workbench/workbench_materials.c
@@ -284,11 +284,11 @@ DRWShadingGroup *workbench_image_setup_ex(WORKBENCH_PrivateData *wpd,
*grp_tex = grp = DRW_shgroup_create_sub(grp);
if (tex_tile_data) {
- DRW_shgroup_uniform_texture_persistent(grp, "imageTileArray", tex);
- DRW_shgroup_uniform_texture_persistent(grp, "imageTileData", tex_tile_data);
+ DRW_shgroup_uniform_texture(grp, "imageTileArray", tex);
+ DRW_shgroup_uniform_texture(grp, "imageTileData", tex_tile_data);
}
else {
- DRW_shgroup_uniform_texture_persistent(grp, "imageTexture", tex);
+ DRW_shgroup_uniform_texture(grp, "imageTexture", tex);
}
DRW_shgroup_uniform_bool_copy(grp, "imagePremult", (ima && ima->alpha_mode == IMA_ALPHA_PREMUL));
DRW_shgroup_uniform_bool_copy(grp, "imageNearest", (interp == SHD_INTERP_CLOSEST));
diff --git a/source/blender/draw/engines/workbench/workbench_opaque.c b/source/blender/draw/engines/workbench/workbench_opaque.c
index c9c43e785ca..27d5b71f35c 100644
--- a/source/blender/draw/engines/workbench/workbench_opaque.c
+++ b/source/blender/draw/engines/workbench/workbench_opaque.c
@@ -95,21 +95,21 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
wpd->prepass[opaque][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
sh = workbench_shader_opaque_image_get(wpd, hair, false);
wpd->prepass[opaque][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
sh = workbench_shader_opaque_image_get(wpd, hair, true);
wpd->prepass[opaque][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
DRW_shgroup_uniform_bool_copy(grp, "useMatcap", use_matcap);
}
@@ -123,9 +123,9 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
sh = workbench_shader_composite_get(wpd);
grp = DRW_shgroup_create(sh, psl->composite_ps);
- DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
- DRW_shgroup_uniform_texture_persistent(grp, "materialBuffer", wpd->material_buffer_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "normalBuffer", wpd->normal_buffer_tx);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_texture(grp, "materialBuffer", wpd->material_buffer_tx);
+ DRW_shgroup_uniform_texture(grp, "normalBuffer", wpd->normal_buffer_tx);
DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
DRW_shgroup_stencil_mask(grp, 0x00);
@@ -137,8 +137,8 @@ void workbench_opaque_cache_init(WORKBENCH_Data *data)
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx;
- DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx);
}
DRW_shgroup_call_procedural_triangles(grp, NULL, 1);
diff --git a/source/blender/draw/engines/workbench/workbench_shader.c b/source/blender/draw/engines/workbench/workbench_shader.c
index 2e796056029..99366779b22 100644
--- a/source/blender/draw/engines/workbench/workbench_shader.c
+++ b/source/blender/draw/engines/workbench/workbench_shader.c
@@ -23,6 +23,7 @@
#include "DRW_render.h"
#include "BLI_dynstr.h"
+#include "BLI_string_utils.h"
#include "workbench_engine.h"
#include "workbench_private.h"
@@ -359,32 +360,24 @@ void workbench_shader_depth_of_field_get(GPUShader **prepare_sh,
GPUShader **resolve_sh)
{
if (e_data.dof_prepare_sh == NULL) {
- e_data.dof_prepare_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define PREPARE\n");
-
- e_data.dof_downsample_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define DOWNSAMPLE\n");
+ char *frag = BLI_string_joinN(datatoc_common_view_lib_glsl,
+ datatoc_workbench_effect_dof_frag_glsl);
+ e_data.dof_prepare_sh = DRW_shader_create_fullscreen(frag, "#define PREPARE\n");
+ e_data.dof_downsample_sh = DRW_shader_create_fullscreen(frag, "#define DOWNSAMPLE\n");
#if 0 /* TODO(fclem) finish COC min_max optimization */
- e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_flatten_v_sh = DRW_shader_create_fullscreen(frag,
"#define FLATTEN_VERTICAL\n");
-
- e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_flatten_h_sh = DRW_shader_create_fullscreen(frag,
"#define FLATTEN_HORIZONTAL\n");
-
- e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_dilate_v_sh = DRW_shader_create_fullscreen(frag,
"#define DILATE_VERTICAL\n");
-
- e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
+ e_data.dof_dilate_h_sh = DRW_shader_create_fullscreen(frag,
"#define DILATE_HORIZONTAL\n");
#endif
- e_data.dof_blur1_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define BLUR1\n");
-
- e_data.dof_blur2_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define BLUR2\n");
-
- e_data.dof_resolve_sh = DRW_shader_create_fullscreen(datatoc_workbench_effect_dof_frag_glsl,
- "#define RESOLVE\n");
+ e_data.dof_blur1_sh = DRW_shader_create_fullscreen(frag, "#define BLUR1\n");
+ e_data.dof_blur2_sh = DRW_shader_create_fullscreen(frag, "#define BLUR2\n");
+ e_data.dof_resolve_sh = DRW_shader_create_fullscreen(frag, "#define RESOLVE\n");
+ MEM_freeN(frag);
}
*prepare_sh = e_data.dof_prepare_sh;
diff --git a/source/blender/draw/engines/workbench/workbench_transparent.c b/source/blender/draw/engines/workbench/workbench_transparent.c
index 39aa721a41c..5fd8229304a 100644
--- a/source/blender/draw/engines/workbench/workbench_transparent.c
+++ b/source/blender/draw/engines/workbench/workbench_transparent.c
@@ -67,7 +67,7 @@ void workbench_transparent_engine_init(WORKBENCH_Data *data)
static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
DRWShadingGroup *grp)
{
- DRW_shgroup_uniform_block_persistent(grp, "world_block", wpd->world_ubo);
+ DRW_shgroup_uniform_block(grp, "world_block", wpd->world_ubo);
DRW_shgroup_uniform_bool_copy(grp, "forceShadowing", false);
if (STUDIOLIGHT_TYPE_MATCAP_ENABLED(wpd)) {
@@ -78,8 +78,8 @@ static void workbench_transparent_lighting_uniforms(WORKBENCH_PrivateData *wpd,
struct GPUTexture *spec_tx = wpd->studio_light->matcap_specular.gputexture;
const bool use_spec = workbench_is_specular_highlight_enabled(wpd);
spec_tx = (use_spec && spec_tx) ? spec_tx : diff_tx;
- DRW_shgroup_uniform_texture_persistent(grp, "matcapDiffuseImage", diff_tx);
- DRW_shgroup_uniform_texture_persistent(grp, "matcapSpecularImage", spec_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapDiffuseImage", diff_tx);
+ DRW_shgroup_uniform_texture(grp, "matcapSpecularImage", spec_tx);
}
}
@@ -116,20 +116,20 @@ void workbench_transparent_cache_init(WORKBENCH_Data *data)
workbench_transparent_lighting_uniforms(wpd, grp);
wpd->prepass[transp][infront][hair].vcol_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. (uses vcol) */
sh = workbench_shader_transparent_image_get(wpd, hair, false);
wpd->prepass[transp][infront][hair].image_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
workbench_transparent_lighting_uniforms(wpd, grp);
sh = workbench_shader_transparent_image_get(wpd, hair, true);
wpd->prepass[transp][infront][hair].image_tiled_shgrp = grp = DRW_shgroup_create(sh, pass);
- DRW_shgroup_uniform_block_persistent(grp, "material_block", wpd->material_ubo_curr);
+ DRW_shgroup_uniform_block(grp, "material_block", wpd->material_ubo_curr);
DRW_shgroup_uniform_int_copy(grp, "materialIndex", 0); /* Default material. */
workbench_transparent_lighting_uniforms(wpd, grp);
}
diff --git a/source/blender/draw/intern/DRW_render.h b/source/blender/draw/intern/DRW_render.h
index d3585b02b7d..b002f68e4d2 100644
--- a/source/blender/draw/intern/DRW_render.h
+++ b/source/blender/draw/intern/DRW_render.h
@@ -221,10 +221,7 @@ struct GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
const eGPUShaderTFBType prim_type,
const char **varying_names,
const int varying_count);
-struct GPUShader *DRW_shader_create_2d(const char *frag, const char *defines);
-struct GPUShader *DRW_shader_create_3d(const char *frag, const char *defines);
struct GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines);
-struct GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig slot);
struct GPUMaterial *DRW_shader_find_from_world(struct World *wo,
const void *engine_type,
const int options,
@@ -235,6 +232,7 @@ struct GPUMaterial *DRW_shader_find_from_material(struct Material *ma,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
struct World *wo,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -245,6 +243,7 @@ struct GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
bool deferred);
struct GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
struct Material *ma,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -376,6 +375,8 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
DRWPass *pass,
struct GPUVertBuf *tf_target);
+void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material);
+
/* return final visibility */
typedef bool(DRWCallVisibilityFn)(bool vis_in, void *user_data);
@@ -471,18 +472,15 @@ void DRW_shgroup_clear_framebuffer(DRWShadingGroup *shgroup,
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup,
const char *name,
const struct GPUTexture *tex);
-void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUTexture *tex);
-void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuffer *ubo);
-void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const struct GPUUniformBuffer *ubo);
void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup,
const char *name,
struct GPUTexture **tex);
+void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
+ const char *name,
+ const struct GPUUniformBuffer *ubo);
+void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
+ const char *name,
+ struct GPUUniformBuffer **ubo);
void DRW_shgroup_uniform_float(DRWShadingGroup *shgroup,
const char *name,
const float *value,
@@ -541,6 +539,8 @@ bool DRW_shgroup_is_empty(DRWShadingGroup *shgroup);
/* Passes */
DRWPass *DRW_pass_create(const char *name, DRWState state);
+DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state);
+void DRW_pass_link(DRWPass *first, DRWPass *second);
/* TODO Replace with passes inheritance. */
void DRW_pass_state_set(DRWPass *pass, DRWState state);
void DRW_pass_state_add(DRWPass *pass, DRWState state);
@@ -554,6 +554,8 @@ void DRW_pass_sort_shgroup_reverse(DRWPass *pass);
bool DRW_pass_is_empty(DRWPass *pass);
#define DRW_PASS_CREATE(pass, state) (pass = DRW_pass_create(#pass, state))
+#define DRW_PASS_INSTANCE_CREATE(pass, original, state) \
+ (pass = DRW_pass_create_instance(#pass, (original), state))
/* Views */
DRWView *DRW_view_create(const float viewmat[4][4],
@@ -707,6 +709,8 @@ typedef struct DRWContextState {
struct Depsgraph *depsgraph;
+ struct TaskGraph *task_graph;
+
eObjectMode object_mode;
eGPUShaderConfig sh_cfg;
diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c
index 23d0d74534d..c23ea3d7c82 100644
--- a/source/blender/draw/intern/draw_cache.c
+++ b/source/blender/draw/intern/draw_cache.c
@@ -3534,13 +3534,15 @@ void drw_batch_cache_generate_requested(Object *ob)
struct Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
switch (ob->type) {
case OB_MESH:
- DRW_mesh_batch_cache_create_requested(ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
+ DRW_mesh_batch_cache_create_requested(
+ DST.task_graph, ob, (Mesh *)ob->data, scene, is_paint_mode, use_hide);
break;
case OB_CURVE:
case OB_FONT:
case OB_SURF:
if (mesh_eval) {
- DRW_mesh_batch_cache_create_requested(ob, mesh_eval, scene, is_paint_mode, use_hide);
+ DRW_mesh_batch_cache_create_requested(
+ DST.task_graph, ob, mesh_eval, scene, is_paint_mode, use_hide);
}
DRW_curve_batch_cache_create_requested(ob);
break;
diff --git a/source/blender/draw/intern/draw_cache_extract.h b/source/blender/draw/intern/draw_cache_extract.h
index b2fea957227..f203c2ff1ea 100644
--- a/source/blender/draw/intern/draw_cache_extract.h
+++ b/source/blender/draw/intern/draw_cache_extract.h
@@ -23,6 +23,8 @@
#ifndef __DRAW_CACHE_EXTRACT_H__
#define __DRAW_CACHE_EXTRACT_H__
+struct TaskGraph;
+
/* Vertex Group Selection and display options */
typedef struct DRW_MeshWeightState {
int defgroup_active;
@@ -249,7 +251,8 @@ typedef struct MeshBatchCache {
bool no_loose_wire;
} MeshBatchCache;
-void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
MeshBufferCache mbc,
Mesh *me,
const bool is_editmode,
diff --git a/source/blender/draw/intern/draw_cache_extract_mesh.c b/source/blender/draw/intern/draw_cache_extract_mesh.c
index cbb5f5f06ff..0fd6bf54856 100644
--- a/source/blender/draw/intern/draw_cache_extract_mesh.c
+++ b/source/blender/draw/intern/draw_cache_extract_mesh.c
@@ -134,15 +134,12 @@ typedef struct MeshRenderData {
float (*poly_normals)[3];
int *lverts, *ledges;
} MeshRenderData;
-
static MeshRenderData *mesh_render_data_create(Mesh *me,
const bool is_editmode,
const bool is_paint_mode,
const float obmat[4][4],
const bool do_final,
const bool do_uvedit,
- const eMRIterType iter_type,
- const eMRDataType data_flag,
const DRW_MeshCDMask *UNUSED(cd_used),
const ToolSettings *ts)
{
@@ -152,9 +149,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
copy_m4_m4(mr->obmat, obmat);
- const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
- const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
-
if (is_editmode) {
BLI_assert(me->edit_mesh->mesh_eval_cage && me->edit_mesh->mesh_eval_final);
mr->bm = me->edit_mesh->bm;
@@ -244,7 +238,32 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->v_origindex = CustomData_get_layer(&mr->me->vdata, CD_ORIGINDEX);
mr->e_origindex = CustomData_get_layer(&mr->me->edata, CD_ORIGINDEX);
mr->p_origindex = CustomData_get_layer(&mr->me->pdata, CD_ORIGINDEX);
+ }
+ else {
+ /* BMesh */
+ BMesh *bm = mr->bm;
+
+ mr->vert_len = bm->totvert;
+ mr->edge_len = bm->totedge;
+ mr->loop_len = bm->totloop;
+ mr->poly_len = bm->totface;
+ mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
+ }
+ return mr;
+}
+
+/* Part of the creation of the MeshRenderData that happens in a thread. */
+static void mesh_render_data_update(MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ Mesh *me = mr->me;
+ const bool is_auto_smooth = (me->flag & ME_AUTOSMOOTH) != 0;
+ const float split_angle = is_auto_smooth ? me->smoothresh : (float)M_PI;
+
+ if (mr->extract_type != MR_EXTRACT_BMESH) {
+ /* Mesh */
if (data_flag & (MR_DATA_POLY_NOR | MR_DATA_LOOP_NOR | MR_DATA_TAN_LOOP_NOR)) {
mr->poly_normals = MEM_mallocN(sizeof(*mr->poly_normals) * mr->poly_len, __func__);
BKE_mesh_calc_normals_poly((MVert *)mr->mvert,
@@ -323,13 +342,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
else {
/* BMesh */
BMesh *bm = mr->bm;
-
- mr->vert_len = bm->totvert;
- mr->edge_len = bm->totedge;
- mr->loop_len = bm->totloop;
- mr->poly_len = bm->totface;
- mr->tri_len = poly_to_tri_count(mr->poly_len, mr->loop_len);
-
if (data_flag & MR_DATA_POLY_NOR) {
/* Use bmface->no instead. */
}
@@ -394,7 +406,6 @@ static MeshRenderData *mesh_render_data_create(Mesh *me,
mr->loop_loose_len = mr->vert_loose_len + mr->edge_loose_len * 2;
}
}
- return mr;
}
static void mesh_render_data_free(MeshRenderData *mr)
@@ -742,46 +753,15 @@ static const MeshExtract extract_lines = {
0,
false,
};
-
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loose Edges Indices
+/** \name Extract Loose Edges Sub Buffer
* \{ */
-static void *extract_lines_loose_init(const MeshRenderData *UNUSED(mr), void *UNUSED(buf))
-{
- return NULL;
-}
-
-static void extract_lines_loose_ledge_mesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(e),
- const MEdge *UNUSED(medge),
- void *UNUSED(elb))
-{
- /* This function is intentionally empty. The existence of this functions ensures that
- * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
- * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
- * field we use in the `extract_lines_loose_finish` function to create a subrange from the
- * `ibo.lines`. */
-}
-
-static void extract_lines_loose_ledge_bmesh(const MeshRenderData *UNUSED(mr),
- int UNUSED(e),
- BMEdge *UNUSED(eed),
- void *UNUSED(elb))
-{
- /* This function is intentionally empty. The existence of this functions ensures that
- * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
- * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
- * field we use in the `extract_lines_loose_finish` function to create a subrange from the
- * `ibo.lines`. */
-}
-
-static void extract_lines_loose_finish(const MeshRenderData *mr,
- void *UNUSED(ibo),
- void *UNUSED(elb))
+static void extract_lines_loose_subbuffer(const MeshRenderData *mr)
{
+ BLI_assert(mr->cache->final.ibo.lines);
/* Multiply by 2 because these are edges indices. */
const int start = mr->edge_len * 2;
const int len = mr->edge_loose_len * 2;
@@ -790,17 +770,24 @@ static void extract_lines_loose_finish(const MeshRenderData *mr,
mr->cache->no_loose_wire = (len == 0);
}
-static const MeshExtract extract_lines_loose = {
- extract_lines_loose_init,
- NULL,
- NULL,
+static void extract_lines_with_lines_loose_finish(const MeshRenderData *mr, void *ibo, void *elb)
+{
+ GPU_indexbuf_build_in_place(elb, ibo);
+ extract_lines_loose_subbuffer(mr);
+ MEM_freeN(elb);
+}
+
+static const MeshExtract extract_lines_with_lines_loose = {
+ extract_lines_init,
NULL,
NULL,
- extract_lines_loose_ledge_bmesh,
- extract_lines_loose_ledge_mesh,
+ extract_lines_loop_bmesh,
+ extract_lines_loop_mesh,
+ extract_lines_ledge_bmesh,
+ extract_lines_ledge_mesh,
NULL,
NULL,
- extract_lines_loose_finish,
+ extract_lines_with_lines_loose_finish,
0,
false,
};
@@ -1716,8 +1703,8 @@ static void extract_lnor_hq_loop_mesh(
}
/* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint
- * mode it will use the unmapped data to draw the wireframe. */
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
+ * paint mode it will use the unmapped data to draw the wireframe. */
if (mpoly->flag & ME_HIDE ||
(mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
@@ -1795,8 +1782,8 @@ static void extract_lnor_loop_mesh(
}
/* Flag for paint mode overlay.
- * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In paint
- * mode it will use the unmapped data to draw the wireframe. */
+ * Only use MR_EXTRACT_MAPPED in edit mode where it is used to display the edge-normals. In
+ * paint mode it will use the unmapped data to draw the wireframe. */
if (mpoly->flag & ME_HIDE ||
(mr->edit_bmesh && mr->extract_type == MR_EXTRACT_MAPPED && (mr->v_origindex) &&
mr->v_origindex[mloop->v] == ORIGINDEX_NONE)) {
@@ -2162,10 +2149,10 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
GPUVertFormat format = {0};
GPU_vertformat_deinterleave(&format);
- CustomData *cd_ldata = &mr->me->ldata;
+ CustomData *cd_ldata = (mr->extract_type == MR_EXTRACT_BMESH) ? &mr->bm->ldata : &mr->me->ldata;
uint32_t vcol_layers = mr->cache->cd_used.vcol;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
char attr_name[32], attr_safe_name[GPU_MAX_SAFE_ATTR_NAME];
const char *layer_name = CustomData_get_layer_name(cd_ldata, CD_MLOOPCOL, i);
@@ -2197,14 +2184,32 @@ static void *extract_vcol_init(const MeshRenderData *mr, void *buf)
} gpuMeshVcol;
gpuMeshVcol *vcol_data = (gpuMeshVcol *)vbo->data;
- for (int i = 0; i < 8; i++) {
+ for (int i = 0; i < MAX_MCOL; i++) {
if (vcol_layers & (1 << i)) {
- MLoopCol *mcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
- for (int l = 0; l < mr->loop_len; l++, mcol++, vcol_data++) {
- vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->r]);
- vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->g]);
- vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mcol->b]);
- vcol_data->a = unit_float_to_ushort_clamp(mcol->a * (1.0f / 255.0f));
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int cd_ofs = CustomData_get_n_offset(cd_ldata, CD_MLOOPCOL, i);
+ BMIter f_iter, l_iter;
+ BMFace *efa;
+ BMLoop *loop;
+ BM_ITER_MESH (efa, &f_iter, mr->bm, BM_FACES_OF_MESH) {
+ BM_ITER_ELEM (loop, &l_iter, efa, BM_LOOPS_OF_FACE) {
+ const MLoopCol *mloopcol = BM_ELEM_CD_GET_VOID_P(loop, cd_ofs);
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ vcol_data++;
+ }
+ }
+ }
+ else {
+ const MLoopCol *mloopcol = (MLoopCol *)CustomData_get_layer_n(cd_ldata, CD_MLOOPCOL, i);
+ for (int l = 0; l < mr->loop_len; l++, mloopcol++, vcol_data++) {
+ vcol_data->r = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->r]);
+ vcol_data->g = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->g]);
+ vcol_data->b = unit_float_to_ushort_clamp(BLI_color_from_srgb_table[mloopcol->b]);
+ vcol_data->a = unit_float_to_ushort_clamp(mloopcol->a * (1.0f / 255.0f));
+ }
}
}
}
@@ -4522,10 +4527,14 @@ static const MeshExtract extract_fdot_idx = {
/** \} */
/* ---------------------------------------------------------------------- */
-/** \name Extract Loop
+/** \name ExtractTaskData
* \{ */
+typedef struct ExtractUserData {
+ void *user_data;
+} ExtractUserData;
typedef struct ExtractTaskData {
+ void *next, *prev;
const MeshRenderData *mr;
const MeshExtract *extract;
eMRIterType iter_type;
@@ -4533,9 +4542,16 @@ typedef struct ExtractTaskData {
/** Decremented each time a task is finished. */
int32_t *task_counter;
void *buf;
- void *user_data;
+ ExtractUserData *user_data;
} ExtractTaskData;
+static void extract_task_data_free(void *data)
+{
+ ExtractTaskData *task_data = data;
+ MEM_SAFE_FREE(task_data->user_data);
+ MEM_freeN(task_data);
+}
+
BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
const eMRIterType iter_type,
int start,
@@ -4612,31 +4628,184 @@ BLI_INLINE void mesh_extract_iter(const MeshRenderData *mr,
}
}
-static void extract_run(TaskPool *__restrict UNUSED(pool), void *taskdata)
+static void extract_init(ExtractTaskData *data)
{
- ExtractTaskData *data = taskdata;
- mesh_extract_iter(
- data->mr, data->iter_type, data->start, data->end, data->extract, data->user_data);
+ data->user_data->user_data = data->extract->init(data->mr, data->buf);
+}
+
+static void extract_run(void *__restrict taskdata)
+{
+ ExtractTaskData *data = (ExtractTaskData *)taskdata;
+ mesh_extract_iter(data->mr,
+ data->iter_type,
+ data->start,
+ data->end,
+ data->extract,
+ data->user_data->user_data);
/* If this is the last task, we do the finish function. */
int remainin_tasks = atomic_sub_and_fetch_int32(data->task_counter, 1);
if (remainin_tasks == 0 && data->extract->finish != NULL) {
- data->extract->finish(data->mr, data->buf, data->user_data);
+ data->extract->finish(data->mr, data->buf, data->user_data->user_data);
+ }
+}
+
+static void extract_init_and_run(void *__restrict taskdata)
+{
+ extract_init((ExtractTaskData *)taskdata);
+ extract_run(taskdata);
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Update Mesh Render Data
+ * \{ */
+typedef struct MeshRenderDataUpdateTaskData {
+ MeshRenderData *mr;
+ eMRIterType iter_type;
+ eMRDataType data_flag;
+} MeshRenderDataUpdateTaskData;
+
+static void mesh_render_data_update_task_data_free(MeshRenderDataUpdateTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ mesh_render_data_free(taskdata->mr);
+ MEM_freeN(taskdata);
+}
+
+static void mesh_extract_render_data_node_exec(void *__restrict task_data)
+{
+ MeshRenderDataUpdateTaskData *update_task_data = task_data;
+ mesh_render_data_update(
+ update_task_data->mr, update_task_data->iter_type, update_task_data->data_flag);
+}
+
+static struct TaskNode *mesh_extract_render_data_node_create(struct TaskGraph *task_graph,
+ MeshRenderData *mr,
+ const eMRIterType iter_type,
+ const eMRDataType data_flag)
+{
+ MeshRenderDataUpdateTaskData *task_data = MEM_mallocN(sizeof(MeshRenderDataUpdateTaskData),
+ __func__);
+ task_data->mr = mr;
+ task_data->iter_type = iter_type;
+ task_data->data_flag = data_flag;
+
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ mesh_extract_render_data_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)mesh_render_data_update_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - Extract Single Threaded
+ * \{ */
+typedef struct ExtractSingleThreadedTaskData {
+ ListBase task_datas;
+} ExtractSingleThreadedTaskData;
+
+static void extract_single_threaded_task_data_free(ExtractSingleThreadedTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
+ extract_task_data_free(td);
+ }
+ BLI_listbase_clear(&taskdata->task_datas);
+ MEM_freeN(taskdata);
+}
+
+static void extract_single_threaded_task_node_exec(void *__restrict task_data)
+{
+ ExtractSingleThreadedTaskData *extract_task_data = task_data;
+ LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
+ extract_init_and_run(td);
+ }
+}
+
+static struct TaskNode *extract_single_threaded_task_node_create(
+ struct TaskGraph *task_graph, ExtractSingleThreadedTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ extract_single_threaded_task_node_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)extract_single_threaded_task_data_free);
+ return task_node;
+}
+
+/** \} */
+
+/* ---------------------------------------------------------------------- */
+/** \name Task Node - UserData Initializer
+ * \{ */
+typedef struct UserDataInitTaskData {
+ ListBase task_datas;
+ int32_t *task_counters;
+
+} UserDataInitTaskData;
+
+static void user_data_init_task_data_free(UserDataInitTaskData *taskdata)
+{
+ BLI_assert(taskdata);
+ LISTBASE_FOREACH_MUTABLE (ExtractTaskData *, td, &taskdata->task_datas) {
+ extract_task_data_free(td);
+ }
+ BLI_listbase_clear(&taskdata->task_datas);
+ MEM_SAFE_FREE(taskdata->task_counters);
+ MEM_freeN(taskdata);
+}
+
+static void user_data_init_task_data_exec(void *__restrict task_data)
+{
+ UserDataInitTaskData *extract_task_data = task_data;
+ LISTBASE_FOREACH (ExtractTaskData *, td, &extract_task_data->task_datas) {
+ extract_init(td);
}
}
-static void extract_range_task_create(
- TaskPool *task_pool, ExtractTaskData *taskdata, const eMRIterType type, int start, int length)
+static struct TaskNode *user_data_init_task_node_create(struct TaskGraph *task_graph,
+ UserDataInitTaskData *task_data)
+{
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph,
+ user_data_init_task_data_exec,
+ task_data,
+ (TaskGraphNodeFreeFunction)user_data_init_task_data_free);
+ return task_node;
+}
+
+/** \} */
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loop
+ * \{ */
+
+static void extract_range_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_user_data_init,
+ ExtractTaskData *taskdata,
+ const eMRIterType type,
+ int start,
+ int length)
{
taskdata = MEM_dupallocN(taskdata);
atomic_add_and_fetch_int32(taskdata->task_counter, 1);
taskdata->iter_type = type;
taskdata->start = start;
taskdata->end = start + length;
- BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL);
+ struct TaskNode *task_node = BLI_task_graph_node_create(
+ task_graph, extract_run, taskdata, MEM_freeN);
+ BLI_task_graph_edge_create(task_node_user_data_init, task_node);
}
-static void extract_task_create(TaskPool *task_pool,
+static void extract_task_create(struct TaskGraph *task_graph,
+ struct TaskNode *task_node_mesh_render_data,
+ struct TaskNode *task_node_user_data_init,
+ ListBase *single_threaded_task_datas,
+ ListBase *user_data_init_task_datas,
const Scene *scene,
const MeshRenderData *mr,
const MeshExtract *extract,
@@ -4654,58 +4823,75 @@ static void extract_task_create(TaskPool *task_pool,
/* Divide extraction of the VBO/IBO into sensible chunks of works. */
ExtractTaskData *taskdata = MEM_mallocN(sizeof(*taskdata), "ExtractTaskData");
+ taskdata->next = NULL;
+ taskdata->prev = NULL;
taskdata->mr = mr;
taskdata->extract = extract;
taskdata->buf = buf;
- taskdata->user_data = extract->init(mr, buf);
+
+ /* ExtractUserData is shared between the iterations as it holds counters to detect if the
+ * extraction is finished. To make sure the duplication of the userdata does not create a new
+ * instance of the counters we allocate the userdata in its own container.
+ *
+ * This structure makes sure that when extract_init is called, that the user data of all
+ * iterations are updated. */
+ taskdata->user_data = MEM_callocN(sizeof(ExtractUserData), __func__);
taskdata->iter_type = mesh_extract_iter_type(extract);
taskdata->task_counter = task_counter;
taskdata->start = 0;
taskdata->end = INT_MAX;
/* Simple heuristic. */
- const bool use_thread = (mr->loop_len + mr->loop_loose_len) > 8192;
+ const int chunk_size = 8192;
+ const bool use_thread = (mr->loop_len + mr->loop_loose_len) > chunk_size;
if (use_thread && extract->use_threading) {
+
/* Divide task into sensible chunks. */
- const int chunk_size = 8192;
if (taskdata->iter_type & MR_ITER_LOOPTRI) {
for (int i = 0; i < mr->tri_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOPTRI, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LOOP) {
for (int i = 0; i < mr->poly_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LOOP, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LOOP, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LEDGE) {
for (int i = 0; i < mr->edge_loose_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LEDGE, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LEDGE, i, chunk_size);
}
}
if (taskdata->iter_type & MR_ITER_LVERT) {
for (int i = 0; i < mr->vert_loose_len; i += chunk_size) {
- extract_range_task_create(task_pool, taskdata, MR_ITER_LVERT, i, chunk_size);
+ extract_range_task_create(
+ task_graph, task_node_user_data_init, taskdata, MR_ITER_LVERT, i, chunk_size);
}
}
- MEM_freeN(taskdata);
+ BLI_addtail(user_data_init_task_datas, taskdata);
}
else if (use_thread) {
/* One task for the whole VBO. */
(*task_counter)++;
- BLI_task_pool_push(task_pool, extract_run, taskdata, true, NULL);
+ struct TaskNode *one_task = BLI_task_graph_node_create(
+ task_graph, extract_init_and_run, taskdata, extract_task_data_free);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, one_task);
}
else {
/* Single threaded extraction. */
(*task_counter)++;
- extract_run(NULL, taskdata);
- MEM_freeN(taskdata);
+ BLI_addtail(single_threaded_task_datas, taskdata);
}
}
-void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
+void mesh_buffer_cache_create_requested(struct TaskGraph *task_graph,
+ MeshBatchCache *cache,
MeshBufferCache mbc,
Mesh *me,
+
const bool is_editmode,
const bool is_paint_mode,
const float obmat[4][4],
@@ -4717,9 +4903,41 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
const ToolSettings *ts,
const bool use_hide)
{
+ /* For each mesh where batches needs to be updated a sub-graph will be added to the task_graph.
+ * This sub-graph starts with an extract_render_data_node. This fills/converts the required data
+ * from Mesh.
+ *
+ * Small extractions and extractions that can't be multi-threaded are grouped in a single
+ * `extract_single_threaded_task_node`.
+ *
+ * Other extractions will create a node for each loop exceeding 8192 items. these nodes are
+ * linked to the `user_data_init_task_node`. the `user_data_init_task_node` prepares the userdata
+ * needed for the extraction based on the data extracted from the mesh. counters are used to
+ * check if the finalize of a task has to be called.
+ *
+ * Mesh extraction sub graph
+ *
+ * +----------------------+
+ * +-----> | extract_task1_loop_1 |
+ * | +----------------------+
+ * +------------------+ +----------------------+ +----------------------+
+ * | mesh_render_data | --> | | --> | extract_task1_loop_2 |
+ * +------------------+ | | +----------------------+
+ * | | | +----------------------+
+ * | | user_data_init | --> | extract_task2_loop_1 |
+ * v | | +----------------------+
+ * +------------------+ | | +----------------------+
+ * | single_threaded | | | --> | extract_task2_loop_2 |
+ * +------------------+ +----------------------+ +----------------------+
+ * | +----------------------+
+ * +-----> | extract_task2_loop_3 |
+ * +----------------------+
+ */
eMRIterType iter_flag = 0;
eMRDataType data_flag = 0;
+ const bool do_lines_loose_subbuffer = mbc.ibo.lines_loose != NULL;
+
#define TEST_ASSIGN(type, type_lowercase, name) \
do { \
if (DRW_TEST_ASSIGN_##type(mbc.type_lowercase.name)) { \
@@ -4757,7 +4975,6 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
TEST_ASSIGN(IBO, ibo, fdots);
TEST_ASSIGN(IBO, ibo, lines_paint_mask);
TEST_ASSIGN(IBO, ibo, lines_adjacency);
- TEST_ASSIGN(IBO, ibo, lines_loose);
TEST_ASSIGN(IBO, ibo, edituv_tris);
TEST_ASSIGN(IBO, ibo, edituv_lines);
TEST_ASSIGN(IBO, ibo, edituv_points);
@@ -4769,16 +4986,8 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
double rdata_start = PIL_check_seconds_timer();
#endif
- MeshRenderData *mr = mesh_render_data_create(me,
- is_editmode,
- is_paint_mode,
- obmat,
- do_final,
- do_uvedit,
- iter_flag,
- data_flag,
- cd_layer_used,
- ts);
+ MeshRenderData *mr = mesh_render_data_create(
+ me, is_editmode, is_paint_mode, obmat, do_final, do_uvedit, cd_layer_used, ts);
mr->cache = cache; /* HACK */
mr->use_hide = use_hide;
mr->use_subsurf_fdots = use_subsurf_fdots;
@@ -4788,20 +4997,32 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
double rdata_end = PIL_check_seconds_timer();
#endif
- TaskPool *task_pool;
-
- /* Create a suspended pool as the finalize method could be called too early.
- * See `extract_run`. */
- task_pool = BLI_task_pool_create_suspended(NULL, TASK_PRIORITY_HIGH);
-
size_t counters_size = (sizeof(mbc) / sizeof(void *)) * sizeof(int32_t);
int32_t *task_counters = MEM_callocN(counters_size, __func__);
int counter_used = 0;
+ struct TaskNode *task_node_mesh_render_data = mesh_extract_render_data_node_create(
+ task_graph, mr, iter_flag, data_flag);
+ ExtractSingleThreadedTaskData *single_threaded_task_data = MEM_callocN(
+ sizeof(ExtractSingleThreadedTaskData), __func__);
+ UserDataInitTaskData *user_data_init_task_data = MEM_callocN(sizeof(UserDataInitTaskData),
+ __func__);
+ user_data_init_task_data->task_counters = task_counters;
+ struct TaskNode *task_node_user_data_init = user_data_init_task_node_create(
+ task_graph, user_data_init_task_data);
+
#define EXTRACT(buf, name) \
if (mbc.buf.name) { \
- extract_task_create( \
- task_pool, scene, mr, &extract_##name, mbc.buf.name, &task_counters[counter_used++]); \
+ extract_task_create(task_graph, \
+ task_node_mesh_render_data, \
+ task_node_user_data_init, \
+ &single_threaded_task_data->task_datas, \
+ &user_data_init_task_data->task_datas, \
+ scene, \
+ mr, \
+ &extract_##name, \
+ mbc.buf.name, \
+ &task_counters[counter_used++]); \
} \
((void)0)
@@ -4829,7 +5050,33 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
EXTRACT(vbo, skin_roots);
EXTRACT(ibo, tris);
- EXTRACT(ibo, lines);
+ if (mbc.ibo.lines) {
+ /* When `lines` and `lines_loose` are requested, schedule lines extraction that also creates
+ * the `lines_loose` sub-buffer. */
+ const MeshExtract *lines_extractor = do_lines_loose_subbuffer ?
+ &extract_lines_with_lines_loose :
+ &extract_lines;
+ extract_task_create(task_graph,
+ task_node_mesh_render_data,
+ task_node_user_data_init,
+ &single_threaded_task_data->task_datas,
+ &user_data_init_task_data->task_datas,
+ scene,
+ mr,
+ lines_extractor,
+ mbc.ibo.lines,
+ &task_counters[counter_used++]);
+ }
+ else {
+ if (do_lines_loose_subbuffer) {
+ /* When `lines_loose` is requested without `lines` we can create the sub-buffer on the fly as
+ * the `lines` buffer should then already be up-to-date.
+ * (see `DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)` in
+ * `DRW_mesh_batch_cache_create_requested`).
+ */
+ extract_lines_loose_subbuffer(mr);
+ }
+ }
EXTRACT(ibo, points);
EXTRACT(ibo, fdots);
EXTRACT(ibo, lines_paint_mask);
@@ -4839,27 +5086,29 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
EXTRACT(ibo, edituv_points);
EXTRACT(ibo, edituv_fdots);
- /* TODO(fclem) Ideally, we should have one global pool for all
- * objects and wait for finish only before drawing when buffers
- * need to be ready. */
- BLI_task_pool_work_and_wait(task_pool);
-
- /* The next task(s) rely on the result of the tasks above. */
+ /* Only create the edge when there are user datas that needs to be inited.
+ * The task is still part of the graph so the task_data will be freed when the graph is freed.
+ */
+ if (!BLI_listbase_is_empty(&user_data_init_task_data->task_datas)) {
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node_user_data_init);
+ }
- /* The `lines_loose` is a sub buffer from `ibo.lines`.
- * We schedule it here due to potential synchronization issues.*/
- EXTRACT(ibo, lines_loose);
+ if (!BLI_listbase_is_empty(&single_threaded_task_data->task_datas)) {
+ struct TaskNode *task_node = extract_single_threaded_task_node_create(
+ task_graph, single_threaded_task_data);
+ BLI_task_graph_edge_create(task_node_mesh_render_data, task_node);
+ }
+ else {
+ extract_single_threaded_task_data_free(single_threaded_task_data);
+ }
- BLI_task_pool_work_and_wait(task_pool);
+ /* Trigger the sub-graph for this mesh. */
+ BLI_task_graph_node_push_work(task_node_mesh_render_data);
#undef EXTRACT
- BLI_task_pool_free(task_pool);
- MEM_freeN(task_counters);
-
- mesh_render_data_free(mr);
-
#ifdef DEBUG_TIME
+ BLI_task_graph_work_and_wait(task_graph);
double end = PIL_check_seconds_timer();
static double avg = 0;
diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h
index daa46252331..80649143537 100644
--- a/source/blender/draw/intern/draw_cache_impl.h
+++ b/source/blender/draw/intern/draw_cache_impl.h
@@ -31,6 +31,7 @@ struct ListBase;
struct ModifierData;
struct PTCacheEdit;
struct ParticleSystem;
+struct TaskGraph;
struct Curve;
struct Hair;
@@ -150,7 +151,8 @@ int DRW_volume_material_count_get(struct Volume *volume);
struct GPUBatch *DRW_volume_batch_cache_get_wireframes_face(struct Volume *volume);
/* Mesh */
-void DRW_mesh_batch_cache_create_requested(struct Object *ob,
+void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
+ struct Object *ob,
struct Mesh *me,
const struct Scene *scene,
const bool is_paint_mode,
diff --git a/source/blender/draw/intern/draw_cache_impl_gpencil.c b/source/blender/draw/intern/draw_cache_impl_gpencil.c
index ee148e0934d..b4974330043 100644
--- a/source/blender/draw/intern/draw_cache_impl_gpencil.c
+++ b/source/blender/draw/intern/draw_cache_impl_gpencil.c
@@ -102,6 +102,7 @@ static GpencilBatchCache *gpencil_batch_cache_init(Object *ob, int cfra)
cache->is_dirty = true;
cache->cache_frame = cfra;
+
return cache;
}
@@ -385,7 +386,8 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
.vert_len = 1, /* Start at 1 for the gl_InstanceID trick to work (see vert shader). */
.tri_len = 0,
};
- BKE_gpencil_visible_stroke_iter(ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gp_object_verts_count_cb, &iter, do_onion, cfra);
/* Create VBOs. */
GPUVertFormat *format = gpencil_stroke_format();
@@ -401,7 +403,7 @@ static void gpencil_batches_ensure(Object *ob, GpencilBatchCache *cache, int cfr
GPU_indexbuf_init(&iter.ibo, GPU_PRIM_TRIS, iter.tri_len, iter.vert_len);
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gpencil_stroke_iter_cb, &iter, do_onion, cfra);
/* Mark last 2 verts as invalid. */
for (int i = 0; i < 2; i++) {
@@ -475,7 +477,7 @@ GPUBatch *DRW_cache_gpencil_face_wireframe_get(Object *ob)
/* IMPORTANT: Keep in sync with gpencil_edit_batches_ensure() */
bool do_onion = true;
- BKE_gpencil_visible_stroke_iter(ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(NULL, ob, NULL, gp_lines_indices_cb, &iter, do_onion, cfra);
GPUIndexBuf *ibo = GPU_indexbuf_build(&iter.ibo);
@@ -724,7 +726,8 @@ static void gpencil_edit_batches_ensure(Object *ob, GpencilBatchCache *cache, in
iter.verts = (gpEditVert *)cache->edit_vbo->data;
/* Fill buffers with data. */
- BKE_gpencil_visible_stroke_iter(ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
+ BKE_gpencil_visible_stroke_iter(
+ NULL, ob, NULL, gpencil_edit_stroke_iter_cb, &iter, do_onion, cfra);
/* Create the batches */
cache->edit_points_batch = GPU_batch_create(GPU_PRIM_POINTS, cache->vbo, NULL);
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 237c7bddfad..99e285a18f1 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -33,6 +33,7 @@
#include "BLI_math_bits.h"
#include "BLI_math_vector.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "DNA_mesh_types.h"
@@ -1019,9 +1020,14 @@ void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime)
}
/* Can be called for any surface type. Mesh *me is the final mesh. */
-void DRW_mesh_batch_cache_create_requested(
- Object *ob, Mesh *me, const Scene *scene, const bool is_paint_mode, const bool use_hide)
-{
+void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph,
+ Object *ob,
+ Mesh *me,
+ const Scene *scene,
+ const bool is_paint_mode,
+ const bool use_hide)
+{
+ BLI_assert(task_graph);
GPUIndexBuf **saved_elem_ranges = NULL;
const ToolSettings *ts = NULL;
if (scene) {
@@ -1378,7 +1384,8 @@ void DRW_mesh_batch_cache_create_requested(
false;
if (do_uvcage) {
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->uv_cage,
me,
is_editmode,
@@ -1394,7 +1401,8 @@ void DRW_mesh_batch_cache_create_requested(
}
if (do_cage) {
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->cage,
me,
is_editmode,
@@ -1409,7 +1417,8 @@ void DRW_mesh_batch_cache_create_requested(
true);
}
- mesh_buffer_cache_create_requested(cache,
+ mesh_buffer_cache_create_requested(task_graph,
+ cache,
cache->final,
me,
is_editmode,
@@ -1422,10 +1431,12 @@ void DRW_mesh_batch_cache_create_requested(
scene,
ts,
use_hide);
-
#ifdef DEBUG
check:
/* Make sure all requested batches have been setup. */
+ /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and
+ * additional looping.*/
+ BLI_task_graph_work_and_wait(task_graph);
for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) {
BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0));
}
diff --git a/source/blender/draw/intern/draw_common.h b/source/blender/draw/intern/draw_common.h
index f14cdc0dbde..656d72b2808 100644
--- a/source/blender/draw/intern/draw_common.h
+++ b/source/blender/draw/intern/draw_common.h
@@ -172,23 +172,11 @@ bool DRW_object_axis_orthogonal_to_view(Object *ob, int axis);
/* This creates a shading group with display hairs.
* The draw call is already added by this function, just add additional uniforms. */
-struct DRWShadingGroup *DRW_shgroup_hair_create(struct Object *object,
- struct ParticleSystem *psys,
- struct ModifierData *md,
- struct DRWPass *hair_pass,
- struct GPUShader *shader);
-
struct DRWShadingGroup *DRW_shgroup_hair_create_sub(struct Object *object,
struct ParticleSystem *psys,
struct ModifierData *md,
struct DRWShadingGroup *shgrp);
-struct DRWShadingGroup *DRW_shgroup_material_hair_create(struct Object *object,
- struct ParticleSystem *psys,
- struct ModifierData *md,
- struct DRWPass *hair_pass,
- struct GPUMaterial *material);
-
void DRW_hair_init(void);
void DRW_hair_update(void);
void DRW_hair_free(void);
diff --git a/source/blender/draw/intern/draw_hair.c b/source/blender/draw/intern/draw_hair.c
index 27de7cc1c7c..2fdaf0d5345 100644
--- a/source/blender/draw/intern/draw_hair.c
+++ b/source/blender/draw/intern/draw_hair.c
@@ -124,13 +124,10 @@ void DRW_hair_init(void)
}
}
-static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWPass *hair_pass,
- DRWShadingGroup *shgrp_parent,
- struct GPUMaterial *gpu_mat,
- GPUShader *gpu_shader)
+DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
+ ParticleSystem *psys,
+ ModifierData *md,
+ DRWShadingGroup *shgrp_parent)
{
/* TODO(fclem): Pass the scene as parameter */
const DRWContextState *draw_ctx = DRW_context_state_get();
@@ -154,24 +151,7 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
need_ft_update = hair_ensure_procedural_data(object, &hair_cache, subdiv, thickness_res);
}
- DRWShadingGroup *shgrp;
- if (shgrp_parent) {
- shgrp = DRW_shgroup_create_sub(shgrp_parent);
- }
- else if (gpu_mat) {
- shgrp = DRW_shgroup_material_create(gpu_mat, hair_pass);
- }
- else if (gpu_shader) {
- shgrp = DRW_shgroup_create(gpu_shader, hair_pass);
- }
- else {
- shgrp = NULL;
- BLI_assert(0);
- }
-
- if (shgrp == NULL) {
- return NULL;
- }
+ DRWShadingGroup *shgrp = DRW_shgroup_create_sub(shgrp_parent);
/* TODO optimize this. Only bind the ones GPUMaterial needs. */
for (int i = 0; i < hair_cache->num_uv_layers; i++) {
@@ -284,29 +264,6 @@ static DRWShadingGroup *drw_shgroup_create_hair_procedural_ex(Object *object,
return shgrp;
}
-DRWShadingGroup *DRW_shgroup_hair_create(
- Object *object, ParticleSystem *psys, ModifierData *md, DRWPass *hair_pass, GPUShader *shader)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, NULL, shader);
-}
-
-DRWShadingGroup *DRW_shgroup_hair_create_sub(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWShadingGroup *shgrp)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, NULL, shgrp, NULL, NULL);
-}
-
-DRWShadingGroup *DRW_shgroup_material_hair_create(Object *object,
- ParticleSystem *psys,
- ModifierData *md,
- DRWPass *hair_pass,
- struct GPUMaterial *material)
-{
- return drw_shgroup_create_hair_procedural_ex(object, psys, md, hair_pass, NULL, material, NULL);
-}
-
void DRW_hair_update(void)
{
#ifndef USE_TRANSFORM_FEEDBACK
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index bdef6d50db8..08c6a0e8da8 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -27,6 +27,7 @@
#include "BLI_memblock.h"
#include "BLI_rect.h"
#include "BLI_string.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "BLF_api.h"
@@ -115,17 +116,6 @@ static ListBase DRW_engines = {NULL, NULL};
static void drw_state_prepare_clean_for_draw(DRWManager *dst)
{
memset(dst, 0x0, offsetof(DRWManager, gl_context));
-
- /* Maybe not the best place for this. */
- if (!DST.uniform_names.buffer) {
- DST.uniform_names.buffer = MEM_callocN(DRW_UNIFORM_BUFFER_NAME, "Name Buffer");
- DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
- }
- else if (DST.uniform_names.buffer_len > DRW_UNIFORM_BUFFER_NAME) {
- DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer, DRW_UNIFORM_BUFFER_NAME);
- DST.uniform_names.buffer_len = DRW_UNIFORM_BUFFER_NAME;
- }
- DST.uniform_names.buffer_ofs = 0;
}
/* This function is used to reset draw manager to a state
@@ -140,6 +130,23 @@ static void drw_state_ensure_not_reused(DRWManager *dst)
#endif
/* -------------------------------------------------------------------- */
+/** \name Threading
+ * \{ */
+static void drw_task_graph_init(void)
+{
+ BLI_assert(DST.task_graph == NULL);
+ DST.task_graph = BLI_task_graph_create();
+}
+
+static void drw_task_graph_deinit(void)
+{
+ BLI_task_graph_work_and_wait(DST.task_graph);
+ BLI_task_graph_free(DST.task_graph);
+ DST.task_graph = NULL;
+}
+/* \} */
+
+/* -------------------------------------------------------------------- */
/** \name Settings
* \{ */
@@ -588,9 +595,6 @@ static void drw_viewport_var_init(void)
ED_view3d_init_mats_rv3d(DST.draw_ctx.object_edit, rv3d);
}
- /* Alloc array of texture reference. */
- memset(&DST.RST, 0x0, sizeof(DST.RST));
-
if (G_draw.view_ubo == NULL) {
G_draw.view_ubo = DRW_uniformbuffer_create(sizeof(DRWViewUboStorage), NULL);
}
@@ -1428,6 +1432,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
/* reuse if caller sets */
.evil_C = DST.draw_ctx.evil_C,
};
+ drw_task_graph_init();
drw_context_state_init();
drw_viewport_var_init();
@@ -1492,6 +1497,7 @@ void DRW_draw_render_loop_ex(struct Depsgraph *depsgraph,
#endif
}
+ drw_task_graph_deinit();
DRW_stats_begin();
GPU_framebuffer_bind(DST.default_framebuffer);
@@ -1772,7 +1778,6 @@ void DRW_render_to_image(RenderEngine *engine, struct Depsgraph *depsgraph)
DST.options.is_image_render = true;
DST.options.is_scene_render = true;
DST.options.draw_background = scene->r.alphamode == R_ADDSKY;
-
DST.draw_ctx = (DRWContextState){
.scene = scene,
.view_layer = view_layer,
@@ -1857,9 +1862,9 @@ void DRW_render_object_iter(
void (*callback)(void *vedata, Object *ob, RenderEngine *engine, struct Depsgraph *depsgraph))
{
const DRWContextState *draw_ctx = DRW_context_state_get();
-
DRW_hair_init();
+ drw_task_graph_init();
const int object_type_exclude_viewport = draw_ctx->v3d ?
draw_ctx->v3d->object_type_exclude_viewport :
0;
@@ -1882,6 +1887,7 @@ void DRW_render_object_iter(
DEG_OBJECT_ITER_FOR_RENDER_ENGINE_END;
drw_duplidata_free();
+ drw_task_graph_deinit();
}
/* Assume a valid gl context is bound (and that the gl_context_mutex has been acquired).
@@ -2053,7 +2059,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
DST.viewport = viewport;
DST.options.is_select = true;
-
+ drw_task_graph_init();
/* Get list of enabled engines */
if (use_obedit) {
drw_engines_enable_overlays();
@@ -2163,6 +2169,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
}
drw_duplidata_free();
+ drw_task_graph_deinit();
drw_engines_cache_finish();
DRW_render_instance_buffer_finish();
@@ -2243,7 +2250,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
.engine_type = engine_type,
.depsgraph = depsgraph,
};
-
+ drw_task_graph_init();
drw_engines_data_validate();
/* Setup framebuffer */
@@ -2287,6 +2294,7 @@ static void drw_draw_depth_loop_imp(struct Depsgraph *depsgraph,
DRW_render_instance_buffer_finish();
}
+ drw_task_graph_deinit();
/* Start Drawing */
DRW_state_reset();
@@ -2376,7 +2384,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
.obact = OBACT(view_layer),
.depsgraph = depsgraph,
};
-
+ drw_task_graph_init();
drw_context_state_init();
/* Setup viewport */
@@ -2411,6 +2419,7 @@ void DRW_draw_select_id(Depsgraph *depsgraph, ARegion *region, View3D *v3d, cons
drw_resource_buffer_finish(DST.vmempool);
#endif
}
+ drw_task_graph_deinit();
/* Start Drawing */
DRW_state_reset();
@@ -2474,8 +2483,10 @@ void DRW_draw_depth_object(
else {
batch = DRW_mesh_batch_cache_get_surface(me);
}
-
- DRW_mesh_batch_cache_create_requested(object, me, scene, false, true);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, object, me, scene, false, true);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
const eGPUShaderConfig sh_cfg = world_clip_planes ? GPU_SHADER_CFG_CLIPPED :
GPU_SHADER_CFG_DEFAULT;
@@ -2721,8 +2732,6 @@ void DRW_engines_free(void)
DRW_TEXTURE_FREE_SAFE(G_draw.ramp);
DRW_TEXTURE_FREE_SAFE(G_draw.weight_ramp);
- MEM_SAFE_FREE(DST.uniform_names.buffer);
-
if (DST.draw_list) {
GPU_draw_list_discard(DST.draw_list);
}
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index f6d8179b193..733711a06da 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -31,6 +31,7 @@
#include "BLI_assert.h"
#include "BLI_linklist.h"
#include "BLI_memblock.h"
+#include "BLI_task.h"
#include "BLI_threads.h"
#include "GPU_batch.h"
@@ -276,10 +277,9 @@ typedef enum {
DRW_UNIFORM_FLOAT,
DRW_UNIFORM_FLOAT_COPY,
DRW_UNIFORM_TEXTURE,
- DRW_UNIFORM_TEXTURE_PERSIST,
DRW_UNIFORM_TEXTURE_REF,
DRW_UNIFORM_BLOCK,
- DRW_UNIFORM_BLOCK_PERSIST,
+ DRW_UNIFORM_BLOCK_REF,
DRW_UNIFORM_TFEEDBACK_TARGET,
/** Per drawcall uniforms/UBO */
DRW_UNIFORM_BLOCK_OBMATS,
@@ -290,7 +290,6 @@ typedef enum {
DRW_UNIFORM_BASE_INSTANCE,
DRW_UNIFORM_MODEL_MATRIX,
DRW_UNIFORM_MODEL_MATRIX_INVERSE,
- DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX,
/* WARNING: set DRWUniform->type
* bit length accordingly. */
} DRWUniformType;
@@ -299,15 +298,28 @@ struct DRWUniform {
union {
/* For reference or array/vector types. */
const void *pvalue;
- /* Single values. */
+ /* DRW_UNIFORM_TEXTURE */
+ struct {
+ union {
+ GPUTexture *texture;
+ GPUTexture **texture_ref;
+ };
+ eGPUSamplerState sampler_state;
+ };
+ /* DRW_UNIFORM_BLOCK */
+ union {
+ GPUUniformBuffer *block;
+ GPUUniformBuffer **block_ref;
+ };
+ /* DRW_UNIFORM_FLOAT_COPY */
float fvalue[4];
+ /* DRW_UNIFORM_INT_COPY */
int ivalue[4];
};
- int location;
+ int location; /* Use as binding point for textures and ubos. */
uint32_t type : 5; /* DRWUniformType */
uint32_t length : 5; /* cannot be more than 16 */
uint32_t arraysize : 5; /* cannot be more than 16 too */
- uint32_t name_ofs : 17; /* name offset in name buffer. */
};
struct DRWShadingGroup {
@@ -342,6 +354,13 @@ struct DRWPass {
DRWShadingGroup *last;
} shgroups;
+ /* Draw the shgroups of this pass instead.
+ * This avoid duplicating drawcalls/shgroups
+ * for similar passes. */
+ DRWPass *original;
+ /* Link list of additional passes to render. */
+ DRWPass *next;
+
DRWResourceHandle handle;
DRWState state;
char name[MAX_PASS_NAME];
@@ -525,6 +544,8 @@ typedef struct DRWManager {
uint select_id;
#endif
+ struct TaskGraph *task_graph;
+
/* ---------- Nothing after this point is cleared after use ----------- */
/* gl_context serves as the offset for clearing only
@@ -537,31 +558,11 @@ typedef struct DRWManager {
GPUDrawList *draw_list;
- /** GPU Resource State: Memory storage between drawing. */
- struct {
- /* High end GPUs supports up to 32 binds per shader stage.
- * We only use textures during the vertex and fragment stage,
- * so 2 * 32 slots is a nice limit. */
- GPUTexture *bound_texs[DST_MAX_SLOTS];
- uint64_t bound_tex_slots;
- uint64_t bound_tex_slots_persist;
-
- GPUUniformBuffer *bound_ubos[DST_MAX_SLOTS];
- uint64_t bound_ubo_slots;
- uint64_t bound_ubo_slots_persist;
- } RST;
-
struct {
/* TODO(fclem) optimize: use chunks. */
DRWDebugLine *lines;
DRWDebugSphere *spheres;
} debug;
-
- struct {
- char *buffer;
- uint buffer_len;
- uint buffer_ofs;
- } uniform_names;
} DRWManager;
extern DRWManager DST; /* TODO: get rid of this and allow multi-threaded rendering. */
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index aa401bcffa5..376bc69b392 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -170,13 +170,20 @@ void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
/** \name Uniforms (DRW_shgroup_uniform)
* \{ */
-static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
- int loc,
- DRWUniformType type,
- const void *value,
- int length,
- int arraysize)
-{
+static void drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
+ int loc,
+ DRWUniformType type,
+ const void *value,
+ eGPUSamplerState sampler_state,
+ int length,
+ int arraysize)
+{
+ if (loc == -1) {
+ /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
+ // BLI_assert(0);
+ return;
+ }
+
DRWUniformChunk *unichunk = shgroup->uniforms;
/* Happens on first uniform or if chunk is full. */
if (!unichunk || unichunk->uniform_used == unichunk->uniform_len) {
@@ -202,22 +209,24 @@ static DRWUniform *drw_shgroup_uniform_create_ex(DRWShadingGroup *shgroup,
BLI_assert(length <= 4);
memcpy(uni->fvalue, value, sizeof(float) * length);
break;
+ case DRW_UNIFORM_BLOCK:
+ uni->block = (GPUUniformBuffer *)value;
+ break;
+ case DRW_UNIFORM_BLOCK_REF:
+ uni->block_ref = (GPUUniformBuffer **)value;
+ break;
+ case DRW_UNIFORM_TEXTURE:
+ uni->texture = (GPUTexture *)value;
+ uni->sampler_state = sampler_state;
+ break;
+ case DRW_UNIFORM_TEXTURE_REF:
+ uni->texture_ref = (GPUTexture **)value;
+ uni->sampler_state = sampler_state;
+ break;
default:
uni->pvalue = (const float *)value;
break;
}
-
- return uni;
-}
-
-static void drw_shgroup_builtin_uniform(
- DRWShadingGroup *shgroup, int builtin, const void *value, int length, int arraysize)
-{
- int loc = GPU_shader_get_builtin_uniform(shgroup->shader, builtin);
-
- if (loc != -1) {
- drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_FLOAT, value, length, arraysize);
- }
}
static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
@@ -227,61 +236,29 @@ static void drw_shgroup_uniform(DRWShadingGroup *shgroup,
int length,
int arraysize)
{
- int location;
- if (ELEM(type, DRW_UNIFORM_BLOCK, DRW_UNIFORM_BLOCK_PERSIST)) {
- location = GPU_shader_get_uniform_block(shgroup->shader, name);
- }
- else {
- location = GPU_shader_get_uniform(shgroup->shader, name);
- }
-
- if (location == -1) {
- /* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
- // BLI_assert(0);
- return;
- }
-
BLI_assert(arraysize > 0 && arraysize <= 16);
BLI_assert(length >= 0 && length <= 16);
-
- DRWUniform *uni = drw_shgroup_uniform_create_ex(
- shgroup, location, type, value, length, arraysize);
-
- /* If location is -2, the uniform has not yet been queried.
- * We save the name for query just before drawing. */
- if (location == -2 || DRW_DEBUG_USE_UNIFORM_NAME) {
- int ofs = DST.uniform_names.buffer_ofs;
- int max_len = DST.uniform_names.buffer_len - ofs;
- size_t len = strlen(name) + 1;
-
- if (len >= max_len) {
- DST.uniform_names.buffer_len += MAX2(DST.uniform_names.buffer_len, len);
- DST.uniform_names.buffer = MEM_reallocN(DST.uniform_names.buffer,
- DST.uniform_names.buffer_len);
- }
-
- char *dst = DST.uniform_names.buffer + ofs;
- memcpy(dst, name, len); /* Copies NULL terminator. */
-
- DST.uniform_names.buffer_ofs += len;
- uni->name_ofs = ofs;
- }
+ BLI_assert(!ELEM(type,
+ DRW_UNIFORM_BLOCK,
+ DRW_UNIFORM_BLOCK_REF,
+ DRW_UNIFORM_TEXTURE,
+ DRW_UNIFORM_TEXTURE_REF));
+ int location = GPU_shader_get_uniform(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, location, type, value, 0, length, arraysize);
}
void DRW_shgroup_uniform_texture(DRWShadingGroup *shgroup, const char *name, const GPUTexture *tex)
{
BLI_assert(tex != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE, tex, 0, 1);
+ int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE, tex, GPU_SAMPLER_MAX, 0, 1);
}
-/* Same as DRW_shgroup_uniform_texture but is guaranteed to be bound if shader does not change
- * between shgrp. */
-void DRW_shgroup_uniform_texture_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const GPUTexture *tex)
+void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
{
BLI_assert(tex != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_PERSIST, tex, 0, 1);
+ int loc = GPU_shader_get_texture_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_TEXTURE_REF, tex, GPU_SAMPLER_MAX, 0, 1);
}
void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
@@ -289,22 +266,17 @@ void DRW_shgroup_uniform_block(DRWShadingGroup *shgroup,
const GPUUniformBuffer *ubo)
{
BLI_assert(ubo != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK, ubo, 0, 1);
+ int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK, ubo, 0, 0, 1);
}
-/* Same as DRW_shgroup_uniform_block but is guaranteed to be bound if shader does not change
- * between shgrp. */
-void DRW_shgroup_uniform_block_persistent(DRWShadingGroup *shgroup,
- const char *name,
- const GPUUniformBuffer *ubo)
+void DRW_shgroup_uniform_block_ref(DRWShadingGroup *shgroup,
+ const char *name,
+ GPUUniformBuffer **ubo)
{
BLI_assert(ubo != NULL);
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_BLOCK_PERSIST, ubo, 0, 1);
-}
-
-void DRW_shgroup_uniform_texture_ref(DRWShadingGroup *shgroup, const char *name, GPUTexture **tex)
-{
- drw_shgroup_uniform(shgroup, name, DRW_UNIFORM_TEXTURE_REF, tex, 0, 1);
+ int loc = GPU_shader_get_uniform_block_binding(shgroup->shader, name);
+ drw_shgroup_uniform_create_ex(shgroup, loc, DRW_UNIFORM_BLOCK_REF, ubo, 0, 0, 1);
}
void DRW_shgroup_uniform_bool(DRWShadingGroup *shgroup,
@@ -441,7 +413,7 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
const float (*value)[4],
int arraysize)
{
- int location = GPU_shader_get_uniform_ensure(shgroup->shader, name);
+ int location = GPU_shader_get_uniform(shgroup->shader, name);
if (location == -1) {
/* Nice to enable eventually, for now eevee uses uniforms that might not exist. */
@@ -450,7 +422,8 @@ void DRW_shgroup_uniform_vec4_array_copy(DRWShadingGroup *shgroup,
}
for (int i = 0; i < arraysize; i++) {
- drw_shgroup_uniform_create_ex(shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 4, 1);
+ drw_shgroup_uniform_create_ex(
+ shgroup, location + i, DRW_UNIFORM_FLOAT_COPY, &value[i], 0, 4, 1);
}
}
@@ -1196,52 +1169,49 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
shgroup->uniforms = NULL;
/* TODO(fclem) make them builtin. */
- int view_ubo_location = GPU_shader_get_uniform_block(shader, "viewBlock");
- int model_ubo_location = GPU_shader_get_uniform_block(shader, "modelBlock");
- int info_ubo_location = GPU_shader_get_uniform_block(shader, "infoBlock");
+ int view_ubo_location = GPU_shader_get_uniform_block_binding(shader, "viewBlock");
+ int model_ubo_location = GPU_shader_get_uniform_block_binding(shader, "modelBlock");
+ int info_ubo_location = GPU_shader_get_uniform_block_binding(shader, "infoBlock");
int baseinst_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_BASE_INSTANCE);
int chunkid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_CHUNK);
int resourceid_location = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_RESOURCE_ID);
if (chunkid_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 1);
+ shgroup, chunkid_location, DRW_UNIFORM_RESOURCE_CHUNK, NULL, 0, 0, 1);
}
if (resourceid_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 1);
+ shgroup, resourceid_location, DRW_UNIFORM_RESOURCE_ID, NULL, 0, 0, 1);
}
if (baseinst_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 1);
+ shgroup, baseinst_location, DRW_UNIFORM_BASE_INSTANCE, NULL, 0, 0, 1);
}
if (model_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 1);
+ shgroup, model_ubo_location, DRW_UNIFORM_BLOCK_OBMATS, NULL, 0, 0, 1);
}
else {
+ /* Note: This is only here to support old hardware fallback where uniform buffer is still
+ * too slow or buggy. */
int model = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL);
int modelinverse = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODEL_INV);
- int modelviewprojection = GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP);
if (model != -1) {
- drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, model, DRW_UNIFORM_MODEL_MATRIX, NULL, 0, 0, 1);
}
if (modelinverse != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 1);
- }
- if (modelviewprojection != -1) {
- drw_shgroup_uniform_create_ex(
- shgroup, modelviewprojection, DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX, NULL, 0, 1);
+ shgroup, modelinverse, DRW_UNIFORM_MODEL_MATRIX_INVERSE, NULL, 0, 0, 1);
}
}
if (info_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 1);
+ shgroup, info_ubo_location, DRW_UNIFORM_BLOCK_OBINFOS, NULL, 0, 0, 1);
/* Abusing this loc to tell shgroup we need the obinfos. */
shgroup->objectinfo = 1;
@@ -1252,25 +1222,21 @@ static void drw_shgroup_init(DRWShadingGroup *shgroup, GPUShader *shader)
if (view_ubo_location != -1) {
drw_shgroup_uniform_create_ex(
- shgroup, view_ubo_location, DRW_UNIFORM_BLOCK_PERSIST, G_draw.view_ubo, 0, 1);
- }
- else {
- /* Only here to support builtin shaders. This should not be used by engines. */
- /* TODO remove. */
- DRWViewUboStorage *storage = &DST.view_storage_cpy;
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW, storage->viewmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEW_INV, storage->viewinv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION, storage->persmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_VIEWPROJECTION_INV, storage->persinv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION, storage->winmat, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_PROJECTION_INV, storage->wininv, 16, 1);
- drw_shgroup_builtin_uniform(shgroup, GPU_UNIFORM_CLIPPLANES, storage->clipplanes, 4, 6);
+ shgroup, view_ubo_location, DRW_UNIFORM_BLOCK, G_draw.view_ubo, 0, 0, 1);
}
/* Not supported. */
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW_INV) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MODELVIEW) == -1);
BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_NORMAL) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEW_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_VIEWPROJECTION_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_PROJECTION_INV) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_CLIPPLANES) == -1);
+ BLI_assert(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_MVP) == -1);
}
static DRWShadingGroup *drw_shgroup_create_ex(struct GPUShader *shader, DRWPass *pass)
@@ -1308,18 +1274,20 @@ static DRWShadingGroup *drw_shgroup_material_create_ex(GPUPass *gpupass, DRWPass
static void drw_shgroup_material_texture(DRWShadingGroup *grp,
GPUMaterialTexture *tex,
const char *name,
+ eGPUSamplerState state,
int textarget)
{
GPUTexture *gputex = GPU_texture_from_blender(tex->ima, tex->iuser, NULL, textarget);
- DRW_shgroup_uniform_texture(grp, name, gputex);
+
+ int loc = GPU_shader_get_texture_binding(grp->shader, name);
+ drw_shgroup_uniform_create_ex(grp, loc, DRW_UNIFORM_TEXTURE, gputex, state, 0, 1);
GPUTexture **gputex_ref = BLI_memblock_alloc(DST.vmempool->images);
*gputex_ref = gputex;
GPU_texture_ref(gputex);
}
-static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
- struct GPUMaterial *material)
+void DRW_shgroup_add_material_resources(DRWShadingGroup *grp, struct GPUMaterial *material)
{
ListBase textures = GPU_material_textures(material);
@@ -1328,11 +1296,14 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
if (tex->ima) {
/* Image */
if (tex->tiled_mapping_name[0]) {
- drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D_ARRAY);
- drw_shgroup_material_texture(grp, tex, tex->tiled_mapping_name, GL_TEXTURE_1D_ARRAY);
+ drw_shgroup_material_texture(
+ grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D_ARRAY);
+ drw_shgroup_material_texture(
+ grp, tex, tex->tiled_mapping_name, tex->sampler_state, GL_TEXTURE_1D_ARRAY);
}
else {
- drw_shgroup_material_texture(grp, tex, tex->sampler_name, GL_TEXTURE_2D);
+ drw_shgroup_material_texture(
+ grp, tex, tex->sampler_name, tex->sampler_state, GL_TEXTURE_2D);
}
}
else if (tex->colorband) {
@@ -1345,8 +1316,6 @@ static DRWShadingGroup *drw_shgroup_material_inputs(DRWShadingGroup *grp,
if (ubo != NULL) {
DRW_shgroup_uniform_block(grp, GPU_UBO_BLOCK_NAME, ubo);
}
-
- return grp;
}
GPUVertFormat *DRW_shgroup_instance_format_array(const DRWInstanceAttrFormat attrs[],
@@ -1371,7 +1340,7 @@ DRWShadingGroup *DRW_shgroup_material_create(struct GPUMaterial *material, DRWPa
if (shgroup) {
drw_shgroup_init(shgroup, GPU_pass_shader_get(gpupass));
- drw_shgroup_material_inputs(shgroup, material);
+ DRW_shgroup_add_material_resources(shgroup, material);
}
return shgroup;
}
@@ -1390,7 +1359,7 @@ DRWShadingGroup *DRW_shgroup_transform_feedback_create(struct GPUShader *shader,
BLI_assert(tf_target != NULL);
DRWShadingGroup *shgroup = drw_shgroup_create_ex(shader, pass);
drw_shgroup_init(shgroup, shader);
- drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 1);
+ drw_shgroup_uniform_create_ex(shgroup, 0, DRW_UNIFORM_TFEEDBACK_TARGET, tf_target, 0, 0, 1);
return shgroup;
}
@@ -1922,9 +1891,28 @@ DRWPass *DRW_pass_create(const char *name, DRWState state)
pass->handle = DST.pass_handle;
DRW_handle_increment(&DST.pass_handle);
+ pass->original = NULL;
+ pass->next = NULL;
+
+ return pass;
+}
+
+DRWPass *DRW_pass_create_instance(const char *name, DRWPass *original, DRWState state)
+{
+ DRWPass *pass = DRW_pass_create(name, state);
+ pass->original = original;
+
return pass;
}
+/* Link two passes so that they are both rendered if the first one is being drawn. */
+void DRW_pass_link(DRWPass *first, DRWPass *second)
+{
+ BLI_assert(first != second);
+ BLI_assert(first->next == NULL);
+ first->next = second;
+}
+
bool DRW_pass_is_empty(DRWPass *pass)
{
LISTBASE_FOREACH (DRWShadingGroup *, shgroup, &pass->shgroups) {
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 6c62d4d2405..144ce573460 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -22,6 +22,7 @@
#include "draw_manager.h"
+#include "BLI_alloca.h"
#include "BLI_math.h"
#include "BLI_math_bits.h"
#include "BLI_memblock.h"
@@ -65,7 +66,6 @@ typedef struct DRWCommandsState {
/* Legacy matrix support. */
int obmat_loc;
int obinv_loc;
- int mvp_loc;
/* Selection ID state. */
GPUVertBuf *select_buf;
uint select_id;
@@ -655,8 +655,7 @@ static void draw_compute_culling(DRWView *view)
BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
DRWResourceHandle *handle,
float obmat_loc,
- float obinv_loc,
- float mvp_loc)
+ float obinv_loc)
{
/* Still supported for compatibility with gpu_shader_* but should be forbidden. */
DRWObjectMatrix *ob_mats = DRW_memblock_elem_from_handle(DST.vmempool->obmats, handle);
@@ -666,13 +665,6 @@ BLI_INLINE void draw_legacy_matrix_update(DRWShadingGroup *shgroup,
if (obinv_loc != -1) {
GPU_shader_uniform_vector(shgroup->shader, obinv_loc, 16, 1, (float *)ob_mats->modelinverse);
}
- /* Still supported for compatibility with gpu_shader_* but should be forbidden
- * and is slow (since it does not cache the result). */
- if (mvp_loc != -1) {
- float mvp[4][4];
- mul_m4_m4m4(mvp, DST.view_active->storage.persmat, ob_mats->model);
- GPU_shader_uniform_vector(shgroup->shader, mvp_loc, 16, 1, (float *)mvp);
- }
}
BLI_INLINE void draw_geometry_bind(DRWShadingGroup *shgroup, GPUBatch *geom)
@@ -744,107 +736,6 @@ BLI_INLINE void draw_indirect_call(DRWShadingGroup *shgroup, DRWCommandsState *s
}
}
-enum {
- BIND_NONE = 0,
- BIND_TEMP = 1, /* Release slot after this shading group. */
- BIND_PERSIST = 2, /* Release slot only after the next shader change. */
-};
-
-static void set_bound_flags(uint64_t *slots, uint64_t *persist_slots, int slot_idx, char bind_type)
-{
- uint64_t slot = 1llu << (unsigned long)slot_idx;
- *slots |= slot;
- if (bind_type == BIND_PERSIST) {
- *persist_slots |= slot;
- }
-}
-
-static int get_empty_slot_index(uint64_t slots)
-{
- uint64_t empty_slots = ~slots;
- /* Find first empty slot using bitscan. */
- if (empty_slots != 0) {
- if ((empty_slots & 0xFFFFFFFFlu) != 0) {
- return (int)bitscan_forward_uint(empty_slots);
- }
- else {
- return (int)bitscan_forward_uint(empty_slots >> 32) + 32;
- }
- }
- else {
- /* Greater than GPU_max_textures() */
- return 99999;
- }
-}
-
-static void bind_texture(GPUTexture *tex, char bind_type)
-{
- int idx = GPU_texture_bound_number(tex);
- if (idx == -1) {
- /* Texture isn't bound yet. Find an empty slot and bind it. */
- idx = get_empty_slot_index(DST.RST.bound_tex_slots);
-
- if (idx < GPU_max_textures()) {
- GPUTexture **gpu_tex_slot = &DST.RST.bound_texs[idx];
- /* Unbind any previous texture. */
- if (*gpu_tex_slot != NULL) {
- GPU_texture_unbind(*gpu_tex_slot);
- }
- GPU_texture_bind(tex, idx);
- *gpu_tex_slot = tex;
- }
- else {
- printf("Not enough texture slots! Reduce number of textures used by your shader.\n");
- return;
- }
- }
- else {
- /* This texture slot was released but the tex
- * is still bound. Just flag the slot again. */
- BLI_assert(DST.RST.bound_texs[idx] == tex);
- }
- set_bound_flags(&DST.RST.bound_tex_slots, &DST.RST.bound_tex_slots_persist, idx, bind_type);
-}
-
-static void bind_ubo(GPUUniformBuffer *ubo, char bind_type)
-{
- int idx = GPU_uniformbuffer_bindpoint(ubo);
- if (idx == -1) {
- /* UBO isn't bound yet. Find an empty slot and bind it. */
- idx = get_empty_slot_index(DST.RST.bound_ubo_slots);
-
- /* [0..1] are reserved ubo slots. */
- idx += 2;
-
- if (idx < GPU_max_ubo_binds()) {
- GPUUniformBuffer **gpu_ubo_slot = &DST.RST.bound_ubos[idx];
- /* Unbind any previous UBO. */
- if (*gpu_ubo_slot != NULL) {
- GPU_uniformbuffer_unbind(*gpu_ubo_slot);
- }
- GPU_uniformbuffer_bind(ubo, idx);
- *gpu_ubo_slot = ubo;
- }
- else {
- /* printf so user can report bad behavior */
- printf("Not enough ubo slots! This should not happen!\n");
- /* This is not depending on user input.
- * It is our responsibility to make sure there is enough slots. */
- BLI_assert(0);
- return;
- }
- }
- else {
- BLI_assert(idx < 64);
- /* This UBO slot was released but the UBO is
- * still bound here. Just flag the slot again. */
- BLI_assert(DST.RST.bound_ubos[idx] == ubo);
- }
- /* Remove offset for flag bitfield. */
- idx -= 2;
- set_bound_flags(&DST.RST.bound_ubo_slots, &DST.RST.bound_ubo_slots_persist, idx, bind_type);
-}
-
#ifndef NDEBUG
/**
* Opengl specification is strict on buffer binding.
@@ -900,28 +791,6 @@ static bool ubo_bindings_validate(DRWShadingGroup *shgroup)
}
#endif
-static void release_texture_slots(bool with_persist)
-{
- if (with_persist) {
- DST.RST.bound_tex_slots = 0;
- DST.RST.bound_tex_slots_persist = 0;
- }
- else {
- DST.RST.bound_tex_slots &= DST.RST.bound_tex_slots_persist;
- }
-}
-
-static void release_ubo_slots(bool with_persist)
-{
- if (with_persist) {
- DST.RST.bound_ubo_slots = 0;
- DST.RST.bound_ubo_slots_persist = 0;
- }
- else {
- DST.RST.bound_ubo_slots &= DST.RST.bound_ubo_slots_persist;
- }
-}
-
static void draw_update_uniforms(DRWShadingGroup *shgroup,
DRWCommandsState *state,
bool *use_tfeedback)
@@ -929,69 +798,42 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
for (DRWUniformChunk *unichunk = shgroup->uniforms; unichunk; unichunk = unichunk->next) {
DRWUniform *uni = unichunk->uniforms;
for (int i = 0; i < unichunk->uniform_used; i++, uni++) {
- GPUTexture *tex;
- GPUUniformBuffer *ubo;
- if (uni->location == -2) {
- uni->location = GPU_shader_get_uniform_ensure(shgroup->shader,
- DST.uniform_names.buffer + uni->name_ofs);
- if (uni->location == -1) {
- continue;
- }
- }
- const void *data = uni->pvalue;
- if (ELEM(uni->type, DRW_UNIFORM_INT_COPY, DRW_UNIFORM_FLOAT_COPY)) {
- data = uni->fvalue;
- }
switch (uni->type) {
case DRW_UNIFORM_INT_COPY:
+ GPU_shader_uniform_vector_int(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->ivalue);
+ break;
case DRW_UNIFORM_INT:
GPU_shader_uniform_vector_int(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_FLOAT_COPY:
+ GPU_shader_uniform_vector(
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->fvalue);
+ break;
case DRW_UNIFORM_FLOAT:
GPU_shader_uniform_vector(
- shgroup->shader, uni->location, uni->length, uni->arraysize, data);
+ shgroup->shader, uni->location, uni->length, uni->arraysize, uni->pvalue);
break;
case DRW_UNIFORM_TEXTURE:
- tex = (GPUTexture *)uni->pvalue;
- BLI_assert(tex);
- bind_texture(tex, BIND_TEMP);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
- break;
- case DRW_UNIFORM_TEXTURE_PERSIST:
- tex = (GPUTexture *)uni->pvalue;
- BLI_assert(tex);
- bind_texture(tex, BIND_PERSIST);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ GPU_texture_bind_ex(uni->texture, uni->sampler_state, uni->location, false);
break;
case DRW_UNIFORM_TEXTURE_REF:
- tex = *((GPUTexture **)uni->pvalue);
- BLI_assert(tex);
- bind_texture(tex, BIND_TEMP);
- GPU_shader_uniform_texture(shgroup->shader, uni->location, tex);
+ GPU_texture_bind_ex(*uni->texture_ref, uni->sampler_state, uni->location, false);
break;
case DRW_UNIFORM_BLOCK:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_TEMP);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(uni->block, uni->location);
break;
- case DRW_UNIFORM_BLOCK_PERSIST:
- ubo = (GPUUniformBuffer *)uni->pvalue;
- bind_ubo(ubo, BIND_PERSIST);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ case DRW_UNIFORM_BLOCK_REF:
+ GPU_uniformbuffer_bind(*uni->block_ref, uni->location);
break;
case DRW_UNIFORM_BLOCK_OBMATS:
state->obmats_loc = uni->location;
- ubo = DST.vmempool->matrices_ubo[0];
- GPU_uniformbuffer_bind(ubo, 0);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[0], uni->location);
break;
case DRW_UNIFORM_BLOCK_OBINFOS:
state->obinfos_loc = uni->location;
- ubo = DST.vmempool->obinfos_ubo[0];
- GPU_uniformbuffer_bind(ubo, 1);
- GPU_shader_uniform_buffer(shgroup->shader, uni->location, ubo);
+ GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[0], uni->location);
break;
case DRW_UNIFORM_RESOURCE_CHUNK:
state->chunkid_loc = uni->location;
@@ -1001,9 +843,9 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
state->resourceid_loc = uni->location;
break;
case DRW_UNIFORM_TFEEDBACK_TARGET:
- BLI_assert(data && (*use_tfeedback == false));
- *use_tfeedback = GPU_shader_transform_feedback_enable(shgroup->shader,
- ((GPUVertBuf *)data)->vbo_id);
+ BLI_assert(uni->pvalue && (*use_tfeedback == false));
+ *use_tfeedback = GPU_shader_transform_feedback_enable(
+ shgroup->shader, ((GPUVertBuf *)uni->pvalue)->vbo_id);
break;
/* Legacy/Fallback support. */
case DRW_UNIFORM_BASE_INSTANCE:
@@ -1015,9 +857,6 @@ static void draw_update_uniforms(DRWShadingGroup *shgroup,
case DRW_UNIFORM_MODEL_MATRIX_INVERSE:
state->obinv_loc = uni->location;
break;
- case DRW_UNIFORM_MODELVIEWPROJECTION_MATRIX:
- state->mvp_loc = uni->location;
- break;
}
}
}
@@ -1110,7 +949,7 @@ static void draw_call_resource_bind(DRWCommandsState *state, const DRWResourceHa
}
if (state->obmats_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->matrices_ubo[state->resource_chunk]);
- GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], 0);
+ GPU_uniformbuffer_bind(DST.vmempool->matrices_ubo[chunk], state->obmats_loc);
}
if (state->obinfos_loc != -1) {
GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[state->resource_chunk]);
@@ -1153,10 +992,8 @@ static void draw_call_single_do(DRWShadingGroup *shgroup,
draw_call_resource_bind(state, &handle);
/* TODO This is Legacy. Need to be removed. */
- if (state->obmats_loc == -1 &&
- (state->obmat_loc != -1 || state->obinv_loc != -1 || state->mvp_loc != -1)) {
- draw_legacy_matrix_update(
- shgroup, &handle, state->obmat_loc, state->obinv_loc, state->mvp_loc);
+ if (state->obmats_loc == -1 && (state->obmat_loc != -1 || state->obinv_loc != -1)) {
+ draw_legacy_matrix_update(shgroup, &handle, state->obmat_loc, state->obinv_loc);
}
if (G.f & G_FLAG_PICKSEL) {
@@ -1262,7 +1099,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
.resourceid_loc = -1,
.obmat_loc = -1,
.obinv_loc = -1,
- .mvp_loc = -1,
.drw_state_enabled = 0,
.drw_state_disabled = 0,
};
@@ -1273,6 +1109,11 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
if (shader_changed) {
if (DST.shader) {
GPU_shader_unbind();
+
+ /* Unbinding can be costly. Skip in normal condition. */
+ if (G.debug & G_DEBUG_GPU) {
+ GPU_texture_unbind_all();
+ }
}
GPU_shader_bind(shgroup->shader);
DST.shader = shgroup->shader;
@@ -1283,9 +1124,6 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
DST.batch = NULL;
}
- release_ubo_slots(shader_changed);
- release_texture_slots(shader_changed);
-
draw_update_uniforms(shgroup, &state, &use_tfeedback);
drw_state_set(pass_state);
@@ -1426,6 +1264,11 @@ static void drw_draw_pass_ex(DRWPass *pass,
DRWShadingGroup *start_group,
DRWShadingGroup *end_group)
{
+ if (pass->original) {
+ start_group = pass->original->shgroups.first;
+ end_group = pass->original->shgroups.last;
+ }
+
if (start_group == NULL) {
return;
}
@@ -1462,24 +1305,9 @@ static void drw_draw_pass_ex(DRWPass *pass,
}
}
- /* Clear Bound textures */
- for (int i = 0; i < DST_MAX_SLOTS; i++) {
- if (DST.RST.bound_texs[i] != NULL) {
- GPU_texture_unbind(DST.RST.bound_texs[i]);
- DST.RST.bound_texs[i] = NULL;
- }
- }
-
- /* Clear Bound Ubos */
- for (int i = 0; i < DST_MAX_SLOTS; i++) {
- if (DST.RST.bound_ubos[i] != NULL) {
- GPU_uniformbuffer_unbind(DST.RST.bound_ubos[i]);
- DST.RST.bound_ubos[i] = NULL;
- }
- }
-
if (DST.shader) {
GPU_shader_unbind();
+ GPU_texture_unbind_all();
DST.shader = NULL;
}
@@ -1511,7 +1339,9 @@ static void drw_draw_pass_ex(DRWPass *pass,
void DRW_draw_pass(DRWPass *pass)
{
- drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+ for (; pass; pass = pass->next) {
+ drw_draw_pass_ex(pass, pass->shgroups.first, pass->shgroups.last);
+ }
}
/* Draw only a subset of shgroups. Used in special situations as grease pencil strokes */
diff --git a/source/blender/draw/intern/draw_manager_shader.c b/source/blender/draw/intern/draw_manager_shader.c
index 0d6527421d0..6304b707cb9 100644
--- a/source/blender/draw/intern/draw_manager_shader.c
+++ b/source/blender/draw/intern/draw_manager_shader.c
@@ -343,27 +343,12 @@ GPUShader *DRW_shader_create_with_transform_feedback(const char *vert,
__func__);
}
-GPUShader *DRW_shader_create_2d(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_2D_vert_glsl, frag, NULL, NULL, defines, __func__);
-}
-
-GPUShader *DRW_shader_create_3d(const char *frag, const char *defines)
-{
- return GPU_shader_create(datatoc_gpu_shader_3D_vert_glsl, frag, NULL, NULL, defines, __func__);
-}
-
GPUShader *DRW_shader_create_fullscreen(const char *frag, const char *defines)
{
return GPU_shader_create(
datatoc_common_fullscreen_vert_glsl, frag, NULL, NULL, defines, __func__);
}
-GPUShader *DRW_shader_create_3d_depth_only(eGPUShaderConfig sh_cfg)
-{
- return GPU_shader_get_builtin_shader_with_config(GPU_SHADER_3D_DEPTH_ONLY, sh_cfg);
-}
-
GPUMaterial *DRW_shader_find_from_world(World *wo,
const void *engine_type,
const int options,
@@ -398,6 +383,7 @@ GPUMaterial *DRW_shader_find_from_material(Material *ma,
GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
World *wo,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -408,7 +394,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
bool deferred)
{
GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
mat = GPU_material_from_nodetree_find(&wo->gpumaterial, engine_type, options);
}
@@ -416,7 +402,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
NULL,
- wo->nodetree,
+ ntree,
&wo->gpumaterial,
engine_type,
options,
@@ -437,6 +423,7 @@ GPUMaterial *DRW_shader_create_from_world(struct Scene *scene,
GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
Material *ma,
+ struct bNodeTree *ntree,
const void *engine_type,
const int options,
const bool is_volume_shader,
@@ -447,7 +434,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
bool deferred)
{
GPUMaterial *mat = NULL;
- if (DRW_state_is_image_render()) {
+ if (DRW_state_is_image_render() || !deferred) {
mat = GPU_material_from_nodetree_find(&ma->gpumaterial, engine_type, options);
}
@@ -455,7 +442,7 @@ GPUMaterial *DRW_shader_create_from_material(struct Scene *scene,
scene = (Scene *)DEG_get_original_id(&DST.draw_ctx.scene->id);
mat = GPU_material_from_nodetree(scene,
ma,
- ma->nodetree,
+ ntree,
&ma->gpumaterial,
engine_type,
options,
diff --git a/source/blender/draw/intern/draw_manager_texture.c b/source/blender/draw/intern/draw_manager_texture.c
index 6abab38e1e6..0cb6535b1c1 100644
--- a/source/blender/draw/intern/draw_manager_texture.c
+++ b/source/blender/draw/intern/draw_manager_texture.c
@@ -61,17 +61,17 @@ static bool drw_texture_format_supports_framebuffer(eGPUTextureFormat format)
void drw_texture_set_parameters(GPUTexture *tex, DRWTextureFlag flags)
{
- GPU_texture_bind(tex, 0);
if (flags & DRW_TEX_MIPMAP) {
GPU_texture_mipmap_mode(tex, true, flags & DRW_TEX_FILTER);
+ GPU_texture_bind(tex, 0);
GPU_texture_generate_mipmap(tex);
+ GPU_texture_unbind(tex);
}
else {
GPU_texture_filter_mode(tex, flags & DRW_TEX_FILTER);
}
GPU_texture_wrap_mode(tex, flags & DRW_TEX_WRAP, true);
GPU_texture_compare_mode(tex, flags & DRW_TEX_COMPARE);
- GPU_texture_unbind(tex);
}
GPUTexture *DRW_texture_create_1d(int w,
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 4203c2677b7..a2a1f7eb1d2 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -62,67 +62,6 @@
/* *************************************************** */
/* CURRENT FRAME DRAWING */
-/* Draw current frame number in a little green box beside the current frame indicator */
-void ANIM_draw_cfra_number(const bContext *C, View2D *v2d, short flag)
-{
- Scene *scene = CTX_data_scene(C);
- const float time = scene->r.cfra + scene->r.subframe;
- const float cfra = (float)(time * scene->r.framelen);
- const bool show_time = (flag & DRAWCFRA_UNIT_SECONDS) != 0;
-
- const uiFontStyle *fstyle = UI_FSTYLE_WIDGET;
- uchar col[4];
- float color[4];
- float xscale, x, y;
- char numstr[32] = " t "; /* t is the character to start replacing from */
- float hlen;
- int slen;
-
- /* because the frame number text is subject to the same scaling as the contents of the view */
- UI_view2d_scale_get(v2d, &xscale, NULL);
- GPU_matrix_push();
- GPU_matrix_scale_2f(1.0f / xscale, 1.0f);
-
- /* get timecode string
- * - padding on str-buf passed so that it doesn't sit on the frame indicator
- */
- if (show_time) {
- BLI_timecode_string_from_time(
- &numstr[2], sizeof(numstr) - 2, 0, FRA2TIME(cfra), FPS, U.timecode_style);
- }
- else {
- BLI_timecode_string_from_time_seconds(&numstr[2], sizeof(numstr) - 2, 1, cfra);
- }
-
- slen = UI_fontstyle_string_width(fstyle, numstr) - 1;
- hlen = slen * 0.5f;
-
- /* get starting coordinates for drawing */
- x = cfra * xscale;
- y = -0.1f * U.widget_unit;
-
- /* draw green box around/behind text */
- UI_GetThemeColor4fv(TH_CFRAME, color);
- color[3] = 3.0f;
-
- UI_draw_roundbox_corner_set(UI_CNR_ALL);
- UI_draw_roundbox_aa(true,
- x - hlen - 0.1f * U.widget_unit,
- y + 3.0f,
- x + hlen + 0.1f * U.widget_unit,
- y - 3.0f + U.widget_unit,
- 0.1f * U.widget_unit,
- color);
-
- /* draw current frame number */
- UI_GetThemeColor4ubv(TH_TEXT_HI, col);
- UI_fontstyle_draw_simple(
- fstyle, x - hlen - 0.15f * U.widget_unit, y + 0.28f * U.widget_unit, numstr, col);
-
- /* restore view transform */
- GPU_matrix_pop();
-}
-
/* General call for drawing current frame indicator in animation editor */
void ANIM_draw_cfra(const bContext *C, View2D *v2d, short flag)
{
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c
index 04061ceea51..0e9b870df88 100644
--- a/source/blender/editors/animation/keyframing.c
+++ b/source/blender/editors/animation/keyframing.c
@@ -1827,7 +1827,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
* updated since the last switching to the edit mode will be keyframed correctly
*/
if (obedit && ANIM_keyingset_find_id(ks, (ID *)obedit->data)) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ED_object_mode_set(C, OB_MODE_OBJECT);
ob_edit_mode = true;
}
@@ -1843,7 +1843,7 @@ static int insert_key_exec(bContext *C, wmOperator *op)
/* restore the edit mode if necessary */
if (ob_edit_mode) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ED_object_mode_set(C, OB_MODE_EDIT);
}
/* report failure or do updates? */
diff --git a/source/blender/editors/curve/editfont_undo.c b/source/blender/editors/curve/editfont_undo.c
index af591e0c7c5..ef9bb7e0c88 100644
--- a/source/blender/editors/curve/editfont_undo.c
+++ b/source/blender/editors/curve/editfont_undo.c
@@ -359,7 +359,7 @@ static void font_undosys_step_decode(
struct bContext *C, struct Main *bmain, UndoStep *us_p, int UNUSED(dir), bool UNUSED(is_final))
{
/* TODO(campbell): undo_system: use low-level API to set mode. */
- ED_object_mode_set(C, OB_MODE_EDIT);
+ ED_object_mode_set_ex(C, OB_MODE_EDIT, false, NULL);
BLI_assert(font_undosys_poll(C));
FontUndoStep *us = (FontUndoStep *)us_p;
diff --git a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
index 1fdf1160d09..a3921791427 100644
--- a/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
+++ b/source/blender/editors/gizmo_library/gizmo_types/snap3d_gizmo.c
@@ -67,7 +67,6 @@ typedef struct SnapGizmo3D {
/* We could have other snap contexts, for now only support 3D view. */
SnapObjectContext *snap_context_v3d;
int mval[2];
- short snap_elem;
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
wmKeyMap *keymap;
@@ -75,6 +74,7 @@ typedef struct SnapGizmo3D {
bool invert_snap;
#endif
int use_snap_override;
+ short snap_elem;
} SnapGizmo3D;
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
@@ -82,11 +82,8 @@ static bool invert_snap(const wmGizmo *gz, const wmWindowManager *wm, const wmEv
{
SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
wmKeyMap *keymap = WM_keymap_active(wm, gizmo_snap->keymap);
- if (!keymap) {
- return false;
- }
- int snap_on = gizmo_snap->snap_on;
+ const int snap_on = gizmo_snap->snap_on;
for (wmKeyMapItem *kmi = keymap->items.first; kmi; kmi = kmi->next) {
if (kmi->flag & KMI_INACTIVE) {
continue;
@@ -408,14 +405,21 @@ static void gizmo_snap_draw(const bContext *C, wmGizmo *gz)
static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2])
{
SnapGizmo3D *gizmo_snap = (SnapGizmo3D *)gz;
+
#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
wmWindowManager *wm = CTX_wm_manager(C);
- const bool invert = invert_snap(gz, wm, wm->winactive->eventstate);
+ if (gizmo_snap->keymap == NULL) {
+ gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map");
+ RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on);
+ }
+
+ const bool invert = wm->winactive ? invert_snap(gz, wm, wm->winactive->eventstate) : false;
if (gizmo_snap->invert_snap == invert && gizmo_snap->mval[0] == mval[0] &&
gizmo_snap->mval[1] == mval[1]) {
/* Performance, do not update. */
return gizmo_snap->snap_elem ? 0 : -1;
}
+
gizmo_snap->invert_snap = invert;
#else
if (gizmo_snap->mval[0] == mval[0] && gizmo_snap->mval[1] == mval[1]) {
@@ -425,14 +429,6 @@ static int gizmo_snap_test_select(bContext *C, wmGizmo *gz, const int mval[2])
#endif
copy_v2_v2_int(gizmo_snap->mval, mval);
-#ifdef USE_SNAP_DETECT_FROM_KEYMAP_HACK
- if (gizmo_snap->keymap == NULL) {
- gizmo_snap->keymap = WM_modalkeymap_find(wm->defaultconf, "Generic Gizmo Tweak Modal Map");
- gizmo_snap->snap_on = -1;
- RNA_enum_value_from_id(gizmo_snap->keymap->modal_items, "SNAP_ON", &gizmo_snap->snap_on);
- }
-#endif
-
ARegion *region = CTX_wm_region(C);
View3D *v3d = CTX_wm_view3d(C);
const float mval_fl[2] = {UNPACK2(mval)};
diff --git a/source/blender/editors/gpencil/annotate_paint.c b/source/blender/editors/gpencil/annotate_paint.c
index c53b90fbfee..723c7d214e3 100644
--- a/source/blender/editors/gpencil/annotate_paint.c
+++ b/source/blender/editors/gpencil/annotate_paint.c
@@ -1729,17 +1729,16 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
}
/* Turn brush cursor in 3D view on/off */
-static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
+static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable)
{
if (p->erasercursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ WM_paint_cursor_end(p->erasercursor);
p->erasercursor = NULL;
}
else if (enable && !p->erasercursor) {
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
+ p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
NULL, /* XXX */
gpencil_draw_eraser,
@@ -1794,17 +1793,17 @@ static void gpencil_draw_stabilizer(bContext *C, int x, int y, void *p_ptr)
}
/* Turn *stabilizer* brush cursor in 3D view on/off */
-static void gpencil_draw_toggle_stabilizer_cursor(bContext *C, tGPsdata *p, short enable)
+static void gpencil_draw_toggle_stabilizer_cursor(tGPsdata *p, short enable)
{
if (p->stabilizer_cursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->stabilizer_cursor);
+ WM_paint_cursor_end(p->stabilizer_cursor);
p->stabilizer_cursor = NULL;
}
else if (enable && !p->stabilizer_cursor) {
/* enable cursor */
p->stabilizer_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, NULL, gpencil_draw_stabilizer, p);
}
}
@@ -1828,10 +1827,10 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
/* check size of buffer before cleanup, to determine if anything happened here */
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* turn off radial brush cursor */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
+ gpencil_draw_toggle_eraser_cursor(p, false);
}
else if (p->paintmode == GP_PAINTMODE_DRAW) {
- gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ gpencil_draw_toggle_stabilizer_cursor(p, false);
}
/* always store the new eraser size to be used again next time
@@ -2039,7 +2038,7 @@ static void gpencil_draw_apply(wmOperator *op, tGPsdata *p, Depsgraph *depsgraph
/* handle draw event */
static void annotation_draw_apply_event(
- bContext *C, wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
+ wmOperator *op, const wmEvent *event, Depsgraph *depsgraph, float x, float y)
{
tGPsdata *p = op->customdata;
PointerRNA itemptr;
@@ -2056,14 +2055,14 @@ static void annotation_draw_apply_event(
/* Using permanent stabilization, shift will deactivate the flag. */
if (p->flags & (GP_PAINTFLAG_USE_STABILIZER)) {
if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
- gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ gpencil_draw_toggle_stabilizer_cursor(p, false);
p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP;
}
}
/* Not using any stabilization flag. Activate temporal one. */
else if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
}
}
/* verify key status for straight lines */
@@ -2092,7 +2091,7 @@ static void annotation_draw_apply_event(
so activate the temp flag back again. */
if (p->flags & GP_PAINTFLAG_USE_STABILIZER) {
if ((p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) == 0) {
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
}
}
@@ -2102,7 +2101,7 @@ static void annotation_draw_apply_event(
else if (p->flags & GP_PAINTFLAG_USE_STABILIZER_TEMP) {
/* Reset temporal stabilizer flag and remove cursor. */
p->flags &= ~GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, false);
+ gpencil_draw_toggle_stabilizer_cursor(p, false);
}
}
@@ -2296,7 +2295,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
- gpencil_draw_toggle_eraser_cursor(C, p, true);
+ gpencil_draw_toggle_eraser_cursor(p, true);
}
else if (p->paintmode == GP_PAINTMODE_DRAW_STRAIGHT) {
if (RNA_enum_get(op->ptr, "arrowstyle_start") != GP_STROKE_ARROWSTYLE_NONE) {
@@ -2313,11 +2312,11 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
p->stabilizer_radius = RNA_int_get(op->ptr, "stabilizer_radius");
if (RNA_boolean_get(op->ptr, "use_stabilizer")) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER | GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
}
else if (event->shift > 0) {
p->flags |= GP_PAINTFLAG_USE_STABILIZER_TEMP;
- gpencil_draw_toggle_stabilizer_cursor(C, p, true);
+ gpencil_draw_toggle_stabilizer_cursor(p, true);
}
}
/* set cursor
@@ -2333,7 +2332,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
p->status = GP_STATUS_PAINTING;
/* handle the initial drawing - i.e. for just doing a simple dot */
- annotation_draw_apply_event(C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
+ annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
op->flag |= OP_IS_MODAL_CURSOR_REGION;
}
else {
@@ -2425,7 +2424,7 @@ static void annotation_add_missing_events(bContext *C,
interp_v2_v2v2(pt, a, b, 0.5f);
sub_v2_v2v2(pt, b, pt);
/* create fake event */
- annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
+ annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]);
}
else if (dist >= factor) {
int slices = 2 + (int)((dist - 1.0) / factor);
@@ -2434,7 +2433,7 @@ static void annotation_add_missing_events(bContext *C,
interp_v2_v2v2(pt, a, b, n * i);
sub_v2_v2v2(pt, b, pt);
/* create fake event */
- annotation_draw_apply_event(C, op, event, depsgraph, pt[0], pt[1]);
+ annotation_draw_apply_event(op, event, depsgraph, pt[0], pt[1]);
}
}
}
@@ -2562,7 +2561,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
* Just hiding this makes it seem like
* you can paint again...
*/
- gpencil_draw_toggle_eraser_cursor(C, p, false);
+ gpencil_draw_toggle_eraser_cursor(p, false);
}
}
@@ -2647,7 +2646,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
p->paintmode = RNA_enum_get(op->ptr, "mode");
}
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+ gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER);
/* not painting, so start stroke (this should be mouse-button down) */
p = gpencil_stroke_begin(C, op);
@@ -2681,8 +2680,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
/* TODO(sergey): Possibly evaluating dependency graph from modal operator? */
- annotation_draw_apply_event(
- C, op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
+ annotation_draw_apply_event(op, event, CTX_data_ensure_evaluated_depsgraph(C), 0.0f, 0.0f);
/* finish painting operation if anything went wrong just now */
if (p->status == GP_STATUS_ERROR) {
diff --git a/source/blender/editors/gpencil/gpencil_edit.c b/source/blender/editors/gpencil/gpencil_edit.c
index 4330a07057e..8771fcb0c8d 100644
--- a/source/blender/editors/gpencil/gpencil_edit.c
+++ b/source/blender/editors/gpencil/gpencil_edit.c
@@ -370,7 +370,7 @@ static int gpencil_paintmode_toggle_exec(bContext *C, wmOperator *op)
if (mode == OB_MODE_PAINT_GPENCIL) {
/* Be sure we have brushes and Paint settings.
- * Need Draw and Vertex (used fro Tint). */
+ * Need Draw and Vertex (used for Tint). */
BKE_paint_ensure(ts, (Paint **)&ts->gp_paint);
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
@@ -485,11 +485,13 @@ static int gpencil_sculptmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_SCULPT_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes. */
BKE_paint_ensure(ts, (Paint **)&ts->gp_sculptpaint);
- BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint);
- BKE_brush_gpencil_sculpt_presets(bmain, ts, false);
+ const bool reset_mode = (ts->gp_sculptpaint->paint.brush == NULL);
+ BKE_brush_gpencil_sculpt_presets(bmain, ts, reset_mode);
+
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_sculptpaint->paint);
}
/* setup other modes */
@@ -592,11 +594,13 @@ static int gpencil_weightmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_WEIGHT_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes. */
BKE_paint_ensure(ts, (Paint **)&ts->gp_weightpaint);
- BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint);
- BKE_brush_gpencil_weight_presets(bmain, ts, false);
+ const bool reset_mode = (ts->gp_weightpaint->paint.brush == NULL);
+ BKE_brush_gpencil_weight_presets(bmain, ts, reset_mode);
+
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_weightpaint->paint);
}
/* setup other modes */
@@ -696,11 +700,13 @@ static int gpencil_vertexmode_toggle_exec(bContext *C, wmOperator *op)
}
if (mode == OB_MODE_VERTEX_GPENCIL) {
- /* be sure we have brushes */
+ /* Be sure we have brushes. */
BKE_paint_ensure(ts, (Paint **)&ts->gp_vertexpaint);
- BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint);
- BKE_brush_gpencil_vertex_presets(bmain, ts, false);
+ const bool reset_mode = (ts->gp_vertexpaint->paint.brush == NULL);
+ BKE_brush_gpencil_vertex_presets(bmain, ts, reset_mode);
+
+ BKE_paint_toolslots_brush_validate(bmain, &ts->gp_vertexpaint->paint);
/* Ensure Palette by default. */
BKE_gpencil_palette_ensure(bmain, CTX_data_scene(C));
diff --git a/source/blender/editors/gpencil/gpencil_paint.c b/source/blender/editors/gpencil/gpencil_paint.c
index 4e83c4fb11c..06079c34d12 100644
--- a/source/blender/editors/gpencil/gpencil_paint.c
+++ b/source/blender/editors/gpencil/gpencil_paint.c
@@ -2299,18 +2299,17 @@ static void gpencil_draw_eraser(bContext *UNUSED(C), int x, int y, void *p_ptr)
}
/* Turn brush cursor in 3D view on/off */
-static void gpencil_draw_toggle_eraser_cursor(bContext *C, tGPsdata *p, short enable)
+static void gpencil_draw_toggle_eraser_cursor(tGPsdata *p, short enable)
{
if (p->erasercursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), p->erasercursor);
+ WM_paint_cursor_end(p->erasercursor);
p->erasercursor = NULL;
}
else if (enable && !p->erasercursor) {
ED_gpencil_toggle_brush_cursor(p->C, false, NULL);
/* enable cursor */
- p->erasercursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
+ p->erasercursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
NULL, /* XXX */
gpencil_draw_eraser,
@@ -2335,7 +2334,7 @@ static void gpencil_draw_exit(bContext *C, wmOperator *op)
/* check size of buffer before cleanup, to determine if anything happened here */
if (p->paintmode == GP_PAINTMODE_ERASER) {
/* turn off radial brush cursor */
- gpencil_draw_toggle_eraser_cursor(C, p, false);
+ gpencil_draw_toggle_eraser_cursor(p, false);
}
/* always store the new eraser size to be used again next time
@@ -3154,7 +3153,7 @@ static int gpencil_draw_invoke(bContext *C, wmOperator *op, const wmEvent *event
/* TODO: set any additional settings that we can take from the events?
* if eraser is on, draw radial aid */
if (p->paintmode == GP_PAINTMODE_ERASER) {
- gpencil_draw_toggle_eraser_cursor(C, p, true);
+ gpencil_draw_toggle_eraser_cursor(p, true);
}
else {
ED_gpencil_toggle_brush_cursor(C, true, NULL);
@@ -3700,7 +3699,7 @@ static int gpencil_draw_modal(bContext *C, wmOperator *op, const wmEvent *event)
p->paintmode = RNA_enum_get(op->ptr, "mode");
}
- gpencil_draw_toggle_eraser_cursor(C, p, p->paintmode == GP_PAINTMODE_ERASER);
+ gpencil_draw_toggle_eraser_cursor(p, p->paintmode == GP_PAINTMODE_ERASER);
/* not painting, so start stroke (this should be mouse-button down) */
p = gpencil_stroke_begin(C, op);
diff --git a/source/blender/editors/gpencil/gpencil_select.c b/source/blender/editors/gpencil/gpencil_select.c
index 69d22b52ded..7accf48832a 100644
--- a/source/blender/editors/gpencil/gpencil_select.c
+++ b/source/blender/editors/gpencil/gpencil_select.c
@@ -43,6 +43,7 @@
#include "BKE_context.h"
#include "BKE_gpencil.h"
+#include "BKE_material.h"
#include "BKE_report.h"
#include "UI_interface.h"
@@ -67,6 +68,45 @@
/** \name Shared Utilities
* \{ */
+/* Check if mouse inside stroke. */
+static bool gpencil_point_inside_stroke(bGPDstroke *gps,
+ GP_SpaceConversion *gsc,
+ int mouse[2],
+ const float diff_mat[4][4])
+{
+ bool hit = false;
+ if (gps->totpoints == 0) {
+ return hit;
+ }
+
+ int(*mcoords)[2] = NULL;
+ int len = gps->totpoints;
+ mcoords = MEM_mallocN(sizeof(int) * 2 * len, __func__);
+
+ /* Convert stroke to 2D array of points. */
+ bGPDspoint *pt;
+ int i;
+ for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
+ bGPDspoint pt2;
+ gp_point_to_parent_space(pt, diff_mat, &pt2);
+ gp_point_to_xy(gsc, gps, &pt2, &mcoords[i][0], &mcoords[i][1]);
+ }
+
+ /* Compute boundbox of lasso (for faster testing later). */
+ rcti rect;
+ BLI_lasso_boundbox(&rect, mcoords, len);
+
+ /* Test if point inside stroke. */
+ hit = ((!ELEM(V2D_IS_CLIPPED, mouse[0], mouse[1])) &&
+ BLI_rcti_isect_pt(&rect, mouse[0], mouse[1]) &&
+ BLI_lasso_is_point_inside(mcoords, len, mouse[0], mouse[1], INT_MAX));
+
+ /* Free memory. */
+ MEM_SAFE_FREE(mcoords);
+
+ return hit;
+}
+
/* Convert sculpt mask mode to Select mode */
static int gpencil_select_mode_from_sculpt(eGP_Sculpt_SelectMaskFlag mode)
{
@@ -1118,10 +1158,8 @@ typedef bool (*GPencilTestFn)(bGPDstroke *gps,
const float diff_mat[4][4],
void *user_data);
-static int gpencil_generic_select_exec(bContext *C,
- wmOperator *op,
- GPencilTestFn is_inside_fn,
- void *user_data)
+static int gpencil_generic_select_exec(
+ bContext *C, wmOperator *op, GPencilTestFn is_inside_fn, rcti box, void *user_data)
{
Object *ob = CTX_data_active_object(C);
bGPdata *gpd = ED_gpencil_data_get_active(C);
@@ -1143,7 +1181,6 @@ static int gpencil_generic_select_exec(bContext *C,
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
const bool segmentmode = ((selectmode == GP_SELECTMODE_SEGMENT) &&
((gpd->flag & GP_DATA_STROKE_PAINTMODE) == 0));
- const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
const eSelectOp sel_op = RNA_enum_get(op->ptr, "mode");
const float scale = ts->gp_sculpt.isect_threshold;
@@ -1180,15 +1217,13 @@ static int gpencil_generic_select_exec(bContext *C,
/* select/deselect points */
GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
+ bool whole = false;
bGPDspoint *pt;
int i;
bool hit = false;
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if (pt->runtime.pt_orig == NULL) {
- continue;
- }
- bGPDspoint *pt_active = pt->runtime.pt_orig;
+ bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
/* convert point coords to screenspace */
const bool is_inside = is_inside_fn(gps, pt, &gsc, gpstroke_iter.diff_mat, user_data);
@@ -1198,9 +1233,10 @@ static int gpencil_generic_select_exec(bContext *C,
if (sel_op_result != -1) {
SET_FLAG_FROM_TEST(pt_active->flag, sel_op_result, GP_SPOINT_SELECT);
changed = true;
+ hit = true;
- /* expand selection to segment */
- if ((sel_op_result != -1) && (segmentmode)) {
+ /* Expand selection to segment. */
+ if (segmentmode) {
bool hit_select = (bool)(pt_active->flag & GP_SPOINT_SELECT);
float r_hita[3], r_hitb[3];
ED_gpencil_select_stroke_segment(
@@ -1216,16 +1252,28 @@ static int gpencil_generic_select_exec(bContext *C,
}
}
- /* if stroke mode expand selection */
- if (strokemode) {
- const bool is_select = BKE_gpencil_stroke_select_check(gps_active);
- const bool is_inside = hit;
+ /* If nothing hit, check if the mouse is inside a filled stroke using the center or
+ * Box or lasso area. */
+ if (!hit) {
+ /* Only check filled strokes. */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
+ continue;
+ }
+ int mval[2];
+ mval[0] = (box.xmax + box.xmin) / 2;
+ mval[1] = (box.ymax + box.ymin) / 2;
+
+ whole = gpencil_point_inside_stroke(gps_active, &gsc, mval, gpstroke_iter.diff_mat);
+ }
+
+ /* if stroke mode expand selection. */
+ if ((strokemode) || (whole)) {
+ const bool is_select = BKE_gpencil_stroke_select_check(gps_active) || whole;
+ const bool is_inside = hit || whole;
const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
if (sel_op_result != -1) {
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
- if ((!is_multiedit) && (pt->runtime.pt_orig == NULL)) {
- continue;
- }
bGPDspoint *pt_active = (pt->runtime.pt_orig) ? pt->runtime.pt_orig : pt;
if (sel_op_result) {
@@ -1261,7 +1309,6 @@ static int gpencil_generic_select_exec(bContext *C,
WM_event_add_notifier(C, NC_GPENCIL | NA_SELECTED, NULL);
WM_event_add_notifier(C, NC_GEOM | ND_SELECT, NULL);
}
-
return OPERATOR_FINISHED;
}
@@ -1293,7 +1340,8 @@ static int gpencil_box_select_exec(bContext *C, wmOperator *op)
{
struct GP_SelectBoxUserData data = {0};
WM_operator_properties_border_to_rcti(op, &data.rect);
- return gpencil_generic_select_exec(C, op, gpencil_test_box, &data);
+ rcti rect = data.rect;
+ return gpencil_generic_select_exec(C, op, gpencil_test_box, rect, &data);
}
void GPENCIL_OT_select_box(wmOperatorType *ot)
@@ -1360,7 +1408,8 @@ static int gpencil_lasso_select_exec(bContext *C, wmOperator *op)
/* Compute boundbox of lasso (for faster testing later). */
BLI_lasso_boundbox(&data.rect, data.mcoords, data.mcoords_len);
- int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, &data);
+ rcti rect = data.rect;
+ int ret = gpencil_generic_select_exec(C, op, gpencil_test_lasso, rect, &data);
MEM_freeN((void *)data.mcoords);
@@ -1424,7 +1473,7 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
const bool is_multiedit = (bool)GPENCIL_MULTIEDIT_SESSIONS_ON(gpd);
/* "radius" is simply a threshold (screen space) to make it easier to test with a tolerance */
- const float radius = 0.50f * U.widget_unit;
+ const float radius = 0.4f * U.widget_unit;
const int radius_squared = (int)(radius * radius);
const bool use_shift_extend = RNA_boolean_get(op->ptr, "use_shift_extend");
@@ -1469,12 +1518,19 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
RNA_int_get_array(op->ptr, "location", mval);
/* First Pass: Find stroke point which gets hit */
- /* XXX: maybe we should go from the top of the stack down instead... */
GP_EVALUATED_STROKES_BEGIN (gpstroke_iter, C, gpl, gps) {
bGPDstroke *gps_active = (gps->runtime.gps_orig) ? gps->runtime.gps_orig : gps;
bGPDspoint *pt;
int i;
+ /* Check boundbox to speedup. */
+ float fmval[2];
+ copy_v2fl_v2i(fmval, mval);
+ if (!ED_gpencil_stroke_check_collision(
+ &gsc, gps_active, fmval, radius, gpstroke_iter.diff_mat)) {
+ continue;
+ }
+
/* firstly, check for hit-point */
for (i = 0, pt = gps->points; i < gps->totpoints; i++, pt++) {
int xy[2];
@@ -1502,11 +1558,27 @@ static int gpencil_select_exec(bContext *C, wmOperator *op)
}
}
}
+ if (ELEM(NULL, hit_stroke, hit_point)) {
+ /* If nothing hit, check if the mouse is inside any filled stroke.
+ * Only check filling materials. */
+ MaterialGPencilStyle *gp_style = BKE_gpencil_material_settings(ob, gps->mat_nr + 1);
+ if ((gp_style->flag & GP_MATERIAL_FILL_SHOW) == 0) {
+ continue;
+ }
+ bool hit_fill = gpencil_point_inside_stroke(gps, &gsc, mval, gpstroke_iter.diff_mat);
+ if (hit_fill) {
+ hit_stroke = gps_active;
+ hit_point = &gps_active->points[0];
+ /* Extend selection to all stroke. */
+ whole = true;
+ }
+ }
}
GP_EVALUATED_STROKES_END(gpstroke_iter);
/* Abort if nothing hit... */
if (ELEM(NULL, hit_stroke, hit_point)) {
+
if (deselect_all) {
/* since left mouse select change, deselect all if click outside any hit */
deselect_all_selected(C);
diff --git a/source/blender/editors/gpencil/gpencil_utils.c b/source/blender/editors/gpencil/gpencil_utils.c
index 3cab26eab44..1962eba5017 100644
--- a/source/blender/editors/gpencil/gpencil_utils.c
+++ b/source/blender/editors/gpencil/gpencil_utils.c
@@ -1871,19 +1871,18 @@ void ED_gpencil_toggle_brush_cursor(bContext *C, bool enable, void *customdata)
if (gset->paintcursor && !enable) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ WM_paint_cursor_end(gset->paintcursor);
gset->paintcursor = NULL;
}
else if (enable) {
/* in some situations cursor could be duplicated, so it is better disable first if exist */
if (gset->paintcursor) {
/* clear cursor */
- WM_paint_cursor_end(CTX_wm_manager(C), gset->paintcursor);
+ WM_paint_cursor_end(gset->paintcursor);
gset->paintcursor = NULL;
}
/* enable cursor */
- gset->paintcursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
+ gset->paintcursor = WM_paint_cursor_activate(SPACE_TYPE_ANY,
RGN_TYPE_ANY,
gp_brush_cursor_poll,
gp_brush_cursor_draw,
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 7d38792f332..426a470b128 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -652,9 +652,6 @@ enum eAnimEditDraw_CurrentFrame {
/* main call to draw current-frame indicator in an Animation Editor */
void ANIM_draw_cfra(const struct bContext *C, struct View2D *v2d, short flag);
-/* main call to draw "number box" in scrollbar for current frame indicator */
-void ANIM_draw_cfra_number(const struct bContext *C, struct View2D *v2d, short flag);
-
/* ------------- Preview Range Drawing -------------- */
/* main call to draw preview range curtains */
diff --git a/source/blender/editors/include/ED_object.h b/source/blender/editors/include/ED_object.h
index 5adc99a8ae0..a2a8fbab6b3 100644
--- a/source/blender/editors/include/ED_object.h
+++ b/source/blender/editors/include/ED_object.h
@@ -212,13 +212,11 @@ bool ED_object_editmode_load(struct Main *bmain, struct Object *obedit);
void ED_object_vpaintmode_enter_ex(struct Main *bmain,
struct Depsgraph *depsgraph,
- struct wmWindowManager *wm,
struct Scene *scene,
struct Object *ob);
void ED_object_vpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph);
void ED_object_wpaintmode_enter_ex(struct Main *bmain,
struct Depsgraph *depsgraph,
- struct wmWindowManager *wm,
struct Scene *scene,
struct Object *ob);
void ED_object_wpaintmode_enter(struct bContext *C, struct Depsgraph *depsgraph);
@@ -329,11 +327,12 @@ bool ED_object_mode_compat_set(struct bContext *C,
struct Object *ob,
eObjectMode mode,
struct ReportList *reports);
-void ED_object_mode_toggle(struct bContext *C, eObjectMode mode);
-void ED_object_mode_set(struct bContext *C, eObjectMode mode);
-void ED_object_mode_exit(struct bContext *C, struct Depsgraph *depsgraph);
+bool ED_object_mode_set_ex(struct bContext *C,
+ eObjectMode mode,
+ bool use_undo,
+ struct ReportList *reports);
+bool ED_object_mode_set(struct bContext *C, eObjectMode mode);
-bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode);
void ED_object_mode_generic_exit(struct Main *bmain,
struct Depsgraph *depsgraph,
struct Scene *scene,
diff --git a/source/blender/editors/include/ED_transform.h b/source/blender/editors/include/ED_transform.h
index 9969acd04b7..a62deb9d69f 100644
--- a/source/blender/editors/include/ED_transform.h
+++ b/source/blender/editors/include/ED_transform.h
@@ -162,6 +162,19 @@ int BIF_countTransformOrientation(const struct bContext *C);
void Transform_Properties(struct wmOperatorType *ot, int flags);
+/* *** transform_orientations.c *** */
+void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]);
+short ED_transform_calc_orientation_from_type_ex(const struct bContext *C,
+ float r_mat[3][3],
+ /* extra args */
+ struct Scene *scene,
+ struct RegionView3D *rv3d,
+ struct Object *ob,
+ struct Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point);
+
/* transform gizmos */
void VIEW3D_GGT_xform_gizmo(struct wmGizmoGroupType *gzgt);
@@ -180,18 +193,6 @@ void ED_widgetgroup_gizmo2d_rotate_callbacks_set(struct wmGizmoGroupType *gzgt);
#define SNAP_INCREMENTAL_ANGLE DEG2RAD(5.0)
-void ED_transform_calc_orientation_from_type(const struct bContext *C, float r_mat[3][3]);
-void ED_transform_calc_orientation_from_type_ex(const struct bContext *C,
- float r_mat[3][3],
- /* extra args */
- struct Scene *scene,
- struct RegionView3D *rv3d,
- struct Object *ob,
- struct Object *obedit,
- const short orientation_type,
- int orientation_index_custom,
- const int pivot_point);
-
struct TransformBounds {
float center[3]; /* Center for transform widget. */
float min[3], max[3]; /* Boundbox of selection for transform widget. */
diff --git a/source/blender/editors/include/UI_interface.h b/source/blender/editors/include/UI_interface.h
index c95f517b155..01bc59f71e7 100644
--- a/source/blender/editors/include/UI_interface.h
+++ b/source/blender/editors/include/UI_interface.h
@@ -1938,7 +1938,7 @@ uiLayout *uiLayoutRadial(uiLayout *layout);
/* templates */
void uiTemplateHeader(uiLayout *layout, struct bContext *C);
void uiTemplateID(uiLayout *layout,
- struct bContext *C,
+ const struct bContext *C,
struct PointerRNA *ptr,
const char *propname,
const char *newop,
@@ -2111,7 +2111,7 @@ void uiTemplateComponentMenu(uiLayout *layout,
const char *name);
void uiTemplateNodeSocket(uiLayout *layout, struct bContext *C, float *color);
void uiTemplateCacheFile(uiLayout *layout,
- struct bContext *C,
+ const struct bContext *C,
struct PointerRNA *ptr,
const char *propname);
@@ -2144,7 +2144,7 @@ void uiTemplateNodeView(uiLayout *layout,
struct bNodeSocket *input);
void uiTemplateTextureUser(uiLayout *layout, struct bContext *C);
void uiTemplateTextureShow(uiLayout *layout,
- struct bContext *C,
+ const struct bContext *C,
struct PointerRNA *ptr,
struct PropertyRNA *prop);
diff --git a/source/blender/editors/interface/interface_eyedropper_color.c b/source/blender/editors/interface/interface_eyedropper_color.c
index ace367fd513..c917ffb3f3e 100644
--- a/source/blender/editors/interface/interface_eyedropper_color.c
+++ b/source/blender/editors/interface/interface_eyedropper_color.c
@@ -138,11 +138,26 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
{
/* we could use some clever */
Main *bmain = CTX_data_main(C);
- bScreen *screen = CTX_wm_screen(C);
- ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ wmWindowManager *wm = CTX_wm_manager(C);
const char *display_device = CTX_data_scene(C)->display_settings.display_device;
struct ColorManagedDisplay *display = IMB_colormanagement_display_get_named(display_device);
+ wmWindow *win = CTX_wm_window(C);
+ bScreen *screen = CTX_wm_screen(C);
+ ScrArea *area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ if (area == NULL) {
+ int mval[2] = {mx, my};
+ if (WM_window_find_under_cursor(wm, NULL, win, mval, &win, mval)) {
+ mx = mval[0];
+ my = mval[1];
+ screen = WM_window_get_active_screen(win);
+ area = BKE_screen_find_area_xy(screen, SPACE_TYPE_ANY, mx, my);
+ }
+ else {
+ win = NULL;
+ }
+ }
+
if (area) {
if (area->spacetype == SPACE_IMAGE) {
ARegion *region = BKE_area_find_region_xy(area, RGN_TYPE_WINDOW, mx, my);
@@ -179,12 +194,15 @@ void eyedropper_color_sample_fl(bContext *C, int mx, int my, float r_col[3])
}
}
- /* fallback to simple opengl picker */
- glReadBuffer(GL_FRONT);
- glReadPixels(mx, my, 1, 1, GL_RGB, GL_FLOAT, r_col);
- glReadBuffer(GL_BACK);
-
- IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+ if (win) {
+ /* Fallback to simple opengl picker. */
+ int mval[2] = {mx, my};
+ WM_window_pixel_sample_read(wm, win, mval, r_col);
+ IMB_colormanagement_display_to_scene_linear_v3(r_col, display);
+ }
+ else {
+ zero_v3(r_col);
+ }
}
/* sets the sample color RGB, maintaining A */
diff --git a/source/blender/editors/interface/interface_icons.c b/source/blender/editors/interface/interface_icons.c
index c94a95890c0..deea3028354 100644
--- a/source/blender/editors/interface/interface_icons.c
+++ b/source/blender/editors/interface/interface_icons.c
@@ -1603,8 +1603,8 @@ static void icon_draw_cache_texture_flush_ex(GLuint texture,
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_MULTI_RECT_COLOR);
GPU_shader_bind(shader);
- int img_loc = GPU_shader_get_uniform_ensure(shader, "image");
- int data_loc = GPU_shader_get_uniform_ensure(shader, "calls_data[0]");
+ int img_loc = GPU_shader_get_uniform(shader, "image");
+ int data_loc = GPU_shader_get_uniform(shader, "calls_data");
glUniform1i(img_loc, 0);
glUniform4fv(data_loc, ICON_DRAW_CACHE_SIZE * 3, (float *)texture_draw_calls->drawcall_cache);
@@ -1750,9 +1750,9 @@ static void icon_draw_texture(float x,
GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), alpha, alpha, alpha, alpha);
}
- glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"), x1, y1, x2, y2);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), x, y, x + w, y + h);
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"), x1, y1, x2, y2);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"), x, y, x + w, y + h);
GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
diff --git a/source/blender/editors/interface/interface_templates.c b/source/blender/editors/interface/interface_templates.c
index 9b59e4419c4..6bf2c721c20 100644
--- a/source/blender/editors/interface/interface_templates.c
+++ b/source/blender/editors/interface/interface_templates.c
@@ -799,7 +799,7 @@ static uiBut *template_id_def_new_but(uiBlock *block,
return but;
}
-static void template_ID(bContext *C,
+static void template_ID(const bContext *C,
uiLayout *layout,
TemplateID *template_ui,
StructRNA *type,
@@ -1140,7 +1140,7 @@ ID *UI_context_active_but_get_tab_ID(bContext *C)
}
}
-static void template_ID_tabs(bContext *C,
+static void template_ID_tabs(const bContext *C,
uiLayout *layout,
TemplateID *template,
StructRNA *type,
@@ -1214,7 +1214,7 @@ static void template_ID_tabs(bContext *C,
}
static void ui_template_id(uiLayout *layout,
- bContext *C,
+ const bContext *C,
PointerRNA *ptr,
const char *propname,
const char *newop,
@@ -1298,7 +1298,7 @@ static void ui_template_id(uiLayout *layout,
}
void uiTemplateID(uiLayout *layout,
- bContext *C,
+ const bContext *C,
PointerRNA *ptr,
const char *propname,
const char *newop,
@@ -7523,7 +7523,10 @@ void uiTemplateNodeSocket(uiLayout *layout, bContext *UNUSED(C), float *color)
/** \name Cache File Template
* \{ */
-void uiTemplateCacheFile(uiLayout *layout, bContext *C, PointerRNA *ptr, const char *propname)
+void uiTemplateCacheFile(uiLayout *layout,
+ const bContext *C,
+ PointerRNA *ptr,
+ const char *propname)
{
if (!ptr->data) {
return;
diff --git a/source/blender/editors/io/io_alembic.c b/source/blender/editors/io/io_alembic.c
index 551f7989d53..dc8ad858a9f 100644
--- a/source/blender/editors/io/io_alembic.c
+++ b/source/blender/editors/io/io_alembic.c
@@ -663,7 +663,7 @@ static int wm_alembic_import_exec(bContext *C, wmOperator *op)
/* Switch out of edit mode to avoid being stuck in it (T54326). */
Object *obedit = CTX_data_edit_object(C);
if (obedit) {
- ED_object_mode_toggle(C, OB_MODE_EDIT);
+ ED_object_mode_set(C, OB_MODE_OBJECT);
}
bool ok = ABC_import(C,
diff --git a/source/blender/editors/mask/mask_draw.c b/source/blender/editors/mask/mask_draw.c
index bea44ee89f8..3786ed2789c 100644
--- a/source/blender/editors/mask/mask_draw.c
+++ b/source/blender/editors/mask/mask_draw.c
@@ -752,7 +752,7 @@ void ED_mask_draw_region(
}
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(
&state, 0.0f, 0.0f, width, height, GL_RED, GL_FLOAT, GL_NEAREST, buffer, 1.0f, 1.0f, NULL);
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index f94cd778e13..5f5599b53df 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -2998,6 +2998,7 @@ static int knifetool_modal(bContext *C, wmOperator *op, const wmEvent *event)
case MOUSEROTATE:
case WHEELUPMOUSE:
case WHEELDOWNMOUSE:
+ case NDOF_MOTION:
return OPERATOR_PASS_THROUGH;
case MOUSEMOVE: /* mouse moved somewhere to select another loop */
if (kcd->mode != MODE_PANNING) {
diff --git a/source/blender/editors/mesh/editmesh_loopcut.c b/source/blender/editors/mesh/editmesh_loopcut.c
index 3861676c2cf..0f52911c603 100644
--- a/source/blender/editors/mesh/editmesh_loopcut.c
+++ b/source/blender/editors/mesh/editmesh_loopcut.c
@@ -515,6 +515,10 @@ static int loopcut_finish(RingSelOpData *lcd, bContext *C, wmOperator *op)
static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
{
+ if (event->type == NDOF_MOTION) {
+ return OPERATOR_PASS_THROUGH;
+ }
+
RingSelOpData *lcd = op->customdata;
float cuts = lcd->cuts;
float smoothness = lcd->smoothness;
@@ -606,7 +610,8 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
handled = true;
break;
- case MOUSEMOVE: /* mouse moved somewhere to select another loop */
+ case MOUSEMOVE: {
+ /* mouse moved somewhere to select another loop */
/* This is normally disabled for all modal operators.
* This is an exception since mouse movement doesn't relate to numeric input.
@@ -615,14 +620,16 @@ static int loopcut_modal(bContext *C, wmOperator *op, const wmEvent *event)
#if 0
if (!has_numinput)
#endif
- {
- lcd->vc.mval[0] = event->mval[0];
- lcd->vc.mval[1] = event->mval[1];
- loopcut_mouse_move(lcd, (int)lcd->cuts);
+ {
+ lcd->vc.mval[0] = event->mval[0];
+ lcd->vc.mval[1] = event->mval[1];
+ loopcut_mouse_move(lcd, (int)lcd->cuts);
- ED_region_tag_redraw(lcd->region);
- handled = true;
- } break;
+ ED_region_tag_redraw(lcd->region);
+ handled = true;
+ }
+ break;
+ }
}
/* Modal numinput inactive, try to handle numeric inputs last... */
diff --git a/source/blender/editors/object/object_edit.c b/source/blender/editors/object/object_edit.c
index 53a557c5871..d522dcabae3 100644
--- a/source/blender/editors/object/object_edit.c
+++ b/source/blender/editors/object/object_edit.c
@@ -1475,10 +1475,9 @@ static bool object_mode_set_poll(bContext *C)
static int object_mode_set_exec(bContext *C, wmOperator *op)
{
- bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
+ const bool use_submode = STREQ(op->idname, "OBJECT_OT_mode_set_with_submode");
Object *ob = CTX_data_active_object(C);
eObjectMode mode = RNA_enum_get(op->ptr, "mode");
- eObjectMode restore_mode = ob->mode;
const bool toggle = RNA_boolean_get(op->ptr, "toggle");
/* by default the operator assume is a mesh, but if gp object change mode */
@@ -1490,43 +1489,63 @@ static int object_mode_set_exec(bContext *C, wmOperator *op)
return OPERATOR_PASS_THROUGH;
}
+ /**
+ * Mode Switching Logic (internal details).
+ *
+ * Notes:
+ * - Code below avoids calling mode switching functions more than once,
+ * as this causes unnecessary calculations and undo steps to be added.
+ * - The previous mode (#Object.restore_mode) is object mode by default.
+ *
+ * Supported Cases:
+ * - Setting the mode (when the 'toggle' setting is off).
+ * - Toggle the mode:
+ * - Toggle between object mode and non-object mode property.
+ * - Toggle between the previous mode (#Object.restore_mode) and the mode property.
+ * - Toggle object mode.
+ * While this is similar to regular toggle,
+ * this operator depends on there being a previous mode set
+ * (this isn't bound to a key with the default key-map).
+ */
if (toggle == false) {
if (ob->mode != mode) {
- if (mode != OB_MODE_OBJECT) {
- /* Enter new mode. */
- ED_object_mode_toggle(C, mode);
- }
- else {
- ED_object_mode_compat_set(C, ob, mode, op->reports);
- }
+ ED_object_mode_set_ex(C, mode, true, op->reports);
}
}
else {
- /* Exit current mode if it's not the mode we're setting */
- if (mode != OB_MODE_OBJECT) {
- /* Enter new mode. */
- ED_object_mode_toggle(C, mode);
- }
-
- /* Special case for Object mode! */
- if ((mode == OB_MODE_OBJECT) && (restore_mode == OB_MODE_OBJECT) &&
- (ob->restore_mode != OB_MODE_OBJECT)) {
- ED_object_mode_toggle(C, ob->restore_mode);
- }
- else if (ob->mode == mode) {
- /* For toggling, store old mode so we know what to go back to */
- ob->restore_mode = restore_mode;
- }
- else if ((ob->restore_mode != OB_MODE_OBJECT) && (ob->restore_mode != mode)) {
- ED_object_mode_toggle(C, ob->restore_mode);
+ const eObjectMode mode_prev = ob->mode;
+ /* When toggling object mode, we always use the restore mode,
+ * otherwise there is nothing to do. */
+ if (mode == OB_MODE_OBJECT) {
+ if (ob->mode != OB_MODE_OBJECT) {
+ if (ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports)) {
+ /* Store old mode so we know what to go back to. */
+ ob->restore_mode = mode_prev;
+ }
+ }
+ else {
+ if (ob->restore_mode != OB_MODE_OBJECT) {
+ ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports);
+ }
+ }
}
- }
-
- /* if type is OB_GPENCIL, set cursor mode */
- if (ob->type == OB_GPENCIL) {
- if (ob->data) {
- bGPdata *gpd = (bGPdata *)ob->data;
- ED_gpencil_setup_modes(C, gpd, ob->mode);
+ else {
+ /* Non-object modes, enter the 'mode' unless it's already set,
+ * in that case use restore mode. */
+ if (ob->mode != mode) {
+ if (ED_object_mode_set_ex(C, mode, true, op->reports)) {
+ /* Store old mode so we know what to go back to. */
+ ob->restore_mode = mode_prev;
+ }
+ }
+ else {
+ if (ob->restore_mode != OB_MODE_OBJECT) {
+ ED_object_mode_set_ex(C, ob->restore_mode, true, op->reports);
+ }
+ else {
+ ED_object_mode_set_ex(C, OB_MODE_OBJECT, true, op->reports);
+ }
+ }
}
}
diff --git a/source/blender/editors/object/object_modes.c b/source/blender/editors/object/object_modes.c
index f06b6a4db2a..fbd935c2e55 100644
--- a/source/blender/editors/object/object_modes.c
+++ b/source/blender/editors/object/object_modes.c
@@ -167,41 +167,6 @@ bool ED_object_mode_compat_set(bContext *C, Object *ob, eObjectMode mode, Report
return ok;
}
-void ED_object_mode_toggle(bContext *C, eObjectMode mode)
-{
- if (mode != OB_MODE_OBJECT) {
- const char *opstring = object_mode_op_string(mode);
-
- if (opstring) {
- wmOperatorType *ot = WM_operatortype_find(opstring, false);
- WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
- }
- }
-}
-
-/* Wrapper for operator */
-void ED_object_mode_set(bContext *C, eObjectMode mode)
-{
- wmWindowManager *wm = CTX_wm_manager(C);
- wm->op_undo_depth++;
- /* needed so we don't do undo pushes. */
- ED_object_mode_generic_enter(C, mode);
- wm->op_undo_depth--;
-}
-
-void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph)
-{
- struct Main *bmain = CTX_data_main(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- FOREACH_OBJECT_BEGIN (view_layer, ob) {
- if (ob->mode & OB_MODE_ALL_MODE_DATA) {
- ED_object_mode_generic_exit(bmain, depsgraph, scene, ob);
- }
- }
- FOREACH_OBJECT_END;
-}
-
/** \} */
/* -------------------------------------------------------------------- */
@@ -212,23 +177,50 @@ void ED_object_mode_exit(bContext *C, Depsgraph *depsgraph)
*
* \{ */
-bool ED_object_mode_generic_enter(struct bContext *C, eObjectMode object_mode)
+bool ED_object_mode_set_ex(bContext *C, eObjectMode mode, bool use_undo, ReportList *reports)
{
+ wmWindowManager *wm = CTX_wm_manager(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
Object *ob = OBACT(view_layer);
if (ob == NULL) {
- return (object_mode == OB_MODE_OBJECT);
+ return (mode == OB_MODE_OBJECT);
+ }
+
+ if ((ob->type == OB_GPENCIL) && (mode == OB_MODE_EDIT)) {
+ mode = OB_MODE_EDIT_GPENCIL;
}
- if (ob->mode == object_mode) {
+
+ if (ob->mode == mode) {
return true;
}
- wmOperatorType *ot = WM_operatortype_find("OBJECT_OT_mode_set", false);
- PointerRNA ptr;
- WM_operator_properties_create_ptr(&ptr, ot);
- RNA_enum_set(&ptr, "mode", object_mode);
- WM_operator_name_call_ptr(C, ot, WM_OP_INVOKE_DEFAULT, &ptr);
- WM_operator_properties_free(&ptr);
- return (ob->mode == object_mode);
+
+ if (!ED_object_mode_compat_test(ob, mode)) {
+ return false;
+ }
+
+ const char *opstring = object_mode_op_string((mode == OB_MODE_OBJECT) ? ob->mode : mode);
+ wmOperatorType *ot = WM_operatortype_find(opstring, false);
+
+ if (!use_undo) {
+ wm->op_undo_depth++;
+ }
+ WM_operator_name_call_ptr(C, ot, WM_OP_EXEC_REGION_WIN, NULL);
+ if (!use_undo) {
+ wm->op_undo_depth--;
+ }
+
+ if (ob->mode != mode) {
+ BKE_reportf(reports, RPT_ERROR, "Unable to execute '%s', error changing modes", ot->name);
+ return false;
+ }
+
+ return true;
+}
+
+bool ED_object_mode_set(bContext *C, eObjectMode mode)
+{
+ /* Don't do undo push by default, since this may be called by lower level code. */
+ return ED_object_mode_set_ex(C, mode, true, NULL);
}
/**
diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 11e9c396552..ca3a559ca1d 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -2516,7 +2516,8 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
ViewLayer *view_layer = CTX_data_view_layer(C);
Collection *new_collection = (Collection *)collection->id.newid;
- BKE_collection_child_add(bmain, scene->master_collection, new_collection);
+ BKE_collection_add_from_object(bmain, scene, obcollection, new_collection);
+
FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (new_collection, new_ob) {
if (new_ob != NULL && new_ob->id.override_library != NULL) {
if ((base = BKE_view_layer_base_find(view_layer, new_ob)) == NULL) {
@@ -2524,14 +2525,7 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
base = BKE_view_layer_base_find(view_layer, new_ob);
DEG_id_tag_update_ex(bmain, &new_ob->id, ID_RECALC_TRANSFORM | ID_RECALC_BASE_FLAGS);
}
- /* parent to 'collection' empty */
- /* Disabled for now, according to some artist this is probably not really useful anyway.
- * And it breaks things like objects parented to bones
- * (most likely due to missing proper setting of inverse parent matrix?)... */
- /* Note: we might even actually want to get rid of that instantiating empty... */
- if (0 && new_ob->parent == NULL) {
- new_ob->parent = obcollection;
- }
+
if (new_ob == (Object *)obact->id.newid) {
/* TODO: is setting active needed? */
BKE_view_layer_base_select_and_set_active(view_layer, base);
@@ -2546,9 +2540,9 @@ static int make_override_library_exec(bContext *C, wmOperator *op)
}
FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
- /* obcollection is no more duplicollection-ing,
- * it merely parents whole collection of overriding instantiated objects. */
- obcollection->instance_collection = NULL;
+ /* Remove the instance empty from this scene, the items now have an overriden collection
+ * instead. */
+ ED_object_base_free_and_unlink(bmain, scene, obcollection);
/* Also, we'd likely want to lock by default things like
* transformations of implicitly overridden objects? */
diff --git a/source/blender/editors/physics/particle_edit.c b/source/blender/editors/physics/particle_edit.c
index 306adb36c52..3639cd64b7c 100644
--- a/source/blender/editors/physics/particle_edit.c
+++ b/source/blender/editors/physics/particle_edit.c
@@ -3235,12 +3235,12 @@ static void toggle_particle_cursor(bContext *C, int enable)
ParticleEditSettings *pset = PE_settings(CTX_data_scene(C));
if (pset->paintcursor && !enable) {
- WM_paint_cursor_end(CTX_wm_manager(C), pset->paintcursor);
+ WM_paint_cursor_end(pset->paintcursor);
pset->paintcursor = NULL;
}
else if (enable) {
pset->paintcursor = WM_paint_cursor_activate(
- CTX_wm_manager(C), SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL);
+ SPACE_VIEW3D, RGN_TYPE_WINDOW, PE_poll_view3d, brush_drawcursor, NULL);
}
}
diff --git a/source/blender/editors/physics/particle_edit_undo.c b/source/blender/editors/physics/particle_edit_undo.c
index 5b363bdca78..205c04f54a9 100644
--- a/source/blender/editors/physics/particle_edit_undo.c
+++ b/source/blender/editors/physics/particle_edit_undo.c
@@ -253,7 +253,7 @@ static void particle_undosys_step_decode(struct bContext *C,
{
Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
/* TODO(campbell): undo_system: use low-level API to set mode. */
- ED_object_mode_set(C, OB_MODE_PARTICLE_EDIT);
+ ED_object_mode_set_ex(C, OB_MODE_PARTICLE_EDIT, false, NULL);
BLI_assert(particle_undosys_poll(C));
ParticleUndoStep *us = (ParticleUndoStep *)us_p;
diff --git a/source/blender/editors/screen/glutil.c b/source/blender/editors/screen/glutil.c
index ddb345ab65e..a9380debbdc 100644
--- a/source/blender/editors/screen/glutil.c
+++ b/source/blender/editors/screen/glutil.c
@@ -83,7 +83,7 @@ static void immDrawPixelsTexSetupAttributes(IMMDrawPixelsTexState *state)
/* To be used before calling immDrawPixelsTex
* Default shader is GPU_SHADER_2D_IMAGE_COLOR
* You can still set uniforms with :
- * GPU_shader_uniform_int(shader, GPU_shader_get_uniform_ensure(shader, "name"), 0);
+ * GPU_shader_uniform_int(shader, GPU_shader_get_uniform(shader, "name"), 0);
* */
IMMDrawPixelsTexState immDrawPixelsTexSetup(int builtin)
{
@@ -191,7 +191,7 @@ void immDrawPixelsTexScaled_clipping(IMMDrawPixelsTexState *state,
/* NOTE: Shader could be null for GLSL OCIO drawing, it is fine, since
* it does not need color.
*/
- if (state->shader != NULL && GPU_shader_get_uniform_ensure(state->shader, "color") != -1) {
+ if (state->shader != NULL && GPU_shader_get_uniform(state->shader, "color") != -1) {
immUniformColor4fv((color) ? color : white);
}
diff --git a/source/blender/editors/screen/workspace_edit.c b/source/blender/editors/screen/workspace_edit.c
index 3edc51b038b..478a0adfd9a 100644
--- a/source/blender/editors/screen/workspace_edit.c
+++ b/source/blender/editors/screen/workspace_edit.c
@@ -83,8 +83,7 @@ static void workspace_change_update(WorkSpace *workspace_new,
eObjectMode mode_new = workspace_new->object_mode;
if (mode_old != mode_new) {
- ED_object_mode_compat_set(C, ob_act, mode_new, &wm->reports);
- ED_object_mode_toggle(C, mode_new);
+ ED_object_mode_set(C, mode_new);
}
#endif
}
@@ -175,7 +174,7 @@ bool ED_workspace_change(WorkSpace *workspace_new, bContext *C, wmWindowManager
/* Automatic mode switching. */
if (workspace_new->object_mode != workspace_old->object_mode) {
- ED_object_mode_generic_enter(C, workspace_new->object_mode);
+ ED_object_mode_set(C, workspace_new->object_mode);
}
return true;
diff --git a/source/blender/editors/sculpt_paint/paint_cursor.c b/source/blender/editors/sculpt_paint/paint_cursor.c
index 191a064a95c..4222a466a7b 100644
--- a/source/blender/editors/sculpt_paint/paint_cursor.c
+++ b/source/blender/editors/sculpt_paint/paint_cursor.c
@@ -1674,23 +1674,13 @@ static void paint_draw_cursor(bContext *C, int x, int y, void *UNUSED(unused))
/* Public API */
-void paint_cursor_start(bContext *C, bool (*poll)(bContext *C))
+void paint_cursor_start(Paint *p, bool (*poll)(bContext *C))
{
- Paint *p = BKE_paint_get_active_from_context(C);
-
if (p && !p->paint_cursor) {
p->paint_cursor = WM_paint_cursor_activate(
- CTX_wm_manager(C), SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
}
/* Invalidate the paint cursors. */
BKE_paint_invalidate_overlay_all();
}
-
-void paint_cursor_start_explicit(Paint *p, wmWindowManager *wm, bool (*poll)(bContext *C))
-{
- if (p && !p->paint_cursor) {
- p->paint_cursor = WM_paint_cursor_activate(
- wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, poll, paint_draw_cursor, NULL);
- }
-}
diff --git a/source/blender/editors/sculpt_paint/paint_image.c b/source/blender/editors/sculpt_paint/paint_image.c
index fd5018f76ff..6ad4d1e650a 100644
--- a/source/blender/editors/sculpt_paint/paint_image.c
+++ b/source/blender/editors/sculpt_paint/paint_image.c
@@ -511,12 +511,8 @@ static PaintOperation *texture_paint_init(bContext *C, wmOperator *op, const flo
}
if ((brush->imagepaint_tool == PAINT_TOOL_FILL) && (brush->flag & BRUSH_USE_GRADIENT)) {
- pop->cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- image_paint_poll,
- gradient_draw_line,
- pop);
+ pop->cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, image_paint_poll, gradient_draw_line, pop);
}
settings->imapaint.flag |= IMAGEPAINT_DRAWING;
@@ -655,7 +651,7 @@ static void paint_stroke_done(const bContext *C, struct PaintStroke *stroke)
}
if (pop->cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), pop->cursor);
+ WM_paint_cursor_end(pop->cursor);
}
ED_image_undo_push_end();
@@ -787,17 +783,17 @@ bool get_imapaint_zoom(bContext *C, float *zoomx, float *zoomy)
static void toggle_paint_cursor(bContext *C, int enable)
{
- wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
ToolSettings *settings = scene->toolsettings;
+ Paint *p = &settings->imapaint.paint;
- if (settings->imapaint.paintcursor && !enable) {
- WM_paint_cursor_end(wm, settings->imapaint.paintcursor);
- settings->imapaint.paintcursor = NULL;
+ if (p->paint_cursor && !enable) {
+ WM_paint_cursor_end(p->paint_cursor);
+ p->paint_cursor = NULL;
paint_cursor_delete_textures();
}
else if (enable) {
- paint_cursor_start(C, image_paint_poll);
+ paint_cursor_start(p, image_paint_poll);
}
}
@@ -827,7 +823,7 @@ void ED_space_image_paint_update(Main *bmain, wmWindowManager *wm, Scene *scene)
if (enabled) {
BKE_paint_init(bmain, scene, PAINT_MODE_TEXTURE_2D, PAINT_CURSOR_TEXTURE_PAINT);
- paint_cursor_start_explicit(&imapaint->paint, wm, image_paint_poll);
+ paint_cursor_start(&imapaint->paint, image_paint_poll);
}
else {
paint_cursor_delete_textures();
diff --git a/source/blender/editors/sculpt_paint/paint_intern.h b/source/blender/editors/sculpt_paint/paint_intern.h
index 018d7f72bb6..0d4e957c77b 100644
--- a/source/blender/editors/sculpt_paint/paint_intern.h
+++ b/source/blender/editors/sculpt_paint/paint_intern.h
@@ -90,10 +90,7 @@ void *paint_stroke_mode_data(struct PaintStroke *stroke);
float paint_stroke_distance_get(struct PaintStroke *stroke);
void paint_stroke_set_mode_data(struct PaintStroke *stroke, void *mode_data);
bool paint_poll(struct bContext *C);
-void paint_cursor_start(struct bContext *C, bool (*poll)(struct bContext *C));
-void paint_cursor_start_explicit(struct Paint *p,
- struct wmWindowManager *wm,
- bool (*poll)(struct bContext *C));
+void paint_cursor_start(struct Paint *p, bool (*poll)(struct bContext *C));
void paint_cursor_delete_textures(void);
/* paint_vertex.c */
diff --git a/source/blender/editors/sculpt_paint/paint_stroke.c b/source/blender/editors/sculpt_paint/paint_stroke.c
index 723ac58bc6e..2c6f708d82a 100644
--- a/source/blender/editors/sculpt_paint/paint_stroke.c
+++ b/source/blender/editors/sculpt_paint/paint_stroke.c
@@ -962,7 +962,7 @@ void paint_stroke_free(bContext *C, wmOperator *op)
}
if (stroke->stroke_cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), stroke->stroke_cursor);
+ WM_paint_cursor_end(stroke->stroke_cursor);
}
BLI_freelistN(&stroke->line);
@@ -1385,12 +1385,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (paint_supports_smooth_stroke(br, mode)) {
- stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- paint_poll,
- paint_draw_smooth_cursor,
- stroke);
+ stroke->stroke_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_smooth_cursor, stroke);
}
stroke->stroke_init = true;
@@ -1416,12 +1412,8 @@ int paint_stroke_modal(bContext *C, wmOperator *op, const wmEvent *event)
}
if (br->flag & BRUSH_LINE) {
- stroke->stroke_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- paint_poll,
- paint_draw_line_cursor,
- stroke);
+ stroke->stroke_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, paint_poll, paint_draw_line_cursor, stroke);
}
first_dab = true;
diff --git a/source/blender/editors/sculpt_paint/paint_vertex.c b/source/blender/editors/sculpt_paint/paint_vertex.c
index 6172b77de07..6de54b3ae6a 100644
--- a/source/blender/editors/sculpt_paint/paint_vertex.c
+++ b/source/blender/editors/sculpt_paint/paint_vertex.c
@@ -1193,12 +1193,8 @@ static void vertex_paint_init_session_data(const ToolSettings *ts, Object *ob)
/** \name Enter Vertex/Weight Paint Mode
* \{ */
-static void ed_vwpaintmode_enter_generic(Main *bmain,
- Depsgraph *depsgraph,
- wmWindowManager *wm,
- Scene *scene,
- Object *ob,
- const eObjectMode mode_flag)
+static void ed_vwpaintmode_enter_generic(
+ Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob, const eObjectMode mode_flag)
{
ob->mode |= mode_flag;
Mesh *me = BKE_mesh_from_object(ob);
@@ -1214,7 +1210,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->vpaint);
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- paint_cursor_start_explicit(paint, wm, vertex_paint_poll);
+ paint_cursor_start(paint, vertex_paint_poll);
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_VERTEX_PAINT);
}
else if (mode_flag == OB_MODE_WEIGHT_PAINT) {
@@ -1222,7 +1218,7 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
BKE_paint_ensure(scene->toolsettings, (Paint **)&scene->toolsettings->wpaint);
Paint *paint = BKE_paint_get_active_from_paintmode(scene, paint_mode);
- paint_cursor_start_explicit(paint, wm, weight_paint_poll);
+ paint_cursor_start(paint, weight_paint_poll);
BKE_paint_init(bmain, scene, paint_mode, PAINT_CURSOR_WEIGHT_PAINT);
/* weight paint specific */
@@ -1248,32 +1244,28 @@ static void ed_vwpaintmode_enter_generic(Main *bmain,
DEG_id_tag_update(&ob->id, ID_RECALC_COPY_ON_WRITE);
}
-void ED_object_vpaintmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob)
+void ED_object_vpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_VERTEX_PAINT);
+ ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_VERTEX_PAINT);
}
void ED_object_vpaintmode_enter(struct bContext *C, Depsgraph *depsgraph)
{
Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
-void ED_object_wpaintmode_enter_ex(
- Main *bmain, Depsgraph *depsgraph, wmWindowManager *wm, Scene *scene, Object *ob)
+void ED_object_wpaintmode_enter_ex(Main *bmain, Depsgraph *depsgraph, Scene *scene, Object *ob)
{
- ed_vwpaintmode_enter_generic(bmain, depsgraph, wm, scene, ob, OB_MODE_WEIGHT_PAINT);
+ ed_vwpaintmode_enter_generic(bmain, depsgraph, scene, ob, OB_MODE_WEIGHT_PAINT);
}
void ED_object_wpaintmode_enter(struct bContext *C, Depsgraph *depsgraph)
{
Main *bmain = CTX_data_main(C);
- wmWindowManager *wm = CTX_wm_manager(C);
Scene *scene = CTX_data_scene(C);
Object *ob = CTX_data_active_object(C);
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
/** \} */
@@ -1384,8 +1376,7 @@ static int wpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (depsgraph) {
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
- wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->wpaint->paint);
}
@@ -2651,8 +2642,7 @@ static int vpaint_mode_toggle_exec(bContext *C, wmOperator *op)
if (depsgraph) {
depsgraph = CTX_data_ensure_evaluated_depsgraph(C);
}
- wmWindowManager *wm = CTX_wm_manager(C);
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
BKE_paint_toolslots_brush_validate(bmain, &ts->vpaint->paint);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt.c b/source/blender/editors/sculpt_paint/sculpt.c
index 4ad6bcc5d0f..b742ce91dd9 100644
--- a/source/blender/editors/sculpt_paint/sculpt.c
+++ b/source/blender/editors/sculpt_paint/sculpt.c
@@ -261,8 +261,15 @@ bool SCULPT_vertex_visible_get(SculptSession *ss, int index)
return !(ss->mvert[index].flag & ME_HIDE);
case PBVH_BMESH:
return !BM_elem_flag_test(BM_vert_at_index(ss->bm, index), BM_ELEM_HIDDEN);
- case PBVH_GRIDS:
- return true;
+ case PBVH_GRIDS: {
+ const CCGKey *key = BKE_pbvh_get_grid_key(ss->pbvh);
+ const int grid_index = index / key->grid_area;
+ const int vertex_index = index - grid_index * key->grid_area;
+ BLI_bitmap **grid_hidden = BKE_pbvh_get_grid_visibility(ss->pbvh);
+ if (grid_hidden && grid_hidden[grid_index]) {
+ return !BLI_BITMAP_TEST(grid_hidden[grid_index], vertex_index);
+ }
+ }
}
return true;
}
@@ -7628,7 +7635,7 @@ void ED_object_sculptmode_enter_ex(Main *bmain,
Paint *paint = BKE_paint_get_active_from_paintmode(scene, PAINT_MODE_SCULPT);
BKE_paint_init(bmain, scene, PAINT_MODE_SCULPT, PAINT_CURSOR_SCULPT);
- paint_cursor_start_explicit(paint, bmain->wm.first, SCULPT_poll_view3d);
+ paint_cursor_start(paint, SCULPT_poll_view3d);
/* Check dynamic-topology flag; re-enter dynamic-topology mode when changing modes,
* As long as no data was added that is not supported. */
@@ -7898,4 +7905,5 @@ void ED_operatortypes_sculpt(void)
WM_operatortype_append(SCULPT_OT_face_sets_change_visibility);
WM_operatortype_append(SCULPT_OT_face_sets_randomize_colors);
WM_operatortype_append(SCULPT_OT_face_sets_init);
+ WM_operatortype_append(SCULPT_OT_cloth_filter);
}
diff --git a/source/blender/editors/sculpt_paint/sculpt_automasking.c b/source/blender/editors/sculpt_paint/sculpt_automasking.c
index f0f6478d3a6..bfa657147fd 100644
--- a/source/blender/editors/sculpt_paint/sculpt_automasking.c
+++ b/source/blender/editors/sculpt_paint/sculpt_automasking.c
@@ -91,7 +91,7 @@ bool SCULPT_is_automasking_enabled(const Sculpt *sd, const SculptSession *ss, co
float SCULPT_automasking_factor_get(SculptSession *ss, int vert)
{
- if (ss->cache->automask) {
+ if (ss->cache && ss->cache->automask) {
return ss->cache->automask[vert];
}
else {
diff --git a/source/blender/editors/sculpt_paint/sculpt_cloth.c b/source/blender/editors/sculpt_paint/sculpt_cloth.c
index 6dac2b51645..3203282c30c 100644
--- a/source/blender/editors/sculpt_paint/sculpt_cloth.c
+++ b/source/blender/editors/sculpt_paint/sculpt_cloth.c
@@ -106,9 +106,11 @@
#define CLOTH_MAX_CONSTRAINTS_PER_VERTEX 1024
#define CLOTH_SIMULATION_TIME_STEP 0.01f
-static void cloth_brush_add_length_constraint(SculptSession *ss, const int v1, const int v2)
+static void cloth_brush_add_length_constraint(SculptSession *ss,
+ SculptClothSimulation *cloth_sim,
+ const int v1,
+ const int v2)
{
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v1 = v1;
cloth_sim->length_constraints[cloth_sim->tot_length_constraints].v2 = v2;
cloth_sim->length_constraints[cloth_sim->tot_length_constraints].length = len_v3v3(
@@ -133,12 +135,11 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
SculptSession *ss = data->ob->sculpt;
PBVHVertexIter vd;
- const float radius = ss->cache->initial_radius;
- const float limit = radius + (radius * data->brush->cloth_sim_limit);
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- if (len_squared_v3v3(vd.co, ss->cache->initial_location) < limit * limit) {
+ if (len_squared_v3v3(vd.co, data->cloth_sim_initial_location) <
+ data->cloth_sim_radius * data->cloth_sim_radius) {
SculptVertexNeighborIter ni;
int build_indices[CLOTH_MAX_CONSTRAINTS_PER_VERTEX];
@@ -159,7 +160,8 @@ static void do_cloth_brush_build_constraints_task_cb_ex(
for (int c_i = 0; c_i < tot_indices; c_i++) {
for (int c_j = 0; c_j < tot_indices; c_j++) {
if (c_i != c_j) {
- cloth_brush_add_length_constraint(ss, build_indices[c_i], build_indices[c_j]);
+ cloth_brush_add_length_constraint(
+ ss, data->cloth_sim, build_indices[c_i], build_indices[c_j]);
}
}
}
@@ -192,11 +194,11 @@ static float cloth_brush_simulation_falloff_get(const Brush *brush,
}
}
-static void cloth_brush_apply_force_to_vertex(SculptSession *ss,
+static void cloth_brush_apply_force_to_vertex(SculptSession *UNUSED(ss),
+ SculptClothSimulation *cloth_sim,
const float force[3],
const int vertex_index)
{
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
madd_v3_v3fl(cloth_sim->acceleration[vertex_index], force, 1.0f / cloth_sim->mass);
}
@@ -290,7 +292,6 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
float brush_disp[3];
float normal[3];
-
if (vd.no) {
normal_short_to_float_v3(normal, vd.no);
}
@@ -348,13 +349,15 @@ static void do_cloth_brush_apply_forces_task_cb_ex(void *__restrict userdata,
madd_v3_v3fl(force, gravity, fade);
- cloth_brush_apply_force_to_vertex(ss, force, vd.index);
+ cloth_brush_apply_force_to_vertex(ss, ss->cache->cloth_sim, force, vd.index);
}
}
BKE_pbvh_vertex_iter_end;
}
-static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, Brush *brush)
+static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss,
+ const float cloth_mass,
+ const float cloth_damping)
{
const int totverts = SCULPT_vertex_count_get(ss);
SculptClothSimulation *cloth_sim;
@@ -373,8 +376,8 @@ static SculptClothSimulation *cloth_brush_simulation_create(SculptSession *ss, B
cloth_sim->length_constraint_tweak = MEM_callocN(sizeof(float) * totverts,
"cloth sim length tweak");
- cloth_sim->mass = brush->cloth_mass;
- cloth_sim->damping = brush->cloth_damping;
+ cloth_sim->mass = cloth_mass;
+ cloth_sim->damping = cloth_damping;
return cloth_sim;
}
@@ -386,12 +389,16 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
SculptSession *ss = data->ob->sculpt;
const Brush *brush = data->brush;
PBVHVertexIter vd;
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
+ SculptClothSimulation *cloth_sim = data->cloth_sim;
const float time_step = data->cloth_time_step;
BKE_pbvh_vertex_iter_begin(ss->pbvh, data->nodes[n], vd, PBVH_ITER_UNIQUE)
{
- const float sim_factor = cloth_brush_simulation_falloff_get(
- brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[vd.index]);
+ const float sim_factor = ss->cache ? cloth_brush_simulation_falloff_get(
+ brush,
+ ss->cache->radius,
+ ss->cache->initial_location,
+ cloth_sim->init_pos[vd.index]) :
+ 1.0f;
if (sim_factor > 0.0f) {
int i = vd.index;
float temp[3];
@@ -412,7 +419,7 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
copy_v3_fl(cloth_sim->acceleration[i], 0.0f);
- copy_v3_v3(vd.co, ss->cache->cloth_sim->pos[vd.index]);
+ copy_v3_v3(vd.co, cloth_sim->pos[vd.index]);
if (vd.mvert) {
vd.mvert->flag |= ME_VERT_PBVH_UPDATE;
}
@@ -424,7 +431,10 @@ static void do_cloth_brush_solve_simulation_task_cb_ex(
static void cloth_brush_build_nodes_constraints(Sculpt *sd,
Object *ob,
PBVHNode **nodes,
- int totnode)
+ int totnode,
+ SculptClothSimulation *cloth_sim,
+ float initial_location[3],
+ const float radius)
{
Brush *brush = BKE_paint_brush(&sd->paint);
@@ -440,6 +450,9 @@ static void cloth_brush_build_nodes_constraints(Sculpt *sd,
.ob = ob,
.brush = brush,
.nodes = nodes,
+ .cloth_sim = cloth_sim,
+ .cloth_sim_initial_location = initial_location,
+ .cloth_sim_radius = radius,
};
BLI_task_parallel_range(
0, totnode, &build_constraints_data, do_cloth_brush_build_constraints_task_cb_ex, &settings);
@@ -480,10 +493,18 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
const float mask_v2 = (1.0f - SCULPT_vertex_mask_get(ss, v2)) *
SCULPT_automasking_factor_get(ss, v2);
- const float sim_factor_v1 = cloth_brush_simulation_falloff_get(
- brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v1]);
- const float sim_factor_v2 = cloth_brush_simulation_falloff_get(
- brush, ss->cache->radius, ss->cache->initial_location, cloth_sim->init_pos[v2]);
+ const float sim_factor_v1 = ss->cache ? cloth_brush_simulation_falloff_get(
+ brush,
+ ss->cache->radius,
+ ss->cache->initial_location,
+ cloth_sim->init_pos[v1]) :
+ 1.0f;
+ const float sim_factor_v2 = ss->cache ? cloth_brush_simulation_falloff_get(
+ brush,
+ ss->cache->radius,
+ ss->cache->initial_location,
+ cloth_sim->init_pos[v2]) :
+ 1.0f;
madd_v3_v3fl(cloth_sim->pos[v1], correction_vector_half, 1.0f * mask_v1 * sim_factor_v1);
madd_v3_v3fl(cloth_sim->pos[v2], correction_vector_half, -1.0f * mask_v2 * sim_factor_v2);
@@ -491,13 +512,12 @@ static void cloth_brush_satisfy_constraints(SculptSession *ss,
}
}
-static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
+static void cloth_brush_do_simulation_step(
+ Sculpt *sd, Object *ob, SculptClothSimulation *cloth_sim, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- SculptClothSimulation *cloth_sim = ss->cache->cloth_sim;
-
/* Update the constraints. */
cloth_brush_satisfy_constraints(ss, brush, cloth_sim);
@@ -508,6 +528,7 @@ static void cloth_brush_do_simulation_step(Sculpt *sd, Object *ob, PBVHNode **no
.brush = brush,
.nodes = nodes,
.cloth_time_step = CLOTH_SIMULATION_TIME_STEP,
+ .cloth_sim = cloth_sim,
};
TaskParallelSettings settings;
@@ -608,7 +629,8 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
/* The simulation structure only needs to be created on the first symmetry pass. */
if (ss->cache->mirror_symmetry_pass == 0) {
- ss->cache->cloth_sim = cloth_brush_simulation_create(ss, brush);
+ ss->cache->cloth_sim = cloth_brush_simulation_create(
+ ss, brush->cloth_mass, brush->cloth_damping);
for (int i = 0; i < totverts; i++) {
copy_v3_v3(ss->cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
copy_v3_v3(ss->cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
@@ -616,7 +638,10 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
}
/* Build the constraints. */
- cloth_brush_build_nodes_constraints(sd, ob, nodes, totnode);
+ const float radius = ss->cache->initial_radius;
+ const float limit = radius + (radius * brush->cloth_sim_limit);
+ cloth_brush_build_nodes_constraints(
+ sd, ob, nodes, totnode, ss->cache->cloth_sim, ss->cache->location, limit);
return;
}
@@ -630,7 +655,7 @@ void SCULPT_do_cloth_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode
cloth_brush_apply_brush_foces(sd, ob, nodes, totnode);
/* Update and write the simulation to the nodes. */
- cloth_brush_do_simulation_step(sd, ob, nodes, totnode);
+ cloth_brush_do_simulation_step(sd, ob, ss->cache->cloth_sim, nodes, totnode);
return;
}
@@ -706,3 +731,246 @@ void SCULPT_cloth_plane_falloff_preview_draw(const uint gpuattr,
immEnd();
}
+
+/* Cloth Filter. */
+
+typedef enum eSculpClothFilterType {
+ CLOTH_FILTER_GRAVITY,
+ CLOTH_FILTER_INFLATE,
+ CLOTH_FILTER_EXPAND,
+ CLOTH_FILTER_PINCH,
+} eSculptClothFilterType;
+
+static EnumPropertyItem prop_cloth_filter_type[] = {
+ {CLOTH_FILTER_GRAVITY, "GRAVITY", 0, "Gravity", "Applies gravity to the simulation"},
+ {CLOTH_FILTER_INFLATE, "INFLATE", 0, "Inflate", "Inflates the cloth"},
+ {CLOTH_FILTER_EXPAND, "EXPAND", 0, "Expand", "Expands the cloth's dimensions"},
+ {CLOTH_FILTER_PINCH,
+ "PINCH",
+ 0,
+ "Pinch",
+ "Pinches the cloth to the point were the cursor was when the filter started"},
+ {0, NULL, 0, NULL, NULL},
+};
+
+static void cloth_filter_apply_forces_task_cb(void *__restrict userdata,
+ const int i,
+ const TaskParallelTLS *__restrict UNUSED(tls))
+{
+ SculptThreadedTaskData *data = userdata;
+ Sculpt *sd = data->sd;
+ SculptSession *ss = data->ob->sculpt;
+ PBVHNode *node = data->nodes[i];
+
+ SculptClothSimulation *cloth_sim = ss->filter_cache->cloth_sim;
+ const int filter_type = data->filter_type;
+
+ float sculpt_gravity[3] = {0.0f};
+ if (sd->gravity_object) {
+ copy_v3_v3(sculpt_gravity, sd->gravity_object->obmat[2]);
+ }
+ else {
+ sculpt_gravity[2] = -1.0f;
+ }
+ mul_v3_fl(sculpt_gravity, sd->gravity_factor * data->filter_strength);
+
+ PBVHVertexIter vd;
+ BKE_pbvh_vertex_iter_begin(ss->pbvh, node, vd, PBVH_ITER_UNIQUE)
+ {
+ float fade = vd.mask ? *vd.mask : 0.0f;
+ fade = 1.0f - fade;
+ float force[3] = {0.0f, 0.0f, 0.0f};
+
+ if (ss->filter_cache->active_face_set != SCULPT_FACE_SET_NONE) {
+ if (!SCULPT_vertex_has_face_set(ss, vd.index, ss->filter_cache->active_face_set)) {
+ continue;
+ }
+ }
+
+ switch (filter_type) {
+ case CLOTH_FILTER_GRAVITY:
+ force[2] = -data->filter_strength * fade;
+ break;
+ case CLOTH_FILTER_INFLATE: {
+ float normal[3];
+ SCULPT_vertex_normal_get(ss, vd.index, normal);
+ mul_v3_v3fl(force, normal, fade * data->filter_strength);
+ } break;
+ case CLOTH_FILTER_EXPAND:
+ cloth_sim->length_constraint_tweak[vd.index] += fade * data->filter_strength * 0.01f;
+ zero_v3(force);
+ break;
+ case CLOTH_FILTER_PINCH:
+ sub_v3_v3v3(force, ss->filter_cache->cloth_sim_pinch_point, vd.co);
+ normalize_v3(force);
+ mul_v3_fl(force, fade * data->filter_strength);
+ break;
+ }
+
+ add_v3_v3(force, sculpt_gravity);
+
+ cloth_brush_apply_force_to_vertex(ss, cloth_sim, force, vd.index);
+ }
+ BKE_pbvh_vertex_iter_end;
+
+ BKE_pbvh_node_mark_update(node);
+}
+
+static int sculpt_cloth_filter_modal(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ SculptSession *ss = ob->sculpt;
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ int filter_type = RNA_enum_get(op->ptr, "type");
+ float filter_strength = RNA_float_get(op->ptr, "strength");
+
+ if (event->type == LEFTMOUSE && event->val == KM_RELEASE) {
+ SCULPT_filter_cache_free(ss);
+ SCULPT_undo_push_end();
+ SCULPT_flush_update_done(C, ob, SCULPT_UPDATE_COORDS);
+ return OPERATOR_FINISHED;
+ }
+
+ if (event->type != MOUSEMOVE) {
+ return OPERATOR_RUNNING_MODAL;
+ }
+
+ float len = event->prevclickx - event->mval[0];
+ filter_strength = filter_strength * -len * 0.001f * UI_DPI_FAC;
+
+ SCULPT_vertex_random_access_init(ss);
+
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ const int totverts = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(ss->filter_cache->cloth_sim->pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+
+ SculptThreadedTaskData data = {
+ .sd = sd,
+ .ob = ob,
+ .nodes = ss->filter_cache->nodes,
+ .filter_type = filter_type,
+ .filter_strength = filter_strength,
+ };
+
+ TaskParallelSettings settings;
+ BKE_pbvh_parallel_range_settings(
+ &settings, (sd->flags & SCULPT_USE_OPENMP), ss->filter_cache->totnode);
+ BLI_task_parallel_range(
+ 0, ss->filter_cache->totnode, &data, cloth_filter_apply_forces_task_cb, &settings);
+
+ /* Update and write the simulation to the nodes. */
+ cloth_brush_do_simulation_step(
+ sd, ob, ss->filter_cache->cloth_sim, ss->filter_cache->nodes, ss->filter_cache->totnode);
+
+ if (ss->deform_modifiers_active || ss->shapekey_active) {
+ SCULPT_flush_stroke_deform(sd, ob, true);
+ }
+ SCULPT_flush_update_step(C, SCULPT_UPDATE_COORDS);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+static int sculpt_cloth_filter_invoke(bContext *C, wmOperator *op, const wmEvent *event)
+{
+ Object *ob = CTX_data_active_object(C);
+ Depsgraph *depsgraph = CTX_data_depsgraph_pointer(C);
+ Sculpt *sd = CTX_data_tool_settings(C)->sculpt;
+ SculptSession *ss = ob->sculpt;
+
+ /* Update the active vertex */
+ float mouse[2];
+ SculptCursorGeometryInfo sgi;
+ mouse[0] = event->mval[0];
+ mouse[1] = event->mval[1];
+ SCULPT_cursor_geometry_info_update(C, &sgi, mouse, false);
+
+ SCULPT_vertex_random_access_init(ss);
+
+ /* Needs mask data to be available as it is used when solving the constraints. */
+ BKE_sculpt_update_object_for_edit(depsgraph, ob, true, true);
+
+ SCULPT_undo_push_begin("Cloth filter");
+ SCULPT_filter_cache_init(ob, sd);
+
+ const float cloth_mass = RNA_float_get(op->ptr, "cloth_mass");
+ const float cloth_damping = RNA_float_get(op->ptr, "cloth_damping");
+ ss->filter_cache->cloth_sim = cloth_brush_simulation_create(ss, cloth_mass, cloth_damping);
+ copy_v3_v3(ss->filter_cache->cloth_sim_pinch_point, SCULPT_active_vertex_co_get(ss));
+
+ const int totverts = SCULPT_vertex_count_get(ss);
+ for (int i = 0; i < totverts; i++) {
+ copy_v3_v3(ss->filter_cache->cloth_sim->prev_pos[i], SCULPT_vertex_co_get(ss, i));
+ copy_v3_v3(ss->filter_cache->cloth_sim->init_pos[i], SCULPT_vertex_co_get(ss, i));
+ }
+
+ float origin[3] = {0.0f, 0.0f, 0.0f};
+ cloth_brush_build_nodes_constraints(sd,
+ ob,
+ ss->filter_cache->nodes,
+ ss->filter_cache->totnode,
+ ss->filter_cache->cloth_sim,
+ origin,
+ FLT_MAX);
+
+ const bool use_face_sets = RNA_boolean_get(op->ptr, "use_face_sets");
+ if (use_face_sets) {
+ ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss);
+ }
+ else {
+ ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
+ }
+
+ WM_event_add_modal_handler(C, op);
+ return OPERATOR_RUNNING_MODAL;
+}
+
+void SCULPT_OT_cloth_filter(struct wmOperatorType *ot)
+{
+ /* Identifiers. */
+ ot->name = "Filter cloth";
+ ot->idname = "SCULPT_OT_cloth_filter";
+ ot->description = "Applies a cloth simulation deformation to the entire mesh";
+
+ /* API callbacks. */
+ ot->invoke = sculpt_cloth_filter_invoke;
+ ot->modal = sculpt_cloth_filter_modal;
+ ot->poll = SCULPT_mode_poll;
+
+ ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
+
+ /* RNA. */
+ RNA_def_enum(ot->srna,
+ "type",
+ prop_cloth_filter_type,
+ CLOTH_FILTER_GRAVITY,
+ "Filter type",
+ "Operation that is going to be applied to the mesh");
+ RNA_def_float(
+ ot->srna, "strength", 1.0f, -10.0f, 10.0f, "Strength", "Filter Strength", -10.0f, 10.0f);
+ RNA_def_float(ot->srna,
+ "cloth_mass",
+ 1.0f,
+ 0.0f,
+ 2.0f,
+ "Cloth Mass",
+ "Mass of each simulation particle",
+ 0.0f,
+ 1.0f);
+ RNA_def_float(ot->srna,
+ "cloth_damping",
+ 0.0f,
+ 0.0f,
+ 1.0f,
+ "Cloth Damping",
+ "How much the applied forces are propagated through the cloth",
+ 0.0f,
+ 1.0f);
+ ot->prop = RNA_def_boolean(ot->srna,
+ "use_face_sets",
+ false,
+ "Use Face Sets",
+ "Apply the filter only to the Face Set under the cursor");
+}
diff --git a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
index 7c438e9245b..58c9e1a569e 100644
--- a/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
+++ b/source/blender/editors/sculpt_paint/sculpt_filter_mesh.c
@@ -121,6 +121,9 @@ void SCULPT_filter_cache_init(Object *ob, Sculpt *sd)
void SCULPT_filter_cache_free(SculptSession *ss)
{
+ if (ss->filter_cache->cloth_sim) {
+ SCULPT_cloth_simulation_free(ss->filter_cache->cloth_sim);
+ }
MEM_SAFE_FREE(ss->filter_cache->nodes);
MEM_SAFE_FREE(ss->filter_cache->mask_update_it);
MEM_SAFE_FREE(ss->filter_cache->prev_mask);
@@ -565,8 +568,7 @@ static int sculpt_mesh_filter_invoke(bContext *C, wmOperator *op, const wmEvent
SCULPT_filter_cache_init(ob, sd);
if (use_face_sets) {
- ss->filter_cache->active_face_set = SCULPT_vertex_face_set_get(ss,
- SCULPT_active_vertex_get(ss));
+ ss->filter_cache->active_face_set = SCULPT_active_face_set_get(ss);
}
else {
ss->filter_cache->active_face_set = SCULPT_FACE_SET_NONE;
diff --git a/source/blender/editors/sculpt_paint/sculpt_intern.h b/source/blender/editors/sculpt_paint/sculpt_intern.h
index 6c217f66940..d7b221ae947 100644
--- a/source/blender/editors/sculpt_paint/sculpt_intern.h
+++ b/source/blender/editors/sculpt_paint/sculpt_intern.h
@@ -592,6 +592,9 @@ typedef struct SculptThreadedTaskData {
float transform_mats[8][4][4];
float cloth_time_step;
+ SculptClothSimulation *cloth_sim;
+ float *cloth_sim_initial_location;
+ float cloth_sim_radius;
float dirty_mask_min;
float dirty_mask_max;
@@ -837,6 +840,10 @@ typedef struct FilterCache {
PBVHNode **nodes;
int totnode;
+ /* Cloth filter. */
+ SculptClothSimulation *cloth_sim;
+ float cloth_sim_pinch_point[3];
+
/* mask expand iteration caches */
int mask_update_current_it;
int mask_update_last_it;
@@ -891,6 +898,9 @@ void SCULPT_OT_set_pivot_position(struct wmOperatorType *ot);
/* Mesh Filter. */
void SCULPT_OT_mesh_filter(struct wmOperatorType *ot);
+/* Cloth Filter. */
+void SCULPT_OT_cloth_filter(struct wmOperatorType *ot);
+
/* Mask filter and Dirty Mask. */
void SCULPT_OT_mask_filter(struct wmOperatorType *ot);
void SCULPT_OT_dirty_mask(struct wmOperatorType *ot);
diff --git a/source/blender/editors/sculpt_paint/sculpt_pose.c b/source/blender/editors/sculpt_paint/sculpt_pose.c
index 35f4870fa12..56ba15bef70 100644
--- a/source/blender/editors/sculpt_paint/sculpt_pose.c
+++ b/source/blender/editors/sculpt_paint/sculpt_pose.c
@@ -401,6 +401,14 @@ typedef struct PoseFloodFillData {
* that have the current face set. */
float fallback_origin[3];
int fallback_count;
+
+ /* Face Set FK mode. */
+ int *floodfill_it;
+ float *fk_weights;
+ int initial_face_set;
+ int masked_face_set_it;
+ int masked_face_set;
+ int target_face_set;
} PoseFloodFillData;
static bool pose_topology_floodfill_cb(
@@ -806,6 +814,119 @@ static SculptPoseIKChain *pose_ik_chain_init_face_sets(
return ik_chain;
}
+static bool pose_face_sets_fk_find_masked_floodfill_cb(
+ SculptSession *ss, int from_v, int to_v, bool is_duplicate, void *userdata)
+{
+ PoseFloodFillData *data = userdata;
+
+ if (!is_duplicate) {
+ data->floodfill_it[to_v] = data->floodfill_it[from_v] + 1;
+ }
+ else {
+ data->floodfill_it[to_v] = data->floodfill_it[from_v];
+ }
+
+ const int to_face_set = SCULPT_vertex_face_set_get(ss, to_v);
+ if (SCULPT_vertex_has_unique_face_set(ss, to_v) &&
+ !SCULPT_vertex_has_unique_face_set(ss, from_v) &&
+ SCULPT_vertex_has_face_set(ss, from_v, to_face_set)) {
+
+ if (data->floodfill_it[to_v] > data->masked_face_set_it) {
+ data->masked_face_set = to_face_set;
+ data->masked_face_set_it = data->floodfill_it[to_v];
+ }
+
+ if (data->target_face_set == SCULPT_FACE_SET_NONE) {
+ data->target_face_set = to_face_set;
+ }
+ }
+
+ return SCULPT_vertex_has_face_set(ss, to_v, data->initial_face_set);
+}
+
+static bool pose_face_sets_fk_set_weights_floodfill_cb(
+ SculptSession *ss, int UNUSED(from_v), int to_v, bool UNUSED(is_duplicate), void *userdata)
+{
+ PoseFloodFillData *data = userdata;
+ data->fk_weights[to_v] = 1.0f;
+ return !SCULPT_vertex_has_face_set(ss, to_v, data->masked_face_set);
+}
+
+static SculptPoseIKChain *pose_ik_chain_init_face_sets_fk(
+ Sculpt *sd, Object *ob, SculptSession *ss, const float radius, const float *initial_location)
+{
+ const int totvert = SCULPT_vertex_count_get(ss);
+
+ SculptPoseIKChain *ik_chain = pose_ik_chain_new(1, totvert);
+
+ const int active_vertex = SCULPT_active_vertex_get(ss);
+ const int active_face_set = SCULPT_active_face_set_get(ss);
+
+ SculptFloodFill flood;
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_initial(&flood, active_vertex);
+ PoseFloodFillData fdata;
+ fdata.floodfill_it = MEM_calloc_arrayN(totvert, sizeof(int), "floodfill iteration");
+ fdata.floodfill_it[active_vertex] = 1;
+ fdata.initial_face_set = active_face_set;
+ fdata.masked_face_set = SCULPT_FACE_SET_NONE;
+ fdata.target_face_set = SCULPT_FACE_SET_NONE;
+ fdata.masked_face_set_it = 0;
+ SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_find_masked_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ int origin_count = 0;
+ float origin_acc[3] = {0.0f};
+ for (int i = 0; i < totvert; i++) {
+ if (fdata.floodfill_it[i] != 0 && SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) &&
+ SCULPT_vertex_has_face_set(ss, i, fdata.masked_face_set)) {
+ add_v3_v3(origin_acc, SCULPT_vertex_co_get(ss, i));
+ origin_count++;
+ }
+ }
+
+ int target_count = 0;
+ float target_acc[3] = {0.0f};
+ if (fdata.target_face_set != fdata.masked_face_set) {
+ for (int i = 0; i < totvert; i++) {
+ if (fdata.floodfill_it[i] != 0 &&
+ SCULPT_vertex_has_face_set(ss, i, fdata.initial_face_set) &&
+ SCULPT_vertex_has_face_set(ss, i, fdata.target_face_set)) {
+ add_v3_v3(target_acc, SCULPT_vertex_co_get(ss, i));
+ target_count++;
+ }
+ }
+ }
+
+ MEM_freeN(fdata.floodfill_it);
+
+ if (origin_count > 0) {
+ copy_v3_v3(ik_chain->segments[0].orig, origin_acc);
+ mul_v3_fl(ik_chain->segments[0].orig, 1.0f / origin_count);
+ }
+ else {
+ zero_v3(ik_chain->segments[0].orig);
+ }
+
+ if (target_count > 0) {
+ copy_v3_v3(ik_chain->segments[0].head, target_acc);
+ mul_v3_fl(ik_chain->segments[0].head, 1.0f / target_count);
+ sub_v3_v3v3(ik_chain->grab_delta_offset, ik_chain->segments[0].head, initial_location);
+ }
+ else {
+ copy_v3_v3(ik_chain->segments[0].head, initial_location);
+ }
+
+ SCULPT_floodfill_init(ss, &flood);
+ SCULPT_floodfill_add_active(sd, ob, ss, &flood, radius);
+ fdata.fk_weights = ik_chain->segments[0].weights;
+ SCULPT_floodfill_execute(ss, &flood, pose_face_sets_fk_set_weights_floodfill_cb, &fdata);
+ SCULPT_floodfill_free(&flood);
+
+ pose_ik_chain_origin_heads_init(ik_chain, ik_chain->segments[0].head);
+ return ik_chain;
+}
+
SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd,
Object *ob,
SculptSession *ss,
@@ -820,6 +941,9 @@ SculptPoseIKChain *SCULPT_pose_ik_chain_init(Sculpt *sd,
case BRUSH_POSE_ORIGIN_FACE_SETS:
return pose_ik_chain_init_face_sets(sd, ob, ss, br, radius);
break;
+ case BRUSH_POSE_ORIGIN_FACE_SETS_FK:
+ return pose_ik_chain_init_face_sets_fk(sd, ob, ss, radius, initial_location);
+ break;
}
return NULL;
}
@@ -905,6 +1029,7 @@ static void sculpt_pose_do_rotate_deform(SculptSession *ss, Brush *brush)
/* Calculate the IK target. */
copy_v3_v3(ik_target, ss->cache->true_location);
add_v3_v3(ik_target, ss->cache->grab_delta);
+ add_v3_v3(ik_target, ik_chain->grab_delta_offset);
/* Solve the IK positions. */
pose_solve_ik_chain(ik_chain, ik_target, brush->flag2 & BRUSH_POSE_IK_ANCHORED);
@@ -935,7 +1060,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
{
SculptSession *ss = ob->sculpt;
Brush *brush = BKE_paint_brush(&sd->paint);
- float grab_delta[3];
const ePaintSymmetryFlags symm = sd->paint.symmetry_flags & PAINT_SYMM_AXIS_ALL;
/* The pose brush applies all enabled symmetry axis in a single iteration, so the rest can be
@@ -945,7 +1069,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
}
SculptPoseIKChain *ik_chain = ss->cache->pose_ik_chain;
- copy_v3_v3(grab_delta, ss->cache->grab_delta);
switch (brush->pose_deform_type) {
case BRUSH_POSE_DEFORM_ROTATE_TWIST:
@@ -999,7 +1122,6 @@ void SCULPT_do_pose_brush(Sculpt *sd, Object *ob, PBVHNode **nodes, int totnode)
.ob = ob,
.brush = brush,
.nodes = nodes,
- .grab_delta = grab_delta,
};
TaskParallelSettings settings;
diff --git a/source/blender/editors/space_action/action_edit.c b/source/blender/editors/space_action/action_edit.c
index e90122f2585..576b52a5cdd 100644
--- a/source/blender/editors/space_action/action_edit.c
+++ b/source/blender/editors/space_action/action_edit.c
@@ -490,7 +490,7 @@ void ACTION_OT_view_frame(wmOperatorType *ot)
/* identifiers */
ot->name = "Go to Current Frame";
ot->idname = "ACTION_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* api callbacks */
ot->exec = actkeys_view_frame_exec;
diff --git a/source/blender/editors/space_buttons/buttons_texture.c b/source/blender/editors/space_buttons/buttons_texture.c
index 5bf431be9f8..3dc5eca8a8b 100644
--- a/source/blender/editors/space_buttons/buttons_texture.c
+++ b/source/blender/editors/space_buttons/buttons_texture.c
@@ -545,7 +545,7 @@ static void template_texture_show(bContext *C, void *data_p, void *prop_p)
}
}
-void uiTemplateTextureShow(uiLayout *layout, bContext *C, PointerRNA *ptr, PropertyRNA *prop)
+void uiTemplateTextureShow(uiLayout *layout, const bContext *C, PointerRNA *ptr, PropertyRNA *prop)
{
/* button to quickly show texture in texture tab */
SpaceProperties *sbuts = CTX_wm_space_properties(C);
diff --git a/source/blender/editors/space_graph/graph_edit.c b/source/blender/editors/space_graph/graph_edit.c
index 8ffd2844f1a..a974ec612a9 100644
--- a/source/blender/editors/space_graph/graph_edit.c
+++ b/source/blender/editors/space_graph/graph_edit.c
@@ -385,7 +385,7 @@ void GRAPH_OT_view_frame(wmOperatorType *ot)
/* identifiers */
ot->name = "Go to Current Frame";
ot->idname = "GRAPH_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* api callbacks */
ot->exec = graphkeys_view_frame_exec;
diff --git a/source/blender/editors/space_image/image_draw.c b/source/blender/editors/space_image/image_draw.c
index 6037c1d2ec8..9040ca5e79c 100644
--- a/source/blender/editors/space_image/image_draw.c
+++ b/source/blender/editors/space_image/image_draw.c
@@ -476,7 +476,7 @@ static void sima_draw_zbuf_pixels(
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(
&state, x1, y1, rectx, recty, GL_RED, GL_INT, GL_NEAREST, recti, zoomx, zoomy, NULL);
@@ -524,7 +524,7 @@ static void sima_draw_zbuffloat_pixels(Scene *scene,
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(
&state, x1, y1, rectx, recty, GL_RED, GL_FLOAT, GL_NEAREST, rectf, zoomx, zoomy, NULL);
@@ -637,7 +637,7 @@ static void draw_image_buffer(const bContext *C,
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
IMB_colormanagement_display_settings_from_ctx(C, &view_settings, &display_settings);
display_buffer = IMB_display_buffer_acquire(
diff --git a/source/blender/editors/space_image/image_undo.c b/source/blender/editors/space_image/image_undo.c
index 5668b88826e..e0c44c3a0ba 100644
--- a/source/blender/editors/space_image/image_undo.c
+++ b/source/blender/editors/space_image/image_undo.c
@@ -958,7 +958,7 @@ static void image_undosys_step_decode(
}
if (us->paint_mode == PAINT_MODE_TEXTURE_3D) {
- ED_object_mode_set(C, OB_MODE_TEXTURE_PAINT);
+ ED_object_mode_set_ex(C, OB_MODE_TEXTURE_PAINT, false, NULL);
}
/* Refresh texture slots. */
diff --git a/source/blender/editors/space_nla/nla_edit.c b/source/blender/editors/space_nla/nla_edit.c
index f68896e21d6..dec7a0fd93c 100644
--- a/source/blender/editors/space_nla/nla_edit.c
+++ b/source/blender/editors/space_nla/nla_edit.c
@@ -567,7 +567,7 @@ void NLA_OT_view_frame(wmOperatorType *ot)
/* identifiers */
ot->name = "Go to Current Frame";
ot->idname = "NLA_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* api callbacks */
ot->exec = nlaedit_viewframe_exec;
diff --git a/source/blender/editors/space_node/drawnode.c b/source/blender/editors/space_node/drawnode.c
index 44003a5b9bc..01ac3a80871 100644
--- a/source/blender/editors/space_node/drawnode.c
+++ b/source/blender/editors/space_node/drawnode.c
@@ -3638,7 +3638,7 @@ void draw_nodespace_back_pix(const bContext *C,
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, shuffle);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, shuffle);
immDrawPixelsTex(&state,
x,
diff --git a/source/blender/editors/space_outliner/outliner_tree.c b/source/blender/editors/space_outliner/outliner_tree.c
index 7bb62b0d1e2..d6efe683673 100644
--- a/source/blender/editors/space_outliner/outliner_tree.c
+++ b/source/blender/editors/space_outliner/outliner_tree.c
@@ -1427,9 +1427,9 @@ static void outliner_add_layer_collections_recursive(SpaceOutliner *soops,
ten->name = id->name + 2;
ten->directdata = lc;
- /* Open by default. */
+ /* Open by default, except linked collections, which may contain many elements. */
TreeStoreElem *tselem = TREESTORE(ten);
- if (!tselem->used) {
+ if (!(tselem->used || ID_IS_LINKED(id) || ID_IS_OVERRIDE_LIBRARY(id))) {
tselem->flag &= ~TSE_CLOSED;
}
diff --git a/source/blender/editors/space_sequencer/sequencer_draw.c b/source/blender/editors/space_sequencer/sequencer_draw.c
index 5d8851d5e3d..1f06ab68516 100644
--- a/source/blender/editors/space_sequencer/sequencer_draw.c
+++ b/source/blender/editors/space_sequencer/sequencer_draw.c
@@ -2299,10 +2299,10 @@ void draw_timeline_seq(const bContext *C, ARegion *region)
cfra_flag |= DRAWCFRA_UNIT_SECONDS;
}
- /* Draw playhead. */
+ /* Draw the current frame indicator. */
ANIM_draw_cfra(C, v2d, cfra_flag);
- /* Draw overlap playhead. */
+ /* Draw overlap frame frame indicator. */
if (scene->ed && scene->ed->over_flag & SEQ_EDIT_OVERLAY_SHOW) {
int cfra_over = (scene->ed->over_flag & SEQ_EDIT_OVERLAY_ABS) ?
scene->ed->over_cfra :
diff --git a/source/blender/editors/space_sequencer/sequencer_edit.c b/source/blender/editors/space_sequencer/sequencer_edit.c
index 232bb1d66e8..ea0d5785d22 100644
--- a/source/blender/editors/space_sequencer/sequencer_edit.c
+++ b/source/blender/editors/space_sequencer/sequencer_edit.c
@@ -214,20 +214,41 @@ static void seq_proxy_build_job(const bContext *C, ReportList *reports)
}
file_list = BLI_gset_new(BLI_ghashutil_strhash_p, BLI_ghashutil_strcmp, "file list");
+ bool selected = false; /* Check for no selected strips */
+
SEQP_BEGIN (ed, seq) {
- if ((seq->flag & SELECT)) {
- bool success = BKE_sequencer_proxy_rebuild_context(
- pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
- if (!success) {
- BKE_reportf(reports, RPT_ERROR, "Could not build proxy for strip %s", seq->name);
- }
+ if (!ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META) ||
+ (seq->flag & SELECT) == 0) {
+ continue;
+ }
+
+ selected = true;
+ if (!(seq->flag & SEQ_USE_PROXY)) {
+ BKE_reportf(reports, RPT_WARNING, "Proxy is not enabled for %s, skipping.", seq->name);
+ continue;
+ }
+ else if (seq->strip->proxy->build_size_flags == 0) {
+ BKE_reportf(reports, RPT_WARNING, "Resolution is not selected for %s, skipping.", seq->name);
+ continue;
+ }
+
+ bool success = BKE_sequencer_proxy_rebuild_context(
+ pj->main, pj->depsgraph, pj->scene, seq, file_list, &pj->queue);
+
+ if (!success && (seq->strip->proxy->build_flags & SEQ_PROXY_SKIP_EXISTING) != 0) {
+ BKE_reportf(reports, RPT_WARNING, "Overwrite is not checked for %s, skipping.", seq->name);
}
}
SEQ_END;
+ if (!selected) {
+ BKE_reportf(reports, RPT_WARNING, "Select movie or image strips.");
+ return;
+ }
+
BLI_gset_free(file_list, MEM_freeN);
- if (!WM_jobs_is_running(wm_job)) {
+ if (selected && !WM_jobs_is_running(wm_job)) {
G.is_break = false;
WM_jobs_start(CTX_wm_manager(C), wm_job);
}
@@ -290,7 +311,7 @@ static int mouse_frame_side(View2D *v2d, short mouse_x, int frame)
mval[0] = mouse_x;
mval[1] = 0;
- /* Choose the side based on which side of the playhead the mouse is on. */
+ /* Choose the side based on which side of the current frame the mouse is on. */
UI_view2d_region_to_view(v2d, mval[0], mval[1], &mouseloc[0], &mouseloc[1]);
return mouseloc[0] > frame ? SEQ_SIDE_RIGHT : SEQ_SIDE_LEFT;
@@ -1355,7 +1376,7 @@ static int sequencer_snap_invoke(bContext *C, wmOperator *op, const wmEvent *UNU
void SEQUENCER_OT_snap(struct wmOperatorType *ot)
{
/* Identifiers. */
- ot->name = "Snap Strips to Playhead";
+ ot->name = "Snap Strips to the Current Frame";
ot->idname = "SEQUENCER_OT_snap";
ot->description = "Frame where selected strips will be snapped";
@@ -1706,7 +1727,7 @@ static int sequencer_slip_modal(bContext *C, wmOperator *op, const wmEvent *even
mouse_x = event->mval[0];
}
- /* Choose the side based on which side of the playhead the mouse is. */
+ /* Choose the side based on which side of the current frame the mouse is. */
UI_view2d_region_to_view(v2d, mouse_x, 0, &mouseloc[0], &mouseloc[1]);
offset = mouseloc[0] - data->init_mouseloc[0];
@@ -2353,7 +2374,7 @@ void SEQUENCER_OT_split(struct wmOperatorType *ot)
"use_cursor_position",
0,
"Use Cursor Position",
- "Split at position of the cursor instead of playhead");
+ "Split at position of the cursor instead of current frame");
prop = RNA_def_enum(ot->srna,
"side",
@@ -2955,7 +2976,7 @@ void SEQUENCER_OT_view_frame(wmOperatorType *ot)
/* Identifiers. */
ot->name = "Go to Current Frame";
ot->idname = "SEQUENCER_OT_view_frame";
- ot->description = "Move the view to the playhead";
+ ot->description = "Move the view to the current frame";
/* Api callbacks. */
ot->exec = sequencer_view_frame_exec;
@@ -3757,12 +3778,7 @@ static int sequencer_enable_proxies_exec(bContext *C, wmOperator *op)
SEQP_BEGIN (ed, seq) {
if ((seq->flag & SELECT)) {
- if (ELEM(seq->type,
- SEQ_TYPE_MOVIE,
- SEQ_TYPE_IMAGE,
- SEQ_TYPE_META,
- SEQ_TYPE_SCENE,
- SEQ_TYPE_MULTICAM)) {
+ if (ELEM(seq->type, SEQ_TYPE_MOVIE, SEQ_TYPE_IMAGE, SEQ_TYPE_META)) {
BKE_sequencer_proxy_set(seq, turnon);
if (seq->strip->proxy == NULL) {
continue;
diff --git a/source/blender/editors/space_sequencer/sequencer_intern.h b/source/blender/editors/space_sequencer/sequencer_intern.h
index 708682cd04f..0e7e691c748 100644
--- a/source/blender/editors/space_sequencer/sequencer_intern.h
+++ b/source/blender/editors/space_sequencer/sequencer_intern.h
@@ -191,6 +191,7 @@ enum {
SEQ_SELECT_LR_MOUSE,
SEQ_SELECT_LR_LEFT,
SEQ_SELECT_LR_RIGHT,
+ SEQ_SELECT_LR_OVERLAP,
};
/* Defines used internally. */
diff --git a/source/blender/editors/space_sequencer/sequencer_select.c b/source/blender/editors/space_sequencer/sequencer_select.c
index c5472ed88e5..2e6cd7f7442 100644
--- a/source/blender/editors/space_sequencer/sequencer_select.c
+++ b/source/blender/editors/space_sequencer/sequencer_select.c
@@ -412,6 +412,7 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
ret_value = OPERATOR_FINISHED;
}
+ /* Select left, right or overlapping the current frame. */
else if (left_right != SEQ_SELECT_LR_NONE) {
/* Use different logic for this. */
float x;
@@ -420,20 +421,35 @@ static int sequencer_select_exec(bContext *C, wmOperator *op)
}
switch (left_right) {
- case SEQ_SELECT_LR_MOUSE:
+ case SEQ_SELECT_LR_MOUSE: {
+ /* 10px margin around current frame to select under the current frame with mouse. */
+ float margin = BLI_rctf_size_x(&v2d->cur) / BLI_rcti_size_x(&v2d->mask) * 10;
x = UI_view2d_region_to_view_x(v2d, mval[0]);
+ if (x >= CFRA - margin && x <= CFRA + margin) {
+ x = CFRA;
+ }
break;
+ }
case SEQ_SELECT_LR_LEFT:
x = CFRA - 1.0f;
break;
case SEQ_SELECT_LR_RIGHT:
+ x = CFRA + 1.0f;
+ break;
+ case SEQ_SELECT_LR_OVERLAP:
default:
x = CFRA;
break;
}
SEQP_BEGIN (ed, seq) {
- if (((x < CFRA) && (seq->enddisp <= CFRA)) || ((x >= CFRA) && (seq->startdisp >= CFRA))) {
+ /* Select overlapping the current frame. */
+ if ((x == CFRA) && (seq->startdisp <= CFRA) && (seq->enddisp >= CFRA)) {
+ seq->flag = SELECT;
+ recurs_sel_seq(seq);
+ }
+ /* Select left or right. */
+ else if ((x < CFRA && seq->enddisp <= CFRA) || (x > CFRA && seq->startdisp >= CFRA)) {
seq->flag |= SELECT;
recurs_sel_seq(seq);
}
@@ -627,8 +643,9 @@ void SEQUENCER_OT_select(wmOperatorType *ot)
static const EnumPropertyItem sequencer_select_left_right_types[] = {
{SEQ_SELECT_LR_NONE, "NONE", 0, "None", "Don't do left-right selection"},
{SEQ_SELECT_LR_MOUSE, "MOUSE", 0, "Mouse", "Use mouse position for selection"},
- {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select left"},
- {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select right"},
+ {SEQ_SELECT_LR_LEFT, "LEFT", 0, "Left", "Select to the left of the current frame"},
+ {SEQ_SELECT_LR_RIGHT, "RIGHT", 0, "Right", "Select to the right of the current frame"},
+ {SEQ_SELECT_LR_OVERLAP, "OVERLAP", 0, "Overlap", "Select overlapping the current frame"},
{0, NULL, 0, NULL, NULL},
};
PropertyRNA *prop;
diff --git a/source/blender/editors/space_userpref/userpref_ops.c b/source/blender/editors/space_userpref/userpref_ops.c
index 1ec459ccfca..d823530fd89 100644
--- a/source/blender/editors/space_userpref/userpref_ops.c
+++ b/source/blender/editors/space_userpref/userpref_ops.c
@@ -25,11 +25,15 @@
#include "DNA_screen_types.h"
+#include "BLI_listbase.h"
+
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_main.h"
#include "BKE_report.h"
+#include "RNA_access.h"
+#include "RNA_define.h"
#include "RNA_types.h"
#include "UI_interface.h"
@@ -41,11 +45,13 @@
#include "ED_userpref.h"
+#include "MEM_guardedalloc.h"
+
/* -------------------------------------------------------------------- */
-/** \name Reset Default Theme
+/** \name Reset Default Theme Operator
* \{ */
-static int reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
+static int preferences_reset_default_theme_exec(bContext *C, wmOperator *UNUSED(op))
{
Main *bmain = CTX_data_main(C);
UI_theme_init_default();
@@ -64,7 +70,7 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot)
ot->description = "Reset to the default theme colors";
/* callbacks */
- ot->exec = reset_default_theme_exec;
+ ot->exec = preferences_reset_default_theme_exec;
/* flags */
ot->flag = OPTYPE_REGISTER;
@@ -72,7 +78,64 @@ static void PREFERENCES_OT_reset_default_theme(wmOperatorType *ot)
/** \} */
+/* -------------------------------------------------------------------- */
+/** \name Add Auto-Execution Path Operator
+ * \{ */
+
+static int preferences_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
+{
+ bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare");
+ BLI_addtail(&U.autoexec_paths, path_cmp);
+ U.runtime.is_dirty = true;
+ return OPERATOR_FINISHED;
+}
+
+static void PREFERENCES_OT_autoexec_path_add(wmOperatorType *ot)
+{
+ ot->name = "Add Autoexec Path";
+ ot->idname = "PREFERENCES_OT_autoexec_path_add";
+ ot->description = "Add path to exclude from auto-execution";
+
+ ot->exec = preferences_autoexec_add_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Remove Auto-Execution Path Operator
+ * \{ */
+
+static int preferences_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op)
+{
+ const int index = RNA_int_get(op->ptr, "index");
+ bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index);
+ if (path_cmp) {
+ BLI_freelinkN(&U.autoexec_paths, path_cmp);
+ U.runtime.is_dirty = true;
+ }
+ return OPERATOR_FINISHED;
+}
+
+static void PREFERENCES_OT_autoexec_path_remove(wmOperatorType *ot)
+{
+ ot->name = "Remove Autoexec Path";
+ ot->idname = "PREFERENCES_OT_autoexec_path_remove";
+ ot->description = "Remove path to exclude from auto-execution";
+
+ ot->exec = preferences_autoexec_remove_exec;
+
+ ot->flag = OPTYPE_INTERNAL;
+
+ RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
+}
+
+/** \} */
+
void ED_operatortypes_userpref(void)
{
WM_operatortype_append(PREFERENCES_OT_reset_default_theme);
+ WM_operatortype_append(PREFERENCES_OT_autoexec_path_add);
+ WM_operatortype_append(PREFERENCES_OT_autoexec_path_remove);
}
diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c
index f81b4bb09e2..cb87ddafea1 100644
--- a/source/blender/editors/space_view3d/view3d_buttons.c
+++ b/source/blender/editors/space_view3d/view3d_buttons.c
@@ -1642,7 +1642,7 @@ static int view3d_object_mode_menu(bContext *C, wmOperator *op)
return OPERATOR_CANCELLED;
}
else if (((ob->mode & OB_MODE_EDIT) == 0) && (ELEM(ob->type, OB_ARMATURE))) {
- ED_object_mode_toggle(C, OB_MODE_POSE);
+ ED_object_mode_set(C, (ob->mode == OB_MODE_OBJECT) ? OB_MODE_POSE : OB_MODE_OBJECT);
return OPERATOR_CANCELLED;
}
else {
diff --git a/source/blender/editors/space_view3d/view3d_edit.c b/source/blender/editors/space_view3d/view3d_edit.c
index 25678820050..edd75d8e561 100644
--- a/source/blender/editors/space_view3d/view3d_edit.c
+++ b/source/blender/editors/space_view3d/view3d_edit.c
@@ -3349,7 +3349,7 @@ void VIEW3D_OT_view_center_pick(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name View Camera Center Operator
+/** \name Frame Camera Bounds Operator
* \{ */
static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
@@ -3386,8 +3386,8 @@ static int view3d_center_camera_exec(bContext *C, wmOperator *UNUSED(op))
void VIEW3D_OT_view_center_camera(wmOperatorType *ot)
{
/* identifiers */
- ot->name = "View Camera Center";
- ot->description = "Center the camera view";
+ ot->name = "Frame Camera Bounds";
+ ot->description = "Center the camera view, resizing the view to fit its bounds";
ot->idname = "VIEW3D_OT_view_center_camera";
/* api callbacks */
diff --git a/source/blender/editors/transform/transform.c b/source/blender/editors/transform/transform.c
index 5fc65522fe6..79090bd633e 100644
--- a/source/blender/editors/transform/transform.c
+++ b/source/blender/editors/transform/transform.c
@@ -49,6 +49,7 @@
#include "ED_space_api.h"
#include "WM_api.h"
+#include "WM_message.h"
#include "WM_types.h"
#include "UI_interface_icons.h"
@@ -1195,7 +1196,7 @@ int transformEvent(TransInfo *t, const wmEvent *event)
stopConstraint(t);
}
else {
- initSelectConstraint(t, event->shift);
+ initSelectConstraint(t);
postSelectConstraint(t);
}
}
@@ -1672,11 +1673,14 @@ void saveTransform(bContext *C, TransInfo *t, wmOperator *op)
if (t->flag & T_MODAL) {
/* do we check for parameter? */
if (transformModeUseSnap(t)) {
- if (t->modifiers & MOD_SNAP) {
- ts->snap_flag |= SCE_SNAP;
- }
- else {
- ts->snap_flag &= ~SCE_SNAP;
+ if (!(t->modifiers & MOD_SNAP) != !(ts->snap_flag & SCE_SNAP)) {
+ if (t->modifiers & MOD_SNAP) {
+ ts->snap_flag |= SCE_SNAP;
+ }
+ else {
+ ts->snap_flag &= ~SCE_SNAP;
+ }
+ WM_msg_publish_rna_prop(t->mbus, &t->scene->id, ts, ToolSettings, use_snap);
}
}
}
@@ -1884,62 +1888,38 @@ bool initTransform(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
t->draw_handle_pixel = ED_region_draw_cb_activate(
t->region->type, drawTransformPixel, t, REGION_DRAW_POST_PIXEL);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_IMAGE) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_CLIP) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_NODE) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_GRAPH) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
else if (t->spacetype == SPACE_ACTION) {
t->draw_handle_view = ED_region_draw_cb_activate(
t->region->type, drawTransformView, t, REGION_DRAW_POST_VIEW);
- t->draw_handle_cursor = WM_paint_cursor_activate(CTX_wm_manager(C),
- SPACE_TYPE_ANY,
- RGN_TYPE_ANY,
- transform_draw_cursor_poll,
- transform_draw_cursor_draw,
- t);
+ t->draw_handle_cursor = WM_paint_cursor_activate(
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, transform_draw_cursor_poll, transform_draw_cursor_draw, t);
}
createTransData(C, t); // make TransData structs from selection
diff --git a/source/blender/editors/transform/transform.h b/source/blender/editors/transform/transform.h
index 7720660e2e8..192728f63d2 100644
--- a/source/blender/editors/transform/transform.h
+++ b/source/blender/editors/transform/transform.h
@@ -560,6 +560,7 @@ typedef struct TransInfo {
void *view;
/** Only valid (non null) during an operator called function. */
struct bContext *context;
+ struct wmMsgBus *mbus;
struct ScrArea *area;
struct ARegion *region;
struct Depsgraph *depsgraph;
@@ -610,56 +611,53 @@ enum {
T_CURSOR = 1 << 5,
/** Transform points, having no rotation/scale. */
T_POINTS = 1 << 6,
-
- /* empty slot - (1 << 7) */
-
/** restrictions flags */
- T_NO_CONSTRAINT = 1 << 8,
- T_NULL_ONE = 1 << 9,
- T_NO_ZERO = 1 << 10,
+ T_NO_CONSTRAINT = 1 << 7,
+ T_NULL_ONE = 1 << 8,
+ T_NO_ZERO = 1 << 9,
T_ALL_RESTRICTIONS = T_NO_CONSTRAINT | T_NULL_ONE | T_NO_ZERO,
- T_PROP_EDIT = 1 << 11,
- T_PROP_CONNECTED = 1 << 12,
- T_PROP_PROJECTED = 1 << 13,
+ T_PROP_EDIT = 1 << 10,
+ T_PROP_CONNECTED = 1 << 11,
+ T_PROP_PROJECTED = 1 << 12,
T_PROP_EDIT_ALL = T_PROP_EDIT | T_PROP_CONNECTED | T_PROP_PROJECTED,
- T_V3D_ALIGN = 1 << 14,
+ T_V3D_ALIGN = 1 << 13,
/** For 2d views like uv or fcurve. */
- T_2D_EDIT = 1 << 15,
- T_CLIP_UV = 1 << 16,
+ T_2D_EDIT = 1 << 14,
+ T_CLIP_UV = 1 << 15,
/** Auto-ik is on. */
- T_AUTOIK = 1 << 18,
+ T_AUTOIK = 1 << 16,
/** Don't use mirror even if the data-block option is set. */
- T_NO_MIRROR = 1 << 19,
+ T_NO_MIRROR = 1 << 17,
/** To indicate that the value set in the `value` parameter is the final
* value of the transformation, modified only by the constrain. */
- T_INPUT_IS_VALUES_FINAL = 1 << 20,
+ T_INPUT_IS_VALUES_FINAL = 1 << 18,
/** To specify if we save back settings at the end. */
- T_MODAL = 1 << 21,
+ T_MODAL = 1 << 19,
/** No retopo. */
- T_NO_PROJECT = 1 << 22,
+ T_NO_PROJECT = 1 << 20,
- T_RELEASE_CONFIRM = 1 << 23,
+ T_RELEASE_CONFIRM = 1 << 21,
/** Alternative transformation. used to add offset to tracking markers. */
- T_ALT_TRANSFORM = 1 << 24,
+ T_ALT_TRANSFORM = 1 << 22,
/** #TransInfo.center has been set, don't change it. */
- T_OVERRIDE_CENTER = 1 << 25,
+ T_OVERRIDE_CENTER = 1 << 23,
- T_MODAL_CURSOR_SET = 1 << 26,
+ T_MODAL_CURSOR_SET = 1 << 24,
- T_CLNOR_REBUILD = 1 << 27,
+ T_CLNOR_REBUILD = 1 << 25,
/* Special Aftertrans. */
- T_AUTOMERGE = 1 << 28,
- T_AUTOSPLIT = 1 << 29,
+ T_AUTOMERGE = 1 << 26,
+ T_AUTOSPLIT = 1 << 27,
};
/** #TransInfo.modifiers */
@@ -706,40 +704,39 @@ enum {
/** #TransData.flag */
enum {
TD_SELECTED = 1 << 0,
- TD_NOACTION = 1 << 2,
- TD_USEQUAT = 1 << 3,
- TD_NOTCONNECTED = 1 << 4,
+ TD_USEQUAT = 1 << 1,
+ TD_NOTCONNECTED = 1 << 2,
/** Used for scaling of #MetaElem.rad */
- TD_SINGLESIZE = 1 << 5,
+ TD_SINGLESIZE = 1 << 3,
/** Scale relative to individual element center */
- TD_INDIVIDUAL_SCALE = 1 << 8,
- TD_NOCENTER = 1 << 9,
+ TD_INDIVIDUAL_SCALE = 1 << 4,
+ TD_NOCENTER = 1 << 5,
/** #TransData.ext abused for particle key timing. */
- TD_NO_EXT = 1 << 10,
+ TD_NO_EXT = 1 << 6,
/** don't transform this data */
- TD_SKIP = 1 << 11,
+ TD_SKIP = 1 << 7,
/** if this is a bez triple, we need to restore the handles,
* if this is set #TransData.hdata needs freeing */
- TD_BEZTRIPLE = 1 << 12,
+ TD_BEZTRIPLE = 1 << 8,
/** when this is set, don't apply translation changes to this element */
- TD_NO_LOC = 1 << 13,
+ TD_NO_LOC = 1 << 9,
/** For Graph Editor autosnap, indicates that point should not undergo autosnapping */
- TD_NOTIMESNAP = 1 << 14,
+ TD_NOTIMESNAP = 1 << 10,
/** For Graph Editor - curves that can only have int-values
* need their keyframes tagged with this. */
- TD_INTVALUES = 1 << 15,
+ TD_INTVALUES = 1 << 11,
/** For editmode mirror, clamp axis to 0 */
- TD_MIRROR_EDGE_X = 1 << 16,
- TD_MIRROR_EDGE_Y = 1 << 17,
- TD_MIRROR_EDGE_Z = 1 << 18,
+ TD_MIRROR_EDGE_X = 1 << 12,
+ TD_MIRROR_EDGE_Y = 1 << 13,
+ TD_MIRROR_EDGE_Z = 1 << 14,
/** For fcurve handles, move them along with their keyframes */
- TD_MOVEHANDLE1 = 1 << 19,
- TD_MOVEHANDLE2 = 1 << 20,
+ TD_MOVEHANDLE1 = 1 << 15,
+ TD_MOVEHANDLE2 = 1 << 16,
/** Exceptional case with pose bone rotating when a parent bone has 'Local Location'
* option enabled and rotating also transforms it. */
- TD_PBONE_LOCAL_MTX_P = 1 << 21,
+ TD_PBONE_LOCAL_MTX_P = 1 << 17,
/** Same as above but for a child bone. */
- TD_PBONE_LOCAL_MTX_C = 1 << 22,
+ TD_PBONE_LOCAL_MTX_C = 1 << 18,
};
/** #TransSnap.status */
@@ -920,7 +917,7 @@ struct TransformOrientation *addMatrixSpace(struct bContext *C,
float mat[3][3],
const char *name,
const bool overwrite);
-bool applyTransformOrientation(const struct TransformOrientation *ts,
+void applyTransformOrientation(const struct TransformOrientation *ts,
float r_mat[3][3],
char r_name[64]);
diff --git a/source/blender/editors/transform/transform_constraints.c b/source/blender/editors/transform/transform_constraints.c
index 0a6e0d6b7f5..0347522b8e8 100644
--- a/source/blender/editors/transform/transform_constraints.c
+++ b/source/blender/editors/transform/transform_constraints.c
@@ -829,11 +829,7 @@ static void drawObjectConstraint(TransInfo *t)
}
}
- if (t->flag & T_OBJECT) {
- copy_v3_v3(co, td->ob->obmat[3]);
- axismtx = td->axismtx;
- }
- else if (t->flag & T_EDIT) {
+ if (t->flag & T_EDIT) {
mul_v3_m4v3(co, tc->mat, td->center);
mul_m3_m3m3(tmp_axismtx, tc->mat3_unit, td->axismtx);
@@ -880,21 +876,15 @@ void stopConstraint(TransInfo *t)
/*------------------------- MMB Select -------------------------------*/
-void initSelectConstraint(TransInfo *t, bool force_global)
+void initSelectConstraint(TransInfo *t)
{
- short orientation;
- if (force_global) {
- orientation = V3D_ORIENT_GLOBAL;
- }
- else {
- if (t->orient_curr == 0) {
- t->orient_curr = 1;
- transform_orientations_current_set(t, t->orient_curr);
- }
- orientation = t->orient[t->orient_curr].type;
+ if (t->orient_curr == 0) {
+ t->orient_curr = 1;
+ transform_orientations_current_set(t, t->orient_curr);
}
- setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "");
+ short orientation = t->orient[t->orient_curr].type;
+ setUserConstraint(t, orientation, CON_APPLY | CON_SELECT, "%s");
setNearestAxis(t);
}
diff --git a/source/blender/editors/transform/transform_constraints.h b/source/blender/editors/transform/transform_constraints.h
index b57a7599321..c41b9361ca4 100644
--- a/source/blender/editors/transform/transform_constraints.h
+++ b/source/blender/editors/transform/transform_constraints.h
@@ -35,7 +35,7 @@ void drawConstraint(TransInfo *t);
void drawPropCircle(const struct bContext *C, TransInfo *t);
void startConstraint(TransInfo *t);
void stopConstraint(TransInfo *t);
-void initSelectConstraint(TransInfo *t, bool force_global);
+void initSelectConstraint(TransInfo *t);
void selectConstraint(TransInfo *t);
void postSelectConstraint(TransInfo *t);
void setNearestAxis(TransInfo *t);
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index b91542a80fc..ac69c2a60fe 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -827,10 +827,6 @@ void clipUVData(TransInfo *t)
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (int a = 0; a < tc->data_len; a++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if ((td->flag & TD_SKIP) || (!td->loc)) {
continue;
}
@@ -2390,10 +2386,6 @@ void special_aftertrans_update(bContext *C, TransInfo *t)
PTCacheID *pid;
ob = td->ob;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c
index b1e69dde0ac..6de962a3ed1 100644
--- a/source/blender/editors/transform/transform_generics.c
+++ b/source/blender/editors/transform/transform_generics.c
@@ -174,9 +174,6 @@ static void clipMirrorModifier(TransInfo *t)
int clip;
float loc[3], iloc[3];
- if (td->flag & TD_NOACTION) {
- break;
- }
if (td->loc == NULL) {
break;
}
@@ -1068,11 +1065,6 @@ static void recalcData_objects(TransInfo *t)
for (int i = 0; i < tc->data_len; i++, td++) {
Object *ob = td->ob;
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -1379,6 +1371,7 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
bGPdata *gpd = CTX_data_gpencil_data(C);
PropertyRNA *prop;
+ t->mbus = CTX_wm_message_bus(C);
t->depsgraph = CTX_data_depsgraph_pointer(C);
t->scene = sce;
t->view_layer = view_layer;
@@ -1649,13 +1642,17 @@ void initTransInfo(bContext *C, TransInfo *t, wmOperator *op, const wmEvent *eve
}
{
- TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
short orient_type_set = -1;
short orient_type_matrix_set = -1;
- short orient_type_scene = orient_slot->type;
- if (orient_type_scene == V3D_ORIENT_CUSTOM) {
- const int index_custom = orient_slot->index_custom;
- orient_type_scene += index_custom;
+ short orient_type_scene = V3D_ORIENT_GLOBAL;
+
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ TransformOrientationSlot *orient_slot = &t->scene->orientation_slots[SCE_ORIENT_DEFAULT];
+ orient_type_scene = orient_slot->type;
+ if (orient_type_scene == V3D_ORIENT_CUSTOM) {
+ const int index_custom = orient_slot->index_custom;
+ orient_type_scene += index_custom;
+ }
}
short orient_types[3];
@@ -1929,7 +1926,7 @@ void postTrans(bContext *C, TransInfo *t)
ED_region_draw_cb_exit(t->region->type, t->draw_handle_pixel);
}
if (t->draw_handle_cursor) {
- WM_paint_cursor_end(CTX_wm_manager(C), t->draw_handle_cursor);
+ WM_paint_cursor_end(t->draw_handle_cursor);
}
if (t->flag & T_MODAL_CURSOR_SET) {
@@ -2408,19 +2405,11 @@ void calculatePropRatio(TransInfo *t)
}
else if ((connected && (td->flag & TD_NOTCONNECTED || td->dist > t->prop_size)) ||
(connected == 0 && td->rdist > t->prop_size)) {
- /*
- * The elements are sorted according to their dist member in the array,
- * that means we can stop when it finds one element outside of the propsize.
- * do not set 'td->flag |= TD_NOACTION', the prop circle is being changed.
- */
-
td->factor = 0.0f;
restoreElement(td);
}
else {
/* Use rdist for falloff calculations, it is the real distance */
- td->flag &= ~TD_NOACTION;
-
if (connected) {
dist = (t->prop_size - td->dist) / t->prop_size;
}
diff --git a/source/blender/editors/transform/transform_gizmo_3d.c b/source/blender/editors/transform/transform_gizmo_3d.c
index 04be7048791..ebc021cd983 100644
--- a/source/blender/editors/transform/transform_gizmo_3d.c
+++ b/source/blender/editors/transform/transform_gizmo_3d.c
@@ -635,101 +635,6 @@ bool gimbal_axis(Object *ob, float gmat[3][3])
return 0;
}
-void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
-{
- ARegion *region = CTX_wm_region(C);
- Scene *scene = CTX_data_scene(C);
- ViewLayer *view_layer = CTX_data_view_layer(C);
- Object *obedit = CTX_data_edit_object(C);
- RegionView3D *rv3d = region->regiondata;
- Object *ob = OBACT(view_layer);
- const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
- const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
- const int pivot_point = scene->toolsettings->transform_pivot_point;
-
- ED_transform_calc_orientation_from_type_ex(
- C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
-}
-
-void ED_transform_calc_orientation_from_type_ex(const bContext *C,
- float r_mat[3][3],
- /* extra args (can be accessed from context) */
- Scene *scene,
- RegionView3D *rv3d,
- Object *ob,
- Object *obedit,
- const short orientation_type,
- int orientation_index_custom,
- const int pivot_point)
-{
- bool ok = false;
-
- switch (orientation_type) {
- case V3D_ORIENT_GLOBAL: {
- break; /* nothing to do */
- }
- case V3D_ORIENT_GIMBAL: {
- if (gimbal_axis(ob, r_mat)) {
- ok = true;
- break;
- }
- /* if not gimbal, fall through to normal */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_NORMAL: {
- if (obedit || ob->mode & OB_MODE_POSE) {
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- /* no break we define 'normal' as 'local' in Object mode */
- ATTR_FALLTHROUGH;
- }
- case V3D_ORIENT_LOCAL: {
- if (ob->mode & OB_MODE_POSE) {
- /* each bone moves on its own local axis, but to avoid confusion,
- * use the active pones axis for display [#33575], this works as expected on a single bone
- * and users who select many bones will understand what's going on and what local means
- * when they start transforming */
- ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
- ok = true;
- break;
- }
- copy_m3_m4(r_mat, ob->obmat);
- normalize_m3(r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_VIEW: {
- if (rv3d != NULL) {
- copy_m3_m4(r_mat, rv3d->viewinv);
- normalize_m3(r_mat);
- ok = true;
- }
- break;
- }
- case V3D_ORIENT_CURSOR: {
- BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat);
- ok = true;
- break;
- }
- case V3D_ORIENT_CUSTOM:
- default: {
- BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM);
- TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
- scene, orientation_index_custom);
- if (applyTransformOrientation(custom_orientation, r_mat, NULL)) {
- ok = true;
- }
- break;
- }
- }
-
- if (!ok) {
- unit_m3(r_mat);
- }
-}
-
/* centroid, boundbox, of selection */
/* returns total items selected */
int ED_transform_calc_gizmo_stats(const bContext *C,
diff --git a/source/blender/editors/transform/transform_mode_align.c b/source/blender/editors/transform/transform_mode_align.c
index 9bce793809b..4fd4599b940 100644
--- a/source/blender/editors/transform/transform_mode_align.c
+++ b/source/blender/editors/transform/transform_mode_align.c
@@ -52,10 +52,6 @@ static void applyAlign(TransInfo *t, const int UNUSED(mval[2]))
for (i = 0; i < tc->data_len; i++, td++) {
float mat[3][3], invmat[3][3];
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_baketime.c b/source/blender/editors/transform/transform_mode_baketime.c
index bb8fd0df13d..4e7fc3578ce 100644
--- a/source/blender/editors/transform/transform_mode_baketime.c
+++ b/source/blender/editors/transform/transform_mode_baketime.c
@@ -97,10 +97,6 @@ static void applyBakeTime(TransInfo *t, const int mval[2])
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_bbone_resize.c b/source/blender/editors/transform/transform_mode_bbone_resize.c
index c81049ac379..77850e74785 100644
--- a/source/blender/editors/transform/transform_mode_bbone_resize.c
+++ b/source/blender/editors/transform/transform_mode_bbone_resize.c
@@ -141,10 +141,6 @@ static void applyBoneSize(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_bend.c b/source/blender/editors/transform/transform_mode_bend.c
index 721d226050a..3b51626b170 100644
--- a/source/blender/editors/transform/transform_mode_bend.c
+++ b/source/blender/editors/transform/transform_mode_bend.c
@@ -186,10 +186,6 @@ static void Bend(TransInfo *t, const int UNUSED(mval[2]))
float delta[3];
float fac, fac_scaled;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_boneenvelope.c b/source/blender/editors/transform/transform_mode_boneenvelope.c
index aa20a5ade95..7045d190478 100644
--- a/source/blender/editors/transform/transform_mode_boneenvelope.c
+++ b/source/blender/editors/transform/transform_mode_boneenvelope.c
@@ -73,10 +73,6 @@ static void applyBoneEnvelope(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_boneroll.c b/source/blender/editors/transform/transform_mode_boneroll.c
index 0564a946148..1503519c519 100644
--- a/source/blender/editors/transform/transform_mode_boneroll.c
+++ b/source/blender/editors/transform/transform_mode_boneroll.c
@@ -75,10 +75,6 @@ static void applyBoneRoll(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
index 057f13ac068..84e4e950804 100644
--- a/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_curveshrinkfatten.c
@@ -73,10 +73,6 @@ static void applyCurveShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_edge_bevelweight.c b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
index 5db7895232c..399cec2d62c 100644
--- a/source/blender/editors/transform/transform_mode_edge_bevelweight.c
+++ b/source/blender/editors/transform/transform_mode_edge_bevelweight.c
@@ -87,10 +87,6 @@ static void applyBevelWeight(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->val) {
*td->val = td->ival + weight * td->factor;
if (*td->val < 0.0f) {
diff --git a/source/blender/editors/transform/transform_mode_edge_crease.c b/source/blender/editors/transform/transform_mode_edge_crease.c
index 4a92a57fef6..53c948c742b 100644
--- a/source/blender/editors/transform/transform_mode_edge_crease.c
+++ b/source/blender/editors/transform/transform_mode_edge_crease.c
@@ -87,10 +87,6 @@ static void applyCrease(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_edge_seq_slide.c b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
index 8690cd54a3b..c1cb4325c09 100644
--- a/source/blender/editors/transform/transform_mode_edge_seq_slide.c
+++ b/source/blender/editors/transform/transform_mode_edge_seq_slide.c
@@ -81,10 +81,6 @@ static void applySeqSlideValue(TransInfo *t, const float val[2])
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_gpopacity.c b/source/blender/editors/transform/transform_mode_gpopacity.c
index 267d297a31c..4712fb7ba01 100644
--- a/source/blender/editors/transform/transform_mode_gpopacity.c
+++ b/source/blender/editors/transform/transform_mode_gpopacity.c
@@ -73,10 +73,6 @@ static void applyGPOpacity(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
index 7c49d107703..ab9a0aa79ed 100644
--- a/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_gpshrinkfatten.c
@@ -73,10 +73,6 @@ static void applyGPShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
index e42439920db..68f3abda85b 100644
--- a/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
+++ b/source/blender/editors/transform/transform_mode_maskshrinkfatten.c
@@ -78,10 +78,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -97,10 +93,6 @@ static void applyMaskShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (td = tc->data, i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_mirror.c b/source/blender/editors/transform/transform_mode_mirror.c
index dae17374481..8d953610eb8 100644
--- a/source/blender/editors/transform/transform_mode_mirror.c
+++ b/source/blender/editors/transform/transform_mode_mirror.c
@@ -69,10 +69,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -93,10 +89,6 @@ static void applyMirror(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_push_pull.c b/source/blender/editors/transform/transform_mode_push_pull.c
index 6eb038ea9b0..4a2f979ec38 100644
--- a/source/blender/editors/transform/transform_mode_push_pull.c
+++ b/source/blender/editors/transform/transform_mode_push_pull.c
@@ -82,10 +82,6 @@ static void applyPushPull(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_resize.c b/source/blender/editors/transform/transform_mode_resize.c
index 00644b9bfdc..d919d5c889d 100644
--- a/source/blender/editors/transform/transform_mode_resize.c
+++ b/source/blender/editors/transform/transform_mode_resize.c
@@ -93,10 +93,6 @@ static void applyResize(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_rotate.c b/source/blender/editors/transform/transform_mode_rotate.c
index 55c97630487..6480cb6c30e 100644
--- a/source/blender/editors/transform/transform_mode_rotate.c
+++ b/source/blender/editors/transform/transform_mode_rotate.c
@@ -82,10 +82,6 @@ static void applyRotationValue(TransInfo *t,
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_shear.c b/source/blender/editors/transform/transform_mode_shear.c
index 3eeb8a1e758..fa33c1550e7 100644
--- a/source/blender/editors/transform/transform_mode_shear.c
+++ b/source/blender/editors/transform/transform_mode_shear.c
@@ -165,11 +165,6 @@ static void applyShear(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
const float *center, *co;
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_shrink_fatten.c b/source/blender/editors/transform/transform_mode_shrink_fatten.c
index ed082e86b6d..78d3efa0d69 100644
--- a/source/blender/editors/transform/transform_mode_shrink_fatten.c
+++ b/source/blender/editors/transform/transform_mode_shrink_fatten.c
@@ -95,10 +95,6 @@ static void applyShrinkFatten(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
float tdistance; /* temp dist */
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_skin_resize.c b/source/blender/editors/transform/transform_mode_skin_resize.c
index b53dbb55c62..23d83050613 100644
--- a/source/blender/editors/transform/transform_mode_skin_resize.c
+++ b/source/blender/editors/transform/transform_mode_skin_resize.c
@@ -73,11 +73,6 @@ static void applySkinResize(TransInfo *t, const int UNUSED(mval[2]))
for (i = 0; i < tc->data_len; i++, td++) {
float tmat[3][3], smat[3][3];
float fsize[3];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_tilt.c b/source/blender/editors/transform/transform_mode_tilt.c
index 2f56f4bd162..ca0a8818477 100644
--- a/source/blender/editors/transform/transform_mode_tilt.c
+++ b/source/blender/editors/transform/transform_mode_tilt.c
@@ -77,10 +77,6 @@ static void applyTilt(TransInfo *t, const int UNUSED(mval[2]))
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_tosphere.c b/source/blender/editors/transform/transform_mode_tosphere.c
index 841ccf41365..f6c5448a906 100644
--- a/source/blender/editors/transform/transform_mode_tosphere.c
+++ b/source/blender/editors/transform/transform_mode_tosphere.c
@@ -79,10 +79,6 @@ static void applyToSphere(TransInfo *t, const int UNUSED(mval[2]))
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
float tratio;
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_trackball.c b/source/blender/editors/transform/transform_mode_trackball.c
index c6e0b205204..ca5a749b275 100644
--- a/source/blender/editors/transform/transform_mode_trackball.c
+++ b/source/blender/editors/transform/transform_mode_trackball.c
@@ -63,10 +63,6 @@ static void applyTrackballValue(TransInfo *t,
FOREACH_TRANS_DATA_CONTAINER (t, tc) {
TransData *td = tc->data;
for (i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_mode_translate.c b/source/blender/editors/transform/transform_mode_translate.c
index 69552eda5bf..96820ca6385 100644
--- a/source/blender/editors/transform/transform_mode_translate.c
+++ b/source/blender/editors/transform/transform_mode_translate.c
@@ -236,10 +236,6 @@ static void applyTranslationValue(TransInfo *t, const float vec[3])
TransData *td = tc->data;
for (int i = 0; i < tc->data_len; i++, td++) {
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_orientations.c b/source/blender/editors/transform/transform_orientations.c
index 32269e1bacc..cd170b144d8 100644
--- a/source/blender/editors/transform/transform_orientations.c
+++ b/source/blender/editors/transform/transform_orientations.c
@@ -397,14 +397,12 @@ int BIF_countTransformOrientation(const bContext *C)
return BLI_listbase_count(transform_orientations);
}
-bool applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
+void applyTransformOrientation(const TransformOrientation *ts, float r_mat[3][3], char *r_name)
{
if (r_name) {
BLI_strncpy(r_name, ts->name, MAX_NAME);
}
copy_m3_m3(r_mat, ts->mat);
-
- return true;
}
/* Updates all `BONE_TRANSFORM` flags.
@@ -438,82 +436,141 @@ static int armature_bone_transflags_update_recursive(bArmature *arm,
return total;
}
-/* Sets the matrix of the specified space orientation.
- * If the matrix cannot be obtained, an orientation different from the one
- * informed is returned */
-short transform_orientation_matrix_get(bContext *C,
- TransInfo *t,
- const short orientation,
- const float custom[3][3],
- float r_spacemtx[3][3])
+void ED_transform_calc_orientation_from_type(const bContext *C, float r_mat[3][3])
{
- Object *ob = CTX_data_active_object(C);
- Object *obedit = CTX_data_active_object(C);
+ ARegion *region = CTX_wm_region(C);
+ Scene *scene = CTX_data_scene(C);
+ ViewLayer *view_layer = CTX_data_view_layer(C);
+ Object *obedit = CTX_data_edit_object(C);
+ RegionView3D *rv3d = region->regiondata;
+ Object *ob = OBACT(view_layer);
+ const short orientation_type = scene->orientation_slots[SCE_ORIENT_DEFAULT].type;
+ const short orientation_index_custom = scene->orientation_slots[SCE_ORIENT_DEFAULT].index_custom;
+ const int pivot_point = scene->toolsettings->transform_pivot_point;
- switch (orientation) {
- case V3D_ORIENT_GLOBAL:
- unit_m3(r_spacemtx);
- return V3D_ORIENT_GLOBAL;
+ ED_transform_calc_orientation_from_type_ex(
+ C, r_mat, scene, rv3d, ob, obedit, orientation_type, orientation_index_custom, pivot_point);
+}
- case V3D_ORIENT_GIMBAL:
- unit_m3(r_spacemtx);
- if (ob && gimbal_axis(ob, r_spacemtx)) {
+short ED_transform_calc_orientation_from_type_ex(const bContext *C,
+ float r_mat[3][3],
+ /* extra args (can be accessed from context) */
+ Scene *scene,
+ RegionView3D *rv3d,
+ Object *ob,
+ Object *obedit,
+ const short orientation_type,
+ int orientation_index_custom,
+ const int pivot_point)
+{
+ switch (orientation_type) {
+ case V3D_ORIENT_GLOBAL: {
+ unit_m3(r_mat);
+ return V3D_ORIENT_GLOBAL;
+ }
+ case V3D_ORIENT_GIMBAL: {
+ if (gimbal_axis(ob, r_mat)) {
return V3D_ORIENT_GIMBAL;
}
- ATTR_FALLTHROUGH; /* no gimbal fallthrough to normal */
-
- case V3D_ORIENT_NORMAL:
- if (obedit || (ob && ob->mode & OB_MODE_POSE)) {
- ED_getTransformOrientationMatrix(C, r_spacemtx, t->around);
+ /* if not gimbal, fall through to normal */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_NORMAL: {
+ if (obedit || ob->mode & OB_MODE_POSE) {
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
return V3D_ORIENT_NORMAL;
}
- ATTR_FALLTHROUGH; /* we define 'normal' as 'local' in Object mode */
-
- case V3D_ORIENT_LOCAL:
+ /* no break we define 'normal' as 'local' in Object mode */
+ ATTR_FALLTHROUGH;
+ }
+ case V3D_ORIENT_LOCAL: {
if (ob) {
- copy_m3_m4(r_spacemtx, ob->obmat);
- normalize_m3(r_spacemtx);
+ if (ob->mode & OB_MODE_POSE) {
+ /* each bone moves on its own local axis, but to avoid confusion,
+ * use the active pones axis for display [#33575], this works as expected on a single
+ * bone and users who select many bones will understand what's going on and what local
+ * means when they start transforming */
+ ED_getTransformOrientationMatrix(C, r_mat, pivot_point);
+ }
+ else {
+ copy_m3_m4(r_mat, ob->obmat);
+ normalize_m3(r_mat);
+ }
return V3D_ORIENT_LOCAL;
}
- unit_m3(r_spacemtx);
+ unit_m3(r_mat);
return V3D_ORIENT_GLOBAL;
-
+ }
case V3D_ORIENT_VIEW: {
- float mat[3][3];
- if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
- RegionView3D *rv3d = t->region->regiondata;
- copy_m3_m4(mat, rv3d->viewinv);
- normalize_m3(mat);
+ if (rv3d != NULL) {
+ copy_m3_m4(r_mat, rv3d->viewinv);
+ normalize_m3(r_mat);
}
else {
- unit_m3(mat);
+ unit_m3(r_mat);
}
- copy_m3_m3(r_spacemtx, mat);
return V3D_ORIENT_VIEW;
}
- case V3D_ORIENT_CURSOR:
- BKE_scene_cursor_rot_to_mat3(&t->scene->cursor, r_spacemtx);
+ case V3D_ORIENT_CURSOR: {
+ BKE_scene_cursor_rot_to_mat3(&scene->cursor, r_mat);
return V3D_ORIENT_CURSOR;
-
- case V3D_ORIENT_CUSTOM_MATRIX:
- copy_m3_m3(r_spacemtx, custom);
- return V3D_ORIENT_CUSTOM_MATRIX;
-
+ }
+ case V3D_ORIENT_CUSTOM_MATRIX: {
+ /* Do nothing. */;
+ break;
+ }
case V3D_ORIENT_CUSTOM:
- default:
- BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
- TransformOrientation *ts = BKE_scene_transform_orientation_find(
- t->scene, orientation - V3D_ORIENT_CUSTOM);
- if (applyTransformOrientation(ts, r_spacemtx, t->spacename)) {
- /* pass */
- }
- else {
- unit_m3(r_spacemtx);
- }
+ default: {
+ BLI_assert(orientation_type >= V3D_ORIENT_CUSTOM);
+ TransformOrientation *custom_orientation = BKE_scene_transform_orientation_find(
+ scene, orientation_index_custom);
+ applyTransformOrientation(custom_orientation, r_mat, NULL);
break;
+ }
}
- return orientation;
+ return orientation_type;
+}
+
+/* Sets the matrix of the specified space orientation.
+ * If the matrix cannot be obtained, an orientation different from the one
+ * informed is returned */
+short transform_orientation_matrix_get(bContext *C,
+ TransInfo *t,
+ const short orientation,
+ const float custom[3][3],
+ float r_spacemtx[3][3])
+{
+ if (orientation == V3D_ORIENT_CUSTOM_MATRIX) {
+ copy_m3_m3(r_spacemtx, custom);
+ return V3D_ORIENT_CUSTOM_MATRIX;
+ }
+
+ if ((t->spacetype == SPACE_VIEW3D) && (t->region->regiontype == RGN_TYPE_WINDOW)) {
+ Object *ob = CTX_data_active_object(C);
+ Object *obedit = CTX_data_active_object(C);
+ RegionView3D *rv3d = t->region->regiondata;
+ int orientation_index_custom = 0;
+
+ if (orientation >= V3D_ORIENT_CUSTOM) {
+ orientation_index_custom = orientation - V3D_ORIENT_CUSTOM;
+ }
+
+ return ED_transform_calc_orientation_from_type_ex(
+ C,
+ r_spacemtx,
+ /* extra args (can be accessed from context) */
+ t->scene,
+ rv3d,
+ ob,
+ obedit,
+ orientation,
+ orientation_index_custom,
+ t->around);
+ }
+
+ unit_m3(r_spacemtx);
+ return V3D_ORIENT_GLOBAL;
}
const char *transform_orientations_spacename_get(TransInfo *t, const short orient_type)
@@ -545,37 +602,7 @@ const char *transform_orientations_spacename_get(TransInfo *t, const short orien
void transform_orientations_current_set(TransInfo *t, const short orient_index)
{
const short orientation = t->orient[orient_index].type;
- const char *spacename;
- switch (orientation) {
- case V3D_ORIENT_GLOBAL:
- spacename = TIP_("global");
- break;
- case V3D_ORIENT_GIMBAL:
- spacename = TIP_("gimbal");
- break;
- case V3D_ORIENT_NORMAL:
- spacename = TIP_("normal");
- break;
- case V3D_ORIENT_LOCAL:
- spacename = TIP_("local");
- break;
- case V3D_ORIENT_VIEW:
- spacename = TIP_("view");
- break;
- case V3D_ORIENT_CURSOR:
- spacename = TIP_("cursor");
- break;
- case V3D_ORIENT_CUSTOM_MATRIX:
- spacename = TIP_("custom");
- break;
- case V3D_ORIENT_CUSTOM:
- default:
- BLI_assert(orientation >= V3D_ORIENT_CUSTOM);
- TransformOrientation *ts = BKE_scene_transform_orientation_find(
- t->scene, orientation - V3D_ORIENT_CUSTOM);
- spacename = ts->name;
- break;
- }
+ const char *spacename = transform_orientations_spacename_get(t, orientation);
BLI_strncpy(t->spacename, spacename, sizeof(t->spacename));
copy_m3_m3(t->spacemtx, t->orient[orient_index].matrix);
diff --git a/source/blender/editors/transform/transform_snap.c b/source/blender/editors/transform/transform_snap.c
index 50f525a324b..82602e7d828 100644
--- a/source/blender/editors/transform/transform_snap.c
+++ b/source/blender/editors/transform/transform_snap.c
@@ -306,11 +306,6 @@ void applyProject(TransInfo *t)
for (i = 0; i < tc->data_len; i++, td++) {
float iloc[3], loc[3], no[3];
float mval_fl[2];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
@@ -417,11 +412,6 @@ void applyGridAbsolute(TransInfo *t)
for (i = 0, td = tc->data; i < tc->data_len; i++, td++) {
float iloc[3], loc[3], tvec[3];
-
- if (td->flag & TD_NOACTION) {
- break;
- }
-
if (td->flag & TD_SKIP) {
continue;
}
diff --git a/source/blender/editors/transform/transform_snap_object.c b/source/blender/editors/transform/transform_snap_object.c
index 77bb0c1c785..c30b8d59dc0 100644
--- a/source/blender/editors/transform/transform_snap_object.c
+++ b/source/blender/editors/transform/transform_snap_object.c
@@ -104,7 +104,7 @@ typedef struct SnapObjectData {
/* SNAP_EDIT_MESH */
BVHTreeFromEditMesh treedata_editmesh;
float min[3], max[3];
- struct LinkNode **bvh_cache_p;
+ struct Mesh_Runtime *mesh_runtime;
};
};
} SnapObjectData;
@@ -144,6 +144,17 @@ struct SnapObjectContext {
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Utilities
+ * \{ */
+
+static bool editmesh_eval_final_is_bmesh(const BMEditMesh *em)
+{
+ return (em->mesh_eval_final->runtime.wrapper_type == ME_WRAPPER_TYPE_BMESH);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Snap Object Data
* \{ */
@@ -244,17 +255,17 @@ static SnapObjectData *snap_object_data_mesh_get(SnapObjectContext *sctx, Object
return sod;
}
-static struct LinkNode **snap_object_data_editmesh_bvh_cache_get(Object *ob)
+static struct Mesh_Runtime *snap_object_data_editmesh_runtime_get(Object *ob)
{
BMEditMesh *em = BKE_editmesh_from_object(ob);
if (em->mesh_eval_final) {
- return &em->mesh_eval_final->runtime.bvh_cache;
+ return &em->mesh_eval_final->runtime;
}
if (em->mesh_eval_cage) {
- return &em->mesh_eval_cage->runtime.bvh_cache;
+ return &em->mesh_eval_cage->runtime;
}
- return &((Mesh *)ob->data)->runtime.bvh_cache;
+ return &((Mesh *)ob->data)->runtime;
}
static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
@@ -291,23 +302,23 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
clear_cache = true;
init = true;
}
- else if (sod->bvh_cache_p) {
- if (sod->bvh_cache_p != snap_object_data_editmesh_bvh_cache_get(ob)) {
+ else if (sod->mesh_runtime) {
+ if (sod->mesh_runtime != snap_object_data_editmesh_runtime_get(ob)) {
clear_cache = true;
init = true;
}
else if (sod->treedata_editmesh.tree && sod->treedata_editmesh.cached &&
- !bvhcache_has_tree(*sod->bvh_cache_p, sod->treedata_editmesh.tree)) {
+ !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->treedata_editmesh.tree)) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
clear = true;
}
else if (sod->bvhtree[0] && sod->cached[0] &&
- !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[0])) {
+ !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[0])) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
clear = true;
}
else if (sod->bvhtree[1] && sod->cached[1] &&
- !bvhcache_has_tree(*sod->bvh_cache_p, sod->bvhtree[1])) {
+ !bvhcache_has_tree(sod->mesh_runtime->bvh_cache, sod->bvhtree[1])) {
/* The tree is owned by the EditMesh and may have been freed since we last used! */
clear = true;
}
@@ -346,7 +357,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
bm_mesh_minmax(em->bm, sod->min, sod->max);
}
- sod->bvh_cache_p = snap_object_data_editmesh_bvh_cache_get(ob);
+ sod->mesh_runtime = snap_object_data_editmesh_runtime_get(ob);
}
return sod;
@@ -359,7 +370,7 @@ static SnapObjectData *snap_object_data_editmesh_get(SnapObjectContext *sctx,
* \{ */
typedef void (*IterSnapObjsCallback)(SnapObjectContext *sctx,
- bool is_obedit,
+ bool use_obedit,
bool use_backface_culling,
Object *ob,
float obmat[4][4],
@@ -835,14 +846,19 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_looptri_ex(
- treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL);
+ treedata, em, elem_mask, looptri_num_active, 0.0f, 4, 6, 0, NULL, NULL);
MEM_freeN(elem_mask);
}
else {
/* Only cache if bvhtree is created without a mask.
* This helps keep a standardized bvhtree in cache. */
- BKE_bvhtree_from_editmesh_get(treedata, em, 4, BVHTREE_FROM_EM_LOOPTRI, sod->bvh_cache_p);
+ BKE_bvhtree_from_editmesh_get(treedata,
+ em,
+ 4,
+ BVHTREE_FROM_EM_LOOPTRI,
+ &sod->mesh_runtime->bvh_cache,
+ sod->mesh_runtime->eval_mutex);
}
if (treedata->tree == NULL) {
@@ -920,41 +936,52 @@ static bool raycastEditMesh(SnapObjectContext *sctx,
return retval;
}
+struct RaycastObjUserData {
+ const float *ray_start;
+ const float *ray_dir;
+ uint ob_index;
+ /* read/write args */
+ float *ray_depth;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ ListBase *r_hit_list;
+ bool use_occlusion_test;
+ bool ret;
+};
+
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static bool raycastObj(SnapObjectContext *sctx,
- const float ray_start[3],
- const float ray_dir[3],
- Object *ob,
- const float obmat[4][4],
- const uint ob_index,
- bool use_obedit,
- bool use_occlusion_test,
- bool use_backface_culling,
- /* read/write args */
- float *ray_depth,
- /* return args */
- float r_loc[3],
- float r_no[3],
- int *r_index,
- Object **r_ob,
- float r_obmat[4][4],
- ListBase *r_hit_list)
+static void raycast_obj_fn(SnapObjectContext *sctx,
+ bool use_obedit,
+ bool use_backface_culling,
+ Object *ob,
+ float obmat[4][4],
+ void *data)
{
+ struct RaycastObjUserData *dt = data;
+ const uint ob_index = dt->ob_index++;
+ bool use_occlusion_test = dt->use_occlusion_test;
+ /* read/write args */
+ float *ray_depth = dt->ray_depth;
+
bool retval = false;
if (use_occlusion_test) {
if (use_obedit && sctx->use_v3d && XRAY_FLAG_ENABLED(sctx->v3d_data.v3d)) {
/* Use of occlude geometry in editing mode disabled. */
- return false;
+ return;
}
if (ELEM(ob->dt, OB_BOUNDBOX, OB_WIRE)) {
/* Do not hit objects that are in wire or bounding box
* display mode. */
- return false;
+ return;
}
}
@@ -963,22 +990,22 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *me = ob->data;
bool use_hide = false;
if (BKE_object_is_in_editmode(ob)) {
- if (use_obedit) {
+ if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
/* Operators only update the editmesh looptris of the original mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
retval = raycastEditMesh(sctx,
- ray_start,
- ray_dir,
+ dt->ray_start,
+ dt->ray_dir,
ob,
em_orig,
obmat,
ob_index,
use_backface_culling,
ray_depth,
- r_loc,
- r_no,
- r_index,
- r_hit_list);
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
break;
}
else {
@@ -990,8 +1017,8 @@ static bool raycastObj(SnapObjectContext *sctx,
}
}
retval = raycastMesh(sctx,
- ray_start,
- ray_dir,
+ dt->ray_start,
+ dt->ray_dir,
ob,
me,
obmat,
@@ -999,10 +1026,10 @@ static bool raycastObj(SnapObjectContext *sctx,
use_hide,
use_backface_culling,
ray_depth,
- r_loc,
- r_no,
- r_index,
- r_hit_list);
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
break;
}
case OB_CURVE:
@@ -1011,8 +1038,8 @@ static bool raycastObj(SnapObjectContext *sctx,
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
if (mesh_eval) {
retval = raycastMesh(sctx,
- ray_start,
- ray_dir,
+ dt->ray_start,
+ dt->ray_dir,
ob,
mesh_eval,
obmat,
@@ -1020,70 +1047,24 @@ static bool raycastObj(SnapObjectContext *sctx,
false,
use_backface_culling,
ray_depth,
- r_loc,
- r_no,
- r_index,
- r_hit_list);
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index,
+ dt->r_hit_list);
break;
}
}
}
if (retval) {
- if (r_ob) {
- *r_ob = ob;
+ if (dt->r_ob) {
+ *dt->r_ob = ob;
}
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
+ if (dt->r_obmat) {
+ copy_m4_m4(dt->r_obmat, obmat);
}
- return true;
+ dt->ret = true;
}
-
- return false;
-}
-
-struct RaycastObjUserData {
- const float *ray_start;
- const float *ray_dir;
- uint ob_index;
- /* read/write args */
- float *ray_depth;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- ListBase *r_hit_list;
- bool use_occlusion_test;
- bool ret;
-};
-
-static void raycast_obj_cb(SnapObjectContext *sctx,
- bool use_obedit,
- bool use_backface_culling,
- Object *ob,
- float obmat[4][4],
- void *data)
-{
- struct RaycastObjUserData *dt = data;
-
- dt->ret |= raycastObj(sctx,
- dt->ray_start,
- dt->ray_dir,
- ob,
- obmat,
- dt->ob_index++,
- use_obedit,
- dt->use_occlusion_test,
- use_backface_culling,
- dt->ray_depth,
- dt->r_loc,
- dt->r_no,
- dt->r_index,
- dt->r_ob,
- dt->r_obmat,
- dt->r_hit_list);
}
/**
@@ -1144,7 +1125,7 @@ static bool raycastObjects(SnapObjectContext *sctx,
.ret = false,
};
- iter_snap_objects(sctx, depsgraph, params, raycast_obj_cb, &data);
+ iter_snap_objects(sctx, depsgraph, params, raycast_obj_fn, &data);
return data.ret;
}
@@ -2524,11 +2505,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_verts_ex(
- &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, verts_mask, verts_num_active, 0.0f, 2, 6, 0, NULL, NULL);
MEM_freeN(verts_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_VERTS, sod->bvh_cache_p);
+ BKE_bvhtree_from_editmesh_get(&treedata,
+ em,
+ 2,
+ BVHTREE_FROM_EM_VERTS,
+ &sod->mesh_runtime->bvh_cache,
+ (ThreadMutex *)sod->mesh_runtime->eval_mutex);
}
sod->bvhtree[0] = treedata.tree;
sod->cached[0] = treedata.cached;
@@ -2551,11 +2537,16 @@ static short snapEditMesh(SnapObjectContext *sctx,
sctx->callbacks.edit_mesh.user_data);
bvhtree_from_editmesh_edges_ex(
- &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL);
+ &treedata, em, edges_mask, edges_num_active, 0.0f, 2, 6, 0, NULL, NULL);
MEM_freeN(edges_mask);
}
else {
- BKE_bvhtree_from_editmesh_get(&treedata, em, 2, BVHTREE_FROM_EM_EDGES, sod->bvh_cache_p);
+ BKE_bvhtree_from_editmesh_get(&treedata,
+ em,
+ 2,
+ BVHTREE_FROM_EM_EDGES,
+ &sod->mesh_runtime->bvh_cache,
+ sod->mesh_runtime->eval_mutex);
}
sod->bvhtree[1] = treedata.tree;
sod->cached[1] = treedata.cached;
@@ -2644,45 +2635,51 @@ static short snapEditMesh(SnapObjectContext *sctx,
return 0;
}
+struct SnapObjUserData {
+ SnapData *snapdata;
+ /* read/write args */
+ float *dist_px;
+ /* return args */
+ float *r_loc;
+ float *r_no;
+ int *r_index;
+ Object **r_ob;
+ float (*r_obmat)[4];
+ short ret;
+};
+
/**
* \param use_obedit: Uses the coordinates of BMesh (if any) to do the snapping;
*
* \note Duplicate args here are documented at #snapObjectsRay
*/
-static short snapObject(SnapObjectContext *sctx,
- SnapData *snapdata,
- Object *ob,
- float obmat[4][4],
+static void sanp_obj_fn(SnapObjectContext *sctx,
bool use_obedit,
bool use_backface_culling,
- /* read/write args */
- float *dist_px,
- /* return args */
- float r_loc[3],
- float r_no[3],
- int *r_index,
- Object **r_ob,
- float r_obmat[4][4])
+ Object *ob,
+ float obmat[4][4],
+ void *data)
{
+ struct SnapObjUserData *dt = data;
short retval = 0;
switch (ob->type) {
case OB_MESH: {
Mesh *me = ob->data;
if (BKE_object_is_in_editmode(ob)) {
- if (use_obedit) {
+ if (use_obedit || editmesh_eval_final_is_bmesh(me->edit_mesh)) {
/* Operators only update the editmesh looptris of the original mesh. */
BMEditMesh *em_orig = BKE_editmesh_from_object(DEG_get_original_object(ob));
retval = snapEditMesh(sctx,
- snapdata,
+ dt->snapdata,
ob,
em_orig,
obmat,
use_backface_culling,
- dist_px,
- r_loc,
- r_no,
- r_index);
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
break;
}
else {
@@ -2694,99 +2691,66 @@ static short snapObject(SnapObjectContext *sctx,
}
else if (ob->dt == OB_BOUNDBOX) {
/* Do not snap to objects that are in bounding box display mode */
- return 0;
+ return;
}
- retval = snapMesh(
- sctx, snapdata, ob, me, obmat, use_backface_culling, dist_px, r_loc, r_no, r_index);
+ retval = snapMesh(sctx,
+ dt->snapdata,
+ ob,
+ me,
+ obmat,
+ use_backface_culling,
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
break;
}
case OB_ARMATURE:
- retval = snapArmature(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ retval = snapArmature(
+ dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CURVE:
- retval = snapCurve(snapdata, ob, obmat, use_obedit, dist_px, r_loc, r_no, r_index);
+ retval = snapCurve(
+ dt->snapdata, ob, obmat, use_obedit, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break; /* Use ATTR_FALLTHROUGH if we want to snap to the generated mesh. */
case OB_SURF:
case OB_FONT: {
Mesh *mesh_eval = BKE_object_get_evaluated_mesh(ob);
if (mesh_eval) {
retval |= snapMesh(sctx,
- snapdata,
+ dt->snapdata,
ob,
mesh_eval,
obmat,
use_backface_culling,
- dist_px,
- r_loc,
- r_no,
- r_index);
+ dt->dist_px,
+ dt->r_loc,
+ dt->r_no,
+ dt->r_index);
}
break;
}
case OB_EMPTY:
- retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_GPENCIL:
- retval = snapEmpty(snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapEmpty(dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
case OB_CAMERA:
- retval = snapCamera(sctx, snapdata, ob, obmat, dist_px, r_loc, r_no, r_index);
+ retval = snapCamera(
+ sctx, dt->snapdata, ob, obmat, dt->dist_px, dt->r_loc, dt->r_no, dt->r_index);
break;
}
if (retval) {
- if (r_ob) {
- *r_ob = ob;
+ if (dt->r_ob) {
+ *dt->r_ob = ob;
}
- if (r_obmat) {
- copy_m4_m4(r_obmat, obmat);
+ if (dt->r_obmat) {
+ copy_m4_m4(dt->r_obmat, obmat);
}
- return retval;
- }
-
- return 0;
-}
-
-struct SnapObjUserData {
- SnapData *snapdata;
- /* read/write args */
- float *dist_px;
- /* return args */
- float *r_loc;
- float *r_no;
- int *r_index;
- Object **r_ob;
- float (*r_obmat)[4];
- short ret;
-};
-
-static void sanp_obj_cb(SnapObjectContext *sctx,
- bool is_obedit,
- bool use_backface_culling,
- Object *ob,
- float obmat[4][4],
- void *data)
-{
- struct SnapObjUserData *dt = data;
-
- short elem = snapObject(sctx,
- dt->snapdata,
- ob,
- obmat,
- is_obedit,
- use_backface_culling,
- /* read/write args */
- dt->dist_px,
- /* return args */
- dt->r_loc,
- dt->r_no,
- dt->r_index,
- dt->r_ob,
- dt->r_obmat);
-
- if (elem) {
- dt->ret = elem;
+ dt->ret = retval;
}
}
@@ -2839,7 +2803,7 @@ static short snapObjectsRay(SnapObjectContext *sctx,
.ret = 0,
};
- iter_snap_objects(sctx, depsgraph, params, sanp_obj_cb, &data);
+ iter_snap_objects(sctx, depsgraph, params, sanp_obj_fn, &data);
return data.ret;
}
diff --git a/source/blender/editors/util/ed_util.c b/source/blender/editors/util/ed_util.c
index f8e19b742e4..af387e4f7c2 100644
--- a/source/blender/editors/util/ed_util.c
+++ b/source/blender/editors/util/ed_util.c
@@ -153,10 +153,10 @@ void ED_editors_init(bContext *C)
ED_object_sculptmode_enter_ex(bmain, depsgraph, scene, ob, true, reports);
}
else if (mode == OB_MODE_VERTEX_PAINT) {
- ED_object_vpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_vpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
else if (mode == OB_MODE_WEIGHT_PAINT) {
- ED_object_wpaintmode_enter_ex(bmain, depsgraph, wm, scene, ob);
+ ED_object_wpaintmode_enter_ex(bmain, depsgraph, scene, ob);
}
else {
BLI_assert(0);
@@ -174,7 +174,7 @@ void ED_editors_init(bContext *C)
else {
/* TODO(campbell): avoid operator calls. */
if (obact == ob) {
- ED_object_mode_toggle(C, mode);
+ ED_object_mode_set(C, mode);
}
}
}
diff --git a/source/blender/editors/uvedit/uvedit_draw.c b/source/blender/editors/uvedit/uvedit_draw.c
index f8cef95c776..897e2f13774 100644
--- a/source/blender/editors/uvedit/uvedit_draw.c
+++ b/source/blender/editors/uvedit/uvedit_draw.c
@@ -39,6 +39,7 @@
#include "../../draw/intern/draw_cache_impl.h"
#include "BLI_math.h"
+#include "BLI_task.h"
#include "BLI_utildefines.h"
#include "BKE_deform.h"
@@ -206,8 +207,10 @@ static void uvedit_get_batches(Object *ob,
else {
batches->faces = NULL;
}
-
- DRW_mesh_batch_cache_create_requested(ob, ob->data, scene, false, false);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, ob, ob->data, scene, false, false);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
if (draw_stretch && (sima->dt_uvstretch == SI_UVDT_STRETCH_AREA)) {
/* after create_requested we can load the actual areas */
@@ -229,7 +232,11 @@ static void draw_uvs_shadow(SpaceImage *sima,
DRW_mesh_batch_cache_validate(me);
GPUBatch *edges = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false);
+
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
if (edges) {
if (sima->flag & SI_SMOOTH_UV) {
@@ -269,7 +276,10 @@ static void draw_uvs_texpaint(const Scene *scene, Object *ob, Depsgraph *depsgra
DRW_mesh_batch_cache_validate(me);
GPUBatch *geom = DRW_mesh_batch_cache_get_uv_edges(me);
- DRW_mesh_batch_cache_create_requested(ob_eval, me, scene, false, false);
+ struct TaskGraph *task_graph = BLI_task_graph_create();
+ DRW_mesh_batch_cache_create_requested(task_graph, ob_eval, me, scene, false, false);
+ BLI_task_graph_work_and_wait(task_graph);
+ BLI_task_graph_free(task_graph);
GPU_batch_program_set_builtin(geom, GPU_SHADER_2D_UV_UNIFORM_COLOR);
GPU_batch_uniform_4fv(geom, "color", col);
diff --git a/source/blender/editors/uvedit/uvedit_ops.c b/source/blender/editors/uvedit/uvedit_ops.c
index 78b6cfc44ac..22b51937083 100644
--- a/source/blender/editors/uvedit/uvedit_ops.c
+++ b/source/blender/editors/uvedit/uvedit_ops.c
@@ -71,6 +71,7 @@
#include "UI_resources.h"
#include "UI_view2d.h"
+#include "intern/math_base_inline.c"
#include "uvedit_intern.h"
/* -------------------------------------------------------------------- */
@@ -1843,11 +1844,12 @@ static void UV_OT_cursor_set(wmOperatorType *ot)
static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
{
+ Scene *scene = CTX_data_scene(C);
ViewLayer *view_layer = CTX_data_view_layer(C);
- int ret = OPERATOR_CANCELLED;
const float limit[2] = {STD_UV_CONNECT_LIMIT, STD_UV_CONNECT_LIMIT};
const bool mark_seams = RNA_boolean_get(op->ptr, "mark_seams");
const bool mark_sharp = RNA_boolean_get(op->ptr, "mark_sharp");
+ bool changed_multi = false;
uint objects_len = 0;
Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data_with_uvs(
@@ -1858,111 +1860,76 @@ static int uv_seams_from_islands_exec(bContext *C, wmOperator *op)
Mesh *me = (Mesh *)ob->data;
BMEditMesh *em = me->edit_mesh;
BMesh *bm = em->bm;
-
- UvVertMap *vmap;
- BMEdge *editedge;
BMIter iter;
if (!EDBM_uv_check(em)) {
continue;
}
- ret = OPERATOR_FINISHED;
-
- /* This code sets editvert->tmp.l to the index. This will be useful later on. */
- BM_mesh_elem_table_ensure(bm, BM_FACE);
- vmap = BM_uv_vert_map_create(bm, limit, false, false);
-
- BM_ITER_MESH (editedge, &iter, bm, BM_EDGES_OF_MESH) {
- /* flags to determine if we uv is separated from first editface match */
- char separated1 = 0, separated2;
- /* set to denote edge must be flagged as seam */
- char faces_separated = 0;
- /* flag to keep track if uv1 is disconnected from first editface match */
- char v1coincident = 1;
- /* For use with v1coincident. v1coincident will change only if we've had commonFaces */
- int commonFaces = 0;
-
- BMFace *efa1, *efa2;
-
- UvMapVert *mv1, *mvinit1, *mv2, *mvinit2, *mviter;
- /* mv2cache stores the first of the list of coincident uv's for later comparison
- * mv2sep holds the last separator and is copied to mv2cache
- * when a hit is first found */
- UvMapVert *mv2cache = NULL, *mv2sep = NULL;
-
- mvinit1 = vmap->vert[BM_elem_index_get(editedge->v1)];
- if (mark_seams) {
- BM_elem_flag_disable(editedge, BM_ELEM_SEAM);
+
+ const int cd_loop_uv_offset = CustomData_get_offset(&bm->ldata, CD_MLOOPUV);
+ bool changed = false;
+
+ BMFace *f;
+ BM_ITER_MESH (f, &iter, bm, BM_FACES_OF_MESH) {
+ if (!uvedit_face_visible_test(scene, f)) {
+ continue;
}
- for (mv1 = mvinit1; mv1 && !faces_separated; mv1 = mv1->next) {
- if (mv1->separate && commonFaces) {
- v1coincident = 0;
+ BMLoop *l_iter;
+ BMLoop *l_first;
+
+ l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+ do {
+ if (l_iter == l_iter->radial_next) {
+ continue;
+ }
+ if (!uvedit_edge_select_test(scene, l_iter, cd_loop_uv_offset)) {
+ continue;
}
- separated2 = 0;
- efa1 = BM_face_at_index(bm, mv1->poly_index);
- mvinit2 = vmap->vert[BM_elem_index_get(editedge->v2)];
+ const MLoopUV *luv_curr = BM_ELEM_CD_GET_VOID_P(l_iter, cd_loop_uv_offset);
+ const MLoopUV *luv_next = BM_ELEM_CD_GET_VOID_P(l_iter->next, cd_loop_uv_offset);
- for (mv2 = mvinit2; mv2; mv2 = mv2->next) {
- if (mv2->separate) {
- mv2sep = mv2;
+ bool mark = false;
+ BMLoop *l_other = l_iter->radial_next;
+ do {
+ const MLoopUV *luv_other_curr = BM_ELEM_CD_GET_VOID_P(l_other, cd_loop_uv_offset);
+ const MLoopUV *luv_other_next = BM_ELEM_CD_GET_VOID_P(l_other->next, cd_loop_uv_offset);
+ if (l_iter->v != l_other->v) {
+ SWAP(const MLoopUV *, luv_other_curr, luv_other_next);
}
- efa2 = BM_face_at_index(bm, mv2->poly_index);
- if (efa1 == efa2) {
- /* if v1 is not coincident no point in comparing */
- if (v1coincident) {
- /* have we found previously anything? */
- if (mv2cache) {
- /* flag seam unless proved to be coincident with previous hit */
- separated2 = 1;
- for (mviter = mv2cache; mviter; mviter = mviter->next) {
- if (mviter->separate && mviter != mv2cache) {
- break;
- }
- /* coincident with previous hit, do not flag seam */
- if (mviter == mv2) {
- separated2 = 0;
- }
- }
- }
- /* First hit case, store the hit in the cache */
- else {
- mv2cache = mv2sep;
- commonFaces = 1;
- }
- }
- else {
- separated1 = 1;
- }
+ if (!compare_ff(luv_curr->uv[0], luv_other_curr->uv[0], limit[0]) ||
+ !compare_ff(luv_curr->uv[1], luv_other_curr->uv[1], limit[1]) ||
- if (separated1 || separated2) {
- faces_separated = 1;
- break;
- }
+ !compare_ff(luv_next->uv[0], luv_other_next->uv[0], limit[0]) ||
+ !compare_ff(luv_next->uv[1], luv_other_next->uv[1], limit[1])) {
+ mark = true;
+ break;
}
- }
- }
+ } while ((l_other = l_other->radial_next) != l_iter);
- if (faces_separated) {
- if (mark_seams) {
- BM_elem_flag_enable(editedge, BM_ELEM_SEAM);
- }
- if (mark_sharp) {
- BM_elem_flag_disable(editedge, BM_ELEM_SMOOTH);
+ if (mark) {
+ if (mark_seams) {
+ BM_elem_flag_enable(l_iter->e, BM_ELEM_SEAM);
+ }
+ if (mark_sharp) {
+ BM_elem_flag_disable(l_iter->e, BM_ELEM_SMOOTH);
+ }
+ changed = true;
}
- }
+ } while ((l_iter = l_iter->next) != l_first);
}
- BM_uv_vert_map_free(vmap);
-
- DEG_id_tag_update(&me->id, 0);
- WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ if (changed) {
+ changed_multi = true;
+ DEG_id_tag_update(&me->id, 0);
+ WM_event_add_notifier(C, NC_GEOM | ND_DATA, me);
+ }
}
MEM_freeN(objects);
- return ret;
+ return changed_multi ? OPERATOR_FINISHED : OPERATOR_CANCELLED;
}
static void UV_OT_seams_from_islands(wmOperatorType *ot)
diff --git a/source/blender/gpu/GPU_draw.h b/source/blender/gpu/GPU_draw.h
index 3fb48292000..ab507d852e8 100644
--- a/source/blender/gpu/GPU_draw.h
+++ b/source/blender/gpu/GPU_draw.h
@@ -50,7 +50,7 @@ void GPU_paint_set_mipmap(struct Main *bmain, bool mipmap);
/* Anisotropic filtering settings
* - these will free textures on changes */
-void GPU_set_anisotropic(struct Main *bmain, float value);
+void GPU_set_anisotropic(float value);
float GPU_get_anisotropic(void);
/* Image updates and free
diff --git a/source/blender/gpu/GPU_material.h b/source/blender/gpu/GPU_material.h
index 337c0b03308..eeb2d2caef2 100644
--- a/source/blender/gpu/GPU_material.h
+++ b/source/blender/gpu/GPU_material.h
@@ -29,6 +29,8 @@
#include "BLI_sys_types.h" /* for bool */
+#include "GPU_texture.h" /* for eGPUSamplerState */
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -138,8 +140,14 @@ typedef enum eGPUMaterialStatus {
GPUNodeLink *GPU_constant(const float *num);
GPUNodeLink *GPU_uniform(const float *num);
GPUNodeLink *GPU_attribute(GPUMaterial *mat, CustomDataType type, const char *name);
-GPUNodeLink *GPU_image(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
-GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
+GPUNodeLink *GPU_image(GPUMaterial *mat,
+ struct Image *ima,
+ struct ImageUser *iuser,
+ eGPUSamplerState sampler_state);
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
+ struct Image *ima,
+ struct ImageUser *iuser,
+ eGPUSamplerState sampler_state);
GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, struct Image *ima, struct ImageUser *iuser);
GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *layer);
GPUNodeLink *GPU_volume_grid(GPUMaterial *mat, const char *name);
@@ -190,6 +198,7 @@ void GPU_materials_free(struct Main *bmain);
struct Scene *GPU_material_scene(GPUMaterial *material);
struct GPUPass *GPU_material_get_pass(GPUMaterial *material);
+struct GPUShader *GPU_material_get_shader(GPUMaterial *material);
struct Material *GPU_material_get_material(GPUMaterial *material);
eGPUMaterialStatus GPU_material_status(GPUMaterial *mat);
@@ -228,6 +237,7 @@ typedef struct GPUMaterialTexture {
char sampler_name[32]; /* Name of sampler in GLSL. */
char tiled_mapping_name[32]; /* Name of tile mapping sampler in GLSL. */
int users;
+ int sampler_state; /* eGPUSamplerState */
} GPUMaterialTexture;
typedef struct GPUMaterialVolumeGrid {
diff --git a/source/blender/gpu/GPU_shader.h b/source/blender/gpu/GPU_shader.h
index 0e382f2225f..40bae88f46d 100644
--- a/source/blender/gpu/GPU_shader.h
+++ b/source/blender/gpu/GPU_shader.h
@@ -92,16 +92,17 @@ void *GPU_shader_get_interface(GPUShader *shader);
void GPU_shader_set_srgb_uniform(const struct GPUShaderInterface *interface);
int GPU_shader_get_uniform(GPUShader *shader, const char *name);
-int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name);
int GPU_shader_get_builtin_uniform(GPUShader *shader, int builtin);
int GPU_shader_get_uniform_block(GPUShader *shader, const char *name);
+
+int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name);
+int GPU_shader_get_texture_binding(GPUShader *shader, const char *name);
+
void GPU_shader_uniform_vector(
GPUShader *shader, int location, int length, int arraysize, const float *value);
void GPU_shader_uniform_vector_int(
GPUShader *shader, int location, int length, int arraysize, const int *value);
-void GPU_shader_uniform_buffer(GPUShader *shader, int location, struct GPUUniformBuffer *ubo);
-void GPU_shader_uniform_texture(GPUShader *shader, int location, struct GPUTexture *tex);
void GPU_shader_uniform_float(GPUShader *shader, int location, float value);
void GPU_shader_uniform_int(GPUShader *shader, int location, int value);
diff --git a/source/blender/gpu/GPU_shader_interface.h b/source/blender/gpu/GPU_shader_interface.h
index 3e7bad409a3..319a79a9e42 100644
--- a/source/blender/gpu/GPU_shader_interface.h
+++ b/source/blender/gpu/GPU_shader_interface.h
@@ -64,41 +64,40 @@ typedef enum {
} GPUUniformBuiltin;
typedef struct GPUShaderInput {
- struct GPUShaderInput *next;
uint32_t name_offset;
- uint name_hash;
- /** Only for uniform inputs. */
- GPUUniformBuiltin builtin_type;
- /** Only for attribute inputs. */
- uint32_t gl_type;
- /** Only for attribute inputs. */
- int32_t size;
+ uint32_t name_hash;
int32_t location;
+ /** Defined at interface creation or in shader. Only for Samplers, UBOs and Vertex Attribs. */
+ int32_t binding;
} GPUShaderInput;
-#define GPU_NUM_SHADERINTERFACE_BUCKETS 257
#define GPU_SHADERINTERFACE_REF_ALLOC_COUNT 16
typedef struct GPUShaderInterface {
- int32_t program;
- uint32_t name_buffer_offset;
- GPUShaderInput *attr_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *uniform_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *ubo_buckets[GPU_NUM_SHADERINTERFACE_BUCKETS];
- GPUShaderInput *builtin_uniforms[GPU_NUM_UNIFORMS];
+ /** Buffer containing all inputs names separated by '\0'. */
char *name_buffer;
- struct GPUBatch **batches; /* references to batches using this interface */
+ /** Reference to GPUBatches using this interface */
+ struct GPUBatch **batches;
uint batches_len;
- /** All enabled attributes in this shader. Used to set default values for unbound attributes. */
+ /** Input counts. */
+ uint attribute_len;
+ uint ubo_len;
+ uint uniform_len;
+ /** Enabled bindpoints that needs to be fed with data. */
uint16_t enabled_attr_mask;
+ uint16_t enabled_ubo_mask;
+ uint64_t enabled_tex_mask;
+ /** Opengl Location of builtin uniforms. Fast access, no lookup needed. */
+ /* TODO replace by location only array. */
+ GPUShaderInput builtins[GPU_NUM_UNIFORMS];
+ /** Flat array. In this order: Attributes, Ubos, Uniforms. */
+ GPUShaderInput inputs[0];
} GPUShaderInterface;
GPUShaderInterface *GPU_shaderinterface_create(int32_t program_id);
void GPU_shaderinterface_discard(GPUShaderInterface *);
const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *, const char *name);
-const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *,
- const char *name);
const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *,
GPUUniformBuiltin);
const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *, const char *name);
diff --git a/source/blender/gpu/GPU_texture.h b/source/blender/gpu/GPU_texture.h
index 3d99a3c8a56..a13f61177e6 100644
--- a/source/blender/gpu/GPU_texture.h
+++ b/source/blender/gpu/GPU_texture.h
@@ -41,6 +41,31 @@ struct PreviewImage;
struct GPUFrameBuffer;
typedef struct GPUTexture GPUTexture;
+/* GPU Samplers state
+ * - Specify the sampler state to bind a texture with.
+ * - Internally used by textures.
+ * - All states are created at startup to avoid runtime costs.
+ */
+
+typedef enum eGPUSamplerState {
+ GPU_SAMPLER_FILTER = (1 << 0),
+ GPU_SAMPLER_MIPMAP = (1 << 1),
+ GPU_SAMPLER_REPEAT_S = (1 << 2),
+ GPU_SAMPLER_REPEAT_T = (1 << 3),
+ GPU_SAMPLER_REPEAT_R = (1 << 4),
+ GPU_SAMPLER_CLAMP_BORDER = (1 << 5), /* Clamp to border color instead of border texel. */
+ GPU_SAMPLER_COMPARE = (1 << 6),
+ GPU_SAMPLER_ANISO = (1 << 7),
+ /* Don't use that. */
+ GPU_SAMPLER_MAX = (1 << 8),
+} eGPUSamplerState;
+
+#define GPU_SAMPLER_DEFAULT GPU_SAMPLER_FILTER
+#define GPU_SAMPLER_REPEAT (GPU_SAMPLER_REPEAT_S | GPU_SAMPLER_REPEAT_T | GPU_SAMPLER_REPEAT_R)
+
+void GPU_samplers_init(void);
+void GPU_samplers_free(void);
+
/* GPU Texture
* - always returns unsigned char RGBA textures
* - if texture with non square dimensions is created, depending on the
@@ -236,8 +261,9 @@ void GPU_texture_free(GPUTexture *tex);
void GPU_texture_ref(GPUTexture *tex);
void GPU_texture_bind(GPUTexture *tex, int number);
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number);
void GPU_texture_unbind(GPUTexture *tex);
-int GPU_texture_bound_number(GPUTexture *tex);
+void GPU_texture_unbind_all(void);
void GPU_texture_copy(GPUTexture *dst, GPUTexture *src);
diff --git a/source/blender/gpu/GPU_vertex_format.h b/source/blender/gpu/GPU_vertex_format.h
index 7adad2ff831..61b14a4c5c0 100644
--- a/source/blender/gpu/GPU_vertex_format.h
+++ b/source/blender/gpu/GPU_vertex_format.h
@@ -101,12 +101,11 @@ typedef struct GPUVertFormat {
char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
} GPUVertFormat;
-struct GPUShaderInterface;
+struct GPUShader;
void GPU_vertformat_clear(GPUVertFormat *);
void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src);
-void GPU_vertformat_from_interface(GPUVertFormat *format,
- const struct GPUShaderInterface *shaderface);
+void GPU_vertformat_from_shader(GPUVertFormat *format, const struct GPUShader *shader);
uint GPU_vertformat_attr_add(
GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index 3e0a1e57664..5f77f13c135 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -375,7 +375,7 @@ void GPU_batch_program_set_no_use(GPUBatch *batch,
const GPUShaderInterface *shaderface)
{
#if TRUST_NO_ONE
- assert(glIsProgram(shaderface->program));
+ assert(glIsProgram(program));
assert(batch->program_in_use == 0);
#endif
batch->interface = shaderface;
@@ -551,11 +551,11 @@ void GPU_batch_program_use_end(GPUBatch *batch)
#if TRUST_NO_ONE
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name); \
assert(uniform);
#else
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(batch->interface, name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(batch->interface, name);
#endif
void GPU_batch_uniform_1ui(GPUBatch *batch, const char *name, uint value)
diff --git a/source/blender/gpu/intern/gpu_codegen.c b/source/blender/gpu/intern/gpu_codegen.c
index 8a46e24d459..c1e7933d7ba 100644
--- a/source/blender/gpu/intern/gpu_codegen.c
+++ b/source/blender/gpu/intern/gpu_codegen.c
@@ -1160,7 +1160,7 @@ static int count_active_texture_sampler(GPUShader *shader, char *source)
if (*code != '\0') {
char sampler_name[64];
code = gpu_str_skip_token(code, sampler_name, sizeof(sampler_name));
- int id = GPU_shader_get_uniform_ensure(shader, sampler_name);
+ int id = GPU_shader_get_uniform(shader, sampler_name);
if (id == -1) {
continue;
diff --git a/source/blender/gpu/intern/gpu_draw.c b/source/blender/gpu/intern/gpu_draw.c
index 7871907a7d4..1c346217e9f 100644
--- a/source/blender/gpu/intern/gpu_draw.c
+++ b/source/blender/gpu/intern/gpu_draw.c
@@ -158,10 +158,10 @@ static GLenum gpu_get_mipmap_filter(bool mag)
}
/* Anisotropic filtering settings */
-void GPU_set_anisotropic(Main *bmain, float value)
+void GPU_set_anisotropic(float value)
{
if (GTS.anisotropic != value) {
- GPU_free_images(bmain);
+ GPU_samplers_free();
/* Clamp value to the maximum value the graphics card supports */
const float max = GPU_max_texture_anisotropy();
@@ -170,6 +170,8 @@ void GPU_set_anisotropic(Main *bmain, float value)
}
GTS.anisotropic = value;
+
+ GPU_samplers_init();
}
}
@@ -449,22 +451,12 @@ static uint gpu_texture_create_tile_array(Image *ima, ImBuf *main_ibuf)
BKE_image_release_ibuf(ima, ibuf, NULL);
}
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap()) {
glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
-
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
@@ -1098,18 +1090,12 @@ void GPU_create_gl_tex(uint *bind,
GL_TEXTURE_2D, 0, internal_format, rectw, recth, 0, GL_RGBA, GL_UNSIGNED_BYTE, rect);
}
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap() && mipmap) {
glGenerateMipmap(GL_TEXTURE_2D);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
}
else if (textarget == GL_TEXTURE_CUBE_MAP) {
int w = rectw / 3, h = recth / 2;
@@ -1132,22 +1118,13 @@ void GPU_create_gl_tex(uint *bind,
}
}
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
-
if (GPU_get_mipmap() && mipmap) {
glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
if (ima) {
ima->gpuflag |= IMA_GPU_MIPMAP_COMPLETE;
}
}
- else {
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- }
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
gpu_del_cube_map(cube_map);
}
@@ -1156,10 +1133,6 @@ void GPU_create_gl_tex(uint *bind,
}
}
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(textarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
-
glBindTexture(textarget, 0);
if (ibuf) {
@@ -1211,10 +1184,6 @@ bool GPU_upload_dxt_texture(ImBuf *ibuf, bool use_srgb)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, gpu_get_mipmap_filter(0));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, gpu_get_mipmap_filter(1));
- if (GLEW_EXT_texture_filter_anisotropic) {
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GPU_get_anisotropic());
- }
-
blocksize = (ibuf->dds_data.fourcc == FOURCC_DXT1) ? 8 : 16;
for (i = 0; i < ibuf->dds_data.nummipmaps && (width || height); i++) {
if (width == 0) {
diff --git a/source/blender/gpu/intern/gpu_extensions.c b/source/blender/gpu/intern/gpu_extensions.c
index ff745787630..8f911f3c77d 100644
--- a/source/blender/gpu/intern/gpu_extensions.c
+++ b/source/blender/gpu/intern/gpu_extensions.c
@@ -355,11 +355,13 @@ void gpu_extensions_init(void)
}
GPU_invalid_tex_init();
+ GPU_samplers_init();
}
void gpu_extensions_exit(void)
{
GPU_invalid_tex_free();
+ GPU_samplers_free();
}
bool GPU_mem_stats_supported(void)
diff --git a/source/blender/gpu/intern/gpu_immediate.c b/source/blender/gpu/intern/gpu_immediate.c
index d95904c0007..b4cc432dd36 100644
--- a/source/blender/gpu/intern/gpu_immediate.c
+++ b/source/blender/gpu/intern/gpu_immediate.c
@@ -759,13 +759,11 @@ void immVertex2iv(uint attr_id, const int data[2])
#if 0
# if TRUST_NO_ONE
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
assert(uniform);
# else
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name);
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name);
# endif
#else
/* NOTE: It is possible to have uniform fully optimized out from the shader.
@@ -773,8 +771,7 @@ void immVertex2iv(uint attr_id, const int data[2])
* TODO(sergey): How can we detect existing-but-optimized-out uniform but still
* catch typos in uniform names passed to immUniform*() functions? */
# define GET_UNIFORM \
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(imm.shader_interface, \
- name); \
+ const GPUShaderInput *uniform = GPU_shaderinterface_uniform(imm.shader_interface, name); \
if (uniform == NULL) \
return;
#endif
@@ -812,20 +809,9 @@ void immUniform3fv(const char *name, const float data[3])
/* can increase this limit or move to another file */
#define MAX_UNIFORM_NAME_LEN 60
-void immUniformArray3fv(const char *bare_name, const float *data, int count)
+/* Note array index is not supported for name (i.e: "array[0]"). */
+void immUniformArray3fv(const char *name, const float *data, int count)
{
- /* look up "name[0]" when given "name" */
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
GET_UNIFORM
glUniform3fv(uniform->location, count, data);
}
@@ -842,20 +828,9 @@ void immUniform4fv(const char *name, const float data[4])
glUniform4fv(uniform->location, 1, data);
}
-void immUniformArray4fv(const char *bare_name, const float *data, int count)
+/* Note array index is not supported for name (i.e: "array[0]"). */
+void immUniformArray4fv(const char *name, const float *data, int count)
{
- /* look up "name[0]" when given "name" */
- const size_t len = strlen(bare_name);
-#if TRUST_NO_ONE
- assert(len <= MAX_UNIFORM_NAME_LEN);
-#endif
- char name[MAX_UNIFORM_NAME_LEN];
- strcpy(name, bare_name);
- name[len + 0] = '[';
- name[len + 1] = '0';
- name[len + 2] = ']';
- name[len + 3] = '\0';
-
GET_UNIFORM
glUniform4fv(uniform->location, count, data);
}
diff --git a/source/blender/gpu/intern/gpu_material.c b/source/blender/gpu/intern/gpu_material.c
index 97e4c880644..d2384b9c065 100644
--- a/source/blender/gpu/intern/gpu_material.c
+++ b/source/blender/gpu/intern/gpu_material.c
@@ -209,6 +209,11 @@ GPUPass *GPU_material_get_pass(GPUMaterial *material)
return material->pass;
}
+GPUShader *GPU_material_get_shader(GPUMaterial *material)
+{
+ return material->pass ? GPU_pass_shader_get(material->pass) : NULL;
+}
+
/* Return can be NULL if it's a world material. */
Material *GPU_material_get_material(GPUMaterial *material)
{
@@ -662,6 +667,9 @@ GPUMaterial *GPU_material_from_nodetree(Scene *scene,
/* Caller must re-use materials. */
BLI_assert(GPU_material_from_nodetree_find(gpumaterials, engine_type, options) == NULL);
+ /* HACK: Eevee assume this to create Ghash keys. */
+ BLI_assert(sizeof(GPUPass) > 16);
+
/* allocate material */
GPUMaterial *mat = MEM_callocN(sizeof(GPUMaterial), "GPUMaterial");
mat->ma = ma;
diff --git a/source/blender/gpu/intern/gpu_node_graph.c b/source/blender/gpu/intern/gpu_node_graph.c
index 876a6bef670..17d97dc05e2 100644
--- a/source/blender/gpu/intern/gpu_node_graph.c
+++ b/source/blender/gpu/intern/gpu_node_graph.c
@@ -34,6 +34,8 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "GPU_texture.h"
+
#include "gpu_material_library.h"
#include "gpu_node_graph.h"
@@ -298,13 +300,14 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
Image *ima,
ImageUser *iuser,
struct GPUTexture **colorband,
- GPUNodeLinkType link_type)
+ GPUNodeLinkType link_type,
+ eGPUSamplerState sampler_state)
{
/* Find existing texture. */
int num_textures = 0;
GPUMaterialTexture *tex = graph->textures.first;
for (; tex; tex = tex->next) {
- if (tex->ima == ima && tex->colorband == colorband) {
+ if (tex->ima == ima && tex->colorband == colorband && tex->sampler_state == sampler_state) {
break;
}
num_textures++;
@@ -316,6 +319,7 @@ static GPUMaterialTexture *gpu_node_graph_add_texture(GPUNodeGraph *graph,
tex->ima = ima;
tex->iuser = iuser;
tex->colorband = colorband;
+ tex->sampler_state = sampler_state;
BLI_snprintf(tex->sampler_name, sizeof(tex->sampler_name), "samp%d", num_textures);
if (ELEM(link_type, GPU_NODE_LINK_IMAGE_TILED, GPU_NODE_LINK_IMAGE_TILED_MAPPING)) {
BLI_snprintf(
@@ -389,21 +393,29 @@ GPUNodeLink *GPU_uniform(const float *num)
return link;
}
-GPUNodeLink *GPU_image(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image(GPUMaterial *mat,
+ Image *ima,
+ ImageUser *iuser,
+ eGPUSamplerState sampler_state)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, sampler_state);
return link;
}
-GPUNodeLink *GPU_image_tiled(GPUMaterial *mat, Image *ima, ImageUser *iuser)
+GPUNodeLink *GPU_image_tiled(GPUMaterial *mat,
+ Image *ima,
+ ImageUser *iuser,
+ eGPUSamplerState sampler_state)
{
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, sampler_state);
return link;
}
@@ -412,7 +424,8 @@ GPUNodeLink *GPU_image_tiled_mapping(GPUMaterial *mat, Image *ima, ImageUser *iu
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_IMAGE_TILED_MAPPING;
- link->texture = gpu_node_graph_add_texture(graph, ima, iuser, NULL, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, ima, iuser, NULL, link->link_type, GPU_SAMPLER_MAX);
return link;
}
@@ -424,7 +437,8 @@ GPUNodeLink *GPU_color_band(GPUMaterial *mat, int size, float *pixels, float *ro
GPUNodeGraph *graph = gpu_material_node_graph(mat);
GPUNodeLink *link = gpu_node_link_create();
link->link_type = GPU_NODE_LINK_COLORBAND;
- link->texture = gpu_node_graph_add_texture(graph, NULL, NULL, colorband, link->link_type);
+ link->texture = gpu_node_graph_add_texture(
+ graph, NULL, NULL, colorband, link->link_type, GPU_SAMPLER_MAX);
return link;
}
diff --git a/source/blender/gpu/intern/gpu_shader.c b/source/blender/gpu/intern/gpu_shader.c
index 8dfc992ae9f..66f98461047 100644
--- a/source/blender/gpu/intern/gpu_shader.c
+++ b/source/blender/gpu/intern/gpu_shader.c
@@ -331,6 +331,8 @@ GPUShader *GPU_shader_load_from_binary(const char *binary,
glGetProgramiv(program, GL_LINK_STATUS, &success);
if (success) {
+ glUseProgram(program);
+
GPUShader *shader = MEM_callocN(sizeof(*shader), __func__);
shader->interface = GPU_shaderinterface_create(program);
shader->program = program;
@@ -572,6 +574,7 @@ GPUShader *GPU_shader_create_ex(const char *vertexcode,
return NULL;
}
+ glUseProgram(shader->program);
shader->interface = GPU_shaderinterface_create(shader->program);
return shader;
@@ -726,13 +729,6 @@ int GPU_shader_get_uniform(GPUShader *shader, const char *name)
{
BLI_assert(shader && shader->program);
const GPUShaderInput *uniform = GPU_shaderinterface_uniform(shader->interface, name);
- return uniform ? uniform->location : -2;
-}
-
-int GPU_shader_get_uniform_ensure(GPUShader *shader, const char *name)
-{
- BLI_assert(shader && shader->program);
- const GPUShaderInput *uniform = GPU_shaderinterface_uniform_ensure(shader->interface, name);
return uniform ? uniform->location : -1;
}
@@ -750,6 +746,20 @@ int GPU_shader_get_uniform_block(GPUShader *shader, const char *name)
return ubo ? ubo->location : -1;
}
+int GPU_shader_get_uniform_block_binding(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+ const GPUShaderInput *ubo = GPU_shaderinterface_ubo(shader->interface, name);
+ return ubo ? ubo->binding : -1;
+}
+
+int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
+{
+ BLI_assert(shader && shader->program);
+ const GPUShaderInput *tex = GPU_shaderinterface_uniform(shader->interface, name);
+ return tex ? tex->binding : -1;
+}
+
void *GPU_shader_get_interface(GPUShader *shader)
{
return shader->interface;
@@ -837,34 +847,6 @@ void GPU_shader_uniform_int(GPUShader *UNUSED(shader), int location, int value)
glUniform1i(location, value);
}
-void GPU_shader_uniform_buffer(GPUShader *shader, int location, GPUUniformBuffer *ubo)
-{
- int bindpoint = GPU_uniformbuffer_bindpoint(ubo);
-
- if (location == -1) {
- return;
- }
-
- glUniformBlockBinding(shader->program, location, bindpoint);
-}
-
-void GPU_shader_uniform_texture(GPUShader *UNUSED(shader), int location, GPUTexture *tex)
-{
- int number = GPU_texture_bound_number(tex);
-
- if (number == -1) {
- fprintf(stderr, "Texture is not bound.\n");
- BLI_assert(0);
- return;
- }
-
- if (location == -1) {
- return;
- }
-
- glUniform1i(location, number);
-}
-
void GPU_shader_set_srgb_uniform(const GPUShaderInterface *interface)
{
const GPUShaderInput *srgb_uniform = GPU_shaderinterface_uniform_builtin(
diff --git a/source/blender/gpu/intern/gpu_shader_interface.c b/source/blender/gpu/intern/gpu_shader_interface.c
index 3218d12bc0d..84be8affc16 100644
--- a/source/blender/gpu/intern/gpu_shader_interface.c
+++ b/source/blender/gpu/intern/gpu_shader_interface.c
@@ -24,6 +24,9 @@
*/
#include "BKE_global.h"
+
+#include "BLI_math_base.h"
+
#include "MEM_guardedalloc.h"
#include "GPU_shader_interface.h"
@@ -91,129 +94,136 @@ GPU_INLINE uint hash_string(const char *str)
return i;
}
-GPU_INLINE void set_input_name(GPUShaderInterface *shaderface,
- GPUShaderInput *input,
- const char *name,
- uint32_t name_len)
+GPU_INLINE uint32_t set_input_name(GPUShaderInterface *shaderface,
+ GPUShaderInput *input,
+ char *name,
+ uint32_t name_len)
{
- input->name_offset = shaderface->name_buffer_offset;
- input->name_hash = hash_string(name);
- shaderface->name_buffer_offset += name_len + 1; /* include NULL terminator */
-}
+ /* remove "[0]" from array name */
+ if (name[name_len - 1] == ']') {
+ name[name_len - 3] = '\0';
+ name_len -= 3;
+ }
-GPU_INLINE void shader_input_to_bucket(GPUShaderInput *input,
- GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
-{
- const uint bucket_index = input->name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
- input->next = buckets[bucket_index];
- buckets[bucket_index] = input;
+ input->name_offset = (uint32_t)(name - shaderface->name_buffer);
+ input->name_hash = hash_string(name);
+ return name_len + 1; /* include NULL terminator */
}
-GPU_INLINE const GPUShaderInput *buckets_lookup(
- GPUShaderInput *const buckets[GPU_NUM_SHADERINTERFACE_BUCKETS],
- const char *name_buffer,
- const char *name)
+GPU_INLINE const GPUShaderInput *input_lookup(const GPUShaderInterface *shaderface,
+ const GPUShaderInput *const inputs,
+ const uint inputs_len,
+ const char *name)
{
const uint name_hash = hash_string(name);
- const uint bucket_index = name_hash % GPU_NUM_SHADERINTERFACE_BUCKETS;
- const GPUShaderInput *input = buckets[bucket_index];
- if (input == NULL) {
- /* Requested uniform is not found at all. */
- return NULL;
- }
- /* Optimization bit: if there is no hash collision detected when constructing shader interface
- * it means we can only request the single possible uniform. Surely, it's possible we request
- * uniform which causes hash collision, but that will be detected in debug builds. */
- if (input->next == NULL) {
- if (name_hash == input->name_hash) {
-#if TRUST_NO_ONE
- assert(match(name_buffer + input->name_offset, name));
-#endif
- return input;
- }
- return NULL;
- }
- /* Work through possible collisions. */
- const GPUShaderInput *next = input;
- while (next != NULL) {
- input = next;
- next = input->next;
- if (input->name_hash != name_hash) {
- continue;
- }
- if (match(name_buffer + input->name_offset, name)) {
- return input;
+ /* Simple linear search for now. */
+ for (int i = inputs_len - 1; i >= 0; i--) {
+ if (inputs[i].name_hash == name_hash) {
+ if ((i > 0) && UNLIKELY(inputs[i - 1].name_hash == name_hash)) {
+ /* Hash colision resolve. */
+ for (; i >= 0 && inputs[i].name_hash == name_hash; i--) {
+ if (match(name, shaderface->name_buffer + inputs[i].name_offset)) {
+ return inputs + i; /* not found */
+ }
+ }
+ return NULL; /* not found */
+ }
+ else {
+ /* This is a bit dangerous since we could have a hash collision.
+ * where the asked uniform that does not exist has the same hash
+ * as a real uniform. */
+ BLI_assert(match(name, shaderface->name_buffer + inputs[i].name_offset));
+ return inputs + i;
+ }
}
}
return NULL; /* not found */
}
-GPU_INLINE void buckets_free(GPUShaderInput *buckets[GPU_NUM_SHADERINTERFACE_BUCKETS])
+/* Note that this modify the src array. */
+GPU_INLINE void sort_input_list(GPUShaderInput *dst, GPUShaderInput *src, const uint input_len)
{
- for (uint bucket_index = 0; bucket_index < GPU_NUM_SHADERINTERFACE_BUCKETS; bucket_index++) {
- GPUShaderInput *input = buckets[bucket_index];
- while (input != NULL) {
- GPUShaderInput *input_next = input->next;
- MEM_freeN(input);
- input = input_next;
+ for (uint i = 0; i < input_len; i++) {
+ GPUShaderInput *input_src = &src[0];
+ for (uint j = 1; j < input_len; j++) {
+ if (src[j].name_hash > input_src->name_hash) {
+ input_src = &src[j];
+ }
}
+ dst[i] = *input_src;
+ input_src->name_hash = 0;
}
}
-static bool setup_builtin_uniform(GPUShaderInput *input, const char *name)
+static int block_binding(int32_t program, uint32_t block_index)
{
- /* TODO: reject DOUBLE, IMAGE, ATOMIC_COUNTER gl_types */
-
- /* detect built-in uniforms (name must match) */
- for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) {
- const char *builtin_name = BuiltinUniform_name(u);
- if (match(name, builtin_name)) {
- input->builtin_type = u;
- return true;
- }
- }
- input->builtin_type = GPU_UNIFORM_CUSTOM;
- return false;
+ /* For now just assign a consecutive index. In the future, we should set it in
+ * the shader using layout(binding = i) and query its value. */
+ glUniformBlockBinding(program, block_index, block_index);
+ return block_index;
}
-static const GPUShaderInput *add_uniform(GPUShaderInterface *shaderface, const char *name)
+static int sampler_binding(int32_t program,
+ uint32_t uniform_index,
+ int32_t uniform_location,
+ int *sampler_len)
{
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Unif");
-
- input->location = glGetUniformLocation(shaderface->program, name);
-
- const uint name_len = strlen(name);
- /* Include NULL terminator. */
- shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer,
- shaderface->name_buffer_offset + name_len + 1);
- char *name_buffer = shaderface->name_buffer + shaderface->name_buffer_offset;
- strcpy(name_buffer, name);
-
- set_input_name(shaderface, input, name, name_len);
- setup_builtin_uniform(input, name);
-
- shader_input_to_bucket(input, shaderface->uniform_buckets);
- if (input->builtin_type != GPU_UNIFORM_NONE && input->builtin_type != GPU_UNIFORM_CUSTOM) {
- shaderface->builtin_uniforms[input->builtin_type] = input;
+ /* Identify sampler uniforms and asign sampler units to them. */
+ GLint type;
+ glGetActiveUniformsiv(program, 1, &uniform_index, GL_UNIFORM_TYPE, &type);
+
+ switch (type) {
+ case GL_SAMPLER_1D:
+ case GL_SAMPLER_2D:
+ case GL_SAMPLER_3D:
+ case GL_SAMPLER_CUBE:
+ case GL_SAMPLER_CUBE_MAP_ARRAY_ARB: /* OpenGL 4.0 */
+ case GL_SAMPLER_1D_SHADOW:
+ case GL_SAMPLER_2D_SHADOW:
+ case GL_SAMPLER_1D_ARRAY:
+ case GL_SAMPLER_2D_ARRAY:
+ case GL_SAMPLER_1D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_ARRAY_SHADOW:
+ case GL_SAMPLER_2D_MULTISAMPLE:
+ case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_SAMPLER_CUBE_SHADOW:
+ case GL_SAMPLER_BUFFER:
+ case GL_INT_SAMPLER_1D:
+ case GL_INT_SAMPLER_2D:
+ case GL_INT_SAMPLER_3D:
+ case GL_INT_SAMPLER_CUBE:
+ case GL_INT_SAMPLER_1D_ARRAY:
+ case GL_INT_SAMPLER_2D_ARRAY:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_INT_SAMPLER_BUFFER:
+ case GL_UNSIGNED_INT_SAMPLER_1D:
+ case GL_UNSIGNED_INT_SAMPLER_2D:
+ case GL_UNSIGNED_INT_SAMPLER_3D:
+ case GL_UNSIGNED_INT_SAMPLER_CUBE:
+ case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
+ case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+ case GL_UNSIGNED_INT_SAMPLER_BUFFER: {
+ /* For now just assign a consecutive index. In the future, we should set it in
+ * the shader using layout(binding = i) and query its value. */
+ int binding = *sampler_len;
+ glUniform1i(uniform_location, binding);
+ (*sampler_len)++;
+ return binding;
+ }
+ default:
+ return -1;
}
-#if DEBUG_SHADER_INTERFACE
- printf("GPUShaderInterface %p, program %d, uniform[] '%s' at location %d\n",
- shaderface,
- shaderface->program,
- name,
- input->location);
-#endif
- return input;
}
GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
{
- GPUShaderInterface *shaderface = MEM_callocN(sizeof(GPUShaderInterface), "GPUShaderInterface");
- shaderface->program = program;
-
-#if DEBUG_SHADER_INTERFACE
- printf("%s {\n", __func__); /* enter function */
- printf("GPUShaderInterface %p, program %d\n", shaderface, program);
+#ifndef NDEBUG
+ GLint curr_program;
+ glGetIntegerv(GL_CURRENT_PROGRAM, &curr_program);
+ BLI_assert(curr_program == program);
#endif
GLint max_attr_name_len = 0, attr_len = 0;
@@ -224,6 +234,11 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_ubo_name_len);
glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &ubo_len);
+ GLint max_uniform_name_len = 0, active_uniform_len = 0, uniform_len = 0;
+ glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_uniform_name_len);
+ glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &active_uniform_len);
+ uniform_len = active_uniform_len;
+
/* Work around driver bug with Intel HD 4600 on Windows 7/8, where
* GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH does not work. */
if (attr_len > 0 && max_attr_name_len == 0) {
@@ -232,87 +247,185 @@ GPUShaderInterface *GPU_shaderinterface_create(int32_t program)
if (ubo_len > 0 && max_ubo_name_len == 0) {
max_ubo_name_len = 256;
}
+ if (uniform_len > 0 && max_uniform_name_len == 0) {
+ max_uniform_name_len = 256;
+ }
+
+ /* GL_ACTIVE_UNIFORMS lied to us! Remove the UBO uniforms from the total before
+ * allocating the uniform array. */
+ GLint *uniforms_block_index = MEM_mallocN(sizeof(GLint) * active_uniform_len, __func__);
+ if (uniform_len > 0) {
+ GLuint *indices = MEM_mallocN(sizeof(GLuint) * active_uniform_len, __func__);
+ for (uint i = 0; i < uniform_len; i++) {
+ indices[i] = i;
+ }
+
+ glGetActiveUniformsiv(
+ program, uniform_len, indices, GL_UNIFORM_BLOCK_INDEX, uniforms_block_index);
+
+ MEM_freeN(indices);
+
+ for (int i = 0; i < active_uniform_len; i++) {
+ /* If GL_UNIFORM_BLOCK_INDEX is not -1 it means the uniform belongs to a UBO. */
+ if (uniforms_block_index[i] != -1) {
+ uniform_len--;
+ }
+ }
+ }
+
+ uint32_t name_buffer_offset = 0;
+ const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len +
+ uniform_len * max_uniform_name_len;
- const uint32_t name_buffer_len = attr_len * max_attr_name_len + ubo_len * max_ubo_name_len;
+ int input_tot_len = attr_len + ubo_len + uniform_len;
+ size_t interface_size = sizeof(GPUShaderInterface) + sizeof(GPUShaderInput) * input_tot_len;
+
+ GPUShaderInterface *shaderface = MEM_callocN(interface_size, "GPUShaderInterface");
+ shaderface->attribute_len = attr_len;
+ shaderface->ubo_len = ubo_len;
+ shaderface->uniform_len = uniform_len;
shaderface->name_buffer = MEM_mallocN(name_buffer_len, "name_buffer");
+ GPUShaderInput *inputs = shaderface->inputs;
+
+ /* Temp buffer. */
+ int input_tmp_len = max_iii(attr_len, ubo_len, uniform_len);
+ GPUShaderInput *inputs_tmp = MEM_mallocN(sizeof(GPUShaderInput) * input_tmp_len, "name_buffer");
/* Attributes */
shaderface->enabled_attr_mask = 0;
- for (uint32_t i = 0; i < attr_len; i++) {
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput Attr");
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ for (int i = 0, idx = 0; i < attr_len; i++) {
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
GLsizei name_len = 0;
+ GLenum type;
+ GLint size;
- glGetActiveAttrib(
- program, i, remaining_buffer, &name_len, &input->size, &input->gl_type, name);
-
- /* remove "[0]" from array name */
- if (name[name_len - 1] == ']') {
- name[name_len - 3] = '\0';
- name_len -= 3;
- }
-
- /* TODO: reject DOUBLE gl_types */
- input->location = glGetAttribLocation(program, name);
+ glGetActiveAttrib(program, i, remaining_buffer, &name_len, &size, &type, name);
+ GLint location = glGetAttribLocation(program, name);
/* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
- if (input->location == -1) {
- MEM_freeN(input);
+ if (location == -1) {
+ shaderface->attribute_len--;
continue;
}
- if (input->location != -1) {
- shaderface->enabled_attr_mask |= (1 << input->location);
- }
-
- set_input_name(shaderface, input, name, name_len);
-
- shader_input_to_bucket(input, shaderface->attr_buckets);
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->location = input->binding = location;
-#if DEBUG_SHADER_INTERFACE
- printf("attr[%u] '%s' at location %d\n", i, name, input->location);
-#endif
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_attr_mask |= (1 << input->location);
}
+ sort_input_list(inputs, inputs_tmp, shaderface->attribute_len);
+ inputs += shaderface->attribute_len;
+
/* Uniform Blocks */
- for (uint32_t i = 0; i < ubo_len; i++) {
- GPUShaderInput *input = MEM_mallocN(sizeof(GPUShaderInput), "GPUShaderInput UBO");
- GLsizei remaining_buffer = name_buffer_len - shaderface->name_buffer_offset;
- char *name = shaderface->name_buffer + shaderface->name_buffer_offset;
+ for (int i = 0, idx = 0; i < ubo_len; i++) {
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
GLsizei name_len = 0;
glGetActiveUniformBlockName(program, i, remaining_buffer, &name_len, name);
- input->location = i;
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->binding = input->location = block_binding(program, i);
- set_input_name(shaderface, input, name, name_len);
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_ubo_mask |= (1 << input->binding);
+ }
+ sort_input_list(inputs, inputs_tmp, shaderface->ubo_len);
+ inputs += shaderface->ubo_len;
- shader_input_to_bucket(input, shaderface->ubo_buckets);
+ /* Uniforms */
+ for (int i = 0, idx = 0, sampler = 0; i < active_uniform_len; i++) {
+ /* If GL_UNIFORM_BLOCK_INDEX is not -1 it means the uniform belongs to a UBO. */
+ if (uniforms_block_index[i] != -1) {
+ continue;
+ }
+ char *name = shaderface->name_buffer + name_buffer_offset;
+ GLsizei remaining_buffer = name_buffer_len - name_buffer_offset;
+ GLsizei name_len = 0;
-#if DEBUG_SHADER_INTERFACE
- printf("ubo '%s' at location %d\n", name, input->location);
-#endif
+ glGetActiveUniformName(program, i, remaining_buffer, &name_len, name);
+
+ GPUShaderInput *input = &inputs_tmp[idx++];
+ input->location = glGetUniformLocation(program, name);
+ input->binding = sampler_binding(program, i, input->location, &sampler);
+
+ name_buffer_offset += set_input_name(shaderface, input, name, name_len);
+ shaderface->enabled_tex_mask |= (input->binding != -1) ? (1lu << input->binding) : 0lu;
}
+ sort_input_list(inputs, inputs_tmp, shaderface->uniform_len);
+
/* Builtin Uniforms */
for (GPUUniformBuiltin u = GPU_UNIFORM_NONE + 1; u < GPU_UNIFORM_CUSTOM; u++) {
- const char *builtin_name = BuiltinUniform_name(u);
- if (glGetUniformLocation(program, builtin_name) != -1) {
- add_uniform((GPUShaderInterface *)shaderface, builtin_name);
- }
+ shaderface->builtins[u].location = glGetUniformLocation(program, BuiltinUniform_name(u));
+ shaderface->builtins[u].binding = -1;
}
+
/* Batches ref buffer */
shaderface->batches_len = GPU_SHADERINTERFACE_REF_ALLOC_COUNT;
shaderface->batches = MEM_callocN(shaderface->batches_len * sizeof(GPUBatch *),
"GPUShaderInterface batches");
+ MEM_freeN(uniforms_block_index);
+ MEM_freeN(inputs_tmp);
+
+ /* Resize name buffer to save some memory. */
+ if (name_buffer_offset < name_buffer_len) {
+ shaderface->name_buffer = MEM_reallocN(shaderface->name_buffer, name_buffer_offset);
+ }
+
+#if DEBUG_SHADER_INTERFACE
+ char *name_buf = shaderface->name_buffer;
+ printf("--- GPUShaderInterface %p, program %d ---\n", shaderface, program);
+ if (shaderface->attribute_len > 0) {
+ printf("Attributes {\n");
+ for (int i = 0; i < shaderface->attribute_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + i;
+ printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset);
+ }
+ printf("};\n");
+ }
+ if (shaderface->ubo_len > 0) {
+ printf("Uniform Buffer Objects {\n");
+ for (int i = 0; i < shaderface->ubo_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len + i;
+ printf("\t(binding = %d) %s;\n", input->binding, name_buf + input->name_offset);
+ }
+ printf("};\n");
+ }
+ if (shaderface->enabled_tex_mask > 0) {
+ printf("Samplers {\n");
+ for (int i = 0; i < shaderface->uniform_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len +
+ shaderface->ubo_len + i;
+ if (input->binding != -1) {
+ printf("\t(location = %d, binding = %d) %s;\n",
+ input->location,
+ input->binding,
+ name_buf + input->name_offset);
+ }
+ }
+ printf("};\n");
+ }
+ if (shaderface->uniform_len > 0) {
+ printf("Uniforms {\n");
+ for (int i = 0; i < shaderface->uniform_len; i++) {
+ GPUShaderInput *input = shaderface->inputs + shaderface->attribute_len +
+ shaderface->ubo_len + i;
+ if (input->binding == -1) {
+ printf("\t(location = %d) %s;\n", input->location, name_buf + input->name_offset);
+ }
+ }
+ printf("};\n");
+ }
+ printf("--- GPUShaderInterface end ---\n\n");
+#endif
+
return shaderface;
}
void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
{
- /* Free memory used by buckets and has entries. */
- buckets_free(shaderface->uniform_buckets);
- buckets_free(shaderface->attr_buckets);
- buckets_free(shaderface->ubo_buckets);
/* Free memory used by name_buffer. */
MEM_freeN(shaderface->name_buffer);
/* Remove this interface from all linked Batches vao cache. */
@@ -326,36 +439,25 @@ void GPU_shaderinterface_discard(GPUShaderInterface *shaderface)
MEM_freeN(shaderface);
}
-const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
- const char *name)
+const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
+ const char *name)
{
- return buckets_lookup(shaderface->uniform_buckets, shaderface->name_buffer, name);
+ uint ofs = 0;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->attribute_len, name);
}
-const GPUShaderInput *GPU_shaderinterface_uniform_ensure(const GPUShaderInterface *shaderface,
- const char *name)
+const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
+ const char *name)
{
- const GPUShaderInput *input = GPU_shaderinterface_uniform(shaderface, name);
- /* If input is not found add it so it's found next time. */
- if (input == NULL) {
- input = add_uniform((GPUShaderInterface *)shaderface, name);
-
- if ((G.debug & G_DEBUG_GPU) && (input->location == -1)) {
- fprintf(stderr, "GPUShaderInterface: Warning: Uniform '%s' not found!\n", name);
- }
- }
+ uint ofs = shaderface->attribute_len;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->ubo_len, name);
+}
-#if DEBUG_SHADER_UNIFORMS
- if ((G.debug & G_DEBUG_GPU) && input->builtin_type != GPU_UNIFORM_NONE &&
- input->builtin_type != GPU_UNIFORM_CUSTOM) {
- /* Warn if we find a matching builtin, since these can be looked up much quicker. */
- fprintf(stderr,
- "GPUShaderInterface: Warning: Uniform '%s' is a builtin uniform but not queried as "
- "such!\n",
- name);
- }
-#endif
- return (input->location != -1) ? input : NULL;
+const GPUShaderInput *GPU_shaderinterface_uniform(const GPUShaderInterface *shaderface,
+ const char *name)
+{
+ uint ofs = shaderface->attribute_len + shaderface->ubo_len;
+ return input_lookup(shaderface, shaderface->inputs + ofs, shaderface->uniform_len, name);
}
const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterface *shaderface,
@@ -366,19 +468,7 @@ const GPUShaderInput *GPU_shaderinterface_uniform_builtin(const GPUShaderInterfa
assert(builtin != GPU_UNIFORM_CUSTOM);
assert(builtin != GPU_NUM_UNIFORMS);
#endif
- return shaderface->builtin_uniforms[builtin];
-}
-
-const GPUShaderInput *GPU_shaderinterface_ubo(const GPUShaderInterface *shaderface,
- const char *name)
-{
- return buckets_lookup(shaderface->ubo_buckets, shaderface->name_buffer, name);
-}
-
-const GPUShaderInput *GPU_shaderinterface_attr(const GPUShaderInterface *shaderface,
- const char *name)
-{
- return buckets_lookup(shaderface->attr_buckets, shaderface->name_buffer, name);
+ return &shaderface->builtins[builtin];
}
void GPU_shaderinterface_add_batch_ref(GPUShaderInterface *shaderface, GPUBatch *batch)
diff --git a/source/blender/gpu/intern/gpu_texture.c b/source/blender/gpu/intern/gpu_texture.c
index 38ba8bc612f..1d870ed2fdc 100644
--- a/source/blender/gpu/intern/gpu_texture.c
+++ b/source/blender/gpu/intern/gpu_texture.c
@@ -50,7 +50,9 @@ static struct GPUTextureGlobal {
GPUTexture *invalid_tex_1D;
GPUTexture *invalid_tex_2D;
GPUTexture *invalid_tex_3D;
-} GG = {NULL, NULL, NULL};
+ /** Sampler objects used to replace internal texture parameters. */
+ GLuint samplers[GPU_SAMPLER_MAX];
+} GG = {NULL};
/* Maximum number of FBOs a texture can be attached to. */
#define GPU_TEX_MAX_FBO_ATTACHED 12
@@ -72,7 +74,7 @@ typedef enum eGPUTextureFormatFlag {
struct GPUTexture {
int w, h, d; /* width/height/depth */
int orig_w, orig_h; /* width/height (of source data), optional. */
- int number; /* number for multitexture binding */
+ int number; /* Texture unit to which this texture is bound. */
int refcount; /* reference count */
GLenum target; /* GL_TEXTURE_* */
GLenum target_base; /* same as target, (but no multisample)
@@ -81,6 +83,7 @@ struct GPUTexture {
eGPUTextureFormat format;
eGPUTextureFormatFlag format_flag;
+ eGPUSamplerState sampler_state; /* Internal Sampler state. */
int mipmaps; /* number of mipmaps */
int components; /* number of color/alpha channels */
@@ -827,12 +830,12 @@ GPUTexture *GPU_texture_create_nD(int w,
tex->h = h;
tex->d = d;
tex->samples = samples;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = 0;
+ tex->number = -1;
if (n == 2) {
if (d == 0) {
@@ -976,26 +979,13 @@ GPUTexture *GPU_texture_create_nD(int w,
if (GPU_texture_stencil(tex) || /* Does not support filtering */
GPU_texture_integer(tex) || /* Does not support filtering */
GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- }
-
- if (GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
-
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- if (n > 1) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- }
- if (n > 2) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1014,12 +1004,12 @@ GPUTexture *GPU_texture_cube_create(int w,
tex->h = w;
tex->d = d;
tex->samples = 0;
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->mipmaps = 0;
tex->format_flag = GPU_FORMAT_CUBE;
+ tex->number = -1;
if (d == 0) {
tex->target_base = tex->target = GL_TEXTURE_CUBE_MAP;
@@ -1117,22 +1107,13 @@ GPUTexture *GPU_texture_cube_create(int w,
if (GPU_texture_stencil(tex) || /* Does not support filtering */
GPU_texture_integer(tex) || /* Does not support filtering */
GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT & ~GPU_SAMPLER_FILTER;
}
else {
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ tex->sampler_state = GPU_SAMPLER_DEFAULT;
}
-
- if (GPU_texture_depth(tex)) {
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, GL_NONE);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
- }
-
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
+ /* Avoid issue with incomplete textures. */
+ glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(tex->target, 0);
@@ -1143,13 +1124,13 @@ GPUTexture *GPU_texture_cube_create(int w,
GPUTexture *GPU_texture_create_buffer(eGPUTextureFormat tex_format, const GLuint buffer)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
- tex->number = -1;
tex->refcount = 1;
tex->format = tex_format;
tex->components = gpu_get_component_count(tex_format);
tex->format_flag = 0;
tex->target_base = tex->target = GL_TEXTURE_BUFFER;
tex->mipmaps = 0;
+ tex->number = -1;
GLenum internalformat = gpu_format_to_gl_internalformat(tex_format);
@@ -1196,11 +1177,15 @@ GPUTexture *GPU_texture_from_bindcode(int textarget, int bindcode)
{
GPUTexture *tex = MEM_callocN(sizeof(GPUTexture), "GPUTexture");
tex->bindcode = bindcode;
- tex->number = -1;
tex->refcount = 1;
tex->target = textarget;
tex->target_base = textarget;
tex->samples = 0;
+ tex->sampler_state = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO;
+ if (GPU_get_mipmap()) {
+ tex->sampler_state |= (GPU_SAMPLER_MIPMAP | GPU_SAMPLER_FILTER);
+ }
+ tex->number = -1;
if (!glIsTexture(tex->bindcode)) {
GPU_print_error_debug("Blender Texture Not Loaded");
@@ -1727,16 +1712,17 @@ void GPU_invalid_tex_free(void)
}
}
-void GPU_texture_bind(GPUTexture *tex, int number)
+/* set_number is to save the the texture unit for setting texture parameters. */
+void GPU_texture_bind_ex(GPUTexture *tex, eGPUSamplerState state, int unit, const bool set_number)
{
- BLI_assert(number >= 0);
+ BLI_assert(unit >= 0);
- if (number >= GPU_max_textures()) {
+ if (unit >= GPU_max_textures()) {
fprintf(stderr, "Not enough texture slots.\n");
return;
}
- if ((G.debug & G_DEBUG)) {
+ if (G.debug & G_DEBUG) {
for (int i = 0; i < GPU_TEX_MAX_FBO_ATTACHED; i++) {
if (tex->fb[i] && GPU_framebuffer_bound(tex->fb[i])) {
fprintf(stderr,
@@ -1748,16 +1734,27 @@ void GPU_texture_bind(GPUTexture *tex, int number)
}
}
- glActiveTexture(GL_TEXTURE0 + number);
+ if (set_number) {
+ tex->number = unit;
+ }
+
+ glActiveTexture(GL_TEXTURE0 + unit);
+
+ state = (state < GPU_SAMPLER_MAX) ? state : tex->sampler_state;
if (tex->bindcode != 0) {
glBindTexture(tex->target, tex->bindcode);
+ glBindSampler(unit, GG.samplers[state]);
}
else {
GPU_invalid_tex_bind(tex->target_base);
+ glBindSampler(unit, 0);
}
+}
- tex->number = number;
+void GPU_texture_bind(GPUTexture *tex, int unit)
+{
+ GPU_texture_bind_ex(tex, GPU_SAMPLER_MAX, unit, true);
}
void GPU_texture_unbind(GPUTexture *tex)
@@ -1768,13 +1765,26 @@ void GPU_texture_unbind(GPUTexture *tex)
glActiveTexture(GL_TEXTURE0 + tex->number);
glBindTexture(tex->target, 0);
-
+ glBindSampler(tex->number, 0);
tex->number = -1;
}
-int GPU_texture_bound_number(GPUTexture *tex)
+void GPU_texture_unbind_all(void)
{
- return tex->number;
+ for (int i = 0; i < GPU_max_textures(); i++) {
+ glActiveTexture(GL_TEXTURE0 + i);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(GL_TEXTURE_2D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_1D, 0);
+ glBindTexture(GL_TEXTURE_1D_ARRAY, 0);
+ glBindTexture(GL_TEXTURE_3D, 0);
+ glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
+ glBindTexture(GL_TEXTURE_BUFFER, 0);
+ if (GPU_arb_texture_cube_map_array_is_supported()) {
+ glBindTexture(GL_TEXTURE_CUBE_MAP_ARRAY_ARB, 0);
+ }
+ glBindSampler(i, 0);
+ }
}
#define WARN_NOT_BOUND(_tex) \
@@ -1798,8 +1808,8 @@ void GPU_texture_generate_mipmap(GPUTexture *tex)
if (GPU_texture_depth(tex)) {
/* Some drivers have bugs when using glGenerateMipmap with depth textures (see T56789).
- * In this case we just create a complete texture with mipmaps manually without down-sampling.
- * You must initialize the texture levels using other methods like
+ * In this case we just create a complete texture with mipmaps manually without
+ * down-sampling. You must initialize the texture levels using other methods like
* GPU_framebuffer_recursive_downsample(). */
eGPUDataFormat data_format = gpu_get_data_format_from_tex_format(tex->format);
for (int i = 1; i < levels; i++) {
@@ -1905,69 +1915,35 @@ void GPU_texture_copy(GPUTexture *dst, GPUTexture *src)
void GPU_texture_compare_mode(GPUTexture *tex, bool use_compare)
{
- WARN_NOT_BOUND(tex);
-
/* Could become an assertion ? (fclem) */
if (!GPU_texture_depth(tex)) {
return;
}
-
- GLenum mode = (use_compare) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_COMPARE_MODE, mode);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_compare, GPU_SAMPLER_COMPARE);
}
void GPU_texture_filter_mode(GPUTexture *tex, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
BLI_assert(!use_filter || !(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_mipmap_mode(GPUTexture *tex, bool use_mipmap, bool use_filter)
{
- WARN_NOT_BOUND(tex);
-
/* Stencil and integer format does not support filtering. */
- BLI_assert((!use_filter && !use_mipmap) ||
+ BLI_assert(!(use_filter || use_mipmap) ||
!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- GLenum filter = (use_filter) ? GL_LINEAR : GL_NEAREST;
- GLenum mipmap = ((use_filter) ? (use_mipmap) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR :
- (use_mipmap) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, mipmap);
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, filter);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_mipmap, GPU_SAMPLER_MIPMAP);
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_filter, GPU_SAMPLER_FILTER);
}
void GPU_texture_wrap_mode(GPUTexture *tex, bool use_repeat, bool use_clamp)
{
- WARN_NOT_BOUND(tex);
-
- GLenum repeat = (use_repeat) ? GL_REPEAT : (use_clamp) ? GL_CLAMP_TO_EDGE : GL_CLAMP_TO_BORDER;
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_S, repeat);
- if (tex->target_base != GL_TEXTURE_1D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_T, repeat);
- }
- if (tex->target_base == GL_TEXTURE_3D) {
- glTexParameteri(tex->target_base, GL_TEXTURE_WRAP_R, repeat);
- }
-
- if (repeat == GL_CLAMP_TO_BORDER) {
- const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
- glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, black);
- }
+ SET_FLAG_FROM_TEST(tex->sampler_state, use_repeat, GPU_SAMPLER_REPEAT);
+ SET_FLAG_FROM_TEST(tex->sampler_state, !use_clamp, GPU_SAMPLER_CLAMP_BORDER);
}
void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
@@ -1981,34 +1957,6 @@ void GPU_texture_swizzle_channel_auto(GPUTexture *tex, int channels)
glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_SWIZZLE_A, (channels >= 4) ? GL_ALPHA : GL_ONE);
}
-static GLenum gpu_get_gl_filterfunction(eGPUFilterFunction filter)
-{
- switch (filter) {
- case GPU_NEAREST:
- return GL_NEAREST;
- case GPU_LINEAR:
- return GL_LINEAR;
- default:
- BLI_assert(!"Unhandled filter mode");
- return GL_NEAREST;
- }
-}
-
-void GPU_texture_filters(GPUTexture *tex,
- eGPUFilterFunction min_filter,
- eGPUFilterFunction mag_filter)
-{
- WARN_NOT_BOUND(tex);
-
- /* Stencil and integer format does not support filtering. */
- BLI_assert(!(GPU_texture_stencil(tex) || GPU_texture_integer(tex)));
- BLI_assert(mag_filter == GPU_NEAREST || mag_filter == GPU_LINEAR);
-
- glActiveTexture(GL_TEXTURE0 + tex->number);
- glTexParameteri(tex->target_base, GL_TEXTURE_MIN_FILTER, gpu_get_gl_filterfunction(min_filter));
- glTexParameteri(tex->target_base, GL_TEXTURE_MAG_FILTER, gpu_get_gl_filterfunction(mag_filter));
-}
-
void GPU_texture_free(GPUTexture *tex)
{
tex->refcount--;
@@ -2169,3 +2117,55 @@ void GPU_texture_get_mipmap_size(GPUTexture *tex, int lvl, int *size)
size[2] = max_ii(1, tex->d / div);
}
}
+
+/* -------------------------------------------------------------------- */
+/** \name GPU Sampler Objects
+ *
+ * Simple wrapper around opengl sampler objects.
+ * Override texture sampler state for one sampler unit only.
+ * \{ */
+
+void GPU_samplers_init(void)
+{
+ glGenSamplers(GPU_SAMPLER_MAX, GG.samplers);
+ for (int i = 0; i < GPU_SAMPLER_MAX; i++) {
+ eGPUSamplerState state = i;
+ GLenum clamp_type = (state & GPU_SAMPLER_CLAMP_BORDER) ? GL_CLAMP_TO_BORDER : GL_CLAMP_TO_EDGE;
+ GLenum wrap_s = (state & GPU_SAMPLER_REPEAT_S) ? GL_REPEAT : clamp_type;
+ GLenum wrap_t = (state & GPU_SAMPLER_REPEAT_T) ? GL_REPEAT : clamp_type;
+ GLenum wrap_r = (state & GPU_SAMPLER_REPEAT_R) ? GL_REPEAT : clamp_type;
+ GLenum mag_filter = (state & GPU_SAMPLER_FILTER) ? GL_LINEAR : GL_NEAREST;
+ GLenum min_filter = (state & GPU_SAMPLER_FILTER) ?
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR) :
+ ((state & GPU_SAMPLER_MIPMAP) ? GL_NEAREST_MIPMAP_LINEAR : GL_NEAREST);
+ GLenum compare_mode = (state & GPU_SAMPLER_COMPARE) ? GL_COMPARE_REF_TO_TEXTURE : GL_NONE;
+ float aniso_filter = ((state & GPU_SAMPLER_MIPMAP) && (state & GPU_SAMPLER_ANISO)) ?
+ GPU_get_anisotropic() :
+ 1.0f;
+
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_S, wrap_s);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_T, wrap_t);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_WRAP_R, wrap_r);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MIN_FILTER, min_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_MAG_FILTER, mag_filter);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_MODE, compare_mode);
+ glSamplerParameteri(GG.samplers[i], GL_TEXTURE_COMPARE_FUNC, GL_LEQUAL);
+ if (GLEW_EXT_texture_filter_anisotropic) {
+ glSamplerParameterf(GG.samplers[i], GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso_filter);
+ }
+
+ /** Other states are left to default:
+ * - GL_TEXTURE_BORDER_COLOR is {0, 0, 0, 0}.
+ * - GL_TEXTURE_MIN_LOD is -1000.
+ * - GL_TEXTURE_MAX_LOD is 1000.
+ * - GL_TEXTURE_LOD_BIAS is 0.0f.
+ **/
+ }
+}
+
+void GPU_samplers_free(void)
+{
+ glDeleteSamplers(GPU_SAMPLER_MAX, GG.samplers);
+}
+
+/** \} */
diff --git a/source/blender/gpu/intern/gpu_vertex_format.c b/source/blender/gpu/intern/gpu_vertex_format.c
index e6a9cb8f2f2..b84a7e0f554 100644
--- a/source/blender/gpu/intern/gpu_vertex_format.c
+++ b/source/blender/gpu/intern/gpu_vertex_format.c
@@ -23,8 +23,6 @@
* GPU vertex format
*/
-#include "GPU_shader_interface.h"
-
#include "GPU_vertex_format.h"
#include "gpu_vertex_format_private.h"
#include <stddef.h>
@@ -34,6 +32,9 @@
#include "BLI_string.h"
#include "BLI_utildefines.h"
+#include "GPU_shader.h"
+#include "gpu_shader_private.h"
+
#define PACK_DEBUG 0
#if PACK_DEBUG
@@ -391,38 +392,37 @@ void VertexFormat_pack(GPUVertFormat *format)
format->packed = true;
}
-static uint calc_input_component_size(const GPUShaderInput *input)
+static uint calc_component_size(const GLenum gl_type)
{
- int size = input->size;
- switch (input->gl_type) {
+ switch (gl_type) {
case GL_FLOAT_VEC2:
case GL_INT_VEC2:
case GL_UNSIGNED_INT_VEC2:
- return size * 2;
+ return 2;
case GL_FLOAT_VEC3:
case GL_INT_VEC3:
case GL_UNSIGNED_INT_VEC3:
- return size * 3;
+ return 3;
case GL_FLOAT_VEC4:
case GL_FLOAT_MAT2:
case GL_INT_VEC4:
case GL_UNSIGNED_INT_VEC4:
- return size * 4;
+ return 4;
case GL_FLOAT_MAT3:
- return size * 9;
+ return 9;
case GL_FLOAT_MAT4:
- return size * 16;
+ return 16;
case GL_FLOAT_MAT2x3:
case GL_FLOAT_MAT3x2:
- return size * 6;
+ return 6;
case GL_FLOAT_MAT2x4:
case GL_FLOAT_MAT4x2:
- return size * 8;
+ return 8;
case GL_FLOAT_MAT3x4:
case GL_FLOAT_MAT4x3:
- return size * 12;
+ return 12;
default:
- return size;
+ return 1;
}
}
@@ -466,42 +466,39 @@ static void get_fetch_mode_and_comp_type(int gl_type,
}
}
-void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterface *shaderface)
+void GPU_vertformat_from_shader(GPUVertFormat *format, const GPUShader *shader)
{
- const char *name_buffer = shaderface->name_buffer;
-
- for (int i = 0; i < GPU_NUM_SHADERINTERFACE_BUCKETS; i++) {
- const GPUShaderInput *input = shaderface->attr_buckets[i];
- if (input == NULL) {
- continue;
- }
+ GPU_vertformat_clear(format);
+ GPUVertAttr *attr = &format->attrs[0];
- const GPUShaderInput *next = input;
- while (next != NULL) {
- input = next;
- next = input->next;
+ GLint attr_len;
+ glGetProgramiv(shader->program, GL_ACTIVE_ATTRIBUTES, &attr_len);
- /* OpenGL attributes such as `gl_VertexID` have a location of -1. */
- if (input->location < 0) {
- continue;
- }
-
- format->name_len++; /* multiname support */
- format->attr_len++;
-
- GPUVertCompType comp_type;
- GPUVertFetchMode fetch_mode;
- get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode);
+ for (int i = 0; i < attr_len; i++) {
+ char name[256];
+ GLenum gl_type;
+ GLint size;
+ glGetActiveAttrib(shader->program, i, sizeof(name), NULL, &size, &gl_type, name);
- GPUVertAttr *attr = &format->attrs[input->location];
-
- attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset);
- attr->offset = 0; /* offsets & stride are calculated later (during pack) */
- attr->comp_len = calc_input_component_size(input);
- attr->sz = attr->comp_len * 4;
- attr->fetch_mode = fetch_mode;
- attr->comp_type = comp_type;
- attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ /* Ignore OpenGL names like `gl_BaseInstanceARB`, `gl_InstanceID` and `gl_VertexID`. */
+ if (glGetAttribLocation(shader->program, name) == -1) {
+ continue;
}
+
+ format->name_len++; /* multiname support */
+ format->attr_len++;
+
+ GPUVertCompType comp_type;
+ GPUVertFetchMode fetch_mode;
+ get_fetch_mode_and_comp_type(gl_type, &comp_type, &fetch_mode);
+
+ attr->names[attr->name_len++] = copy_attr_name(format, name);
+ attr->offset = 0; /* offsets & stride are calculated later (during pack) */
+ attr->comp_len = calc_component_size(gl_type) * size;
+ attr->sz = attr->comp_len * 4;
+ attr->fetch_mode = fetch_mode;
+ attr->comp_type = comp_type;
+ attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
+ attr += 1;
}
}
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index f30270b9eed..753da8544ea 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -382,12 +382,10 @@ GPUTexture *GPU_viewport_texture_pool_query(
}
tex = GPU_texture_create_2d(width, height, format, NULL, NULL);
- GPU_texture_bind(tex, 0);
/* Doing filtering for depth does not make sense when not doing shadow mapping,
* and enabling texture filtering on integer texture make them unreadable. */
bool do_filter = !GPU_texture_depth(tex) && !GPU_texture_integer(tex);
GPU_texture_filter_mode(tex, do_filter);
- GPU_texture_unbind(tex);
ViewportTempTexture *tmp_tex = MEM_callocN(sizeof(ViewportTempTexture), "ViewportTempTexture");
tmp_tex->texture = tex;
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
index 62f76d46088..4cb00c15b78 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_output_material.glsl
@@ -1,8 +1,16 @@
-void node_output_material(Closure surface, Closure volume, vec3 displacement, out Closure result)
+void node_output_material(
+ Closure surface, Closure volume, vec3 displacement, float alpha_threshold, out Closure result)
{
#ifdef VOLUMETRICS
result = volume;
#else
result = surface;
+# if defined(USE_ALPHA_HASH)
+ /* Alpha clip emulation. */
+ if (alpha_threshold >= 0.0) {
+ float alpha = saturate(1.0 - avg(result.transmittance));
+ result.transmittance = vec3(step(alpha, alpha_threshold));
+ }
+# endif
#endif
}
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
index 9bd36f8a757..20a65f23c05 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_environment.glsl
@@ -15,16 +15,11 @@ void node_tex_environment_texco(vec3 viewvec, out vec3 worldvec)
#endif
}
-void node_tex_environment_equirectangular(vec3 co, float clamp_size, sampler2D ima, out vec3 uv)
+void node_tex_environment_equirectangular(vec3 co, out vec3 uv)
{
vec3 nco = normalize(co);
uv.x = -atan(nco.y, nco.x) / (2.0 * M_PI) + 0.5;
uv.y = atan(nco.z, hypot(nco.x, nco.y)) / M_PI + 0.5;
-
- /* Fix pole bleeding */
- float half_height = clamp_size / float(textureSize(ima, 0).y);
- uv.y = clamp(uv.y, half_height, 1.0 - half_height);
- uv.z = 0.0;
}
void node_tex_environment_mirror_ball(vec3 co, out vec3 uv)
diff --git a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
index c39bec8ac64..df949f7358b 100644
--- a/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
+++ b/source/blender/gpu/shaders/material/gpu_shader_material_tex_image.glsl
@@ -54,19 +54,6 @@ void node_tex_image_linear(vec3 co, sampler2D ima, out vec4 color, out float alp
alpha = color.a;
}
-void node_tex_image_linear_no_mip(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- color = safe_color(textureLod(ima, co.xy, 0.0));
- alpha = color.a;
-}
-
-void node_tex_image_nearest(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- ivec2 pix = ivec2(fract(co.xy) * textureSize(ima, 0).xy);
- color = safe_color(texelFetch(ima, pix, 0));
- alpha = color.a;
-}
-
/** \param f: Signed distance to texel center. */
void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2 w3)
{
@@ -79,8 +66,7 @@ void cubic_bspline_coefs(vec2 f, out vec2 w0, out vec2 w1, out vec2 w2, out vec2
w2 = 1.0 - w0 - w1 - w3;
}
-void node_tex_image_cubic_ex(
- vec3 co, sampler2D ima, float do_extend, out vec4 color, out float alpha)
+void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
{
vec2 tex_size = vec2(textureSize(ima, 0).xy);
@@ -101,9 +87,6 @@ void node_tex_image_cubic_ex(
final_co.xy = tc - 1.0 + f0;
final_co.zw = tc + 1.0 + f1;
- if (do_extend == 1.0) {
- final_co = clamp(final_co, vec4(0.5), tex_size.xyxy - 0.5);
- }
final_co /= tex_size.xyxy;
color = safe_color(textureLod(ima, final_co.xy, 0.0)) * s0.x * s0.y;
@@ -136,22 +119,6 @@ void node_tex_image_cubic_ex(
alpha = color.a;
}
-void node_tex_image_cubic(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
-void node_tex_image_cubic_extend(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- node_tex_image_cubic_ex(co, ima, 1.0, color, alpha);
-}
-
-void node_tex_image_smart(vec3 co, sampler2D ima, out vec4 color, out float alpha)
-{
- /* use cubic for now */
- node_tex_image_cubic_ex(co, ima, 0.0, color, alpha);
-}
-
void tex_box_sample_linear(
vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
{
@@ -175,32 +142,6 @@ void tex_box_sample_linear(
color3 = texture(ima, uv);
}
-void tex_box_sample_nearest(
- vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
-{
- /* X projection */
- vec2 uv = texco.yz;
- if (N.x < 0.0) {
- uv.x = 1.0 - uv.x;
- }
- ivec2 pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color1 = texelFetch(ima, pix, 0);
- /* Y projection */
- uv = texco.xz;
- if (N.y > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color2 = texelFetch(ima, pix, 0);
- /* Z projection */
- uv = texco.yx;
- if (N.z > 0.0) {
- uv.x = 1.0 - uv.x;
- }
- pix = ivec2(fract(uv.xy) * textureSize(ima, 0).xy);
- color3 = texelFetch(ima, pix, 0);
-}
-
void tex_box_sample_cubic(
vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
{
@@ -210,36 +151,23 @@ void tex_box_sample_cubic(
if (N.x < 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color1, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color1, alpha);
/* Y projection */
uv = texco.xz;
if (N.y > 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color2, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color2, alpha);
/* Z projection */
uv = texco.yx;
if (N.z > 0.0) {
uv.x = 1.0 - uv.x;
}
- node_tex_image_cubic_ex(uv.xyy, ima, 0.0, color3, alpha);
+ node_tex_image_cubic(uv.xyy, ima, color3, alpha);
}
-void tex_box_sample_smart(
- vec3 texco, vec3 N, sampler2D ima, out vec4 color1, out vec4 color2, out vec4 color3)
-{
- tex_box_sample_cubic(texco, N, ima, color1, color2, color3);
-}
-
-void node_tex_image_box(vec3 texco,
- vec3 N,
- vec4 color1,
- vec4 color2,
- vec4 color3,
- sampler2D ima,
- float blend,
- out vec4 color,
- out float alpha)
+void tex_box_blend(
+ vec3 N, vec4 color1, vec4 color2, vec4 color3, float blend, out vec4 color, out float alpha)
{
/* project from direction vector to barycentric coordinates in triangles */
N = abs(N);
@@ -284,70 +212,6 @@ void node_tex_image_box(vec3 texco,
alpha = color.a;
}
-void tex_clip_linear(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
- vec2 minco = min(co.xy, 1.0 - co.xy);
- minco = clamp(minco * tex_size + 0.5, 0.0, 1.0);
- float fac = minco.x * minco.y;
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_nearest(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec4 minco = vec4(co.xy, 1.0 - co.xy);
- color = (any(lessThan(minco, vec4(0.0)))) ? vec4(0.0) : icolor;
- alpha = color.a;
-}
-
-void tex_clip_cubic(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- vec2 tex_size = vec2(textureSize(ima, 0).xy);
-
- co.xy *= tex_size;
- /* texel center */
- vec2 tc = floor(co.xy - 0.5) + 0.5;
- vec2 w0, w1, w2, w3;
- cubic_bspline_coefs(co.xy - tc, w0, w1, w2, w3);
-
- /* TODO Optimize this part. I'm sure there is a smarter way to do that.
- * Could do that when sampling? */
-#define CLIP_CUBIC_SAMPLE(samp, size) \
- (float(all(greaterThan(samp, vec2(-0.5)))) * float(all(lessThan(ivec2(samp), itex_size))))
- ivec2 itex_size = textureSize(ima, 0).xy;
- float fac;
- fac = CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, -1.0), itex_size) * w0.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, -1.0), itex_size) * w1.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, -1.0), itex_size) * w2.x * w0.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, -1.0), itex_size) * w3.x * w0.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 0.0), itex_size) * w0.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 0.0), itex_size) * w1.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 0.0), itex_size) * w2.x * w1.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 0.0), itex_size) * w3.x * w1.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 1.0), itex_size) * w0.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 1.0), itex_size) * w1.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 1.0), itex_size) * w2.x * w2.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 1.0), itex_size) * w3.x * w2.y;
-
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(-1.0, 2.0), itex_size) * w0.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(0.0, 2.0), itex_size) * w1.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(1.0, 2.0), itex_size) * w2.x * w3.y;
- fac += CLIP_CUBIC_SAMPLE(tc + vec2(2.0, 2.0), itex_size) * w3.x * w3.y;
-#undef CLIP_CUBIC_SAMPLE
-
- color = mix(vec4(0.0), icolor, fac);
- alpha = color.a;
-}
-
-void tex_clip_smart(vec3 co, sampler2D ima, vec4 icolor, out vec4 color, out float alpha)
-{
- tex_clip_cubic(co, ima, icolor, color, alpha);
-}
-
void node_tex_image_empty(vec3 co, out vec4 color, out float alpha)
{
color = vec4(0.0);
@@ -389,20 +253,6 @@ void node_tex_tile_linear(
alpha = color.a;
}
-void node_tex_tile_nearest(
- vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
-{
- if (node_tex_tile_lookup(co, ima, map)) {
- ivec3 pix = ivec3(fract(co.xy) * textureSize(ima, 0).xy, co.z);
- color = safe_color(texelFetch(ima, pix, 0));
- }
- else {
- color = vec4(1.0, 0.0, 1.0, 1.0);
- }
-
- alpha = color.a;
-}
-
void node_tex_tile_cubic(
vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
{
@@ -437,9 +287,3 @@ void node_tex_tile_cubic(
alpha = color.a;
}
-
-void node_tex_tile_smart(
- vec3 co, sampler2DArray ima, sampler1DArray map, out vec4 color, out float alpha)
-{
- node_tex_tile_cubic(co, ima, map, color, alpha);
-}
diff --git a/source/blender/makesdna/DNA_brush_types.h b/source/blender/makesdna/DNA_brush_types.h
index a747ed3be11..8c9c1ba8b32 100644
--- a/source/blender/makesdna/DNA_brush_types.h
+++ b/source/blender/makesdna/DNA_brush_types.h
@@ -339,6 +339,7 @@ typedef enum eBrushPoseDeformType {
typedef enum eBrushPoseOriginType {
BRUSH_POSE_ORIGIN_TOPOLOGY = 0,
BRUSH_POSE_ORIGIN_FACE_SETS = 1,
+ BRUSH_POSE_ORIGIN_FACE_SETS_FK = 2,
} eBrushPoseOriginType;
/* Gpencilsettings.Vertex_mode */
diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h
index 029352f3d85..acc020ec710 100644
--- a/source/blender/makesdna/DNA_mesh_types.h
+++ b/source/blender/makesdna/DNA_mesh_types.h
@@ -33,6 +33,7 @@ extern "C" {
#endif
struct AnimData;
+struct BVHCache;
struct Ipo;
struct Key;
struct LinkNode;
@@ -99,8 +100,8 @@ typedef struct Mesh_Runtime {
struct MLoopTri_Store looptris;
- /** 'BVHCache', for 'BKE_bvhutil.c' */
- struct LinkNode *bvh_cache;
+ /** `BVHCache` defined in 'BKE_bvhutil.c' */
+ struct BVHCache *bvh_cache;
/** Non-manifold boundary data for Shrinkwrap Target Project. */
struct ShrinkwrapBoundaryData *shrinkwrap_data;
diff --git a/source/blender/makesdna/DNA_scene_types.h b/source/blender/makesdna/DNA_scene_types.h
index 18cd3872d1f..37d0d25227e 100644
--- a/source/blender/makesdna/DNA_scene_types.h
+++ b/source/blender/makesdna/DNA_scene_types.h
@@ -906,8 +906,6 @@ typedef struct ImagePaintSettings {
/** Mode used for texture painting. */
int mode;
- /** Wm handle. */
- void *paintcursor;
/** Workaround until we support true layer masks. */
struct Image *stencil;
/** Clone layer for image mode for projective texture painting. */
diff --git a/source/blender/makesrna/RNA_define.h b/source/blender/makesrna/RNA_define.h
index 7a7ab1085dd..1bcf7f434f2 100644
--- a/source/blender/makesrna/RNA_define.h
+++ b/source/blender/makesrna/RNA_define.h
@@ -50,6 +50,7 @@ void RNA_free(BlenderRNA *brna);
void RNA_define_verify_sdna(bool verify);
void RNA_define_animate_sdna(bool animate);
void RNA_define_fallback_property_update(int noteflag, const char *updatefunc);
+void RNA_define_lib_overridable(const bool make_overridable);
void RNA_init(void);
void RNA_exit(void);
diff --git a/source/blender/makesrna/intern/makesrna.c b/source/blender/makesrna/intern/makesrna.c
index 85bd17c737e..f87e8824bc2 100644
--- a/source/blender/makesrna/intern/makesrna.c
+++ b/source/blender/makesrna/intern/makesrna.c
@@ -637,7 +637,7 @@ static char *rna_def_property_get_func(
if (!manualfunc) {
if (!dp->dnastructname || !dp->dnaname) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
@@ -654,7 +654,7 @@ static char *rna_def_property_get_func(
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -667,7 +667,7 @@ static char *rna_def_property_get_func(
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -679,7 +679,7 @@ static char *rna_def_property_get_func(
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1020,7 +1020,7 @@ static char *rna_def_property_set_func(
if (!dp->dnastructname || !dp->dnaname) {
if (prop->flag & PROP_EDITABLE) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
return NULL;
}
@@ -1263,7 +1263,7 @@ static char *rna_def_property_length_func(
if (!manualfunc) {
if (!dp->dnastructname || !dp->dnaname) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1289,7 +1289,7 @@ static char *rna_def_property_length_func(
if (prop->type == PROP_COLLECTION &&
(!(dp->dnalengthname || dp->dnalengthfixed) || !dp->dnaname)) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1338,7 +1338,7 @@ static char *rna_def_property_begin_func(
if (!manualfunc) {
if (!dp->dnastructname || !dp->dnaname) {
CLOG_ERROR(&LOG, "%s.%s has no valid dna info.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -1848,7 +1848,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
if (!pprop->type) {
CLOG_ERROR(
&LOG, "%s.%s, pointer must have a struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
break;
}
@@ -1896,21 +1896,21 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
"%s.%s, collection must have a begin function.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (!cprop->next) {
CLOG_ERROR(&LOG,
"%s.%s, collection must have a next function.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (!cprop->get) {
CLOG_ERROR(&LOG,
"%s.%s, collection must have a get function.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
if (!cprop->item_type) {
@@ -1918,7 +1918,7 @@ static void rna_def_property_funcs(FILE *f, StructRNA *srna, PropertyDefRNA *dp)
"%s.%s, collection must have a struct type.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
break;
}
@@ -3656,7 +3656,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
errnest,
prop->identifier,
eprop->defaultvalue & ~totflag);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
else {
@@ -3666,7 +3666,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
srna->identifier,
errnest,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -3676,7 +3676,7 @@ static void rna_generate_property(FILE *f, StructRNA *srna, const char *nest, Pr
srna->identifier,
errnest,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
break;
}
@@ -4218,7 +4218,7 @@ static void rna_generate_struct(BlenderRNA *UNUSED(brna), StructRNA *srna, FILE
if (srna->reg && !srna->refine) {
CLOG_ERROR(
&LOG, "%s has a register function, must also have refine function.", srna->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
func = srna->functions.first;
diff --git a/source/blender/makesrna/intern/rna_brush.c b/source/blender/makesrna/intern/rna_brush.c
index 9e78eec9c25..209e5a1ff8b 100644
--- a/source/blender/makesrna/intern/rna_brush.c
+++ b/source/blender/makesrna/intern/rna_brush.c
@@ -1978,6 +1978,11 @@ static void rna_def_brush(BlenderRNA *brna)
0,
"Face Sets",
"Creates a pose segment per face sets, starting from the active face set"},
+ {BRUSH_POSE_ORIGIN_FACE_SETS_FK,
+ "FACE_SETS_FK",
+ 0,
+ "Face Sets FK",
+ "Simulates an FK deformation using the Face Set under the cursor as control"},
{0, NULL, 0, NULL, NULL},
};
diff --git a/source/blender/makesrna/intern/rna_camera.c b/source/blender/makesrna/intern/rna_camera.c
index 47a09233769..79ee9619e36 100644
--- a/source/blender/makesrna/intern/rna_camera.c
+++ b/source/blender/makesrna/intern/rna_camera.c
@@ -193,6 +193,8 @@ static void rna_def_camera_background_image(BlenderRNA *brna)
RNA_def_struct_ui_text(
srna, "Background Image", "Image and settings for display in the 3D View background");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "source", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "source");
RNA_def_property_enum_items(prop, bgpic_source_items);
@@ -301,6 +303,8 @@ static void rna_def_camera_background_image(BlenderRNA *brna)
RNA_def_property_enum_items(prop, bgpic_camera_frame_items);
RNA_def_property_ui_text(prop, "Frame Method", "How the image fits in the camera frame");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_camera_background_images(BlenderRNA *brna, PropertyRNA *cprop)
@@ -356,6 +360,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_struct_nested(brna, srna, "Camera");
RNA_def_struct_ui_text(srna, "Stereo", "Stereoscopy settings for a Camera data-block");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "convergence_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, convergence_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
@@ -409,6 +415,8 @@ static void rna_def_camera_stereo_data(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Pole Merge End Angle", "Angle at which interocular distance is 0");
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, NULL);
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
@@ -421,6 +429,8 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_CameraDOFSettings_path");
RNA_def_struct_ui_text(srna, "Depth of Field", "Depth of Field settings");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_dof", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAM_DOF_ENABLED);
RNA_def_property_ui_text(prop, "Depth of Field", "Use Depth of Field");
@@ -469,6 +479,8 @@ static void rna_def_camera_dof_settings_data(BlenderRNA *brna)
RNA_def_property_range(prop, 0.01f, FLT_MAX);
RNA_def_property_ui_range(prop, 1.0f, 2.0f, 0.1, 3);
RNA_def_property_update(prop, NC_OBJECT | ND_DRAW, "rna_Camera_dof_update");
+
+ RNA_define_lib_overridable(false);
}
void RNA_def_camera(BlenderRNA *brna)
@@ -505,6 +517,8 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Camera", "Camera data-block for storing camera settings");
RNA_def_struct_ui_icon(srna, ICON_CAMERA_DATA);
+ RNA_define_lib_overridable(true);
+
/* Enums */
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_type_items);
@@ -736,6 +750,8 @@ void RNA_def_camera(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Background Images", "List of background images");
RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, NULL);
+ RNA_define_lib_overridable(false);
+
rna_def_animdata_common(srna);
rna_def_camera_background_image(brna);
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index dc0cde953f4..07ad8cbb37d 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -824,6 +824,8 @@ static void rna_def_constraint_headtail_common(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "head_tail", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, "bConstraint", "headtail");
RNA_def_property_ui_text(prop, "Head/Tail", "Target along length of bone: Head=0, Tail=1");
@@ -835,12 +837,16 @@ static void rna_def_constraint_headtail_common(StructRNA *srna)
"Follow B-Bone",
"Follow shape of B-Bone segments when calculating Head/Tail position");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_target_common(StructRNA *srna)
{
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(prop, "Target", "Target object");
@@ -852,6 +858,8 @@ static void rna_def_constraint_target_common(StructRNA *srna)
RNA_def_property_string_sdna(prop, NULL, "subtarget");
RNA_def_property_ui_text(prop, "Sub-Target", "Armature bone, mesh or lattice vertex group, ...");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constrainttarget(BlenderRNA *brna)
@@ -864,6 +872,8 @@ static void rna_def_constrainttarget(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_ConstraintTarget_path");
RNA_def_struct_sdna(srna, "bConstraintTarget");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(prop, "Target", "Target object");
@@ -879,6 +889,8 @@ static void rna_def_constrainttarget(BlenderRNA *brna)
prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_dependency_update");
/* space, flag and type still to do */
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constrainttarget_bone(BlenderRNA *brna)
@@ -892,6 +904,8 @@ static void rna_def_constrainttarget_bone(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_ConstraintTarget_path");
RNA_def_struct_sdna(srna, "bConstraintTarget");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_ui_text(prop, "Target", "Target armature");
@@ -913,6 +927,8 @@ static void rna_def_constrainttarget_bone(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Blend Weight", "Blending weight of this bone");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_ConstraintTarget_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_childof(BlenderRNA *brna)
@@ -928,6 +944,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_location_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CHILDOF_LOCX);
RNA_def_property_ui_text(prop, "Location X", "Use X Location of Parent");
@@ -985,6 +1003,8 @@ static void rna_def_constraint_childof(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_ui_text(prop, "Inverse Matrix", "Transformation matrix to apply before");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_python(BlenderRNA *brna)
@@ -996,6 +1016,8 @@ static void rna_def_constraint_python(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Python Constraint", "Use Python script for constraint evaluation");
RNA_def_struct_sdna_from(srna, "bPythonConstraint", "data");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "targets", NULL);
RNA_def_property_struct_type(prop, "ConstraintTarget");
@@ -1021,6 +1043,8 @@ static void rna_def_constraint_python(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", PYCON_SCRIPTERROR);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Script Error", "The linked Python script has thrown an error");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_armature_deform_targets(BlenderRNA *brna, PropertyRNA *cprop)
@@ -1065,6 +1089,8 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bArmatureConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_ARMATURE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "targets", NULL);
RNA_def_property_struct_type(prop, "ConstraintTargetBone");
@@ -1095,6 +1121,8 @@ static void rna_def_constraint_armature_deform(BlenderRNA *brna)
"Use the current bone location for envelopes and choosing B-Bone "
"segments instead of rest position");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_kinematic(BlenderRNA *brna)
@@ -1121,6 +1149,8 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "iterations", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 10000);
RNA_def_property_ui_text(prop, "Iterations", "Maximum number of solving iterations");
@@ -1240,6 +1270,8 @@ static void rna_def_constraint_kinematic(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0, 100.f);
RNA_def_property_ui_text(prop, "Distance", "Radius of limiting sphere");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_track_to(BlenderRNA *brna)
@@ -1266,6 +1298,8 @@ static void rna_def_constraint_track_to(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_CON_TRACKTO);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "reserved1");
RNA_def_property_enum_items(prop, track_axis_items);
@@ -1283,6 +1317,8 @@ static void rna_def_constraint_track_to(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Target Z", "Target's Z axis, not World Z axis, will constraint the Up direction");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_locate_like(BlenderRNA *brna)
@@ -1300,6 +1336,8 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_X);
RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X location");
@@ -1334,6 +1372,8 @@ static void rna_def_constraint_locate_like(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", LOCLIKE_OFFSET);
RNA_def_property_ui_text(prop, "Offset", "Add original location into copied location");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_rotate_like(BlenderRNA *brna)
@@ -1370,6 +1410,8 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", ROTLIKE_X);
RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X rotation");
@@ -1420,6 +1462,8 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Offset", "DEPRECATED: Add original rotation into copied rotation");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_size_like(BlenderRNA *brna)
@@ -1434,6 +1478,8 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", SIZELIKE_X);
RNA_def_property_ui_text(prop, "Copy X", "Copy the target's X scale");
@@ -1476,6 +1522,8 @@ static void rna_def_constraint_size_like(BlenderRNA *brna)
"Additive",
"Use addition instead of multiplication to combine scale (2.7 compatibility)");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_same_volume(BlenderRNA *brna)
@@ -1518,6 +1566,8 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSameVolumeConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SAMEVOL);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "free_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "free_axis");
RNA_def_property_enum_items(prop, axis_items);
@@ -1535,6 +1585,8 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
RNA_def_property_range(prop, 0.001f, 100.0f);
RNA_def_property_ui_text(prop, "Volume", "Volume of the bone at rest");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_transform_like(BlenderRNA *brna)
@@ -1575,12 +1627,16 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
RNA_def_property_enum_items(prop, mix_mode_items);
RNA_def_property_ui_text(
prop, "Mix Mode", "Specify how the copied and existing transformations are combined");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_minmax(BlenderRNA *brna)
@@ -1606,6 +1662,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "floor_location", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "minmaxflag");
RNA_def_property_enum_items(prop, minmax_items);
@@ -1622,6 +1680,8 @@ static void rna_def_constraint_minmax(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -100.0f, 100.0f, 1, -1);
RNA_def_property_ui_text(prop, "Offset", "Offset of floor from object origin");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_action(BlenderRNA *brna)
@@ -1673,6 +1733,8 @@ static void rna_def_constraint_action(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
RNA_def_property_enum_items(prop, mix_mode_items);
@@ -1733,6 +1795,8 @@ static void rna_def_constraint_action(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Minimum", "Minimum value for target channel range");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_ActionConstraint_minmax_range");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_locked_track(BlenderRNA *brna)
@@ -1760,6 +1824,8 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "trackflag");
RNA_def_property_enum_items(prop, track_axis_items);
@@ -1771,6 +1837,8 @@ static void rna_def_constraint_locked_track(BlenderRNA *brna)
RNA_def_property_enum_items(prop, lock_items);
RNA_def_property_ui_text(prop, "Locked Axis", "Axis that points upward");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_follow_path(BlenderRNA *brna)
@@ -1800,6 +1868,8 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bFollowPathConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_FOLLOWPATH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
@@ -1852,6 +1922,8 @@ static void rna_def_constraint_follow_path(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "followflag", FOLLOWPATH_RADIUS);
RNA_def_property_ui_text(prop, "Curve Radius", "Object is scaled by the curve radius");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_stretch_to(BlenderRNA *brna)
@@ -1888,6 +1960,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "volume", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "volmode");
RNA_def_property_enum_items(prop, volume_items);
@@ -1941,6 +2015,8 @@ static void rna_def_constraint_stretch_to(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_clamp_to(BlenderRNA *brna)
@@ -1964,6 +2040,8 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bClampToConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_CLAMPTO);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Curve_object_poll");
@@ -1983,6 +2061,8 @@ static void rna_def_constraint_clamp_to(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Cyclic", "Treat curve as cyclic curve (no clamping to curve bounding box)");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_transform(BlenderRNA *brna)
@@ -2033,6 +2113,8 @@ static void rna_def_constraint_transform(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "map_from", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "from");
RNA_def_property_enum_items(prop, transform_items);
@@ -2323,6 +2405,8 @@ static void rna_def_constraint_transform(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Scale Mix Mode", "Specify how to combine the new scale with original");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_location_limit(BlenderRNA *brna)
@@ -2336,6 +2420,8 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bLocLimitConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_LOCLIMIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XMIN);
RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value");
@@ -2407,6 +2493,8 @@ static void rna_def_constraint_location_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
@@ -2420,6 +2508,8 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bRotLimitConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_ROTLIMIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_limit_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XROT);
RNA_def_property_ui_text(prop, "Limit X", "Use the minimum X value");
@@ -2476,6 +2566,8 @@ static void rna_def_constraint_rotation_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_size_limit(BlenderRNA *brna)
@@ -2489,6 +2581,8 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSizeLimitConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SIZELIMIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_min_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMIT_XMIN);
RNA_def_property_ui_text(prop, "Minimum X", "Use the minimum X value");
@@ -2560,6 +2654,8 @@ static void rna_def_constraint_size_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_distance_limit(BlenderRNA *brna)
@@ -2578,6 +2674,8 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "distance", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "dist");
RNA_def_property_ui_range(prop, 0.0f, 100.0f, 10, 3);
@@ -2596,6 +2694,8 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "For Transform", "Transforms are affected by this constraint as well");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
@@ -2649,6 +2749,8 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bShrinkwrapConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SHRINKWRAP);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "target"); /* TODO, mesh type */
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
@@ -2734,6 +2836,8 @@ static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
RNA_def_property_enum_items(prop, track_axis_items);
RNA_def_property_ui_text(prop, "Track Axis", "Axis that is aligned to the normal");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_damped_track(BlenderRNA *brna)
@@ -2752,11 +2856,15 @@ static void rna_def_constraint_damped_track(BlenderRNA *brna)
rna_def_constraint_target_common(srna);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "track_axis", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "trackflag");
RNA_def_property_enum_items(prop, track_axis_items);
RNA_def_property_ui_text(prop, "Track Axis", "Axis that points to the target object");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_spline_ik(BlenderRNA *brna)
@@ -2804,6 +2912,8 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bSplineIKConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_SPLINEIK);
+ RNA_define_lib_overridable(true);
+
/* target chain */
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
@@ -2922,6 +3032,8 @@ static void rna_def_constraint_spline_ik(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Volume Variation Smoothness", "Strength of volume stretching clamping");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_pivot(BlenderRNA *brna)
@@ -2973,6 +3085,8 @@ static void rna_def_constraint_pivot(BlenderRNA *brna)
RNA_def_struct_ui_icon(srna, ICON_CON_PIVOT);
+ RNA_define_lib_overridable(true);
+
/* target-defined pivot */
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "tar");
@@ -3011,6 +3125,8 @@ static void rna_def_constraint_pivot(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Enabled Rotation Range", "Rotation range on which pivoting should occur");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_follow_track(BlenderRNA *brna)
@@ -3031,6 +3147,8 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bFollowTrackConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_FOLLOWTRACK);
+ RNA_define_lib_overridable(true);
+
/* movie clip */
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
@@ -3106,6 +3224,8 @@ static void rna_def_constraint_follow_track(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", FOLLOWTRACK_USE_UNDISTORTION);
RNA_def_property_ui_text(prop, "Undistort", "Parent to undistorted position of 2D track");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_camera_solver(BlenderRNA *brna)
@@ -3119,6 +3239,8 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bCameraSolverConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_CAMERASOLVER);
+ RNA_define_lib_overridable(true);
+
/* movie clip */
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
@@ -3132,6 +3254,8 @@ static void rna_def_constraint_camera_solver(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", CAMERASOLVER_ACTIVECLIP);
RNA_def_property_ui_text(prop, "Active Clip", "Use active clip defined in scene");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_object_solver(BlenderRNA *brna)
@@ -3145,6 +3269,8 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bObjectSolverConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_OBJECTSOLVER);
+ RNA_define_lib_overridable(true);
+
/* movie clip */
prop = RNA_def_property(srna, "clip", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "clip");
@@ -3184,6 +3310,8 @@ static void rna_def_constraint_object_solver(BlenderRNA *brna)
"rna_Constraint_objectSolver_camera_set",
NULL,
"rna_Constraint_cameraObject_poll");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_constraint_transform_cache(BlenderRNA *brna)
@@ -3197,6 +3325,8 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna)
RNA_def_struct_sdna_from(srna, "bTransformCacheConstraint", "data");
RNA_def_struct_ui_icon(srna, ICON_CON_TRANSFORM_CACHE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "cache_file");
RNA_def_property_struct_type(prop, "CacheFile");
@@ -3211,6 +3341,8 @@ static void rna_def_constraint_transform_cache(BlenderRNA *brna)
"Object Path",
"Path to the object in the Alembic archive used to lookup the transform matrix");
RNA_def_property_update(prop, 0, "rna_Constraint_update");
+
+ RNA_define_lib_overridable(false);
}
/* base struct for constraints */
@@ -3241,6 +3373,8 @@ void RNA_def_constraint(BlenderRNA *brna)
RNA_def_property_enum_items(prop, rna_enum_constraint_type_items);
RNA_def_property_ui_text(prop, "Type", "");
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "owner_space", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "ownspace");
RNA_def_property_enum_items(prop, owner_space_pchan_items);
@@ -3258,7 +3392,6 @@ void RNA_def_constraint(BlenderRNA *brna)
/* flags */
prop = RNA_def_property(srna, "mute", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_OFF);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Disable", "Enable/Disable Constraint");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
RNA_def_property_ui_icon(prop, ICON_HIDE_OFF, -1);
@@ -3266,7 +3399,6 @@ void RNA_def_constraint(BlenderRNA *brna)
prop = RNA_def_property(srna, "show_expanded", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_flag(prop, PROP_NO_DEG_UPDATE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", CONSTRAINT_EXPAND);
- RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Expanded", "Constraint's panel is expanded in UI");
RNA_def_property_ui_icon(prop, ICON_DISCLOSURE_TRI_RIGHT, 1);
@@ -3315,6 +3447,8 @@ void RNA_def_constraint(BlenderRNA *brna)
"Rot error",
"Amount of residual error in radians for constraints that work on orientation");
+ RNA_define_lib_overridable(false);
+
/* pointers */
rna_def_constrainttarget(brna);
rna_def_constrainttarget_bone(brna);
diff --git a/source/blender/makesrna/intern/rna_define.c b/source/blender/makesrna/intern/rna_define.c
index 7a439a11a54..f59a1790e7b 100644
--- a/source/blender/makesrna/intern/rna_define.c
+++ b/source/blender/makesrna/intern/rna_define.c
@@ -61,7 +61,18 @@ static CLG_LogRef LOG = {"rna.define"};
/* Global used during defining */
-BlenderDefRNA DefRNA = {NULL, {NULL, NULL}, {NULL, NULL}, NULL, 0, 0, 0, 1, 1};
+BlenderDefRNA DefRNA = {
+ .sdna = NULL,
+ .structs = {NULL, NULL},
+ .allocs = {NULL, NULL},
+ .laststruct = NULL,
+ .error = 0,
+ .silent = false,
+ .preprocess = false,
+ .verify = true,
+ .animate = true,
+ .make_overridable = false,
+};
#ifndef RNA_RUNTIME
static struct {
@@ -691,13 +702,13 @@ BlenderRNA *RNA_create(void)
BLI_listbase_clear(&DefRNA.structs);
brna->structs_map = BLI_ghash_str_new_ex(__func__, 2048);
- DefRNA.error = 0;
- DefRNA.preprocess = 1;
+ DefRNA.error = false;
+ DefRNA.preprocess = true;
DefRNA.sdna = DNA_sdna_from_data(DNAstr, DNAlen, false, false, &error_message);
if (DefRNA.sdna == NULL) {
CLOG_ERROR(&LOG, "Failed to decode SDNA: %s.", error_message);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
/* We need both alias and static (on-disk) DNA names. */
@@ -737,7 +748,7 @@ void RNA_define_free(BlenderRNA *UNUSED(brna))
DefRNA.sdna = NULL;
}
- DefRNA.error = 0;
+ DefRNA.error = false;
}
void RNA_define_verify_sdna(bool verify)
@@ -745,6 +756,15 @@ void RNA_define_verify_sdna(bool verify)
DefRNA.verify = verify;
}
+/**
+ * Properties defined when this is enabled are lib-overridable by default (except for Pointer
+ * ones).
+ */
+void RNA_define_lib_overridable(const bool make_overridable)
+{
+ DefRNA.make_overridable = make_overridable;
+}
+
#ifndef RNA_RUNTIME
void RNA_define_animate_sdna(bool animate)
{
@@ -910,7 +930,7 @@ StructRNA *RNA_def_struct_ptr(BlenderRNA *brna, const char *identifier, StructRN
if (rna_validate_identifier(identifier, error, false) == 0) {
CLOG_ERROR(&LOG, "struct identifier \"%s\" error - %s", identifier, error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -1040,7 +1060,7 @@ StructRNA *RNA_def_struct(BlenderRNA *brna, const char *identifier, const char *
srnafrom = BLI_ghash_lookup(brna->structs_map, from);
if (!srnafrom) {
CLOG_ERROR(&LOG, "struct %s not found to define %s.", from, identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -1065,7 +1085,7 @@ void RNA_def_struct_sdna(StructRNA *srna, const char *structname)
if (DNA_struct_find_nr_wrapper(DefRNA.sdna, structname) == -1) {
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "%s not found.", structname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
return;
}
@@ -1093,7 +1113,7 @@ void RNA_def_struct_sdna_from(StructRNA *srna, const char *structname, const cha
if (DNA_struct_find_nr_wrapper(DefRNA.sdna, structname) == -1) {
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "%s not found.", structname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
return;
}
@@ -1106,7 +1126,7 @@ void RNA_def_struct_name_property(struct StructRNA *srna, struct PropertyRNA *pr
{
if (prop->type != PROP_STRING) {
CLOG_ERROR(&LOG, "\"%s.%s\", must be a string property.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
else {
srna->nameproperty = prop;
@@ -1121,7 +1141,7 @@ void RNA_def_struct_nested(BlenderRNA *brna, StructRNA *srna, const char *struct
srnafrom = BLI_ghash_lookup(brna->structs_map, structname);
if (!srnafrom) {
CLOG_ERROR(&LOG, "struct %s not found for %s.", structname, srna->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
srna->nested = srnafrom;
@@ -1271,7 +1291,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
if (rna_validate_identifier(identifier, error, true) == 0) {
CLOG_ERROR(
&LOG, "property identifier \"%s.%s\" - %s", CONTAINER_RNA_ID(cont), identifier, error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
dcont = rna_find_container_def(cont);
@@ -1279,7 +1299,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
/* XXX - toto, detect supertype collisions */
if (rna_findlink(&dcont->properties, identifier)) {
CLOG_ERROR(&LOG, "duplicate identifier \"%s.%s\"", CONTAINER_RNA_ID(cont), identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
dprop = MEM_callocN(sizeof(PropertyDefRNA), "PropertyDefRNA");
@@ -1294,7 +1314,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
CONTAINER_RNA_ID(cont),
identifier,
error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
}
@@ -1309,7 +1329,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
"subtype does not apply to 'PROP_BOOLEAN' \"%s.%s\"",
CONTAINER_RNA_ID(cont),
identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
break;
@@ -1322,7 +1342,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
"subtype does not apply to 'PROP_INT' \"%s.%s\"",
CONTAINER_RNA_ID(cont),
identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
@@ -1371,7 +1391,7 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
break;
default:
CLOG_ERROR(&LOG, "\"%s.%s\", invalid property type.", CONTAINER_RNA_ID(cont), identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
@@ -1404,6 +1424,14 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
}
}
+#ifndef RNA_RUNTIME
+ if (type != PROP_POINTER) {
+ if (DefRNA.make_overridable) {
+ prop->flag_override |= PROPOVERRIDE_OVERRIDABLE_LIBRARY;
+ }
+ }
+#endif
+
if (type == PROP_STRING) {
/* used so generated 'get/length/set' functions skip a NULL check
* in some cases we want it */
@@ -1413,42 +1441,42 @@ PropertyRNA *RNA_def_property(StructOrFunctionRNA *cont_,
if (DefRNA.preprocess) {
switch (type) {
case PROP_BOOLEAN:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_boolean_sdna(prop, NULL, identifier, 0);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
case PROP_INT: {
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_int_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
case PROP_FLOAT: {
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_float_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
case PROP_STRING: {
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_string_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
case PROP_ENUM:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_enum_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
case PROP_POINTER:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_pointer_sdna(prop, NULL, identifier);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
case PROP_COLLECTION:
- DefRNA.silent = 1;
+ DefRNA.silent = true;
RNA_def_property_collection_sdna(prop, NULL, identifier, NULL);
- DefRNA.silent = 0;
+ DefRNA.silent = false;
break;
}
}
@@ -1543,7 +1571,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
"\"%s.%s\", array length must be zero of greater.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1553,7 +1581,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
srna->identifier,
prop->identifier,
RNA_MAX_ARRAY_LENGTH);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1563,7 +1591,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
srna->identifier,
prop->identifier,
prop->arraydimension);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1580,7 +1608,7 @@ void RNA_def_property_array(PropertyRNA *prop, int length)
"\"%s.%s\", only boolean/int/float can be array.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1606,7 +1634,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le
srna->identifier,
prop->identifier,
RNA_MAX_ARRAY_DIMENSION);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -1620,7 +1648,7 @@ void RNA_def_property_multi_array(PropertyRNA *prop, int dimension, const int le
"\"%s.%s\", only boolean/int/float can be array.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
@@ -1680,22 +1708,22 @@ void RNA_def_property_ui_range(
#ifndef NDEBUG
if (min > max) {
CLOG_ERROR(&LOG, "\"%s.%s\", min > max.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (step < 0 || step > 100) {
CLOG_ERROR(&LOG, "\"%s.%s\", step outside range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (step == 0) {
CLOG_ERROR(&LOG, "\"%s.%s\", step is zero.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
if (precision < -1 || precision > UI_PRECISION_FLOAT_MAX) {
CLOG_ERROR(&LOG, "\"%s.%s\", precision outside range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
@@ -1718,7 +1746,7 @@ void RNA_def_property_ui_range(
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for ui range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1730,7 +1758,7 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max)
#ifdef DEBUG
if (min > max) {
CLOG_ERROR(&LOG, "\"%s.%s\", min > max.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
#endif
@@ -1753,7 +1781,7 @@ void RNA_def_property_range(PropertyRNA *prop, double min, double max)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", invalid type for range.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1781,7 +1809,7 @@ void RNA_def_property_struct_type(PropertyRNA *prop, const char *type)
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1814,7 +1842,7 @@ void RNA_def_property_struct_runtime(PropertyRNA *prop, StructRNA *type)
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1831,7 +1859,7 @@ void RNA_def_property_enum_native_type(PropertyRNA *prop, const char *native_enu
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1856,7 +1884,7 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item
"\"%s.%s\", enum identifiers must not contain spaces.",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
else if (item[i].value == eprop->defaultvalue) {
@@ -1879,7 +1907,7 @@ void RNA_def_property_enum_items(PropertyRNA *prop, const EnumPropertyItem *item
default:
CLOG_ERROR(
&LOG, "\"%s.%s\", invalid type for struct type.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1896,7 +1924,7 @@ void RNA_def_property_string_maxlength(PropertyRNA *prop, int maxlength)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1920,7 +1948,7 @@ void RNA_def_property_boolean_default(PropertyRNA *prop, bool value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1937,7 +1965,7 @@ void RNA_def_property_boolean_array_default(PropertyRNA *prop, const bool *array
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1959,7 +1987,7 @@ void RNA_def_property_int_default(PropertyRNA *prop, int value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -1981,7 +2009,7 @@ void RNA_def_property_int_array_default(PropertyRNA *prop, const int *array)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2003,7 +2031,7 @@ void RNA_def_property_float_default(PropertyRNA *prop, float value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2025,7 +2053,7 @@ void RNA_def_property_float_array_default(PropertyRNA *prop, const float *array)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2043,7 +2071,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
"\"%s.%s\", NULL string passed (dont call in this case).",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
@@ -2052,7 +2080,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
"\"%s.%s\", empty string passed (dont call in this case).",
srna->identifier,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
// BLI_assert(0);
break;
}
@@ -2066,7 +2094,7 @@ void RNA_def_property_string_default(PropertyRNA *prop, const char *value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2096,7 +2124,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value)
srna->identifier,
prop->identifier,
eprop->defaultvalue & ~totflag);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
else {
@@ -2113,7 +2141,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value)
else {
CLOG_ERROR(
&LOG, "\"%s.%s\", default is not in items.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -2122,7 +2150,7 @@ void RNA_def_property_enum_default(PropertyRNA *prop, int value)
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -2175,7 +2203,7 @@ static PropertyDefRNA *rna_def_property_sdna(PropertyRNA *prop,
structname,
propname,
prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return NULL;
}
}
@@ -2219,13 +2247,13 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop,
if (prop->type != PROP_BOOLEAN) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
- if (DefRNA.silent == 0) {
+ if (!DefRNA.silent) {
/* error check to ensure floats are not wrapped as ints/bools */
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_BOOLEAN_COMPAT(dp->dnatype) == 0) {
CLOG_ERROR(&LOG,
@@ -2234,7 +2262,7 @@ void RNA_def_property_boolean_sdna(PropertyRNA *prop,
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
}
@@ -2323,14 +2351,14 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const
if (prop->type != PROP_INT) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
/* error check to ensure floats are not wrapped as ints/bools */
- if (DefRNA.silent == 0) {
+ if (!DefRNA.silent) {
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_INT_COMPAT(dp->dnatype) == 0) {
CLOG_ERROR(&LOG,
"%s.%s is a '%s' but wrapped as type '%s'.",
@@ -2338,7 +2366,7 @@ void RNA_def_property_int_sdna(PropertyRNA *prop, const char *structname, const
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
}
@@ -2470,13 +2498,13 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons
if (prop->type != PROP_FLOAT) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
if ((dp = rna_def_property_sdna(prop, structname, propname))) {
/* silent is for internal use */
- if (DefRNA.silent == 0) {
+ if (!DefRNA.silent) {
if (dp->dnatype && *dp->dnatype && IS_DNATYPE_FLOAT_COMPAT(dp->dnatype) == 0) {
/* Colors are an exception. these get translated. */
if (prop->subtype != PROP_COLOR_GAMMA) {
@@ -2486,7 +2514,7 @@ void RNA_def_property_float_sdna(PropertyRNA *prop, const char *structname, cons
prop->identifier,
dp->dnatype,
RNA_property_typename(prop->type));
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
}
@@ -2578,7 +2606,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const
if (prop->type != PROP_ENUM) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2589,7 +2617,7 @@ void RNA_def_property_enum_sdna(PropertyRNA *prop, const char *structname, const
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\", array not supported for enum type.", structname, propname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -2672,7 +2700,7 @@ void RNA_def_property_string_sdna(PropertyRNA *prop, const char *structname, con
if (prop->type != PROP_STRING) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2716,7 +2744,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co
if (prop->type != PROP_POINTER) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not pointer.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2727,7 +2755,7 @@ void RNA_def_property_pointer_sdna(PropertyRNA *prop, const char *structname, co
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\", array not supported for pointer type.", structname, propname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -2749,7 +2777,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop,
if (prop->type != PROP_COLLECTION) {
CLOG_ERROR(&LOG, "\"%s.%s\", type is not collection.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2760,7 +2788,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop,
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\", array of collections not supported.", structname, propname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
@@ -2806,7 +2834,7 @@ void RNA_def_property_collection_sdna(PropertyRNA *prop,
else {
if (!DefRNA.silent) {
CLOG_ERROR(&LOG, "\"%s.%s\" not found.", structname, lengthpropname);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
}
@@ -2904,7 +2932,7 @@ void RNA_def_property_dynamic_array_funcs(PropertyRNA *prop, const char *getleng
if (!(prop->flag & PROP_DYNAMIC)) {
CLOG_ERROR(&LOG, "property is a not dynamic array.");
- DefRNA.error = 1;
+ DefRNA.error = true;
return;
}
@@ -2946,7 +2974,7 @@ void RNA_def_property_boolean_funcs(PropertyRNA *prop, const char *get, const ch
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not boolean.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3036,7 +3064,7 @@ void RNA_def_property_int_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not int.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3134,7 +3162,7 @@ void RNA_def_property_float_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not float.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3222,7 +3250,7 @@ void RNA_def_property_enum_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not enum.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3289,7 +3317,7 @@ void RNA_def_property_string_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not string.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3351,7 +3379,7 @@ void RNA_def_property_pointer_funcs(
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not pointer.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -3405,7 +3433,7 @@ void RNA_def_property_collection_funcs(PropertyRNA *prop,
}
default:
CLOG_ERROR(&LOG, "\"%s.%s\", type is not collection.", srna->identifier, prop->identifier);
- DefRNA.error = 1;
+ DefRNA.error = true;
break;
}
}
@@ -4170,7 +4198,7 @@ static FunctionRNA *rna_def_function(StructRNA *srna, const char *identifier)
if (rna_validate_identifier(identifier, error, false) == 0) {
CLOG_ERROR(&LOG, "function identifier \"%s\" - %s", identifier, error);
- DefRNA.error = 1;
+ DefRNA.error = true;
}
}
diff --git a/source/blender/makesrna/intern/rna_fluid.c b/source/blender/makesrna/intern/rna_fluid.c
index 93c7c1f3480..43d2234ddf2 100644
--- a/source/blender/makesrna/intern/rna_fluid.c
+++ b/source/blender/makesrna/intern/rna_fluid.c
@@ -227,8 +227,11 @@ static void rna_Fluid_flip_parts_update(Main *bmain, Scene *scene, PointerRNA *p
mmd = (FluidModifierData *)BKE_modifiers_findby_type(ob, eModifierType_Fluid);
bool exists = rna_Fluid_parts_exists(ptr, PART_FLUID_FLIP);
- /* Only create a particle system in liquid domain mode. */
+ /* Only create a particle system in liquid domain mode.
+ * Remove any remainings of a liquid sim when switching to gas. */
if (mmd->domain->type != FLUID_DOMAIN_TYPE_LIQUID) {
+ rna_Fluid_parts_delete(ptr, PART_FLUID_FLIP);
+ mmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP;
rna_Fluid_domain_reset(bmain, scene, ptr);
return;
}
diff --git a/source/blender/makesrna/intern/rna_internal.h b/source/blender/makesrna/intern/rna_internal.h
index 9faf589fe8a..6afa740fec3 100644
--- a/source/blender/makesrna/intern/rna_internal.h
+++ b/source/blender/makesrna/intern/rna_internal.h
@@ -118,7 +118,14 @@ typedef struct BlenderDefRNA {
ListBase structs;
ListBase allocs;
struct StructRNA *laststruct;
- int error, silent, preprocess, verify, animate;
+ bool error;
+ bool silent;
+ bool preprocess;
+ bool verify;
+ bool animate;
+ /** Whether RNA properties defined should be overridable or not by default. */
+ bool make_overridable;
+
/* Keep last. */
#ifndef RNA_RUNTIME
struct {
diff --git a/source/blender/makesrna/intern/rna_light.c b/source/blender/makesrna/intern/rna_light.c
index c19dafb3bc6..2caf315e09e 100644
--- a/source/blender/makesrna/intern/rna_light.c
+++ b/source/blender/makesrna/intern/rna_light.c
@@ -186,25 +186,45 @@ static void rna_def_light(BlenderRNA *brna)
rna_def_animdata_common(srna);
}
-static void rna_def_light_energy(StructRNA *srna, bool distant)
+static void rna_def_light_energy(StructRNA *srna, const short light_type)
{
PropertyRNA *prop;
- if (distant) {
- /* Distant light strength has no unit defined, it's proportional to
- * Watt/m^2 and is not sensitive to scene unit scale. */
- prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
- RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
- RNA_def_property_ui_text(prop, "Strength", "Amount of light emitted");
- RNA_def_property_update(prop, 0, "rna_Light_draw_update");
- }
- else {
- /* Lights with a location have power in Watt, which is sensitive to
- * scene unit scale. */
- prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
- RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
- RNA_def_property_ui_text(prop, "Power", "Amount of light emitted");
- RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ switch (light_type) {
+ case LA_SUN: {
+ /* Distant light strength has no unit defined,
+ * it's proportional to 'watt/m^2' and is not sensitive to scene unit scale. */
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_ui_range(prop, 0.0f, 10.0f, 1, 3);
+ RNA_def_property_ui_text(
+ prop, "Strength", "Sunlight strength in watts per meter squared (W/m^2)");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ break;
+ }
+ case LA_SPOT: {
+ /* Lights with a location have power in Watts,
+ * which is sensitive to scene unit scale. */
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
+ RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
+ RNA_def_property_ui_text(prop,
+ "Power",
+ "The energy this light would emit over its entire area "
+ "if it wasn't limited by the spot angle");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ break;
+ }
+ default: {
+ /* Lights with a location have power in Watts,
+ * which is sensitive to scene unit scale. */
+ prop = RNA_def_property(srna, "energy", PROP_FLOAT, PROP_POWER);
+ RNA_def_property_ui_range(prop, 0.0f, 1000000.0f, 10, 5);
+ RNA_def_property_ui_text(
+ prop,
+ "Power",
+ "Light energy emitted over the entire area of the light in all directions");
+ RNA_def_property_update(prop, 0, "rna_Light_draw_update");
+ break;
+ }
}
}
@@ -395,7 +415,7 @@ static void rna_def_point_light(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Point Light", "Omnidirectional point Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_POINT);
- rna_def_light_energy(srna, false);
+ rna_def_light_energy(srna, LA_LOCAL);
rna_def_light_falloff(srna);
rna_def_light_shadow(srna, false);
}
@@ -418,7 +438,7 @@ static void rna_def_area_light(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Area Light", "Directional area Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_AREA);
- rna_def_light_energy(srna, false);
+ rna_def_light_energy(srna, LA_AREA);
rna_def_light_shadow(srna, false);
rna_def_light_falloff(srna);
@@ -457,7 +477,7 @@ static void rna_def_spot_light(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Spot Light", "Directional cone Light");
RNA_def_struct_ui_icon(srna, ICON_LIGHT_SPOT);
- rna_def_light_energy(srna, false);
+ rna_def_light_energy(srna, LA_SPOT);
rna_def_light_falloff(srna);
rna_def_light_shadow(srna, false);
@@ -503,7 +523,7 @@ static void rna_def_sun_light(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Angle", "Angular diameter of the Sun as seen from the Earth");
RNA_def_property_update(prop, 0, "rna_Light_update");
- rna_def_light_energy(srna, true);
+ rna_def_light_energy(srna, LA_SUN);
rna_def_light_shadow(srna, true);
}
diff --git a/source/blender/makesrna/intern/rna_modifier.c b/source/blender/makesrna/intern/rna_modifier.c
index f5a437b7892..1e21278c8eb 100644
--- a/source/blender/makesrna/intern/rna_modifier.c
+++ b/source/blender/makesrna/intern/rna_modifier.c
@@ -1682,6 +1682,8 @@ static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const c
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "uv_smooth", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "uv_smooth");
RNA_def_property_enum_items(prop, prop_uv_smooth_items);
@@ -1702,6 +1704,8 @@ static PropertyRNA *rna_def_property_subdivision_common(StructRNA *srna, const c
RNA_def_property_ui_text(prop, "Subdivision Type", "Select type of subdivision algorithm");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
return prop;
}
@@ -1717,6 +1721,8 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
rna_def_property_subdivision_common(srna, "subdivType");
+ RNA_define_lib_overridable(true);
+
/* see CCGSUBSURF_LEVEL_MAX for max limit */
prop = RNA_def_property(srna, "levels", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "levels");
@@ -1743,6 +1749,8 @@ static void rna_def_modifier_subsurf(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Creases", "Use mesh edge crease information to sharpen edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_generic_map_info(StructRNA *srna)
@@ -1769,6 +1777,8 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna)
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "texture", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Texture", "");
RNA_def_property_flag(prop, PROP_EDITABLE);
@@ -1799,6 +1809,8 @@ static void rna_def_modifier_generic_map_info(StructRNA *srna)
RNA_def_property_string_sdna(prop, NULL, "map_bone");
RNA_def_property_ui_text(prop, "Texture Coordinate Bone", "Bone to set the texture coordinates");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_warp(BlenderRNA *brna)
@@ -1811,6 +1823,8 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WarpModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_WARP);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object_from", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "object_from");
RNA_def_property_ui_text(prop, "Object From", "Object to transform from");
@@ -1872,6 +1886,8 @@ static void rna_def_modifier_warp(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
rna_def_modifier_generic_map_info(srna);
}
@@ -1885,6 +1901,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MultiresModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MULTIRES);
+ RNA_define_lib_overridable(true);
+
prop = rna_def_property_subdivision_common(srna, "simple");
RNA_def_property_enum_funcs(prop, NULL, "rna_MultiresModifier_type_set", NULL);
@@ -1936,6 +1954,8 @@ static void rna_def_modifier_multires(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Use Creases", "Use mesh edge crease information to sharpen edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_lattice(BlenderRNA *brna)
@@ -1948,6 +1968,8 @@ static void rna_def_modifier_lattice(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "LatticeModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_LATTICE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Lattice object to deform with");
RNA_def_property_pointer_funcs(
@@ -1975,6 +1997,8 @@ static void rna_def_modifier_lattice(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 1, 10, 2);
RNA_def_property_ui_text(prop, "Strength", "Strength of modifier effect");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_curve(BlenderRNA *brna)
@@ -1997,6 +2021,8 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CurveModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_CURVE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Curve object to deform with");
RNA_def_property_pointer_funcs(
@@ -2024,6 +2050,8 @@ static void rna_def_modifier_curve(BlenderRNA *brna)
RNA_def_property_enum_items(prop, prop_deform_axis_items);
RNA_def_property_ui_text(prop, "Deform Axis", "The axis that the curve deforms along");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_build(BlenderRNA *brna)
@@ -2036,6 +2064,8 @@ static void rna_def_modifier_build(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BuildModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_BUILD);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME);
RNA_def_property_float_sdna(prop, NULL, "start");
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
@@ -2062,6 +2092,8 @@ static void rna_def_modifier_build(BlenderRNA *brna)
RNA_def_property_range(prop, 1, MAXFRAMEF);
RNA_def_property_ui_text(prop, "Seed", "Seed for random if used");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_mirror(BlenderRNA *brna)
@@ -2074,6 +2106,8 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MirrorModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MIRROR);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_axis", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_MIR_AXIS_X);
RNA_def_property_array(prop, 3);
@@ -2174,6 +2208,8 @@ static void rna_def_modifier_mirror(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE | PROP_ID_SELF_CHECK);
RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_decimate(BlenderRNA *brna)
@@ -2199,6 +2235,8 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DecimateModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DECIM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "decimate_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, modifier_decim_mode_items);
@@ -2287,6 +2325,8 @@ static void rna_def_modifier_decimate(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(
prop, "Face Count", "The current number of faces in the decimated mesh");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_wave(BlenderRNA *brna)
@@ -2299,6 +2339,8 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WaveModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_WAVE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WAVE_X);
RNA_def_property_ui_text(prop, "X", "X axis motion");
@@ -2426,6 +2468,8 @@ static void rna_def_modifier_wave(BlenderRNA *brna)
"the more narrow the wave");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
rna_def_modifier_generic_map_info(srna);
}
@@ -2439,6 +2483,8 @@ static void rna_def_modifier_armature(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ArmatureModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_ARMATURE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Armature object to deform with");
RNA_def_property_pointer_funcs(
@@ -2486,6 +2532,8 @@ static void rna_def_modifier_armature(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "deformflag", ARM_DEF_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_hook(BlenderRNA *brna)
@@ -2501,6 +2549,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "HookModifierData");
RNA_def_struct_ui_icon(srna, ICON_HOOK);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "strength", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "force");
RNA_def_property_range(prop, 0, 1);
@@ -2595,6 +2645,8 @@ static void rna_def_modifier_hook(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_HOOK_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_softbody(BlenderRNA *brna)
@@ -2645,6 +2697,8 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BooleanModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_BOOLEAN);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Mesh object to use for Boolean operation");
RNA_def_property_pointer_funcs(
@@ -2687,6 +2741,8 @@ static void rna_def_modifier_boolean(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_ENUM_FLAG);
RNA_def_property_ui_text(prop, "Debug", "Debugging options, only when started with '-d'");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_array(BlenderRNA *brna)
@@ -2714,6 +2770,8 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ArrayModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_ARRAY);
+ RNA_define_lib_overridable(true);
+
/* Length parameters */
prop = RNA_def_property(srna, "fit_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_fit_type_items);
@@ -2836,6 +2894,8 @@ static void rna_def_modifier_array(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -1, 1, 2, 4);
RNA_def_property_ui_text(prop, "V Offset", "Amount to offset array UVs on the V axis");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_edgesplit(BlenderRNA *brna)
@@ -2849,6 +2909,8 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "EdgeSplitModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_EDGESPLIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "split_angle", PROP_FLOAT, PROP_ANGLE);
RNA_def_property_range(prop, 0.0f, DEG2RADF(180.0f));
RNA_def_property_ui_range(prop, 0.0f, DEG2RADF(180.0f), 10, 2);
@@ -2864,6 +2926,8 @@ static void rna_def_modifier_edgesplit(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_EDGESPLIT_FROMFLAG);
RNA_def_property_ui_text(prop, "Use Sharp Edges", "Split edges that are marked as sharp");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_displace(BlenderRNA *brna)
@@ -2917,6 +2981,8 @@ static void rna_def_modifier_displace(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DisplaceModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DISPLACE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(
@@ -2954,6 +3020,8 @@ static void rna_def_modifier_displace(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
rna_def_modifier_generic_map_info(srna);
}
@@ -3049,6 +3117,8 @@ static void rna_def_modifier_smooth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SmoothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_X);
RNA_def_property_ui_text(prop, "X", "Smooth object along X axis");
@@ -3090,6 +3160,8 @@ static void rna_def_modifier_smooth(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SMOOTH_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
@@ -3131,6 +3203,8 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CorrectiveSmoothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "factor", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_float_sdna(prop, NULL, "lambda");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
@@ -3194,6 +3268,8 @@ static void rna_def_modifier_correctivesmooth(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Pin Boundaries", "Excludes boundary vertices from being smoothed");
RNA_def_property_update(prop, 0, "rna_CorrectiveSmoothModifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
@@ -3206,6 +3282,8 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "LaplacianSmoothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SMOOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "use_x", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_X);
RNA_def_property_ui_text(prop, "X", "Smooth object along X axis");
@@ -3264,6 +3342,8 @@ static void rna_def_modifier_laplaciansmooth(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_LAPLACIANSMOOTH_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_cast(BlenderRNA *brna)
@@ -3283,6 +3363,8 @@ static void rna_def_modifier_cast(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "CastModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_CAST);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cast_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_cast_type_items);
@@ -3359,6 +3441,8 @@ static void rna_def_modifier_cast(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_CastModifier_defgrp_name_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_meshdeform(BlenderRNA *brna)
@@ -3379,6 +3463,8 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MeshDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Object", "Mesh object to deform with");
RNA_def_property_pointer_funcs(
@@ -3423,6 +3509,8 @@ static void rna_def_modifier_meshdeform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Mode", "Method of binding vertices are bound to cage mesh");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# endif
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_particlesystem(BlenderRNA *brna)
@@ -3438,6 +3526,7 @@ static void rna_def_modifier_particlesystem(BlenderRNA *brna)
prop = RNA_def_property(srna, "particle_system", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "psys");
+ RNA_def_property_override_flag(prop, PROPOVERRIDE_OVERRIDABLE_LIBRARY);
RNA_def_property_ui_text(prop, "Particle System", "Particle System that this modifier controls");
}
@@ -3465,6 +3554,8 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ParticleInstanceModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_PARTICLES);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob");
RNA_def_property_pointer_funcs(prop, NULL, NULL, NULL, "rna_Mesh_object_poll");
@@ -3592,6 +3683,8 @@ static void rna_def_modifier_particleinstance(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Value Layer Name", "Custom data layer name for the randomized value");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_explode(BlenderRNA *brna)
@@ -3605,6 +3698,8 @@ static void rna_def_modifier_explode(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ExplodeModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_EXPLODE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_funcs(prop,
"rna_ExplodeModifier_vgroup_get",
@@ -3652,6 +3747,8 @@ static void rna_def_modifier_explode(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", eExplodeFlag_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_cloth(BlenderRNA *brna)
@@ -3664,6 +3761,8 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ClothModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_CLOTH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "settings", PROP_POINTER, PROP_NONE);
RNA_def_property_flag(prop, PROP_NEVER_NULL);
RNA_def_property_pointer_sdna(prop, NULL, "sim_parms");
@@ -3697,6 +3796,8 @@ static void rna_def_modifier_cloth(BlenderRNA *brna)
RNA_def_property_int_sdna(prop, NULL, "hair_grid_res");
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Hair Grid Resolution", "");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_fluid(BlenderRNA *brna)
@@ -3717,6 +3818,8 @@ static void rna_def_modifier_fluid(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "FluidModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_FLUIDSIM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "domain_settings", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "domain");
RNA_def_property_ui_text(prop, "Domain Settings", "");
@@ -3735,6 +3838,8 @@ static void rna_def_modifier_fluid(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update(prop, 0, "rna_fluid_set_type");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_dynamic_paint(BlenderRNA *brna)
@@ -3863,6 +3968,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "BevelModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_BEVEL);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "width", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "value");
RNA_def_property_range(prop, 0, FLT_MAX);
@@ -4000,6 +4107,8 @@ static void rna_def_modifier_bevel(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Vertex Mesh Method", "The method to use to create the mesh at intersections");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
@@ -4054,6 +4163,8 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ShrinkwrapModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SHRINKWRAP);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "wrap_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "shrinkType");
RNA_def_property_enum_items(prop, shrink_type_items);
@@ -4164,6 +4275,8 @@ static void rna_def_modifier_shrinkwrap(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "shrinkOpts", MOD_SHRINKWRAP_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_mask(BlenderRNA *brna)
@@ -4182,6 +4295,8 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MaskModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MASK);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, modifier_mask_mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
@@ -4213,6 +4328,8 @@ static void rna_def_modifier_mask(BlenderRNA *brna)
RNA_def_property_ui_range(prop, 0, 1, 0.1, 3);
RNA_def_property_ui_text(prop, "Threshold", "Weights over this threshold remain");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_simpledeform(BlenderRNA *brna)
@@ -4252,6 +4369,8 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SimpleDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SIMPLEDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "deform_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, simple_deform_mode_items);
@@ -4316,6 +4435,8 @@ static void rna_def_modifier_simpledeform(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_SIMPLEDEFORM_FLAG_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_surface(BlenderRNA *brna)
@@ -4392,6 +4513,8 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SolidifyModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SOLIDIFY);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "solidify_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "mode");
RNA_def_property_enum_items(prop, mode_items);
@@ -4562,6 +4685,8 @@ static void rna_def_modifier_solidify(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -1.0, 1.0, 0.1, 3);
RNA_def_property_ui_text(prop, "Bevel Convex", "Edge bevel weight to be added to outside edges");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_screw(BlenderRNA *brna)
@@ -4574,6 +4699,8 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "ScrewModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SCREW);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob_axis");
RNA_def_property_ui_text(prop, "Object", "Object to define the screw axis");
@@ -4672,6 +4799,8 @@ static void rna_def_modifier_screw(BlenderRNA *brna)
prop, "Object Angle", "Use the angle between the objects rather than the fixed angle");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
# endif
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_uvwarp(BlenderRNA *brna)
@@ -4684,6 +4813,8 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "UVWarpModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_UVPROJECT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "axis_u", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "axis_u");
RNA_def_property_enum_items(prop, rna_enum_axis_xyz_items);
@@ -4756,10 +4887,13 @@ static void rna_def_modifier_uvwarp(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "UV Layer", "UV Layer name");
RNA_def_property_string_funcs(prop, NULL, NULL, "rna_UVWarpModifier_uvlayer_name_set");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
StructRNA *srna,
+ const char *mask_flags,
const char *mask_vgroup_setter,
const char *mask_uvlayer_setter)
{
@@ -4789,6 +4923,8 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
PropertyRNA *prop;
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mask_constant", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
RNA_def_property_ui_range(prop, 0.0, 1.0, 1, -1);
@@ -4802,6 +4938,11 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
RNA_def_property_string_funcs(prop, NULL, NULL, mask_vgroup_setter);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, mask_flags, MOD_WVG_EDIT_INVERT_VGROUP_MASK);
+ RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
+ RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
prop = RNA_def_property(srna, "mask_texture", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Masking Tex", "Masking texture");
RNA_def_property_flag(prop, PROP_EDITABLE);
@@ -4842,6 +4983,8 @@ static void rna_def_modifier_weightvg_mask(BlenderRNA *UNUSED(brna),
RNA_def_property_ui_text(
prop, "Texture Coordinate Bone", "Which bone to take texture coordinates from");
RNA_def_property_update(prop, 0, "rna_Modifier_dependency_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
@@ -4871,6 +5014,8 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightVGEditModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
@@ -4946,16 +5091,14 @@ static void rna_def_modifier_weightvgedit(BlenderRNA *brna)
"to be removed from the vgroup");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
/* Common masking properties. */
rna_def_modifier_weightvg_mask(brna,
srna,
+ "edit_flags",
"rna_WeightVGEditModifier_mask_defgrp_name_set",
"rna_WeightVGEditModifier_mask_tex_uvlayer_name_set");
-
- prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "edit_flags", MOD_WVG_EDIT_INVERT_VGROUP_MASK);
- RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
@@ -5000,6 +5143,8 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightVGMixModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group_a", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name_a");
RNA_def_property_ui_text(prop, "Vertex Group A", "First vertex group name");
@@ -5053,17 +5198,6 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Vertex Set", "Which vertices should be affected");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
- /* Common masking properties. */
- rna_def_modifier_weightvg_mask(brna,
- srna,
- "rna_WeightVGMixModifier_mask_defgrp_name_set",
- "rna_WeightVGMixModifier_mask_tex_uvlayer_name_set");
-
- prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_INVERT_VGROUP_MASK);
- RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
-
prop = RNA_def_property(srna, "normalize", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WVG_MIX_WEIGHTS_NORMALIZE);
RNA_def_property_ui_text(
@@ -5071,6 +5205,15 @@ static void rna_def_modifier_weightvgmix(BlenderRNA *brna)
"Normalize Weights",
"Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
+
+ /* Common masking properties. */
+ rna_def_modifier_weightvg_mask(brna,
+ srna,
+ "flag",
+ "rna_WeightVGMixModifier_mask_defgrp_name_set",
+ "rna_WeightVGMixModifier_mask_tex_uvlayer_name_set");
}
static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
@@ -5124,6 +5267,8 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightVGProximityModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_VERTEX_WEIGHT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "defgrp_name");
RNA_def_property_ui_text(prop, "Vertex Group", "Vertex group name");
@@ -5186,17 +5331,14 @@ static void rna_def_modifier_weightvgproximity(BlenderRNA *brna)
"Normalize the resulting weights (otherwise they are only clamped within [0.0, 1.0] range)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
/* Common masking properties. */
rna_def_modifier_weightvg_mask(brna,
srna,
+ "proximity_flags",
"rna_WeightVGProximityModifier_mask_defgrp_name_set",
"rna_WeightVGProximityModifier_mask_tex_uvlayer_name_set");
-
- prop = RNA_def_property(srna, "invert_mask_vertex_group", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(
- prop, NULL, "proximity_flags", MOD_WVG_PROXIMITY_INVERT_VGROUP_MASK);
- RNA_def_property_ui_text(prop, "Invert", "Invert vertex group mask influence");
- RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
static void rna_def_modifier_remesh(BlenderRNA *brna)
@@ -5232,6 +5374,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "RemeshModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_REMESH);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, mode_items);
RNA_def_property_ui_text(prop, "Mode", "");
@@ -5300,6 +5444,8 @@ static void rna_def_modifier_remesh(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Smooth Shading", "Output faces with smooth shading rather than flat shaded");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_ocean(BlenderRNA *brna)
@@ -5357,6 +5503,8 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "OceanModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_OCEAN);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "geometry_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "geometry_mode");
RNA_def_property_enum_items(prop, geometry_items);
@@ -5550,6 +5698,8 @@ static void rna_def_modifier_ocean(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Cache Path", "Path to a folder to store external baked images");
/*RNA_def_property_update(prop, 0, "rna_Modifier_update"); */
/* XXX how to update? */
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_skin(BlenderRNA *brna)
@@ -5562,6 +5712,8 @@ static void rna_def_modifier_skin(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SkinModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_SKIN);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "branch_smoothing", PROP_FLOAT, PROP_FACTOR);
RNA_def_property_ui_text(prop, "Branch Smoothing", "Smooth complex geometry around branches");
RNA_def_property_ui_range(prop, 0, 1, 1, -1);
@@ -5587,6 +5739,8 @@ static void rna_def_modifier_skin(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "symmetry_axes", MOD_SKIN_SYMM_Z);
RNA_def_property_ui_text(prop, "Z", "Avoid making unsymmetrical quads across the Z axis");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_triangulate(BlenderRNA *brna)
@@ -5599,6 +5753,8 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "TriangulateModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_TRIANGULATE);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "quad_method", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "quad_method");
RNA_def_property_enum_items(prop, rna_enum_modifier_triangulate_quad_method_items);
@@ -5629,6 +5785,8 @@ static void rna_def_modifier_triangulate(BlenderRNA *brna)
"Try to preserve custom normals (WARNING: depending on chosen triangulation method, "
"shading may not be fully preserved, 'Fixed' method usually gives the best result here)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_meshcache(BlenderRNA *brna)
@@ -5695,6 +5853,8 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MeshCacheModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cache_format", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, prop_format_type_items);
@@ -5789,6 +5949,8 @@ static void rna_def_modifier_meshcache(BlenderRNA *brna)
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Evaluation Factor", "Evaluation time in seconds");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
@@ -5801,6 +5963,8 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "MeshSeqCacheModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM); /* XXX, needs own icon */
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "cache_file", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "cache_file");
RNA_def_property_struct_type(prop, "CacheFile");
@@ -5829,6 +5993,8 @@ static void rna_def_modifier_meshseqcache(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "read_flag");
RNA_def_property_enum_items(prop, read_flag_items);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
@@ -5841,6 +6007,8 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "LaplacianDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "vertex_group", PROP_STRING, PROP_NONE);
RNA_def_property_string_sdna(prop, NULL, "anchor_grp_name");
RNA_def_property_ui_text(
@@ -5864,6 +6032,8 @@ static void rna_def_modifier_laplaciandeform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+ RNA_define_lib_overridable(false);
+
RNA_def_property_update(prop, 0, "rna_Modifier_update");
}
@@ -5877,6 +6047,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeldModifierData");
RNA_def_struct_ui_icon(srna, ICON_AUTOMERGE_OFF);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "merge_threshold", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "merge_dist");
RNA_def_property_range(prop, 0, FLT_MAX);
@@ -5904,6 +6076,8 @@ static void rna_def_modifier_weld(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WELD_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_wireframe(BlenderRNA *brna)
@@ -5916,6 +6090,8 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WireframeModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_WIREFRAME);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "thickness", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "offset");
RNA_def_property_range(prop, -FLT_MAX, FLT_MAX);
@@ -5987,6 +6163,8 @@ static void rna_def_modifier_wireframe(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WIREFRAME_INVERT_VGROUP);
RNA_def_property_ui_text(prop, "Invert", "Invert vertex group influence");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_datatransfer(BlenderRNA *brna)
@@ -6048,6 +6226,8 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "DataTransferModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_DATA_TRANSFER);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "ob_source");
RNA_def_property_ui_text(prop, "Source Object", "Object to transfer data from");
@@ -6348,6 +6528,8 @@ static void rna_def_modifier_datatransfer(BlenderRNA *brna)
srna, "invert_vertex_group", false, "Invert", "Invert vertex group influence");
RNA_def_property_boolean_sdna(prop, NULL, "flags", MOD_DATATRANSFER_INVERT_VGROUP);
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_normaledit(BlenderRNA *brna)
@@ -6387,6 +6569,8 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "NormalEditModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, prop_mode_items);
RNA_def_property_ui_text(prop, "Mode", "How to affect (generate) normals");
@@ -6469,6 +6653,8 @@ static void rna_def_modifier_normaledit(BlenderRNA *brna)
"Use same direction for all normals, from origin to target's center "
"(Directional mode only)");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
@@ -6481,6 +6667,8 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SurfaceDeformModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_MESHDEFORM);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Target", "Mesh object to deform with");
RNA_def_property_pointer_funcs(
@@ -6517,6 +6705,8 @@ static void rna_def_modifier_surfacedeform(BlenderRNA *brna)
RNA_def_property_ui_range(prop, -100, 100, 10, 2);
RNA_def_property_ui_text(prop, "Strength", "Strength of modifier deformations");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_weightednormal(BlenderRNA *brna)
@@ -6548,6 +6738,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "WeightedNormalModifierData");
RNA_def_struct_ui_icon(srna, ICON_MOD_NORMALEDIT);
+ RNA_define_lib_overridable(true);
+
prop = RNA_def_property(srna, "weight", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_range(prop, 1, 100, 1, -1);
@@ -6594,6 +6786,8 @@ static void rna_def_modifier_weightednormal(BlenderRNA *brna)
RNA_def_property_boolean_sdna(prop, NULL, "flag", MOD_WEIGHTEDNORMAL_FACE_INFLUENCE);
RNA_def_property_ui_text(prop, "Face Influence", "Use influence of face for weighting");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
static void rna_def_modifier_simulation_access(BlenderRNA *brna)
@@ -6606,6 +6800,8 @@ static void rna_def_modifier_simulation_access(BlenderRNA *brna)
RNA_def_struct_sdna(srna, "SimulationModifierData");
RNA_def_struct_ui_icon(srna, ICON_PHYSICS); /* TODO: Use correct icon. */
+ RNA_define_lib_overridable(true);
+
# ifdef WITH_NEW_SIMULATION_TYPE
prop = RNA_def_property(srna, "simulation", PROP_POINTER, PROP_NONE);
RNA_def_property_ui_text(prop, "Simulation", "Simulation to access");
@@ -6617,6 +6813,8 @@ static void rna_def_modifier_simulation_access(BlenderRNA *brna)
RNA_def_property_ui_text(
prop, "Data Path", "Identifier of the simulation component that should be accessed");
RNA_def_property_update(prop, 0, "rna_Modifier_update");
+
+ RNA_define_lib_overridable(false);
}
void RNA_def_modifier(BlenderRNA *brna)
diff --git a/source/blender/makesrna/intern/rna_render.c b/source/blender/makesrna/intern/rna_render.c
index 6c21e4ad01b..6af031eb7b0 100644
--- a/source/blender/makesrna/intern/rna_render.c
+++ b/source/blender/makesrna/intern/rna_render.c
@@ -131,7 +131,7 @@ static void engine_bind_display_space_shader(RenderEngine *UNUSED(engine), Scene
GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE);
GPU_shader_bind(shader);
- int img_loc = GPU_shader_get_uniform_ensure(shader, "image");
+ int img_loc = GPU_shader_get_uniform(shader, "image");
GPU_shader_uniform_int(shader, img_loc, 0);
}
diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c
index e65d3eb18b0..3dc1d05810c 100644
--- a/source/blender/makesrna/intern/rna_scene.c
+++ b/source/blender/makesrna/intern/rna_scene.c
@@ -2201,12 +2201,12 @@ static void rna_Scene_update_active_object_data(bContext *C, PointerRNA *UNUSED(
}
}
-static void rna_SceneCamera_update(Main *bmain, Scene *UNUSED(scene), PointerRNA *ptr)
+static void rna_SceneCamera_update(Main *UNUSED(bmain), Scene *UNUSED(scene), PointerRNA *ptr)
{
Scene *scene = (Scene *)ptr->owner_id;
Object *camera = scene->camera;
- BKE_sequence_invalidate_scene_strips(bmain, scene);
+ BKE_sequencer_cache_cleanup(scene);
if (camera && (camera->type == OB_CAMERA)) {
DEG_id_tag_update(&camera->id, ID_RECALC_GEOMETRY);
diff --git a/source/blender/makesrna/intern/rna_sequencer.c b/source/blender/makesrna/intern/rna_sequencer.c
index 45d7bc24017..39ea054456f 100644
--- a/source/blender/makesrna/intern/rna_sequencer.c
+++ b/source/blender/makesrna/intern/rna_sequencer.c
@@ -2016,7 +2016,7 @@ static void rna_def_editor(BlenderRNA *brna)
RNA_def_property_ui_text(
prop,
"Prefetch Frames",
- "Render frames ahead of playhead in the background for faster playback");
+ "Render frames ahead of current frame in the background for faster playback");
RNA_def_property_update(prop, NC_SCENE | ND_SEQUENCER, NULL);
prop = RNA_def_property(srna, "recycle_max_cost", PROP_FLOAT, PROP_NONE);
diff --git a/source/blender/makesrna/intern/rna_ui_api.c b/source/blender/makesrna/intern/rna_ui_api.c
index 2a64ffa73cd..8d0e403aa2d 100644
--- a/source/blender/makesrna/intern/rna_ui_api.c
+++ b/source/blender/makesrna/intern/rna_ui_api.c
@@ -485,6 +485,21 @@ static void rna_uiTemplateAnyID(uiLayout *layout,
uiTemplateAnyID(layout, ptr, propname, proptypename, name);
}
+static void rna_uiTemplateCacheFile(uiLayout *layout,
+ bContext *C,
+ PointerRNA *ptr,
+ const char *propname)
+{
+ PropertyRNA *prop = RNA_struct_find_property(ptr, propname);
+
+ if (!prop) {
+ RNA_warning("property not found: %s.%s", RNA_struct_identifier(ptr->type), propname);
+ return;
+ }
+
+ uiTemplateCacheFile(layout, C, ptr, propname);
+}
+
static void rna_uiTemplatePathBuilder(uiLayout *layout,
PointerRNA *ptr,
const char *propname,
@@ -1577,7 +1592,7 @@ void RNA_api_ui_layout(StructRNA *srna)
RNA_def_float_array(
func, "color", 4, node_socket_color_default, 0.0f, 1.0f, "Color", "", 0.0f, 1.0f);
- func = RNA_def_function(srna, "template_cache_file", "uiTemplateCacheFile");
+ func = RNA_def_function(srna, "template_cache_file", "rna_uiTemplateCacheFile");
RNA_def_function_ui_description(
func, "Item(s). User interface for selecting cache files and their source paths");
RNA_def_function_flag(func, FUNC_USE_CONTEXT);
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 479d0a0d1a7..49a0121dadb 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -360,7 +360,7 @@ static void rna_userdef_load_ui_update(Main *UNUSED(bmain), Scene *UNUSED(scene)
static void rna_userdef_anisotropic_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
- GPU_set_anisotropic(bmain, U.anisotropic_filter);
+ GPU_set_anisotropic(U.anisotropic_filter);
rna_userdef_update(bmain, scene, ptr);
}
diff --git a/source/blender/modifiers/intern/MOD_skin.c b/source/blender/modifiers/intern/MOD_skin.c
index 98c7d809f33..34590736e37 100644
--- a/source/blender/modifiers/intern/MOD_skin.c
+++ b/source/blender/modifiers/intern/MOD_skin.c
@@ -922,7 +922,13 @@ static Mesh *subdivide_base(Mesh *orig)
u = e->v1;
radrat = (half_v2(outnode[e->v2].radius) / half_v2(outnode[e->v1].radius));
- radrat = (radrat + 1) / 2;
+ if (isfinite(radrat)) {
+ radrat = (radrat + 1) / 2;
+ }
+ else {
+ /* Happens when skin is scaled to zero. */
+ radrat = 1.0f;
+ }
/* Add vertices and edge segments */
for (j = 0; j < edge_subd[i]; j++, v++, outedge++) {
diff --git a/source/blender/modifiers/intern/MOD_weld.c b/source/blender/modifiers/intern/MOD_weld.c
index e21410ad63d..3bef0ad6bf7 100644
--- a/source/blender/modifiers/intern/MOD_weld.c
+++ b/source/blender/modifiers/intern/MOD_weld.c
@@ -1677,8 +1677,18 @@ static Mesh *weldModifier_doWeld(WeldModifierData *wmd, const ModifierEvalContex
/* Get overlap map. */
/* TODO: For a better performanse use KD-Tree. */
struct BVHTreeFromMesh treedata;
- BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(
- &treedata, mvert, totvert, false, v_mask, v_mask_act, wmd->merge_dist / 2, 2, 6, 0, NULL);
+ BVHTree *bvhtree = bvhtree_from_mesh_verts_ex(&treedata,
+ mvert,
+ totvert,
+ false,
+ v_mask,
+ v_mask_act,
+ wmd->merge_dist / 2,
+ 2,
+ 6,
+ 0,
+ NULL,
+ NULL);
if (v_mask) {
MEM_freeN(v_mask);
diff --git a/source/blender/nodes/shader/nodes/node_shader_output_material.c b/source/blender/nodes/shader/nodes/node_shader_output_material.c
index 4b7bd964052..578262e9f17 100644
--- a/source/blender/nodes/shader/nodes/node_shader_output_material.c
+++ b/source/blender/nodes/shader/nodes/node_shader_output_material.c
@@ -45,9 +45,18 @@ static int node_shader_gpu_output_material(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- GPUNodeLink *outlink;
+ GPUNodeLink *outlink, *alpha_threshold_link;
- GPU_stack_link(mat, node, "node_output_material", in, out, &outlink);
+ Material *ma = GPU_material_get_material(mat);
+ if (ma && ma->blend_method == MA_BM_CLIP) {
+ alpha_threshold_link = GPU_uniform(&ma->alpha_threshold);
+ }
+ else {
+ static float no_alpha_threshold = -1.0f;
+ alpha_threshold_link = GPU_uniform(&no_alpha_threshold);
+ }
+
+ GPU_stack_link(mat, node, "node_output_material", in, out, alpha_threshold_link, &outlink);
GPU_material_output_link(mat, outlink);
return true;
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
index fd4efb1b7ec..0cf4b51f307 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_environment.c
@@ -19,6 +19,8 @@
#include "../node_shader_util.h"
+#include "GPU_draw.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_environment_in[] = {
@@ -56,6 +58,10 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
bNode *node_original = node->original ? node->original : node;
NodeTexImage *tex_original = node_original->storage;
ImageUser *iuser = &tex_original->iuser;
+ eGPUSamplerState sampler = GPU_SAMPLER_REPEAT | GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER;
+ if (GPU_get_mipmap()) {
+ sampler |= GPU_SAMPLER_MIPMAP;
+ }
GPUNodeLink *outalpha;
@@ -72,49 +78,41 @@ static int node_shader_gpu_tex_environment(GPUMaterial *mat,
/* Compute texture coordinate. */
if (tex->projection == SHD_PROJ_EQUIRECTANGULAR) {
- /* To fix pole issue we clamp the v coordinate. The clamp value depends on the filter size. */
- float clamp_size = (ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) ? 1.5 : 0.5;
- GPU_link(mat,
- "node_tex_environment_equirectangular",
- in[0].link,
- GPU_constant(&clamp_size),
- GPU_image(mat, ima, iuser),
- &in[0].link);
+ GPU_link(mat, "node_tex_environment_equirectangular", in[0].link, &in[0].link);
+ /* To fix pole issue we clamp the v coordinate. */
+ sampler &= ~GPU_SAMPLER_REPEAT_T;
+ /* Force the highest mipmap and don't do anisotropic filtering.
+ * This is to fix the artifact caused by derivatives discontinuity. */
+ sampler &= ~(GPU_SAMPLER_MIPMAP | GPU_SAMPLER_ANISO);
}
else {
GPU_link(mat, "node_tex_environment_mirror_ball", in[0].link, &in[0].link);
+ /* Fix pole issue. */
+ sampler &= ~GPU_SAMPLER_REPEAT;
}
- /* Sample texture with correct interpolation. */
+ const char *gpufunc;
+ static const char *names[] = {
+ "node_tex_image_linear",
+ "node_tex_image_cubic",
+ };
+
switch (tex->interpolation) {
case SHD_INTERP_LINEAR:
- /* Force the highest mipmap and don't do anisotropic filtering.
- * This is to fix the artifact caused by derivatives discontinuity. */
- GPU_link(mat,
- "node_tex_image_linear_no_mip",
- in[0].link,
- GPU_image(mat, ima, iuser),
- &out[0].link,
- &outalpha);
+ gpufunc = names[0];
break;
case SHD_INTERP_CLOSEST:
- GPU_link(mat,
- "node_tex_image_nearest",
- in[0].link,
- GPU_image(mat, ima, iuser),
- &out[0].link,
- &outalpha);
+ sampler &= ~(GPU_SAMPLER_FILTER | GPU_SAMPLER_MIPMAP);
+ gpufunc = names[0];
break;
default:
- GPU_link(mat,
- "node_tex_image_cubic",
- in[0].link,
- GPU_image(mat, ima, iuser),
- &out[0].link,
- &outalpha);
+ gpufunc = names[1];
break;
}
+ /* Sample texture with correct interpolation. */
+ GPU_link(mat, gpufunc, in[0].link, GPU_image(mat, ima, iuser, sampler), &out[0].link, &outalpha);
+
if (out[0].hasoutput) {
if (ELEM(ima->alpha_mode, IMA_ALPHA_IGNORE, IMA_ALPHA_CHANNEL_PACKED) ||
IMB_colormanagement_space_name_is_data(ima->colorspace_settings.name)) {
diff --git a/source/blender/nodes/shader/nodes/node_shader_tex_image.c b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
index bfef9341913..cbda72cd228 100644
--- a/source/blender/nodes/shader/nodes/node_shader_tex_image.c
+++ b/source/blender/nodes/shader/nodes/node_shader_tex_image.c
@@ -19,6 +19,8 @@
#include "../node_shader_util.h"
+#include "GPU_draw.h"
+
/* **************** OUTPUT ******************** */
static bNodeSocketTemplate sh_node_tex_image_in[] = {
@@ -57,31 +59,6 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
GPUNodeStack *in,
GPUNodeStack *out)
{
- static const char *names[] = {
- "node_tex_image_linear",
- "node_tex_image_nearest",
- "node_tex_image_cubic",
- "node_tex_image_smart",
- };
- static const char *names_tiled[] = {
- "node_tex_tile_linear",
- "node_tex_tile_nearest",
- "node_tex_tile_cubic",
- "node_tex_tile_smart",
- };
- static const char *names_box[] = {
- "tex_box_sample_linear",
- "tex_box_sample_nearest",
- "tex_box_sample_cubic",
- "tex_box_sample_smart",
- };
- static const char *names_clip[] = {
- "tex_clip_linear",
- "tex_clip_nearest",
- "tex_clip_cubic",
- "tex_clip_smart",
- };
-
Image *ima = (Image *)node->id;
NodeTexImage *tex = node->storage;
@@ -91,26 +68,11 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
NodeTexImage *tex_original = node_original->storage;
ImageUser *iuser = &tex_original->iuser;
- const char *gpu_node_name = (tex->projection == SHD_PROJ_BOX) ? names_box[tex->interpolation] :
- names[tex->interpolation];
- bool do_texco_extend = (tex->extension != SHD_IMAGE_EXTENSION_REPEAT);
- const bool do_texco_clip = (tex->extension == SHD_IMAGE_EXTENSION_CLIP);
-
- if (do_texco_extend && (tex->projection != SHD_PROJ_BOX) &&
- ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART)) {
- gpu_node_name = "node_tex_image_cubic_extend";
- /* We do it inside the sampling function */
- do_texco_extend = false;
- }
-
- GPUNodeLink *norm, *col1, *col2, *col3, *input_coords, *gpu_image;
- GPUNodeLink *vnor, *ob_mat, *blend;
- GPUNodeLink **texco = &in[0].link;
-
if (!ima) {
return GPU_stack_link(mat, node, "node_tex_image_empty", in, out);
}
+ GPUNodeLink **texco = &in[0].link;
if (!*texco) {
*texco = GPU_attribute(mat, CD_MTFACE, "");
node_shader_gpu_bump_tex_coord(mat, node, texco);
@@ -118,88 +80,73 @@ static int node_shader_gpu_tex_image(GPUMaterial *mat,
node_shader_gpu_tex_mapping(mat, node, in, out);
+ eGPUSamplerState sampler_state = 0;
+
+ switch (tex->extension) {
+ case SHD_IMAGE_EXTENSION_REPEAT:
+ sampler_state |= GPU_SAMPLER_REPEAT;
+ break;
+ case SHD_IMAGE_EXTENSION_CLIP:
+ sampler_state |= GPU_SAMPLER_CLAMP_BORDER;
+ break;
+ default:
+ break;
+ }
+
+ if (tex->interpolation != SHD_INTERP_CLOSEST) {
+ sampler_state |= GPU_SAMPLER_ANISO | GPU_SAMPLER_FILTER;
+ sampler_state |= GPU_get_mipmap() ? GPU_SAMPLER_MIPMAP : 0;
+ }
+ const bool use_cubic = ELEM(tex->interpolation, SHD_INTERP_CUBIC, SHD_INTERP_SMART);
+
if (ima->source == IMA_SRC_TILED) {
+ const char *gpu_node_name = use_cubic ? "node_tex_tile_cubic" : "node_tex_tile_linear";
+ GPUNodeLink *gpu_image = GPU_image_tiled(mat, ima, iuser, sampler_state);
+ GPUNodeLink *gpu_image_tile_mapping = GPU_image_tiled_mapping(mat, ima, iuser);
/* UDIM tiles needs a samper2DArray and sampler1DArray for tile mapping. */
- GPU_stack_link(mat,
- node,
- names_tiled[tex->interpolation],
- in,
- out,
- GPU_image_tiled(mat, ima, iuser),
- GPU_image_tiled_mapping(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image, gpu_image_tile_mapping);
}
else {
+ const char *gpu_node_name = use_cubic ? "node_tex_image_cubic" : "node_tex_image_linear";
+
switch (tex->projection) {
- case SHD_PROJ_FLAT:
- if (do_texco_clip) {
- /* This seems redundant, but is required to ensure the texco link
- * is not freed by GPU_link, as it is still needed for GPU_stack_link.
- * Intermediate links like this can only be used once and are then
- * freed immediately, but if we make it the output link of a set_rgb
- * node it will be kept and can be used multiple times. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
- }
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
+ case SHD_PROJ_FLAT: {
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
-
- case SHD_PROJ_BOX:
- vnor = GPU_builtin(GPU_WORLD_NORMAL);
- ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
- blend = GPU_uniform(&tex->projection_blend);
- gpu_image = GPU_image(mat, ima, iuser);
-
+ }
+ case SHD_PROJ_BOX: {
+ gpu_node_name = use_cubic ? "tex_box_sample_cubic" : "tex_box_sample_linear";
+ GPUNodeLink *wnor, *col1, *col2, *col3;
+ GPUNodeLink *vnor = GPU_builtin(GPU_WORLD_NORMAL);
+ GPUNodeLink *ob_mat = GPU_builtin(GPU_OBJECT_MATRIX);
+ GPUNodeLink *blend = GPU_uniform(&tex->projection_blend);
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
/* equivalent to normal_world_to_object */
- GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &norm);
- {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- in[0].link = input_coords;
- }
- GPU_link(
- mat, gpu_node_name, *texco, norm, GPU_image(mat, ima, iuser), &col1, &col2, &col3);
- GPU_stack_link(
- mat, node, "node_tex_image_box", in, out, norm, col1, col2, col3, gpu_image, blend);
+ GPU_link(mat, "normal_transform_transposed_m4v3", vnor, ob_mat, &wnor);
+ GPU_link(mat, gpu_node_name, in[0].link, wnor, gpu_image, &col1, &col2, &col3);
+ GPU_link(mat, "tex_box_blend", wnor, col1, col2, col3, blend, &out[0].link, &out[1].link);
break;
-
- case SHD_PROJ_SPHERE:
+ }
+ case SHD_PROJ_SPHERE: {
+ /* This projection is known to have a derivative discontinuity.
+ * Hide it by turning off mipmapping. */
+ sampler_state &= ~GPU_SAMPLER_MIPMAP;
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
GPU_link(mat, "point_texco_remap_square", *texco, texco);
GPU_link(mat, "point_map_to_sphere", *texco, texco);
- if (do_texco_clip) {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
- }
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
-
- case SHD_PROJ_TUBE:
+ }
+ case SHD_PROJ_TUBE: {
+ /* This projection is known to have a derivative discontinuity.
+ * Hide it by turning off mipmapping. */
+ sampler_state &= ~GPU_SAMPLER_MIPMAP;
+ GPUNodeLink *gpu_image = GPU_image(mat, ima, iuser, sampler_state);
GPU_link(mat, "point_texco_remap_square", *texco, texco);
GPU_link(mat, "point_map_to_tube", *texco, texco);
- if (do_texco_clip) {
- /* See SHD_PROJ_FLAT for explanation. */
- GPU_link(mat, "set_rgb", *texco, texco);
- GPU_link(mat, "set_rgb", *texco, &input_coords);
- }
- if (do_texco_extend) {
- GPU_link(mat, "point_texco_clamp", *texco, GPU_image(mat, ima, iuser), texco);
- }
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser));
+ GPU_stack_link(mat, node, gpu_node_name, in, out, gpu_image);
break;
- }
-
- if (tex->projection != SHD_PROJ_BOX) {
- if (do_texco_clip) {
- gpu_node_name = names_clip[tex->interpolation];
- in[0].link = input_coords;
- GPU_stack_link(mat, node, gpu_node_name, in, out, GPU_image(mat, ima, iuser), out[0].link);
}
}
}
diff --git a/source/blender/python/gpu/gpu_py_shader.c b/source/blender/python/gpu/gpu_py_shader.c
index 38a5629a2cc..165286c3661 100644
--- a/source/blender/python/gpu/gpu_py_shader.c
+++ b/source/blender/python/gpu/gpu_py_shader.c
@@ -78,7 +78,7 @@ static int bpygpu_uniform_location_get(GPUShader *shader,
const char *name,
const char *error_prefix)
{
- int uniform = GPU_shader_get_uniform_ensure(shader, name);
+ int uniform = GPU_shader_get_uniform(shader, name);
if (uniform == -1) {
PyErr_Format(PyExc_ValueError, "%s: uniform %.32s not found", error_prefix, name);
@@ -524,7 +524,7 @@ PyDoc_STRVAR(bpygpu_shader_calc_format_doc,
static PyObject *bpygpu_shader_calc_format(BPyGPUShader *self, PyObject *UNUSED(arg))
{
BPyGPUVertFormat *ret = (BPyGPUVertFormat *)BPyGPUVertFormat_CreatePyObject(NULL);
- GPU_vertformat_from_interface(&ret->fmt, GPU_shader_get_interface(self->shader));
+ GPU_vertformat_from_shader(&ret->fmt, self->shader);
return (PyObject *)ret;
}
diff --git a/source/blender/python/intern/bpy_app_handlers.c b/source/blender/python/intern/bpy_app_handlers.c
index 28498e116df..dde1d13477f 100644
--- a/source/blender/python/intern/bpy_app_handlers.c
+++ b/source/blender/python/intern/bpy_app_handlers.c
@@ -44,8 +44,16 @@ void bpy_app_generic_callback(struct Main *main,
static PyTypeObject BlenderAppCbType;
static PyStructSequence_Field app_cb_info_fields[] = {
- {"frame_change_pre", "on frame change for playback and rendering (before)"},
- {"frame_change_post", "on frame change for playback and rendering (after)"},
+ {"frame_change_pre",
+ "Called after frame change for playback and rendering, before any data is evaluated for the "
+ "new frame. This makes it possible to change data and relations (for example swap an object "
+ "to another mesh) for the new frame. Note that this handler is **not** to be used as 'before "
+ "the frame changes' event. The dependency graph is not available in this handler, as data "
+ "and relations may have been altered and the dependency graph has not yet been updated for "
+ "that."},
+ {"frame_change_post",
+ "Called after frame change for playback and rendering, after the data has been evaluated "
+ "for the new frame."},
{"render_pre", "on render (before)"},
{"render_post", "on render (after)"},
{"render_write", "on writing a render frame (directly after the frame is written)"},
diff --git a/source/blender/python/intern/bpy_rna_callback.c b/source/blender/python/intern/bpy_rna_callback.c
index cc9f5746bba..f9bcb8943f4 100644
--- a/source/blender/python/intern/bpy_rna_callback.c
+++ b/source/blender/python/intern/bpy_rna_callback.c
@@ -324,10 +324,8 @@ PyObject *pyrna_callback_classmethod_add(PyObject *UNUSED(self), PyObject *args)
return NULL;
}
- bContext *C = BPy_GetContext();
- struct wmWindowManager *wm = CTX_wm_manager(C);
handle = WM_paint_cursor_activate(
- wm, params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args);
+ params.space_type, params.region_type, NULL, cb_wm_cursor_draw, (void *)args);
}
else if (RNA_struct_is_a(srna, &RNA_Space)) {
const char *error_prefix = "Space.draw_handler_add";
@@ -424,9 +422,7 @@ PyObject *pyrna_callback_classmethod_remove(PyObject *UNUSED(self), PyObject *ar
args, "OO!:WindowManager.draw_cursor_remove", &cls, &PyCapsule_Type, &py_handle)) {
return NULL;
}
- bContext *C = BPy_GetContext();
- struct wmWindowManager *wm = CTX_wm_manager(C);
- WM_paint_cursor_end(wm, handle);
+ WM_paint_cursor_end(handle);
capsule_clear = true;
}
else if (RNA_struct_is_a(srna, &RNA_Space)) {
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index ffa5bc15876..802780b37f1 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -106,6 +106,17 @@ void WM_reinit_gizmomap_all(struct Main *bmain);
void WM_script_tag_reload(void);
+bool WM_window_find_under_cursor(const wmWindowManager *wm,
+ const wmWindow *win_ignore,
+ const wmWindow *win,
+ const int mval[2],
+ wmWindow **r_win,
+ int r_mval[2]);
+void WM_window_pixel_sample_read(const wmWindowManager *wm,
+ const wmWindow *win,
+ const int pos[2],
+ float r_col[3]);
+
uint *WM_window_pixels_read(struct wmWindowManager *wm, struct wmWindow *win, int r_size[2]);
int WM_window_pixels_x(const struct wmWindow *win);
@@ -198,14 +209,13 @@ void WM_cursor_grab_disable(struct wmWindow *win, const int mouse_ungrab_xy[2]);
void WM_cursor_time(struct wmWindow *win, int nr);
struct wmPaintCursor *WM_paint_cursor_activate(
- struct wmWindowManager *wm,
short space_type,
short region_type,
bool (*poll)(struct bContext *C),
void (*draw)(struct bContext *C, int, int, void *customdata),
void *customdata);
-bool WM_paint_cursor_end(struct wmWindowManager *wm, struct wmPaintCursor *handle);
+bool WM_paint_cursor_end(struct wmPaintCursor *handle);
void WM_paint_cursor_tag_redraw(struct wmWindow *win, struct ARegion *region);
void WM_cursor_warp(struct wmWindow *win, int x, int y);
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 07d7ccf31db..2af68956923 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -150,7 +150,7 @@ void WM_cursor_set(wmWindow *win, int curs)
}
if (win->cursor == curs) {
- return; /* Cursor is already set */
+ return; /* Cursor is already set */
}
win->cursor = curs;
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 4cc9f4ee7d1..fa12d6cf974 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -574,13 +574,13 @@ void wm_draw_region_blend(ARegion *region, int view, bool blend)
alpha = 1.0f;
}
- glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"),
+ glUniform1i(GPU_shader_get_uniform(shader, "image"), 0);
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_icon"),
rect_tex.xmin,
rect_tex.ymin,
rect_tex.xmax,
rect_tex.ymax);
- glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"),
+ glUniform4f(GPU_shader_get_uniform(shader, "rect_geom"),
rect_geo.xmin,
rect_geo.ymin,
rect_geo.xmax,
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index e5f288b1963..53d6df915d6 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -1,4 +1,4 @@
-/*
+/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
@@ -4254,7 +4254,7 @@ static void attach_ndof_data(wmEvent *event, const GHOST_TEventNDOFMotionData *g
/* imperfect but probably usable... draw/enable drags to other windows */
static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *win, wmEvent *event)
{
- int mx = event->x, my = event->y;
+ int mval[2] = {event->x, event->y};
if (wm->windows.first == wm->windows.last) {
return NULL;
@@ -4263,7 +4263,8 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
/* in order to use window size and mouse position (pixels), we have to use a WM function */
/* check if outside, include top window bar... */
- if (mx < 0 || my < 0 || mx > WM_window_pixels_x(win) || my > WM_window_pixels_y(win) + 30) {
+ if (mval[0] < 0 || mval[1] < 0 || mval[0] > WM_window_pixels_x(win) ||
+ mval[1] > WM_window_pixels_y(win) + 30) {
wmWindow *owin;
wmEventHandler *handler;
@@ -4276,25 +4277,10 @@ static wmWindow *wm_event_cursor_other_windows(wmWindowManager *wm, wmWindow *wi
}
}
- /* to desktop space */
- mx += (int)(U.pixelsize * win->posx);
- my += (int)(U.pixelsize * win->posy);
-
- /* check other windows to see if it has mouse inside */
- for (owin = wm->windows.first; owin; owin = owin->next) {
-
- if (owin != win) {
- int posx = (int)(U.pixelsize * owin->posx);
- int posy = (int)(U.pixelsize * owin->posy);
-
- if (mx - posx >= 0 && owin->posy >= 0 && mx - posx <= WM_window_pixels_x(owin) &&
- my - posy <= WM_window_pixels_y(owin)) {
- event->x = mx - (int)(U.pixelsize * owin->posx);
- event->y = my - (int)(U.pixelsize * owin->posy);
-
- return owin;
- }
- }
+ if (WM_window_find_under_cursor(wm, win, win, mval, &owin, mval)) {
+ event->x = mval[0];
+ event->y = mval[1];
+ return owin;
}
}
return NULL;
diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c
index cc81e4f2715..ed1b29d61ce 100644
--- a/source/blender/windowmanager/intern/wm_files.c
+++ b/source/blender/windowmanager/intern/wm_files.c
@@ -141,11 +141,37 @@ static void wm_history_file_free(RecentFile *recent);
static void wm_history_file_update(void);
static void wm_history_file_write(void);
-/* To be able to read files without windows closing, opening, moving
+/* -------------------------------------------------------------------- */
+/** \name Misc Utility Functions
+ * \{ */
+
+void WM_file_tag_modified(void)
+{
+ wmWindowManager *wm = G_MAIN->wm.first;
+ if (wm->file_saved) {
+ wm->file_saved = 0;
+ /* notifier that data changed, for save-over warning or header */
+ WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL);
+ }
+}
+
+bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm)
+{
+ return !wm->file_saved || ED_image_should_save_modified(bmain);
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Window Matching for File Reading
+ * \{ */
+
+/**
+ * To be able to read files without windows closing, opening, moving
* we try to prepare for worst case:
* - active window gets active screen from file
* - restoring the screens from non-active windows
- * Best case is all screens match, in that case they get assigned to proper window
+ * Best case is all screens match, in that case they get assigned to proper window.
*/
static void wm_window_match_init(bContext *C, ListBase *wmlist)
{
@@ -355,6 +381,12 @@ static void wm_window_match_do(bContext *C,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Preferences Initialization & Versioning
+ * \{ */
+
/* in case UserDef was read, we re-initialize all, and do versioning */
static void wm_init_userdef(Main *bmain)
{
@@ -389,6 +421,15 @@ static void wm_init_userdef(Main *bmain)
# define BKE_READ_EXOTIC_OK_OTHER 1 /* other supported formats */
#endif
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Exotic File Formats
+ *
+ * Currently only supports '.blend' files,
+ * we could support registering other file formats and their loaders.
+ * \{ */
+
/* intended to check for non-blender formats but for now it only reads blends */
static int wm_read_exotic(const char *name)
{
@@ -441,6 +482,12 @@ static int wm_read_exotic(const char *name)
return retval;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Blend-File Shared Utilities
+ * \{ */
+
void WM_file_autoexec_init(const char *filepath)
{
if (G.f & G_FLAG_SCRIPT_OVERRIDE_PREF) {
@@ -486,6 +533,24 @@ void wm_file_read_report(bContext *C, Main *bmain)
/**
* Logic shared between #WM_file_read & #wm_homefile_read,
+ * call before loading a file.
+ * \note In the case of #WM_file_read the file may fail to load.
+ * Change here shouldn't cause user-visible changes in that case.
+ */
+static void wm_file_read_pre(bContext *C, bool use_data, bool UNUSED(use_userdef))
+{
+ if (use_data) {
+ BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
+ BLI_timer_on_file_load();
+ }
+
+ /* Always do this as both startup and preferences may have loaded in many font's
+ * at a different zoom level to the file being loaded. */
+ UI_view2d_zoom_cache_reset();
+}
+
+/**
+ * Logic shared between #WM_file_read & #wm_homefile_read,
* updates to make after reading a file.
*/
static void wm_file_read_post(bContext *C,
@@ -510,12 +575,16 @@ static void wm_file_read_post(bContext *C,
if (is_startup_file) {
/* possible python hasn't been initialized */
if (CTX_py_init_get(C)) {
- if (reset_app_template) {
+ bool reset_all = use_userdef;
+ if (use_userdef || reset_app_template) {
/* Only run when we have a template path found. */
if (BKE_appdir_app_template_any()) {
BPY_execute_string(
C, (const char *[]){"bl_app_template_utils", NULL}, "bl_app_template_utils.reset()");
+ reset_all = true;
}
+ }
+ if (reset_all) {
/* sync addons, these may have changed from the defaults */
BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
}
@@ -601,21 +670,27 @@ static void wm_file_read_post(bContext *C,
}
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Main Blend-File API
+ * \{ */
+
bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
{
/* assume automated tasks with background, don't write recent file list */
const bool do_history = (G.background == false) && (CTX_wm_manager(C)->op_undo_depth == 0);
bool success = false;
+ const bool use_data = true;
+ const bool use_userdef = false;
+
/* so we can get the error message */
errno = 0;
WM_cursor_wait(1);
- BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
- BLI_timer_on_file_load();
-
- UI_view2d_zoom_cache_reset();
+ wm_file_read_pre(C, use_data, use_userdef);
/* first try to append data from exotic file formats... */
/* it throws error box when file doesn't exist and returns -1 */
@@ -675,8 +750,6 @@ bool WM_file_read(bContext *C, const char *filepath, ReportList *reports)
}
}
- const bool use_data = true;
- const bool use_userdef = false;
wm_file_read_post(C, false, false, use_data, use_userdef, false);
}
#if 0
@@ -746,6 +819,12 @@ const char *WM_init_state_app_template_get(void)
return wm_init_state_app_template.override ? wm_init_state_app_template.app_template : NULL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Startup & Preferences Blend-File API
+ * \{ */
+
/**
* Called on startup, (context entirely filled with NULLs)
* or called for 'New File' both startup.blend and userpref.blend are checked.
@@ -802,6 +881,23 @@ void wm_homefile_read(bContext *C,
* or use app-template startup.blend which the user hasn't saved. */
bool is_factory_startup = true;
+ const char *app_template = NULL;
+ bool update_defaults = false;
+
+ if (filepath_startup_override != NULL) {
+ /* pass */
+ }
+ else if (app_template_override) {
+ /* This may be clearing the current template by setting to an empty string. */
+ app_template = app_template_override;
+ }
+ else if (!use_factory_settings && U.app_template[0]) {
+ app_template = U.app_template;
+ }
+
+ const bool reset_app_template = ((!app_template && U.app_template[0]) ||
+ (app_template && !STREQ(app_template, U.app_template)));
+
/* options exclude eachother */
BLI_assert((use_factory_settings && filepath_startup_override) == 0);
@@ -809,18 +905,30 @@ void wm_homefile_read(bContext *C,
SET_FLAG_FROM_TEST(G.f, (U.flag & USER_SCRIPT_AUTOEXEC_DISABLE) == 0, G_FLAG_SCRIPT_AUTOEXEC);
}
- if (use_data) {
- BKE_callback_exec_null(CTX_data_main(C), BKE_CB_EVT_LOAD_PRE);
- BLI_timer_on_file_load();
+ if (use_userdef || reset_app_template) {
+#ifdef WITH_PYTHON
+ /* This only runs once Blender has already started. */
+ if (CTX_py_init_get(C)) {
+ /* This is restored by 'wm_file_read_post', disable before loading any preferences
+ * so an add-on can read their own preferences when un-registering,
+ * and use new preferences if/when re-registering, see T67577.
+ *
+ * Note that this fits into 'wm_file_read_pre' function but gets messy
+ * since we need to know if 'reset_app_template' is true. */
+ BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.disable_all()");
+ }
+#endif /* WITH_PYTHON */
+ }
+
+ wm_file_read_pre(C, use_data, use_userdef);
+ if (use_data) {
G.relbase_valid = 0;
/* put aside screens to match with persistent windows later */
wm_window_match_init(C, &wmbase);
}
- UI_view2d_zoom_cache_reset();
-
filepath_startup[0] = '\0';
filepath_userdef[0] = '\0';
app_template_system[0] = '\0';
@@ -861,28 +969,6 @@ void wm_homefile_read(bContext *C,
}
}
- const char *app_template = NULL;
- bool update_defaults = false;
- bool reset_app_template = false;
-
- if (filepath_startup_override != NULL) {
- /* pass */
- }
- else if (app_template_override) {
- /* This may be clearing the current template by setting to an empty string. */
- app_template = app_template_override;
- }
- else if (!use_factory_settings && U.app_template[0]) {
- app_template = U.app_template;
- }
-
- if ((!app_template && U.app_template[0]) ||
- (app_template && !STREQ(app_template, U.app_template))) {
- /* Always load UI when switching to another template. */
- G.fileflags &= ~G_FILE_NO_UI;
- reset_app_template = true;
- }
-
if ((app_template != NULL) && (app_template[0] != '\0')) {
if (!BKE_appdir_app_template_id_search(
app_template, app_template_system, sizeof(app_template_system))) {
@@ -1028,6 +1114,11 @@ void wm_homefile_read(bContext *C,
* Screws up autosaves otherwise can remove this eventually,
* only in a 2.53 and older, now its not written. */
G.fileflags &= ~G_FILE_RELATIVE_REMAP;
+
+ if (reset_app_template) {
+ /* Always load UI when switching to another template. */
+ G.fileflags &= ~G_FILE_NO_UI;
+ }
}
bmain = CTX_data_main(C);
@@ -1035,7 +1126,6 @@ void wm_homefile_read(bContext *C,
if (use_userdef) {
/* check userdef before open window, keymaps etc */
wm_init_userdef(bmain);
- reset_app_template = true;
}
if (use_data) {
@@ -1070,7 +1160,7 @@ void wm_homefile_read(bContext *C,
}
/* -------------------------------------------------------------------- */
-/** \name WM History File API
+/** \name Blend-File History API
* \{ */
void wm_history_file_read(void)
@@ -1199,7 +1289,7 @@ static void wm_history_file_update(void)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Save Main .blend File (internal)
+/** \name Save Main Blend-File (internal)
* \{ */
/* screen can be NULL */
@@ -1623,18 +1713,8 @@ void wm_open_init_use_scripts(wmOperator *op, bool use_prefs)
/** \} */
-void WM_file_tag_modified(void)
-{
- wmWindowManager *wm = G_MAIN->wm.first;
- if (wm->file_saved) {
- wm->file_saved = 0;
- /* notifier that data changed, for save-over warning or header */
- WM_main_add_notifier(NC_WM | ND_DATACHANGED, NULL);
- }
-}
-
/* -------------------------------------------------------------------- */
-/** \name Preferences/startup save & load.
+/** \name Startup File Save Operator
* \{ */
/**
@@ -1699,48 +1779,11 @@ void WM_OT_save_homefile(wmOperatorType *ot)
ot->exec = wm_homefile_write_exec;
}
-static int wm_userpref_autoexec_add_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
-{
- bPathCompare *path_cmp = MEM_callocN(sizeof(bPathCompare), "bPathCompare");
- BLI_addtail(&U.autoexec_paths, path_cmp);
- U.runtime.is_dirty = true;
- return OPERATOR_FINISHED;
-}
-
-void WM_OT_userpref_autoexec_path_add(wmOperatorType *ot)
-{
- ot->name = "Add Autoexec Path";
- ot->idname = "WM_OT_userpref_autoexec_path_add";
- ot->description = "Add path to exclude from autoexecution";
-
- ot->exec = wm_userpref_autoexec_add_exec;
-
- ot->flag = OPTYPE_INTERNAL;
-}
-
-static int wm_userpref_autoexec_remove_exec(bContext *UNUSED(C), wmOperator *op)
-{
- const int index = RNA_int_get(op->ptr, "index");
- bPathCompare *path_cmp = BLI_findlink(&U.autoexec_paths, index);
- if (path_cmp) {
- BLI_freelinkN(&U.autoexec_paths, path_cmp);
- U.runtime.is_dirty = true;
- }
- return OPERATOR_FINISHED;
-}
-
-void WM_OT_userpref_autoexec_path_remove(wmOperatorType *ot)
-{
- ot->name = "Remove Autoexec Path";
- ot->idname = "WM_OT_userpref_autoexec_path_remove";
- ot->description = "Remove path to exclude from autoexecution";
-
- ot->exec = wm_userpref_autoexec_remove_exec;
-
- ot->flag = OPTYPE_INTERNAL;
+/** \} */
- RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
-}
+/* -------------------------------------------------------------------- */
+/** \name Write Preferences Operator
+ * \{ */
/* Only save the prefs block. operator entry */
static int wm_userpref_write_exec(bContext *C, wmOperator *op)
@@ -1765,6 +1808,12 @@ void WM_OT_save_userpref(wmOperatorType *ot)
ot->exec = wm_userpref_write_exec;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Preferences Operator
+ * \{ */
+
/**
* When reading preferences, there are some exceptions for values which are reset.
*/
@@ -1828,10 +1877,6 @@ static void wm_userpref_update_when_changed(bContext *C,
rna_struct_update_when_changed(C, bmain, &ptr_a, &ptr_b);
-#ifdef WITH_PYTHON
- BPY_execute_string(C, (const char *[]){"addon_utils", NULL}, "addon_utils.reset_all()");
-#endif
-
WM_reinit_gizmomap_all(bmain);
WM_keyconfig_reload(C);
@@ -1897,6 +1942,12 @@ void WM_OT_read_factory_userpref(wmOperatorType *ot)
ot->exec = wm_userpref_read_exec;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read File History Operator
+ * \{ */
+
static int wm_history_file_read_exec(bContext *UNUSED(C), wmOperator *UNUSED(op))
{
ED_file_read_bookmarks();
@@ -1917,6 +1968,14 @@ void WM_OT_read_history(wmOperatorType *ot)
ot->flag = OPTYPE_INTERNAL;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Read Startup & Preferences Operator
+ *
+ * Both #WM_OT_read_homefile & #WM_OT_read_factory_settings.
+ * \{ */
+
static int wm_homefile_read_exec(bContext *C, wmOperator *op)
{
const bool use_factory_settings = (STREQ(op->type->idname, "WM_OT_read_factory_settings"));
@@ -2442,7 +2501,7 @@ void WM_OT_revert_mainfile(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Recover last session & auto-save.
+/** \name Recover Last Session Operator
* \{ */
void WM_recover_last_session(bContext *C, ReportList *reports)
@@ -2486,6 +2545,12 @@ void WM_OT_recover_last_session(wmOperatorType *ot)
ot->exec = wm_recover_last_session_exec;
}
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Auto-Save Main .blend File Operator
+ * \{ */
+
static int wm_recover_auto_save_exec(bContext *C, wmOperator *op)
{
char filepath[FILE_MAX];
@@ -2540,6 +2605,8 @@ void WM_OT_recover_auto_save(wmOperatorType *ot)
/* -------------------------------------------------------------------- */
/** \name Save Main .blend File Operator
+ *
+ * Both #WM_OT_save_as_mainfile & #WM_OT_save_mainfile.
* \{ */
static void wm_filepath_default(char *filepath)
@@ -2766,7 +2833,7 @@ void WM_OT_save_mainfile(wmOperatorType *ot)
/** \} */
/* -------------------------------------------------------------------- */
-/** \name Auto-execution of scripts warning popup
+/** \name Auto Script Execution Warning Dialog
* \{ */
static void wm_block_autorun_warning_ignore(bContext *C, void *arg_block, void *UNUSED(arg))
@@ -2968,8 +3035,11 @@ void wm_test_autorun_warning(bContext *C)
}
}
-/* Close File Dialog
- *************************************/
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Close File Dialog
+ * \{ */
static char save_images_when_file_is_closed = true;
@@ -3235,9 +3305,4 @@ void wm_close_file_dialog(bContext *C, wmGenericCallback *post_action)
}
}
-bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm)
-{
- return !wm->file_saved || ED_image_should_save_modified(bmain);
-}
-
/** \} */
diff --git a/source/blender/windowmanager/intern/wm_gesture.c b/source/blender/windowmanager/intern/wm_gesture.c
index 9aa401722b7..6b2a74138c9 100644
--- a/source/blender/windowmanager/intern/wm_gesture.c
+++ b/source/blender/windowmanager/intern/wm_gesture.c
@@ -365,7 +365,7 @@ static void draw_filled_lasso(wmGesture *gt)
IMMDrawPixelsTexState state = immDrawPixelsTexSetup(GPU_SHADER_2D_IMAGE_SHUFFLE_COLOR);
GPU_shader_bind(state.shader);
GPU_shader_uniform_vector(
- state.shader, GPU_shader_get_uniform_ensure(state.shader, "shuffle"), 4, 1, red);
+ state.shader, GPU_shader_get_uniform(state.shader, "shuffle"), 4, 1, red);
immDrawPixelsTex(&state,
rect.xmin,
diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c
index fc3f0c87b69..001acc459c2 100644
--- a/source/blender/windowmanager/intern/wm_init_exit.c
+++ b/source/blender/windowmanager/intern/wm_init_exit.c
@@ -187,7 +187,7 @@ void WM_init_opengl(Main *bmain)
GPU_init();
GPU_set_mipmap(bmain, true);
GPU_set_linear_mipmap(true);
- GPU_set_anisotropic(bmain, U.anisotropic_filter);
+ GPU_set_anisotropic(U.anisotropic_filter);
GPU_pass_cache_init();
diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index 39811d67b9a..f99f47bc3ad 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -2059,13 +2059,14 @@ static void WM_OT_console_toggle(wmOperatorType *ot)
*
* \{ */
-wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm,
- short space_type,
+wmPaintCursor *WM_paint_cursor_activate(short space_type,
short region_type,
bool (*poll)(bContext *C),
wmPaintCursorDraw draw,
void *customdata)
{
+ wmWindowManager *wm = G_MAIN->wm.first;
+
wmPaintCursor *pc = MEM_callocN(sizeof(wmPaintCursor), "paint cursor");
BLI_addtail(&wm->paintcursors, pc);
@@ -2080,11 +2081,10 @@ wmPaintCursor *WM_paint_cursor_activate(wmWindowManager *wm,
return pc;
}
-bool WM_paint_cursor_end(wmWindowManager *wm, wmPaintCursor *handle)
+bool WM_paint_cursor_end(wmPaintCursor *handle)
{
- wmPaintCursor *pc;
-
- for (pc = wm->paintcursors.first; pc; pc = pc->next) {
+ wmWindowManager *wm = G_MAIN->wm.first;
+ for (wmPaintCursor *pc = wm->paintcursors.first; pc; pc = pc->next) {
if (pc == (wmPaintCursor *)handle) {
BLI_remlink(&wm->paintcursors, pc);
MEM_freeN(pc);
@@ -2759,7 +2759,7 @@ static int radial_control_invoke(bContext *C, wmOperator *op, const wmEvent *eve
/* add radial control paint cursor */
rc->cursor = WM_paint_cursor_activate(
- wm, SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc);
+ SPACE_TYPE_ANY, RGN_TYPE_ANY, op->type->poll, radial_control_paint_cursor, rc);
WM_event_add_modal_handler(C, op);
@@ -2793,7 +2793,7 @@ static void radial_control_cancel(bContext *C, wmOperator *op)
ED_area_status_text(area, NULL);
- WM_paint_cursor_end(wm, rc->cursor);
+ WM_paint_cursor_end(rc->cursor);
/* restore original paint cursors */
wm->paintcursors = rc->orig_paintcursors;
@@ -3778,8 +3778,6 @@ void wm_operatortypes_register(void)
WM_operatortype_append(WM_OT_save_userpref);
WM_operatortype_append(WM_OT_read_userpref);
WM_operatortype_append(WM_OT_read_factory_userpref);
- WM_operatortype_append(WM_OT_userpref_autoexec_path_add);
- WM_operatortype_append(WM_OT_userpref_autoexec_path_remove);
WM_operatortype_append(WM_OT_window_fullscreen_toggle);
WM_operatortype_append(WM_OT_quit_blender);
WM_operatortype_append(WM_OT_open_mainfile);
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 02b50af0ac3..1ba22652157 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -1984,6 +1984,90 @@ bool wm_window_get_swap_interval(wmWindow *win, int *intervalOut)
/** \} */
/* -------------------------------------------------------------------- */
+/** \name Find Window Utility
+ *
+ * \{ */
+static void wm_window_desktop_pos_get(const wmWindow *win,
+ const int screen_pos[2],
+ int r_desk_pos[2])
+{
+ /* To desktop space. */
+ r_desk_pos[0] = screen_pos[0] + (int)(U.pixelsize * win->posx);
+ r_desk_pos[1] = screen_pos[1] + (int)(U.pixelsize * win->posy);
+}
+
+static void wm_window_screen_pos_get(const wmWindow *win,
+ const int desktop_pos[2],
+ int r_scr_pos[2])
+{
+ /* To window space. */
+ r_scr_pos[0] = desktop_pos[0] - (int)(U.pixelsize * win->posx);
+ r_scr_pos[1] = desktop_pos[1] - (int)(U.pixelsize * win->posy);
+}
+
+bool WM_window_find_under_cursor(const wmWindowManager *wm,
+ const wmWindow *win_ignore,
+ const wmWindow *win,
+ const int mval[2],
+ wmWindow **r_win,
+ int r_mval[2])
+{
+ int desk_pos[2];
+ wm_window_desktop_pos_get(win, mval, desk_pos);
+
+ /* TODO: This should follow the order of the activated windows.
+ * The current solution is imperfect but usable in most cases. */
+ LISTBASE_FOREACH (wmWindow *, win_iter, &wm->windows) {
+ if (win_iter == win_ignore) {
+ continue;
+ }
+
+ if (win_iter->windowstate == GHOST_kWindowStateMinimized) {
+ continue;
+ }
+
+ int scr_pos[2];
+ wm_window_screen_pos_get(win_iter, desk_pos, scr_pos);
+
+ if (scr_pos[0] >= 0 && win_iter->posy >= 0 && scr_pos[0] <= WM_window_pixels_x(win_iter) &&
+ scr_pos[1] <= WM_window_pixels_y(win_iter)) {
+
+ *r_win = win_iter;
+ copy_v2_v2_int(r_mval, scr_pos);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void WM_window_pixel_sample_read(const wmWindowManager *wm,
+ const wmWindow *win,
+ const int pos[2],
+ float r_col[3])
+{
+ bool setup_context = wm->windrawable != win;
+
+ if (setup_context) {
+ GHOST_ActivateWindowDrawingContext(win->ghostwin);
+ GPU_context_active_set(win->gpuctx);
+ }
+
+ glReadBuffer(GL_FRONT);
+ glReadPixels(pos[0], pos[1], 1, 1, GL_RGB, GL_FLOAT, r_col);
+ glReadBuffer(GL_BACK);
+
+ if (setup_context) {
+ if (wm->windrawable) {
+ GHOST_ActivateWindowDrawingContext(wm->windrawable->ghostwin);
+ GPU_context_active_set(wm->windrawable->gpuctx);
+ }
+ }
+}
+
+/** \} */
+
+/* -------------------------------------------------------------------- */
/** \name Window Screen Shot Utility
*
* Include here since it can involve low level buffer switching.
diff --git a/source/blender/windowmanager/wm_files.h b/source/blender/windowmanager/wm_files.h
index e081742b904..42eab35cdb9 100644
--- a/source/blender/windowmanager/wm_files.h
+++ b/source/blender/windowmanager/wm_files.h
@@ -45,8 +45,6 @@ void wm_close_file_dialog(bContext *C, struct wmGenericCallback *post_action);
bool wm_file_or_image_is_modified(const Main *bmain, const wmWindowManager *wm);
void WM_OT_save_homefile(struct wmOperatorType *ot);
-void WM_OT_userpref_autoexec_path_add(struct wmOperatorType *ot);
-void WM_OT_userpref_autoexec_path_remove(struct wmOperatorType *ot);
void WM_OT_save_userpref(struct wmOperatorType *ot);
void WM_OT_read_userpref(struct wmOperatorType *ot);
void WM_OT_read_factory_userpref(struct wmOperatorType *ot);
diff --git a/source/tools b/source/tools
-Subproject 8a36c2833db48ed78c436ee19534ce5cf3b2eee
+Subproject 5cf2fc3e5dc28025394b57d8743401295528f31