From ff8cd484181fb6c6ee03ebd10433cdd176b1c323 Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Thu, 8 Sep 2022 20:23:02 +0200 Subject: Fix T100833: Cycles UDIM baking broken after recent changes --- intern/cycles/blender/session.cpp | 2 +- intern/cycles/blender/session.h | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/intern/cycles/blender/session.cpp b/intern/cycles/blender/session.cpp index 321771b67a5..1b7aa38efb4 100644 --- a/intern/cycles/blender/session.cpp +++ b/intern/cycles/blender/session.cpp @@ -704,7 +704,7 @@ void BlenderSession::bake(BL::Depsgraph &b_depsgraph_, buffer_params.window_width = bake_width; buffer_params.window_height = bake_height; /* Unique layer name for multi-image baking. */ - buffer_params.layer = string_printf("bake_%d\n", (int)full_buffer_files_.size()); + buffer_params.layer = string_printf("bake_%d\n", bake_id++); /* Update session. */ session->reset(session_params, buffer_params); diff --git a/intern/cycles/blender/session.h b/intern/cycles/blender/session.h index f9a5b6faf7e..ceca86016b8 100644 --- a/intern/cycles/blender/session.h +++ b/intern/cycles/blender/session.h @@ -146,6 +146,8 @@ class BlenderSession { BlenderDisplayDriver *display_driver_ = nullptr; vector full_buffer_files_; + + int bake_id = 0; }; CCL_NAMESPACE_END -- cgit v1.2.3 From 4a71765f9a41d6e13b36a53b121338bc373887ac Mon Sep 17 00:00:00 2001 From: Dominik Fill Date: Thu, 8 Sep 2022 17:03:54 -0500 Subject: Fix T100521: Nodes added with link drag search not added to frame Use macro NODE_OT_translate_attach for attaching node created through link-drag-search to frame, as suggested by Leon Schittek (@lone_noel) in D15888. Differential Revision: https://developer.blender.org/D15920 --- source/blender/editors/space_node/link_drag_search.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/editors/space_node/link_drag_search.cc b/source/blender/editors/space_node/link_drag_search.cc index 21d5d8d7d26..a4be0a65230 100644 --- a/source/blender/editors/space_node/link_drag_search.cc +++ b/source/blender/editors/space_node/link_drag_search.cc @@ -227,7 +227,7 @@ static void link_drag_search_exec_fn(bContext *C, void *arg1, void *arg2) ED_node_tree_propagate_change(C, &bmain, snode.edittree); /* Start translation operator with the new node. */ - wmOperatorType *ot = WM_operatortype_find("TRANSFORM_OT_translate", true); + wmOperatorType *ot = WM_operatortype_find("NODE_OT_translate_attach", true); BLI_assert(ot); PointerRNA ptr; WM_operator_properties_create_ptr(&ptr, ot); -- cgit v1.2.3 From 81558783e40394c2c60f61626eb6814f17128503 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 10:25:35 +1000 Subject: Python: install "bpy" as a package WITH_PYTHON_MODULE Building WITH_PYTHON_MODULE was creating a "bpy" module that required Blenders data-files to be located in the module search path too. This mean that a typical installation on Linux would create: - `/usr/lib/python3.10/site-packages/bpy.so` - `/usr/lib/python3.10/site-packages/3.4` (containing `scripts` & `datafiles`). The new behavior creates: - `/usr/lib/python3.10/site-packages/bpy/__init__.so` - `/usr/lib/python3.10/site-packages/bpy/3.4` With the advantage that the "bpy" directory is the self contained Python module. No changes are needed for the module loading logic as the mechanism to swap in blend internal Python "bpy" module (defined in `release/scripts/modules/bpy/__init__.py`) works the same in both instances. Thanks to Brecht for macOS support. Reviewed by brecht Ref D15911 --- source/blender/blenkernel/CMakeLists.txt | 4 +++ source/blender/blenkernel/intern/appdir.c | 2 +- source/creator/CMakeLists.txt | 55 ++++++++++++++++++++----------- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/source/blender/blenkernel/CMakeLists.txt b/source/blender/blenkernel/CMakeLists.txt index 9521da8417e..b982c69a378 100644 --- a/source/blender/blenkernel/CMakeLists.txt +++ b/source/blender/blenkernel/CMakeLists.txt @@ -659,6 +659,10 @@ if(WITH_PYTHON) ) add_definitions(-DWITH_PYTHON) + if(WITH_PYTHON_MODULE) + add_definitions(-DWITH_PYTHON_MODULE) + endif() + if(WITH_PYTHON_SAFETY) add_definitions(-DWITH_PYTHON_SAFETY) endif() diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index c19afdb4fb8..4bd8cfd5f47 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -374,7 +374,7 @@ static bool get_path_local_ex(char *targetpath, /* Try `{g_app.program_dirname}/2.xx/{folder_name}` the default directory * for a portable distribution. See `WITH_INSTALL_PORTABLE` build-option. */ const char *path_base = g_app.program_dirname; -#ifdef __APPLE__ +#if defined(__APPLE__) && !defined(WITH_PYTHON_MODULE) /* Due new code-sign situation in OSX > 10.9.5 * we must move the blender_version dir with contents to Resources. */ char osx_resourses[FILE_MAX]; diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 0e9c3a853aa..a5afcefbc29 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -247,19 +247,29 @@ add_cc_flags_custom_test(blender) if(WITH_PYTHON_MODULE) add_definitions(-DWITH_PYTHON_MODULE) - # creates ./bin/bpy.so which can be imported as a python module. + # Creates `./bpy/__init__.so` which can be imported as a python module. # # note that 'SHARED' works on Linux and Windows, # but not OSX which _must_ be 'MODULE' add_library(blender MODULE ${SRC}) + + + get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) + if(GENERATOR_IS_MULTI_CONFIG) + set(BPY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/$/bpy) + else() + set(BPY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/bpy) + endif() + set_target_properties( blender PROPERTIES PREFIX "" - OUTPUT_NAME bpy - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin # only needed on windows + OUTPUT_NAME __init__ + LIBRARY_OUTPUT_DIRECTORY ${BPY_OUTPUT_DIRECTORY} + RUNTIME_OUTPUT_DIRECTORY ${BPY_OUTPUT_DIRECTORY} ) + unset(BPY_OUTPUT_DIRECTORY) if(APPLE) set_target_properties(blender PROPERTIES MACOSX_BUNDLE TRUE) @@ -306,13 +316,13 @@ set(BLENDER_TEXT_FILES if(UNIX AND NOT APPLE) if(WITH_PYTHON_MODULE) if(WITH_INSTALL_PORTABLE) - set(TARGETDIR_BPY .) - set(TARGETDIR_VER ${BLENDER_VERSION}) - set(TARGETDIR_LIB lib) + set(TARGETDIR_BPY bpy) + set(TARGETDIR_VER bpy/${BLENDER_VERSION}) + set(TARGETDIR_LIB bpy/lib) else() - set(TARGETDIR_BPY ${PYTHON_SITE_PACKAGES}) - set(TARGETDIR_VER ${PYTHON_SITE_PACKAGES}/${BLENDER_VERSION}) - set(TARGETDIR_LIB ${PYTHON_SITE_PACKAGES}/lib) + set(TARGETDIR_BPY ${PYTHON_SITE_PACKAGES}/bpy) + set(TARGETDIR_VER ${PYTHON_SITE_PACKAGES}/bpy/${BLENDER_VERSION}) + set(TARGETDIR_LIB ${PYTHON_SITE_PACKAGES}/bpy/lib) endif() else() if(WITH_INSTALL_PORTABLE) @@ -326,21 +336,28 @@ if(UNIX AND NOT APPLE) endif() elseif(WIN32) - set(TARGETDIR_VER ${BLENDER_VERSION}) - set(TARGETDIR_TEXT .) - set(TARGETDIR_LIB .) - + if(WITH_PYTHON_MODULE) + set(TARGETDIR_BPY $) + set(TARGETDIR_VER $/${BLENDER_VERSION}) + # Important the DLL's are next to `__init__.pyd` otherwise it won't load. + set(TARGETDIR_LIB $) + else() + set(TARGETDIR_VER ${BLENDER_VERSION}) + set(TARGETDIR_TEXT .) + set(TARGETDIR_LIB .) + endif() elseif(APPLE) if(WITH_PYTHON_MODULE) if(WITH_INSTALL_PORTABLE) - set(TARGETDIR_VER $/../Resources/${BLENDER_VERSION}) - set(TARGETDIR_LIB lib) + set(TARGETDIR_BPY bpy) + set(TARGETDIR_VER bpy/${BLENDER_VERSION}) + set(TARGETDIR_LIB bpy/lib) else() # Paths defined in terms of site-packages since the site-packages # directory can be a symlink (brew for example). - set(TARGETDIR_BPY ${PYTHON_LIBPATH}/site-packages) - set(TARGETDIR_VER ${TARGETDIR_BPY}/../Resources/${BLENDER_VERSION}) - set(TARGETDIR_LIB ${TARGETDIR_BPY}/lib) + set(TARGETDIR_BPY ${PYTHON_LIBPATH}/site-packages/bpy) + set(TARGETDIR_VER ${PYTHON_LIBPATH}/site-packages/bpy/${BLENDER_VERSION}) + set(TARGETDIR_LIB ${PYTHON_LIBPATH}/site-packages/bpy/lib) endif() else() set(TARGETDIR_VER Blender.app/Contents/Resources/${BLENDER_VERSION}) -- cgit v1.2.3 From fad7a30de31977dee8c090dc196c796e17d2fcde Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 11:09:01 +1000 Subject: Cleanup: comments, spelling, line length for creator's CMake file --- source/creator/CMakeLists.txt | 221 +++++++++++++++++++++++------------------- 1 file changed, 119 insertions(+), 102 deletions(-) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index a5afcefbc29..2aa534d55eb 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -26,9 +26,8 @@ if(HAVE_FEENABLEEXCEPT) endif() if(WITH_TBB) - # Force TBB libraries to be in front of MKL (part of OpenImageDenoise), so - # that it is initialized before MKL and static library initialization order - # issues are avoided. + # Force TBB libraries to be in front of MKL (part of `OpenImageDenoise`), so + # that it is initialized before MKL and static library initialization order issues are avoided. # # This isn't fully robust but seems to work. list(INSERT LIB 0 ${TBB_LIBRARIES}) @@ -58,7 +57,7 @@ endif() if(WITH_TBB) blender_include_dirs(${TBB_INCLUDE_DIRS}) if(WIN32) - # For pragma that links tbbmalloc_proxy.lib + # For `pragma` that links `tbbmalloc_proxy.lib`. link_directories(${LIBDIR}/tbb/lib) endif() endif() @@ -108,7 +107,7 @@ if(WITH_OPENCOLORIO) add_definitions(-DWITH_OCIO) endif() -# Setup the exe sources and buildinfo +# Setup the EXE sources and `buildinfo`. set(SRC creator.c creator_args.c @@ -117,7 +116,7 @@ set(SRC creator_intern.h ) -# MSVC 2010 gives linking errors with the manifest +# MSVC 2010 gives linking errors with the manifest. if(WIN32 AND NOT UNIX) add_definitions( -DBLEN_VER_RC_STR="${BLENDER_VERSION}" @@ -173,19 +172,20 @@ if(WITH_BUILDINFO) unset(BUILD_SYSTEM) # -------------------------------------------------------------------------- - # write header for values that change each build - # note, generated file is in build dir's source/creator - # except when used as an include path. + # Write header for values that change each build + # + # NOTE: generated file is in build directory `source/creator` + # except when used as an include path. add_definitions(-DWITH_BUILDINFO_HEADER) - # include the output directory, where the buildinfo.h file is generated + # Include the output directory, where the `buildinfo.h` file is generated. include_directories(${CMAKE_CURRENT_BINARY_DIR}) - # XXX, ${buildinfo_h_fake} is used here, + # XXX: `${buildinfo_h_fake}` is used here, # because we rely on that file being detected as missing - # every build so that the real header "buildinfo.h" is updated. + # every build so that the real header `buildinfo.h` is updated. # # Keep this until we find a better way to resolve! @@ -196,11 +196,12 @@ if(WITH_BUILDINFO) message(FATAL_ERROR "File \"${buildinfo_h_fake}\" found, this should never be created, remove!") endif() - # From the cmake documentation "If the output of the custom command is not actually created as a + # From the CMAKE documentation "If the output of the custom command is not actually created as a # file on disk it should be marked with the SYMBOLIC source file property." # - # Not doing this leads to build warnings for the not generated file on windows when using msbuild - SET_SOURCE_FILES_PROPERTIES(${buildinfo_h_fake} PROPERTIES SYMBOLIC TRUE) + # Not doing this leads to build warnings for the not generated file on + # MS-Windows when using `msbuild`. + set_source_files_properties(${buildinfo_h_fake} PROPERTIES SYMBOLIC TRUE) # a custom target that is always built add_custom_target( @@ -208,19 +209,19 @@ if(WITH_BUILDINFO) DEPENDS ${buildinfo_h_fake} ) - # creates buildinfo.h using cmake script + # Creates `buildinfo.h` using CMAKE script. add_custom_command( OUTPUT ${buildinfo_h_fake} # ensure we always run ${buildinfo_h_real} COMMAND ${CMAKE_COMMAND} -DSOURCE_DIR=${CMAKE_SOURCE_DIR} - # overrides only used when non-empty strings + # Overrides only used when non-empty strings. -DBUILD_DATE=${BUILDINFO_OVERRIDE_DATE} -DBUILD_TIME=${BUILDINFO_OVERRIDE_TIME} -P ${CMAKE_SOURCE_DIR}/build_files/cmake/buildinfo.cmake) - # buildinfo.h is a generated file + # `buildinfo.h` is a generated file. set_source_files_properties( ${buildinfo_h_real} PROPERTIES GENERATED TRUE @@ -229,7 +230,7 @@ if(WITH_BUILDINFO) unset(buildinfo_h_real) unset(buildinfo_h_fake) - # add deps below, after adding blender + # Add dependencies below, after adding Blender # -------------- done with header values. list(APPEND SRC @@ -247,10 +248,9 @@ add_cc_flags_custom_test(blender) if(WITH_PYTHON_MODULE) add_definitions(-DWITH_PYTHON_MODULE) - # Creates `./bpy/__init__.so` which can be imported as a python module. + # Creates `./bpy/__init__.so` which can be imported as a Python module. # - # note that 'SHARED' works on Linux and Windows, - # but not OSX which _must_ be 'MODULE' + # Note that 'SHARED' works on Linux and Windows, but not MACOS which _must_ be 'MODULE'. add_library(blender MODULE ${SRC}) @@ -276,7 +276,7 @@ if(WITH_PYTHON_MODULE) endif() if(WIN32) - # python modules use this + # Python modules use this. set_target_properties( blender PROPERTIES @@ -298,20 +298,22 @@ else() endif() if(WITH_BUILDINFO) - # explicitly say that the executable depends on the buildinfo + # Explicitly say that the executable depends on the `buildinfo`. add_dependencies(blender buildinfo) endif() set(BLENDER_TEXT_FILES ${CMAKE_SOURCE_DIR}/release/text/copyright.txt - # generate this file - # ${CMAKE_SOURCE_DIR}/release/text/readme.html + # Generate this file: + # `${CMAKE_SOURCE_DIR}/release/text/readme.html` ) # ----------------------------------------------------------------------------- -# Platform specific target destinations for version dir, libs, bpy, text files. +# Platform specific target destinations +# +# Setup version directory, libraries, `bpy` & text files. if(UNIX AND NOT APPLE) if(WITH_PYTHON_MODULE) @@ -365,7 +367,7 @@ elseif(APPLE) set(TARGETDIR_TEXT Blender.app/Contents/Resources/text) endif() - # Skip relinking on cpack / install + # Skip re-linking on CPACK / install. set_target_properties(blender PROPERTIES BUILD_WITH_INSTALL_RPATH true) endif() @@ -388,14 +390,14 @@ if(WITH_PYTHON) "${BLENDER_VERSION_CYCLE}" STREQUAL "rc") set(ADDON_EXCLUDE_CONDITIONAL "addons_contrib/*") else() - set(ADDON_EXCLUDE_CONDITIONAL "_addons_contrib/*") # dummy, won't do anything + set(ADDON_EXCLUDE_CONDITIONAL "_addons_contrib/*") # Dummy, won't do anything. endif() # do not install freestyle dir if disabled if(NOT WITH_FREESTYLE) set(FREESTYLE_EXCLUDE_CONDITIONAL "freestyle/*") else() - set(FREESTYLE_EXCLUDE_CONDITIONAL "_freestyle/*") # dummy, won't do anything + set(FREESTYLE_EXCLUDE_CONDITIONAL "_freestyle/*") # Dummy, won't do anything. endif() install( @@ -415,8 +417,7 @@ endif() # fonts install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/datafiles/fonts + DIRECTORY ${CMAKE_SOURCE_DIR}/release/datafiles/fonts DESTINATION ${TARGETDIR_VER}/datafiles ) @@ -430,14 +431,14 @@ if(WITH_INTERNATIONAL) msgfmt_simple(${_po_file} _all_mo_files) endforeach() - # Create a custom target which will compile all po to mo + # Create a custom target which will compile all `*.po` to `*.mo`. add_custom_target( locales DEPENDS ${_all_mo_files} ) add_dependencies(blender locales) - # Generate INSTALL rules + # Generate INSTALL rules. install( FILES ${_locale_dir}/languages DESTINATION ${_locale_target_dir} @@ -462,7 +463,7 @@ if(WITH_INTERNATIONAL) unset(_locale_dir) endif() -# color management +# Color management. if(WITH_OPENCOLORIO) install( DIRECTORY ${CMAKE_SOURCE_DIR}/release/datafiles/colormanagement @@ -470,9 +471,9 @@ if(WITH_OPENCOLORIO) ) endif() -# helpful tip when using make +# Helpful tip when using make. if("${CMAKE_GENERATOR}" MATCHES ".*Makefiles.*") - # message after building. + # Message to display after building. add_custom_command( TARGET blender POST_BUILD MAIN_DEPENDENCY blender COMMAND ${CMAKE_COMMAND} -E @@ -505,7 +506,7 @@ if(UNIX AND NOT APPLE) ) endif() - # there are a few differences between portable and system install + # There are a few differences between portable and system install. if(WITH_PYTHON_MODULE) if(WITH_INSTALL_PORTABLE) install( @@ -578,14 +579,14 @@ if(UNIX AND NOT APPLE) DESTINATION bin ) if(WITH_DOC_MANPAGE) - # manpage only with 'blender' binary + # Manual page (only with `blender` binary). install( FILES ${CMAKE_CURRENT_BINARY_DIR}/blender.1 DESTINATION share/man/man1 ) endif() - # misc files + # Misc files. install( FILES ${CMAKE_SOURCE_DIR}/release/freedesktop/blender.desktop DESTINATION share/applications @@ -614,11 +615,9 @@ if(UNIX AND NOT APPLE) DESTINATION ${TARGETDIR_VER}/python/bin ) - # on some platforms (like openSUSE) Python is linked - # to be used from lib64 folder. - # determine this from Python's libraries path - # - # ugh, its possible 'lib64' is just a symlink to 'lib' which causes incorrect use of 'lib64' + # On some platforms (like openSUSE) Python is linked to be used from `lib64` directory. + # determine this from Python's libraries path. + # Ugh, its possible `lib64` is just a symlink to 'lib' which causes incorrect use of `lib64`. get_filename_component(_pypath_real ${PYTHON_LIBPATH} REALPATH) if(${_pypath_real} MATCHES "lib64$") set(_target_LIB "lib64") @@ -627,7 +626,7 @@ if(UNIX AND NOT APPLE) endif() unset(_pypath_real) - # Copy the systems python into the install directory + # Copy the systems python into the install directory: # install(CODE "message(\"copying a subset of the systems python...\")") install( DIRECTORY ${PYTHON_LIBPATH}/python${PYTHON_VERSION} @@ -645,8 +644,8 @@ if(UNIX AND NOT APPLE) PATTERN "wininst*.exe" EXCLUDE # from distutils, avoid malware false positive ) - # Needed for distutils/pip - # get the last part of the include dir, will be 'python{version}{abiflag}', + # Needed for `distutils/pip`. + # Get the last part of the include dir, will be `python{version}{abiflag}`. get_filename_component(_py_inc_suffix ${PYTHON_INCLUDE_DIR} NAME) install( FILES ${PYTHON_INCLUDE_DIR}/pyconfig.h @@ -656,7 +655,7 @@ if(UNIX AND NOT APPLE) if(WITH_PYTHON_INSTALL_NUMPY) # Install to the same directory as the source, so debian-like - # distros are happy with their policy. + # distributions are happy with their policy. set(_suffix "site-packages") if(${PYTHON_NUMPY_PATH} MATCHES "dist-packages") set(_suffix "dist-packages") @@ -693,7 +692,7 @@ if(UNIX AND NOT APPLE) if(WITH_PYTHON_INSTALL_ZSTANDARD) # Install to the same directory as the source, so debian-like - # distros are happy with their policy. + # distributions are happy with their policy. set(_suffix "site-packages") if(${PYTHON_ZSTANDARD_PATH} MATCHES "dist-packages") set(_suffix "dist-packages") @@ -709,7 +708,7 @@ if(UNIX AND NOT APPLE) unset(_suffix) endif() - # Copy requests, we need to generalize site-packages + # Copy requests, we need to generalize site-packages. if(WITH_PYTHON_INSTALL_REQUESTS) set(_suffix "site-packages") if(${PYTHON_REQUESTS_PATH} MATCHES "dist-packages") @@ -725,9 +724,8 @@ if(UNIX AND NOT APPLE) ) # On some platforms requests does have extra dependencies. # - # Either 'chardet' or 'charset_normalizer" is used, depending on the - # version of Python. The code below silently skips the one that's not - # available, so we can just list both here. + # Either `chardet` or `charset_normalizer` is used, depending on the version of Python. + # The code below silently skips the one that's not available, so we can list both here. set(_requests_deps "certifi" "chardet" "charset_normalizer" "idna" "urllib3") foreach(_requests_dep ${_requests_deps}) if(EXISTS ${PYTHON_REQUESTS_PATH}/${_requests_dep}) @@ -782,11 +780,12 @@ elseif(WIN32) ) endif() if(MSVC_ASAN) - # The asan dll's can be found in the same folder as the compiler, this is the easiest way to find these. + # The ASAN DLL's can be found in the same folder as the compiler, + # this is the easiest way to find these. string(REPLACE "cl.exe" "clang_rt.asan_dynamic-x86_64.dll" ASAN_DLL ${CMAKE_C_COMPILER}) string(REPLACE "cl.exe" "clang_rt.asan_dbg_dynamic-x86_64.dll" ASAN_DEBUG_DLL ${CMAKE_C_COMPILER}) if(NOT EXISTS "${ASAN_DLL}") - message(FATAL_ERROR "Asan is enabled, but the ASAN runtime is not detected, this is an optional component during the MSVC install, please install it") + message(FATAL_ERROR "ASAN is enabled, but the ASAN runtime is not detected, this is an optional component during the MSVC install, please install it") endif() install( FILES ${ASAN_DLL} @@ -821,10 +820,14 @@ elseif(WIN32) if(WITH_WINDOWS_PDB) if(WITH_WINDOWS_STRIPPED_PDB) - # Icky hack for older cmake from https://stackoverflow.com/a/21198501 - # $ will work in newer cmake but the version currently (3.12) - # on the buildbot does not support this endavour. - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}/blender_public.pdb DESTINATION . RENAME blender.pdb) + # Icky hack for older CMAKE from https://stackoverflow.com/a/21198501 + # `$` will work in newer CMAKE but the version currently (3.12) + # on the build-bot does not support this endeavor. + install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}/blender_public.pdb + DESTINATION . + RENAME blender.pdb + ) else() install(FILES $ DESTINATION . RENAME blender.pdb) endif() @@ -848,22 +851,25 @@ elseif(WIN32) if(NOT CMAKE_COMPILER_IS_GNUCC) install( - FILES ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}.dll - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3.dll + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}.dll + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3.dll DESTINATION ${TARGETDIR_LIB} CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}_d.dll - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3_d.dll + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}_d.dll + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3_d.dll DESTINATION ${TARGETDIR_LIB} CONFIGURATIONS Debug ) endif() if(WITH_PYTHON_INSTALL) - # note, as far as python is concerned 'RelWithDebInfo' is not debug since its without debug flags. + # NOTE: as far as python is concerned `RelWithDebInfo` + # is not debug since its without debug flags. install(DIRECTORY DESTINATION ${TARGETDIR_VER}/python) install(DIRECTORY DESTINATION ${TARGETDIR_VER}/python/lib) @@ -873,7 +879,7 @@ elseif(WIN32) DESTINATION ${BLENDER_VERSION}/python/ CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel PATTERN ".svn" EXCLUDE - PATTERN "*_d.*" EXCLUDE # * debug libraries * + PATTERN "*_d.*" EXCLUDE # * debug libraries * PATTERN "__pycache__" EXCLUDE # * any cache * PATTERN "*.pyc" EXCLUDE # * any cache * PATTERN "*.pyo" EXCLUDE # * any cache * @@ -904,27 +910,31 @@ elseif(WIN32) ) install( - FILES ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}.dll - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python.exe + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}.dll + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python.exe DESTINATION ${BLENDER_VERSION}/python/bin CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}_d.dll - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python_d.exe + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}_d.dll + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python_d.exe DESTINATION ${BLENDER_VERSION}/python/bin CONFIGURATIONS Debug ) if(WINDOWS_PYTHON_DEBUG) install( - FILES ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}.pdb + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}.pdb DESTINATION ${TARGETDIR_LIB} CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel ) install( - FILES ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}_d.pdb + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/libs/python${_PYTHON_VERSION_NO_DOTS}_d.pdb DESTINATION ${TARGETDIR_LIB} CONFIGURATIONS Debug ) @@ -935,9 +945,8 @@ elseif(WIN32) endif() if(WITH_CODEC_FFMPEG) - # Filenames change slightly between ffmpeg versions - # check both 5.0 and fallback to 4.4 to ease the transition - # between versions. + # Filenames change slightly between FFMPEG versions check both 5.0 and fallback to 4.4 + # to ease the transition between versions. if(EXISTS "${LIBDIR}/ffmpeg/lib/avcodec-59.dll") install( FILES @@ -1052,12 +1061,12 @@ elseif(WIN32) endif() elseif(APPLE) if(NOT WITH_PYTHON_MODULE) - # Uppercase name for app bundle + # Uppercase name for app bundle. set_target_properties(blender PROPERTIES OUTPUT_NAME Blender) endif() - # handy install macro to exclude files, we use \$ escape for the "to" - # argument when calling so ${BUILD_TYPE} does not get expanded + # Handy install macro to exclude files, we use \$ escape for the "to" + # argument when calling so `${BUILD_TYPE}` does not get expanded. macro(install_dir from to) install( DIRECTORY ${from} @@ -1085,7 +1094,7 @@ elseif(APPLE) set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/Blender.app) - # setup Info.plist + # Setup `Info.plist`. execute_process(COMMAND date "+%Y-%m-%d" OUTPUT_VARIABLE BLENDER_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) @@ -1096,14 +1105,14 @@ elseif(APPLE) MACOSX_BUNDLE_LONG_VERSION_STRING "${BLENDER_VERSION}.${BLENDER_VERSION_PATCH} ${BLENDER_DATE}" ) - # Gather the date in finder-style + # Gather the date in finder-style. execute_process(COMMAND date "+%m/%d/%Y/%H:%M" OUTPUT_VARIABLE SETFILE_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) - # Give the bundle actual creation/modification date + # Give the bundle actual creation/modification date. # - # Note that the directory might not yet exist, which happens when CMake is first run. + # Note that the directory might not yet exist, which happens when CMAKE is first run. if(NOT EXISTS ${EXECUTABLE_OUTPUT_PATH}/Blender.app) file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Blender.app) endif() @@ -1139,9 +1148,9 @@ elseif(APPLE) ) endif() - # python + # Python. if(WITH_PYTHON AND NOT WITH_PYTHON_MODULE AND NOT WITH_PYTHON_FRAMEWORK) - # Copy the python libs into the install directory + # Copy the python libraries into the install directory. install_dir( ${PYTHON_LIBPATH} ${TARGETDIR_VER}/python/lib @@ -1153,8 +1162,8 @@ elseif(APPLE) DESTINATION ${TARGETDIR_VER}/python/bin ) - # Needed for distutils/pip - # get the last part of the include dir, will be 'python{version}{abiflag}', + # Needed for `distutils/pip`. + # Get the last part of the include dir, will be `python{version}{abiflag}`. get_filename_component(_py_inc_suffix ${PYTHON_INCLUDE_DIR} NAME) install( FILES ${PYTHON_INCLUDE_DIR}/pyconfig.h @@ -1198,13 +1207,12 @@ if(DEFINED TARGETDIR_TEXT) ) install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/license + DIRECTORY ${CMAKE_SOURCE_DIR}/release/license DESTINATION "${TARGETDIR_TEXT}" ) endif() -# install more files specified elsewhere +# Install more files specified elsewhere. delayed_do_install(${TARGETDIR_VER}) unset(BLENDER_TEXT_FILES) @@ -1231,16 +1239,18 @@ unset(_icon_names) unset(_icon_files) unset(_f) + # ----------------------------------------------------------------------------- # Studio Lights + install( - DIRECTORY - ${CMAKE_SOURCE_DIR}/release/datafiles/studiolights + DIRECTORY ${CMAKE_SOURCE_DIR}/release/datafiles/studiolights DESTINATION ${TARGETDIR_VER}/datafiles ) + # ----------------------------------------------------------------------------- -# Setup link libs +# Setup link libraries add_dependencies(blender makesdna) target_link_libraries(blender ${LIB}) @@ -1253,22 +1263,23 @@ if(DEFINED PLATFORM_SYMBOLS_MAP) set_target_properties(blender PROPERTIES LINK_DEPENDS ${PLATFORM_SYMBOLS_MAP}) endif() + # ----------------------------------------------------------------------------- # USD registry. -# USD requires a set of JSON files that define the standard schemas. These -# files are required at runtime. + +# USD requires a set of JSON files that define the standard schemas. +# These files are required at runtime. if(WITH_USD) add_definitions(-DWITH_USD) - install(DIRECTORY - ${USD_LIBRARY_DIR}/usd + install( + DIRECTORY ${USD_LIBRARY_DIR}/usd DESTINATION "${TARGETDIR_VER}/datafiles" ) endif() -# vcpkg substitutes our libs with theirs, which will cause issues when you -# you run these builds on other systems due to missing dlls. So we opt out -# the use of vcpkg +# `vcpkg` substitutes our libraries with theirs, which will cause issues when you you run +# these builds on other systems due to missing DLL's. So we opt out the use of `vcpkg`. if(WIN32) set_target_properties(blender PROPERTIES VS_GLOBAL_VcpkgEnabled "false") set_target_properties(blender PROPERTIES @@ -1278,12 +1289,18 @@ if(WIN32) if(WITH_WINDOWS_PDB AND WITH_WINDOWS_STRIPPED_PDB) # This is slightly messy, but single target generators like ninja will not have the # `CMAKE_CFG_INTDIR` variable and multi-target generators like `msbuild` will not have - # `CMAKE_BUILD_TYPE`. This can be simplified by target_link_options and the `$` + # `CMAKE_BUILD_TYPE`. This can be simplified by `target_link_options` and the `$` # generator expression in newer CMAKE (2.13+) but until that time this fill have suffice. if(CMAKE_BUILD_TYPE) - set_property(TARGET blender APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/blender_public.pdb") + set_property( + TARGET blender APPEND_STRING PROPERTY LINK_FLAGS + " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/blender_public.pdb" + ) else() - set_property(TARGET blender APPEND_STRING PROPERTY LINK_FLAGS " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/blender_public.pdb") + set_property( + TARGET blender APPEND_STRING PROPERTY LINK_FLAGS + " /PDBSTRIPPED:${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/blender_public.pdb" + ) endif() endif() endif() -- cgit v1.2.3 From 22b84424c702a6a85ccf127dfcbb6ce28b101774 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 11:13:05 +1000 Subject: Cleanup: check for Python module in BKE_appdir_program_path_init Replace the argument with an in ifdef in BKE_appdir_program_path_init. At the time `blenkernel` didn't define WITH_PYTHON_MODULE, since it does now there is no need for an argument. With the minor benefit of fewer preprocessor checks in the main() function. --- source/blender/blenkernel/BKE_appdir.h | 5 +---- source/blender/blenkernel/intern/appdir.c | 12 +++++++++++- source/creator/creator.c | 12 +----------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/source/blender/blenkernel/BKE_appdir.h b/source/blender/blenkernel/BKE_appdir.h index 16488bdbf09..dcacc2ca7b3 100644 --- a/source/blender/blenkernel/BKE_appdir.h +++ b/source/blender/blenkernel/BKE_appdir.h @@ -105,11 +105,8 @@ void BKE_appdir_app_templates(struct ListBase *templates); /** * Initialize path to program executable. - * - * \param strict: When true, use `argv0` unmodified (besides making absolute & normalizing). - * Otherwise other methods may be used to find the program path, including searching `$PATH`. */ -void BKE_appdir_program_path_init(const char *argv0, bool strict); +void BKE_appdir_program_path_init(const char *argv0); /** * Path to executable diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 4bd8cfd5f47..845a890ba8b 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -793,6 +793,8 @@ const char *BKE_appdir_folder_id_version(const int folder_id, * \param fullname: The full path and full name of the executable * (must be #FILE_MAX minimum) * \param name: The name of the executable (usually `argv[0]`) to be checked + * \param strict: When true, use `argv0` unmodified (besides making absolute & normalizing). + * Otherwise other methods may be used to find the program path, including searching `$PATH`. */ static void where_am_i(char *fullname, const size_t maxlen, const char *name, const bool strict) { @@ -864,8 +866,16 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name, co } } -void BKE_appdir_program_path_init(const char *argv0, const bool strict) +void BKE_appdir_program_path_init(const char *argv0) { +#ifdef WITH_PYTHON_MODULE + /* NOTE(@campbellbarton): Always use `argv[0]` as is, when building as a Python module. + * Otherwise other methods of detecting the binary that override this argument + * which must point to the Python module for data-files to be detected. */ + const bool strict = true; +#else + const bool strict = false; +#endif where_am_i(g_app.program_filepath, sizeof(g_app.program_filepath), argv0, strict); BLI_split_dir_part(g_app.program_filepath, g_app.program_dirname, sizeof(g_app.program_dirname)); } diff --git a/source/creator/creator.c b/source/creator/creator.c index e7e9eeed79a..7f236a39974 100644 --- a/source/creator/creator.c +++ b/source/creator/creator.c @@ -396,17 +396,7 @@ int main(int argc, #endif /* Initialize path to executable. */ - { -#ifdef WITH_PYTHON_MODULE - /* NOTE(@campbellbarton): Always use `argv[0]` as is, when building as a Python module. - * Otherwise other methods of detecting the binary that override this argument - * which must point to the Python module for data-files to be detected. */ - const bool strict = true; -#else - const bool strict = false; -#endif - BKE_appdir_program_path_init(argv[0], strict); - } + BKE_appdir_program_path_init(argv[0]); BLI_threadapi_init(); -- cgit v1.2.3 From 9e0c2f6867d34a35e009d9a0caee256a4528edc5 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 11:32:42 +1000 Subject: CMake: exclude Python libs & batch scripts WITH_PYTHON_MODULE for WIN32 --- source/creator/CMakeLists.txt | 55 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 2aa534d55eb..23cb38362c2 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -849,22 +849,24 @@ elseif(WIN32) if(WITH_PYTHON) string(REPLACE "." "" _PYTHON_VERSION_NO_DOTS ${PYTHON_VERSION}) - if(NOT CMAKE_COMPILER_IS_GNUCC) - install( - FILES - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}.dll - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3.dll - DESTINATION ${TARGETDIR_LIB} - CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel - ) + if(NOT WITH_PYTHON_MODULE) + if(NOT CMAKE_COMPILER_IS_GNUCC) + install( + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}.dll + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3.dll + DESTINATION ${TARGETDIR_LIB} + CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel + ) - install( - FILES - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}_d.dll - ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3_d.dll - DESTINATION ${TARGETDIR_LIB} - CONFIGURATIONS Debug - ) + install( + FILES + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python${_PYTHON_VERSION_NO_DOTS}_d.dll + ${LIBDIR}/python/${_PYTHON_VERSION_NO_DOTS}/bin/python3_d.dll + DESTINATION ${TARGETDIR_LIB} + CONFIGURATIONS Debug + ) + endif() endif() if(WITH_PYTHON_INSTALL) @@ -1035,16 +1037,19 @@ elseif(WIN32) ) endif() - install( - FILES - ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_gpu.cmd - ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_gpu_glitchworkaround.cmd - ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_log.cmd - ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_factory_startup.cmd - ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_oculus.cmd - ${CMAKE_SOURCE_DIR}/release/windows/batch/oculus.json - DESTINATION ${TARGETDIR_LIB} - ) + + if(NOT WITH_PYTHON_MODULE) + install( + FILES + ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_gpu.cmd + ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_gpu_glitchworkaround.cmd + ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_debug_log.cmd + ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_factory_startup.cmd + ${CMAKE_SOURCE_DIR}/release/windows/batch/blender_oculus.cmd + ${CMAKE_SOURCE_DIR}/release/windows/batch/oculus.json + DESTINATION ${TARGETDIR_LIB} + ) + endif() if(WITH_BLENDER_THUMBNAILER) install( -- cgit v1.2.3 From 3a01c23a84c0641f0f656c805ac29194a240728e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 11:52:14 +1000 Subject: Cleanup: cmake line length, wrapping --- CMakeLists.txt | 41 +++++++++++++++++++++--------- source/creator/CMakeLists.txt | 58 +++++++++++++++++++++++++++---------------- 2 files changed, 66 insertions(+), 33 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9688c711bc7..53859196cfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -888,7 +888,11 @@ endif() if(WITH_CYCLES AND WITH_CYCLES_DEVICE_CUDA AND NOT WITH_CUDA_DYNLOAD) find_package(CUDA) if(NOT CUDA_FOUND) - message(STATUS "CUDA toolkit not found, using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead") + message( + STATUS + "CUDA toolkit not found, " + "using dynamic runtime loading of libraries (WITH_CUDA_DYNLOAD) instead" + ) set(WITH_CUDA_DYNLOAD ON) endif() endif() @@ -905,7 +909,8 @@ if(WITH_INTERNATIONAL) file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/datafiles/locale") list(LENGTH RESULT DIR_LEN) if(DIR_LEN EQUAL 0) - message(WARNING + message( + WARNING "Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, " "This is a 'git submodule', which are known not to work with bridges to other version " "control systems, disabling 'WITH_INTERNATIONAL'." @@ -923,13 +928,17 @@ if(WITH_PYTHON) # because UNIX will search for the old Python paths which may not exist. # giving errors about missing paths before this case is met. if(DEFINED PYTHON_VERSION AND "${PYTHON_VERSION}" VERSION_LESS "3.10") - message(FATAL_ERROR "At least Python 3.10 is required to build, but found Python ${PYTHON_VERSION}") + message( + FATAL_ERROR + "At least Python 3.10 is required to build, but found Python ${PYTHON_VERSION}" + ) endif() file(GLOB RESULT "${CMAKE_SOURCE_DIR}/release/scripts/addons") list(LENGTH RESULT DIR_LEN) if(DIR_LEN EQUAL 0) - message(WARNING + message( + WARNING "Addons path '${CMAKE_SOURCE_DIR}/release/scripts/addons' is missing, " "This is a 'git submodule', which are known not to work with bridges to other version " "control systems: * CONTINUING WITHOUT ADDONS *" @@ -1037,13 +1046,15 @@ endif() if(WITH_CYCLES) if(NOT WITH_OPENIMAGEIO) - message(FATAL_ERROR + message( + FATAL_ERROR "Cycles requires WITH_OPENIMAGEIO, the library may not have been found. " "Configure OIIO or disable WITH_CYCLES" ) endif() if(NOT WITH_BOOST) - message(FATAL_ERROR + message( + FATAL_ERROR "Cycles requires WITH_BOOST, the library may not have been found. " "Configure BOOST or disable WITH_CYCLES" ) @@ -1051,7 +1062,8 @@ if(WITH_CYCLES) if(WITH_CYCLES_OSL) if(NOT WITH_LLVM) - message(FATAL_ERROR + message( + FATAL_ERROR "Cycles OSL requires WITH_LLVM, the library may not have been found. " "Configure LLVM or disable WITH_CYCLES_OSL" ) @@ -1061,7 +1073,8 @@ endif() if(WITH_INTERNATIONAL) if(NOT WITH_BOOST) - message(FATAL_ERROR + message( + FATAL_ERROR "Internationalization requires WITH_BOOST, the library may not have been found. " "Configure BOOST or disable WITH_INTERNATIONAL" ) @@ -1606,7 +1619,8 @@ endif() # be most problematic. if(WITH_PYTHON) if(NOT EXISTS "${PYTHON_INCLUDE_DIR}/Python.h") - message(FATAL_ERROR + message( + FATAL_ERROR "Missing: \"${PYTHON_INCLUDE_DIR}/Python.h\",\n" "Set the cache entry 'PYTHON_INCLUDE_DIR' to point " "to a valid python include path. Containing " @@ -1675,9 +1689,11 @@ if(WITH_COMPILER_SHORT_FILE_MACRO) if(XCODE AND ${XCODE_VERSION} VERSION_LESS 12.0) # Developers may have say LLVM Clang-10.0.1 toolchain (which supports the flag) # with Xcode-11 (the Clang of which doesn't support the flag). - message(WARNING + message( + WARNING "-fmacro-prefix-map flag is NOT supported by Clang shipped with Xcode-${XCODE_VERSION}." - " Some Xcode functionality in Product menu may not work. Disabling WITH_COMPILER_SHORT_FILE_MACRO." + " Some Xcode functionality in Product menu may not work. " + "Disabling WITH_COMPILER_SHORT_FILE_MACRO." ) set(WITH_COMPILER_SHORT_FILE_MACRO OFF) endif() @@ -1693,7 +1709,8 @@ if(WITH_COMPILER_SHORT_FILE_MACRO) unset(_bin_dir) endif() else() - message(WARNING + message( + WARNING "-fmacro-prefix-map flag is NOT supported by C/C++ compiler." " Disabling WITH_COMPILER_SHORT_FILE_MACRO." ) diff --git a/source/creator/CMakeLists.txt b/source/creator/CMakeLists.txt index 23cb38362c2..f8cbb9bc07c 100644 --- a/source/creator/CMakeLists.txt +++ b/source/creator/CMakeLists.txt @@ -193,7 +193,10 @@ if(WITH_BUILDINFO) set(buildinfo_h_fake "${CMAKE_CURRENT_BINARY_DIR}/buildinfo.h_fake") if(EXISTS ${buildinfo_h_fake}) - message(FATAL_ERROR "File \"${buildinfo_h_fake}\" found, this should never be created, remove!") + message( + FATAL_ERROR + "File \"${buildinfo_h_fake}\" found, this should never be created, remove!" + ) endif() # From the CMAKE documentation "If the output of the custom command is not actually created as a @@ -214,12 +217,14 @@ if(WITH_BUILDINFO) OUTPUT ${buildinfo_h_fake} # ensure we always run ${buildinfo_h_real} - COMMAND ${CMAKE_COMMAND} - -DSOURCE_DIR=${CMAKE_SOURCE_DIR} - # Overrides only used when non-empty strings. - -DBUILD_DATE=${BUILDINFO_OVERRIDE_DATE} - -DBUILD_TIME=${BUILDINFO_OVERRIDE_TIME} - -P ${CMAKE_SOURCE_DIR}/build_files/cmake/buildinfo.cmake) + COMMAND + ${CMAKE_COMMAND} + -DSOURCE_DIR=${CMAKE_SOURCE_DIR} + # Overrides only used when non-empty strings. + -DBUILD_DATE=${BUILDINFO_OVERRIDE_DATE} + -DBUILD_TIME=${BUILDINFO_OVERRIDE_TIME} + -P ${CMAKE_SOURCE_DIR}/build_files/cmake/buildinfo.cmake + ) # `buildinfo.h` is a generated file. set_source_files_properties( @@ -476,8 +481,9 @@ if("${CMAKE_GENERATOR}" MATCHES ".*Makefiles.*") # Message to display after building. add_custom_command( TARGET blender POST_BUILD MAIN_DEPENDENCY blender - COMMAND ${CMAKE_COMMAND} -E - echo 'now run: \"make install\" to copy runtime files and scripts to ${TARGETDIR_VER}' + COMMAND + ${CMAKE_COMMAND} -E + echo 'now run: \"make install\" to copy runtime files and scripts to ${TARGETDIR_VER}' ) endif() @@ -491,9 +497,10 @@ if(UNIX AND NOT APPLE) if(WITH_DOC_MANPAGE) add_custom_target( blender_man_page ALL - COMMAND ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py - --blender ${EXECUTABLE_OUTPUT_PATH}/blender - --output ${CMAKE_CURRENT_BINARY_DIR}/blender.1 + COMMAND + ${CMAKE_SOURCE_DIR}/doc/manpage/blender.1.py + --blender ${EXECUTABLE_OUTPUT_PATH}/blender + --output ${CMAKE_CURRENT_BINARY_DIR}/blender.1 ) add_dependencies(blender_man_page blender) endif() @@ -785,7 +792,11 @@ elseif(WIN32) string(REPLACE "cl.exe" "clang_rt.asan_dynamic-x86_64.dll" ASAN_DLL ${CMAKE_C_COMPILER}) string(REPLACE "cl.exe" "clang_rt.asan_dbg_dynamic-x86_64.dll" ASAN_DEBUG_DLL ${CMAKE_C_COMPILER}) if(NOT EXISTS "${ASAN_DLL}") - message(FATAL_ERROR "ASAN is enabled, but the ASAN runtime is not detected, this is an optional component during the MSVC install, please install it") + message( + FATAL_ERROR + "ASAN is enabled, but the ASAN runtime is not detected, " + "this is an optional component during the MSVC install, please install it" + ) endif() install( FILES ${ASAN_DLL} @@ -1100,9 +1111,11 @@ elseif(APPLE) set(OSX_APP_SOURCEDIR ${CMAKE_SOURCE_DIR}/release/darwin/Blender.app) # Setup `Info.plist`. - execute_process(COMMAND date "+%Y-%m-%d" - OUTPUT_VARIABLE BLENDER_DATE - OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process( + COMMAND date "+%Y-%m-%d" + OUTPUT_VARIABLE BLENDER_DATE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) set_target_properties(blender PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${OSX_APP_SOURCEDIR}/Contents/Info.plist @@ -1111,9 +1124,11 @@ elseif(APPLE) ) # Gather the date in finder-style. - execute_process(COMMAND date "+%m/%d/%Y/%H:%M" - OUTPUT_VARIABLE SETFILE_DATE - OUTPUT_STRIP_TRAILING_WHITESPACE) + execute_process( + COMMAND date "+%m/%d/%Y/%H:%M" + OUTPUT_VARIABLE SETFILE_DATE + OUTPUT_STRIP_TRAILING_WHITESPACE + ) # Give the bundle actual creation/modification date. # @@ -1121,8 +1136,9 @@ elseif(APPLE) if(NOT EXISTS ${EXECUTABLE_OUTPUT_PATH}/Blender.app) file(MAKE_DIRECTORY ${EXECUTABLE_OUTPUT_PATH}/Blender.app) endif() - execute_process(COMMAND SetFile -d ${SETFILE_DATE} -m ${SETFILE_DATE} - ${EXECUTABLE_OUTPUT_PATH}/Blender.app) + execute_process( + COMMAND SetFile -d ${SETFILE_DATE} -m ${SETFILE_DATE} ${EXECUTABLE_OUTPUT_PATH}/Blender.app + ) install( TARGETS blender -- cgit v1.2.3 From ce5ad663305a46a61e95ade1700b9b290c6847f6 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 12:17:09 +1000 Subject: GNUmakefile: change message to reference "bpy" when building as a module --- GNUmakefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index a82d1bedace..a218b1d226c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -162,6 +162,7 @@ CPU:=$(shell uname -m) # Source and Build DIR's BLENDER_DIR:=$(shell pwd -P) BUILD_TYPE:=Release +BLENDER_IS_PYTHON_MODULE:= # CMake arguments, assigned to local variable to make it mutable. CMAKE_CONFIG_ARGS := $(BUILD_CMAKE_ARGS) @@ -259,6 +260,7 @@ endif ifneq "$(findstring bpy, $(MAKECMDGOALS))" "" BUILD_DIR:=$(BUILD_DIR)_bpy CMAKE_CONFIG_ARGS:=-C"$(BLENDER_DIR)/build_files/cmake/config/bpy_module.cmake" $(CMAKE_CONFIG_ARGS) + BLENDER_IS_PYTHON_MODULE:=1 endif ifneq "$(findstring developer, $(MAKECMDGOALS))" "" @@ -297,8 +299,10 @@ endif # use the default build path can still use utility helpers. ifeq ($(OS), Darwin) BLENDER_BIN?="$(BUILD_DIR)/bin/Blender.app/Contents/MacOS/Blender" + BLENDER_BIN_DIR?="$(BUILD_DIR)/bin/Blender.app/Contents/MacOS/Blender" else BLENDER_BIN?="$(BUILD_DIR)/bin/blender" + BLENDER_BIN_DIR?="$(BUILD_DIR)/bin" endif @@ -355,8 +359,12 @@ all: .FORCE @echo Building Blender ... $(BUILD_COMMAND) -C "$(BUILD_DIR)" -j $(NPROCS) install @echo - @echo edit build configuration with: "$(BUILD_DIR)/CMakeCache.txt" run make again to rebuild. - @echo Blender successfully built, run from: $(BLENDER_BIN) + @echo Edit build configuration with: \"$(BUILD_DIR)/CMakeCache.txt\" run make again to rebuild. + @if test "$(BLENDER_IS_PYTHON_MODULE)" == ""; then \ + echo Blender successfully built, run from: $(BLENDER_BIN); \ + else \ + echo Blender successfully built as a Python module, \"bpy\" can be imported from: $(BLENDER_BIN_DIR); \ + fi @echo debug: all -- cgit v1.2.3 From d455f1a0baacac952792f36a30ac254a07510ac7 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 12:17:59 +1000 Subject: Cleanup: quiet conversion warning --- source/blender/draw/intern/draw_resource.hh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/source/blender/draw/intern/draw_resource.hh b/source/blender/draw/intern/draw_resource.hh index 22ee43592a9..2df38e32ed2 100644 --- a/source/blender/draw/intern/draw_resource.hh +++ b/source/blender/draw/intern/draw_resource.hh @@ -85,10 +85,11 @@ inline void ObjectInfos::sync(const blender::draw::ObjectRef ref, bool is_active if (ref.dupli_object == nullptr) { /* TODO(fclem): this is rather costly to do at draw time. Maybe we can * put it in ob->runtime and make depsgraph ensure it is up to date. */ - random = BLI_hash_int_2d(BLI_hash_string(ref.object->id.name + 2), 0) * (1.0f / 0xFFFFFFFF); + random = BLI_hash_int_2d(BLI_hash_string(ref.object->id.name + 2), 0) * + (1.0f / (float)0xFFFFFFFF); } else { - random = ref.dupli_object->random_id * (1.0f / 0xFFFFFFFF); + random = ref.dupli_object->random_id * (1.0f / (float)0xFFFFFFFF); } /* Default values. Set if needed. */ random = 0.0f; -- cgit v1.2.3 From f7a4ede79f9512f39db8632ff112e08a93f3a9d4 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 13:59:53 +1000 Subject: Python: change bpy.app.binary_path behavior WITH_PYTHON_MODULE The following changes have been made to this attribute with WITH_PYTHON_MODULE is defined: - Defaults to an empty string (instead of pointing to __init__.so). - It's writable, so script authors can point to a valid Blender binary. `where_am_i(..)` is no longer used by BKE_appdir_program_path_init, there is now a separate code-path for setting the initial program directory, calls after this can be used to set the binary path. --- source/blender/blenkernel/intern/appdir.c | 51 ++++++++++++++++++------------- source/blender/python/intern/bpy_app.c | 39 ++++++++++++++++++++--- 2 files changed, 65 insertions(+), 25 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 845a890ba8b..295e85a5fc4 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -782,6 +782,7 @@ const char *BKE_appdir_folder_id_version(const int folder_id, * Access locations of Blender & Python. * \{ */ +#ifndef WITH_PYTHON_MODULE /** * Checks if name is a fully qualified filename to an executable. * If not it searches `$PATH` for the file. On Windows it also @@ -793,14 +794,12 @@ const char *BKE_appdir_folder_id_version(const int folder_id, * \param fullname: The full path and full name of the executable * (must be #FILE_MAX minimum) * \param name: The name of the executable (usually `argv[0]`) to be checked - * \param strict: When true, use `argv0` unmodified (besides making absolute & normalizing). - * Otherwise other methods may be used to find the program path, including searching `$PATH`. */ -static void where_am_i(char *fullname, const size_t maxlen, const char *name, const bool strict) +static void where_am_i(char *fullname, const size_t maxlen, const char *name) { -#ifdef WITH_BINRELOC +# ifdef WITH_BINRELOC /* Linux uses `binreloc` since `argv[0]` is not reliable, call `br_init(NULL)` first. */ - if (!strict) { + { const char *path = NULL; path = br_find_exe(NULL); if (path) { @@ -809,9 +808,9 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name, co return; } } -#endif +# endif -#ifdef _WIN32 +# ifdef _WIN32 if (!strict) { wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath"); if (GetModuleFileNameW(0, fullname_16, maxlen)) { @@ -827,7 +826,7 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name, co MEM_freeN(fullname_16); } -#endif +# endif /* Unix and non Linux. */ if (name && name[0]) { @@ -835,36 +834,35 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name, co BLI_strncpy(fullname, name, maxlen); if (name[0] == '.') { BLI_path_abs_from_cwd(fullname, maxlen); -#ifdef _WIN32 +# ifdef _WIN32 if (!strict) { BLI_path_program_extensions_add_win32(fullname, maxlen); } -#endif +# endif } else if (BLI_path_slash_rfind(name)) { /* Full path. */ BLI_strncpy(fullname, name, maxlen); -#ifdef _WIN32 +# ifdef _WIN32 if (!strict) { BLI_path_program_extensions_add_win32(fullname, maxlen); } -#endif +# endif } else { - if (!strict) { - BLI_path_program_search(fullname, maxlen, name); - } + BLI_path_program_search(fullname, maxlen, name); } /* Remove "/./" and "/../" so string comparisons can be used on the path. */ BLI_path_normalize(NULL, fullname); -#if defined(DEBUG) +# if defined(DEBUG) if (!STREQ(name, fullname)) { CLOG_INFO(&LOG, 2, "guessing '%s' == '%s'", name, fullname); } -#endif +# endif } } +#endif /* WITH_PYTHON_MODULE */ void BKE_appdir_program_path_init(const char *argv0) { @@ -872,17 +870,28 @@ void BKE_appdir_program_path_init(const char *argv0) /* NOTE(@campbellbarton): Always use `argv[0]` as is, when building as a Python module. * Otherwise other methods of detecting the binary that override this argument * which must point to the Python module for data-files to be detected. */ - const bool strict = true; + STRNCPY(g_app.program_filepath, argv0); + BLI_path_abs_from_cwd(g_app.program_filepath, sizeof(g_app.program_filepath)); + BLI_path_normalize(NULL, g_app.program_filepath); + + if (g_app.program_dirname[0] == '\0') { + /* First time initializing, the file binary path isn't valid from a Python module. + * Calling again must set the `filepath` and leave the directory as-is. */ + BLI_split_dir_part( + g_app.program_filepath, g_app.program_dirname, sizeof(g_app.program_dirname)); + g_app.program_filepath[0] = '\0'; + } #else - const bool strict = false; -#endif - where_am_i(g_app.program_filepath, sizeof(g_app.program_filepath), argv0, strict); + where_am_i(g_app.program_filepath, sizeof(g_app.program_filepath), argv0); BLI_split_dir_part(g_app.program_filepath, g_app.program_dirname, sizeof(g_app.program_dirname)); +#endif } const char *BKE_appdir_program_path(void) { +#ifndef WITH_PYTHON_MODULE /* Default's to empty when building as as Python module. */ BLI_assert(g_app.program_filepath[0]); +#endif return g_app.program_filepath; } diff --git a/source/blender/python/intern/bpy_app.c b/source/blender/python/intern/bpy_app.c index 939473ceaa0..a0129157b95 100644 --- a/source/blender/python/intern/bpy_app.c +++ b/source/blender/python/intern/bpy_app.c @@ -79,8 +79,6 @@ static PyStructSequence_Field app_info_fields[] = { {"version_string", "The Blender version formatted as a string"}, {"version_cycle", "The release status of this build alpha/beta/rc/release"}, {"version_char", "Deprecated, always an empty string"}, - {"binary_path", - "The location of Blender's executable, useful for utilities that open new instances"}, {"background", "Boolean, True when blender is running without a user interface (started with -b)"}, {"factory_startup", "Boolean, True when blender is running with --factory-startup)"}, @@ -151,7 +149,6 @@ static PyObject *make_app_info(void) SetStrItem(STRINGIFY(BLENDER_VERSION_CYCLE)); SetStrItem(""); - SetStrItem(BKE_appdir_program_path()); SetObjItem(PyBool_FromLong(G.background)); SetObjItem(PyBool_FromLong(G.factory_startup)); @@ -345,6 +342,33 @@ static PyObject *bpy_app_autoexec_fail_message_get(PyObject *UNUSED(self), void return PyC_UnicodeFromByte(G.autoexec_fail); } +PyDoc_STRVAR(bpy_app_binary_path_doc, + "The location of Blender's executable, useful for utilities that open new instances. " + "Read-only unless Blender is built as a Python module - in this case the value is " + "an empty string which script authors may point to a Blender binary."); +static PyObject *bpy_app_binary_path_get(PyObject *UNUSED(self), void *UNUSED(closure)) +{ + return PyC_UnicodeFromByte(BKE_appdir_program_path()); +} + +static int bpy_app_binary_path_set(PyObject *UNUSED(self), PyObject *value, void *UNUSED(closure)) +{ +#ifndef WITH_PYTHON_MODULE + PyErr_SetString(PyExc_AttributeError, + "bpy.app.binary_path is only writable when built as a Python module"); + return -1; +#endif + PyObject *value_coerce = NULL; + const char *filepath = PyC_UnicodeAsByte(value, &value_coerce); + if (filepath == NULL) { + PyErr_Format(PyExc_ValueError, "expected a string or bytes, got %s", Py_TYPE(value)->tp_name); + return -1; + } + BKE_appdir_program_path_init(filepath); + Py_XDECREF(value_coerce); + return 0; +} + static PyGetSetDef bpy_app_getsets[] = { {"debug", bpy_app_debug_get, bpy_app_debug_set, bpy_app_debug_doc, (void *)G_DEBUG}, {"debug_ffmpeg", @@ -450,7 +474,14 @@ static PyGetSetDef bpy_app_getsets[] = { (void *)G_FLAG_SCRIPT_AUTOEXEC_FAIL_QUIET}, {"autoexec_fail_message", bpy_app_autoexec_fail_message_get, NULL, NULL, NULL}, - /* End-of-list marker. */ + /* Support script authors setting the Blender binary path to use, otherwise this value + * is not known when built as a Python module. */ + {"binary_path", + bpy_app_binary_path_get, + bpy_app_binary_path_set, + bpy_app_binary_path_doc, + NULL}, + {NULL, NULL, NULL, NULL, NULL}, }; -- cgit v1.2.3 From 0c9749093b95f9af9ce86f8730753e1cfe215f4e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 15:37:33 +1000 Subject: Cleanup: spelling in comments --- source/blender/blenkernel/BKE_lib_id.h | 2 +- source/blender/blenkernel/intern/mesh_mirror.c | 4 ++-- source/blender/blenkernel/intern/mesh_tangent.cc | 2 +- source/blender/blenlib/BLI_bit_vector.hh | 2 +- .../blender/compositor/operations/COM_SMAAOperation.cc | 2 +- source/blender/draw/engines/eevee/eevee_lightcache.c | 2 +- source/blender/draw/engines/eevee/eevee_private.h | 2 +- source/blender/draw/engines/gpencil/gpencil_draw_data.c | 2 +- source/blender/draw/engines/gpencil/gpencil_engine.c | 2 +- source/blender/draw/intern/draw_view.cc | 16 +++++++++------- source/blender/editors/interface/interface_drag.cc | 2 +- source/blender/editors/mesh/meshtools.cc | 2 +- source/blender/editors/space_outliner/outliner_draw.cc | 2 +- source/blender/makesdna/DNA_gpencil_types.h | 2 +- source/blender/modifiers/intern/MOD_array.c | 4 ++-- 15 files changed, 25 insertions(+), 23 deletions(-) diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index 4e4b393fcd6..e5b013ce201 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -623,7 +623,7 @@ bool BKE_id_can_be_asset(const struct ID *id); /** * Return the owner ID of the given `id`, if any. * - * \note: This will only return non-NULL for embedded IDs (master collections etc.), and shapekeys. + * \note This will only return non-NULL for embedded IDs (master collections etc.), and shape-keys. */ struct ID *BKE_id_owner_get(struct ID *id); diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c index 2a64f6628f2..a2804db609b 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.c +++ b/source/blender/blenkernel/intern/mesh_mirror.c @@ -208,8 +208,8 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, maxLoops); CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, maxPolys); - /* Subsurf for eg won't have mesh data in the custom-data arrays. - * now add mvert/medge/mpoly layers. */ + /* Subdivision-surface for eg won't have mesh data in the custom-data arrays. + * Now add #MVert/#MEdge/#MPoly layers. */ if (!CustomData_has_layer(&mesh->vdata, CD_MVERT)) { memcpy(BKE_mesh_verts_for_write(result), BKE_mesh_verts(mesh), sizeof(MVert) * mesh->totvert); } diff --git a/source/blender/blenkernel/intern/mesh_tangent.cc b/source/blender/blenkernel/intern/mesh_tangent.cc index 3c1cdf84b3d..8f9af5e9258 100644 --- a/source/blender/blenkernel/intern/mesh_tangent.cc +++ b/source/blender/blenkernel/intern/mesh_tangent.cc @@ -68,7 +68,7 @@ struct BKEMeshToTangent { } const MPoly *mpolys; /* faces */ - const MLoop *mloops; /* faces's vertices */ + const MLoop *mloops; /* faces vertices */ const MVert *mverts; /* vertices */ const MLoopUV *luvs; /* texture coordinates */ const float (*lnors)[3]; /* loops' normals */ diff --git a/source/blender/blenlib/BLI_bit_vector.hh b/source/blender/blenlib/BLI_bit_vector.hh index 3cbd2483a31..2cec190f84a 100644 --- a/source/blender/blenlib/BLI_bit_vector.hh +++ b/source/blender/blenlib/BLI_bit_vector.hh @@ -196,7 +196,7 @@ class BitVector { /** Current size of the vector in bits. */ int64_t size_in_bits_; - /** Number of bits that fit into the vector until a reallocation has to occure. */ + /** Number of bits that fit into the vector until a reallocation has to occur. */ int64_t capacity_in_bits_; /** Used for allocations when the inline buffer is too small. */ diff --git a/source/blender/compositor/operations/COM_SMAAOperation.cc b/source/blender/compositor/operations/COM_SMAAOperation.cc index 11e51e81ef0..261426b31e2 100644 --- a/source/blender/compositor/operations/COM_SMAAOperation.cc +++ b/source/blender/compositor/operations/COM_SMAAOperation.cc @@ -12,7 +12,7 @@ extern "C" { namespace blender::compositor { /* - * An implementation of Enhanced Subpixel Morphological Antialiasing (SMAA) + * An implementation of Enhanced Sub-pixel Morphological Anti-aliasing (SMAA) * * The algorithm was proposed by: * Jorge Jimenez, Jose I. Echevarria, Tiago Sousa, Diego Gutierrez diff --git a/source/blender/draw/engines/eevee/eevee_lightcache.c b/source/blender/draw/engines/eevee/eevee_lightcache.c index 7f722ff1764..614ea0b0892 100644 --- a/source/blender/draw/engines/eevee/eevee_lightcache.c +++ b/source/blender/draw/engines/eevee/eevee_lightcache.c @@ -849,7 +849,7 @@ static void eevee_lightbake_delete_resources(EEVEE_LightBake *lbake) DRW_opengl_context_enable(); } - /* XXX Free the resources contained in the viewlayer data + /* XXX: Free the resources contained in the view-layer data * to be able to free the context before deleting the depsgraph. */ if (lbake->sldata) { EEVEE_view_layer_data_free(lbake->sldata); diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 8d47d80987c..8c6d96254ae 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -1015,7 +1015,7 @@ typedef struct EEVEE_PrivateData { struct GHash *material_hash; float background_alpha; /* TODO: find a better place for this. */ bool disable_ligthprobes; - /* Chosen lightcache: can come from Lookdev or the viewlayer. */ + /** Chosen light-cache: can come from Lookdev or the view-layer. */ struct LightCache *light_cache; /* For planar probes */ float planar_texel_size[2]; diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c index 65ddb80ad55..e54ac99a888 100644 --- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c +++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c @@ -460,7 +460,7 @@ GPENCIL_ViewLayerData *GPENCIL_view_layer_data_ensure(void) GPENCIL_ViewLayerData **vldata = (GPENCIL_ViewLayerData **)DRW_view_layer_engine_data_ensure( &draw_engine_gpencil_type, gpencil_view_layer_data_free); - /* NOTE(&fclem): Putting this stuff in viewlayer means it is shared by all viewports. + /* NOTE(@fclem): Putting this stuff in view-layer means it is shared by all viewports. * For now it is ok, but in the future, it could become a problem if we implement * the caching system. */ if (*vldata == NULL) { diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c index 4f520e61936..42c396a0d43 100644 --- a/source/blender/draw/engines/gpencil/gpencil_engine.c +++ b/source/blender/draw/engines/gpencil/gpencil_engine.c @@ -799,7 +799,7 @@ static void gpencil_draw_mask(GPENCIL_Data *vedata, GPENCIL_tObject *ob, GPENCIL } GPENCIL_tLayer *mask_layer = gpencil_layer_cache_get(ob, i); - /* When filtering by viewlayer, the mask could be null and must be ignored. */ + /* When filtering by view-layer, the mask could be null and must be ignored. */ if (mask_layer == NULL) { continue; } diff --git a/source/blender/draw/intern/draw_view.cc b/source/blender/draw/intern/draw_view.cc index 326e8629e52..cb0e1370c28 100644 --- a/source/blender/draw/intern/draw_view.cc +++ b/source/blender/draw/intern/draw_view.cc @@ -260,13 +260,15 @@ void View::update_view_vectors() } /** - * If ortho : view_vecs[0] is the near-bottom-left corner of the frustum and - * view_vecs[1] is the vector going from the near-bottom-left corner to - * the far-top-right corner. - * If Persp : view_vecs[0].xy and view_vecs[1].xy are respectively the bottom-left corner - * when Z = 1, and top-left corner if Z = 1. - * view_vecs[0].z the near clip distance and view_vecs[1].z is the (signed) - * distance from the near plane to the far clip plane. + * - If orthographic: + * `view_vecs[0]` is the near-bottom-left corner of the frustum and + * `view_vecs[1]` is the vector going from the near-bottom-left corner to + * the far-top-right corner. + * - If perspective: + * `view_vecs[0].xy` and `view_vecs[1].xy` are respectively the bottom-left corner + * when `Z = 1`, and top-left corner if `Z = 1`. + * `view_vecs[0].z` the near clip distance and `view_vecs[1].z` is the (signed) + * distance from the near plane to the far clip plane. */ copy_v3_v3(data_.viewvecs[0], view_vecs[0]); diff --git a/source/blender/editors/interface/interface_drag.cc b/source/blender/editors/interface/interface_drag.cc index 0c7c3a238ec..4bf2dac4151 100644 --- a/source/blender/editors/interface/interface_drag.cc +++ b/source/blender/editors/interface/interface_drag.cc @@ -37,7 +37,7 @@ void UI_but_drag_set_asset(uiBut *but, { wmDragAsset *asset_drag = WM_drag_create_asset_data(asset, metadata, path, import_type); - /* FIXME: This is temporary evil solution to get scene/viewlayer/etc in the copy callback of the + /* FIXME: This is temporary evil solution to get scene/view-layer/etc in the copy callback of the * #wmDropBox. * TODO: Handle link/append in operator called at the end of the drop process, and NOT in its * copy callback. diff --git a/source/blender/editors/mesh/meshtools.cc b/source/blender/editors/mesh/meshtools.cc index 9d1ea499e42..108fa210075 100644 --- a/source/blender/editors/mesh/meshtools.cc +++ b/source/blender/editors/mesh/meshtools.cc @@ -253,7 +253,7 @@ static void join_mesh_single(Depsgraph *depsgraph, CustomData_merge(&me->pdata, pdata, CD_MASK_MESH.pmask, CD_SET_DEFAULT, totpoly); CustomData_copy_data_named(&me->pdata, pdata, 0, *polyofs, me->totpoly); - /* Apply matmap. In case we dont have material indices yet, create them if more than one + /* Apply matmap. In case we don't have material indices yet, create them if more than one * material is the result of joining. */ int *material_indices = static_cast( CustomData_get_layer_named(pdata, CD_PROP_INT32, "material_index")); diff --git a/source/blender/editors/space_outliner/outliner_draw.cc b/source/blender/editors/space_outliner/outliner_draw.cc index d8c94d8ee6c..4259d3572be 100644 --- a/source/blender/editors/space_outliner/outliner_draw.cc +++ b/source/blender/editors/space_outliner/outliner_draw.cc @@ -285,7 +285,7 @@ static void outliner_object_set_flag_recursive_fn(bContext *C, } else { Base *base_iter = BKE_view_layer_base_find(view_layer, ob_iter); - /* Child can be in a collection excluded from viewlayer. */ + /* Child can be in a collection excluded from view-layer. */ if (base_iter == nullptr) { continue; } diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h index a83262d7639..6a2f25f3975 100644 --- a/source/blender/makesdna/DNA_gpencil_types.h +++ b/source/blender/makesdna/DNA_gpencil_types.h @@ -579,7 +579,7 @@ typedef enum eGPDlayer_Flag { GP_LAYER_USE_MASK = (1 << 13), /* TODO: DEPRECATED */ /* Ruler Layer */ GP_LAYER_IS_RULER = (1 << 14), - /* Disable masks in viewlayer render */ + /* Disable masks in view-layer render */ GP_LAYER_DISABLE_MASKS_IN_VIEWLAYER = (1 << 15), } eGPDlayer_Flag; diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index bcf1bd36539..5ac6bfea879 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -560,8 +560,8 @@ static Mesh *arrayModifier_doArray(ArrayModifierData *amd, CustomData_copy_data(&mesh->ldata, &result->ldata, 0, 0, chunk_nloops); CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, chunk_npolys); - /* Subsurf for eg won't have mesh data in the custom data arrays. - * now add mvert/medge/mpoly layers. */ + /* Subdivision-surface for eg won't have mesh data in the custom-data arrays. + * Now add #MVert/#MEdge/#MPoly layers. */ if (!CustomData_has_layer(&mesh->vdata, CD_MVERT)) { memcpy(result_verts, src_verts, sizeof(MVert) * mesh->totvert); } -- cgit v1.2.3 From 274dc024f62c4d65cbcf6689462327068c4d2206 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 15:38:27 +1000 Subject: Cleanup: format, trailing space --- source/blender/draw/intern/draw_command.hh | 2 +- .../blender/draw/intern/shaders/draw_resource_finalize_comp.glsl | 2 +- source/blender/draw/intern/shaders/draw_visibility_comp.glsl | 2 +- source/blender/editors/sculpt_paint/curves_sculpt_density.cc | 9 ++++----- .../blender/gpu/metal/kernels/gpu_shader_fullscreen_blit_info.hh | 2 +- source/blender/gpu/metal/mtl_primitive.hh | 2 +- 6 files changed, 9 insertions(+), 10 deletions(-) diff --git a/source/blender/draw/intern/draw_command.hh b/source/blender/draw/intern/draw_command.hh index b9117580d91..46a9199a267 100644 --- a/source/blender/draw/intern/draw_command.hh +++ b/source/blender/draw/intern/draw_command.hh @@ -531,4 +531,4 @@ class DrawMultiBuf { /** \} */ -}; // namespace blender::draw::command \ No newline at end of file +}; // namespace blender::draw::command diff --git a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl index d834435e54e..511d4e49651 100644 --- a/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_resource_finalize_comp.glsl @@ -61,4 +61,4 @@ void main() vec3 size_inv = safe_rcp(size); infos_buf[resource_id].orco_add = -loc * size_inv; infos_buf[resource_id].orco_mul = size_inv; -} \ No newline at end of file +} diff --git a/source/blender/draw/intern/shaders/draw_visibility_comp.glsl b/source/blender/draw/intern/shaders/draw_visibility_comp.glsl index 7ec58c8f919..86add2d1fe2 100644 --- a/source/blender/draw/intern/shaders/draw_visibility_comp.glsl +++ b/source/blender/draw/intern/shaders/draw_visibility_comp.glsl @@ -43,4 +43,4 @@ void main() mask_visibility_bit(); } } -} \ No newline at end of file +} diff --git a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc index c33ee5e0727..a37eb4bb560 100644 --- a/source/blender/editors/sculpt_paint/curves_sculpt_density.cc +++ b/source/blender/editors/sculpt_paint/curves_sculpt_density.cc @@ -137,11 +137,10 @@ struct DensityAddOperationExecutor { /* Find UV map. */ VArraySpan surface_uv_map; if (curves_id_orig_->surface_uv_map != nullptr) { - surface_uv_map = surface_orig_->attributes() - .lookup(curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER); - surface_uv_map_eval_ = surface_eval_->attributes() - .lookup(curves_id_orig_->surface_uv_map, - ATTR_DOMAIN_CORNER); + surface_uv_map = surface_orig_->attributes().lookup(curves_id_orig_->surface_uv_map, + ATTR_DOMAIN_CORNER); + surface_uv_map_eval_ = surface_eval_->attributes().lookup( + curves_id_orig_->surface_uv_map, ATTR_DOMAIN_CORNER); } if (surface_uv_map.is_empty()) { report_missing_uv_map_on_original_surface(stroke_extension.reports); diff --git a/source/blender/gpu/metal/kernels/gpu_shader_fullscreen_blit_info.hh b/source/blender/gpu/metal/kernels/gpu_shader_fullscreen_blit_info.hh index 6af67ad44d2..469e488c176 100644 --- a/source/blender/gpu/metal/kernels/gpu_shader_fullscreen_blit_info.hh +++ b/source/blender/gpu/metal/kernels/gpu_shader_fullscreen_blit_info.hh @@ -20,4 +20,4 @@ GPU_SHADER_CREATE_INFO(fullscreen_blit) .sampler(0, ImageType::FLOAT_2D, "imageTexture", Frequency::PASS) .vertex_source("gpu_shader_fullscreen_blit_vert.glsl") .fragment_source("gpu_shader_fullscreen_blit_frag.glsl") - .do_static_compilation(true); \ No newline at end of file + .do_static_compilation(true); diff --git a/source/blender/gpu/metal/mtl_primitive.hh b/source/blender/gpu/metal/mtl_primitive.hh index 5aa7a533b95..b32854a04bf 100644 --- a/source/blender/gpu/metal/mtl_primitive.hh +++ b/source/blender/gpu/metal/mtl_primitive.hh @@ -97,4 +97,4 @@ static inline bool mtl_vertex_count_fits_primitive_type(uint32_t vertex_count, return false; } -} // namespace blender::gpu \ No newline at end of file +} // namespace blender::gpu -- cgit v1.2.3 From fb07bbb751223ddfa25ad326ae31004e5e5b96fb Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 15:44:03 +1000 Subject: License headers: use SPDX identifiers --- source/blender/blenlib/tests/BLI_bit_vector_test.cc | 2 +- source/blender/gpu/metal/mtl_index_buffer.hh | 1 + source/blender/gpu/metal/mtl_index_buffer.mm | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/source/blender/blenlib/tests/BLI_bit_vector_test.cc b/source/blender/blenlib/tests/BLI_bit_vector_test.cc index c477b464f0c..210f2be012d 100644 --- a/source/blender/blenlib/tests/BLI_bit_vector_test.cc +++ b/source/blender/blenlib/tests/BLI_bit_vector_test.cc @@ -1,4 +1,4 @@ -/* Apache License, Version 2.0 */ +/* SPDX-License-Identifier: Apache-2.0 */ #include "BLI_bit_vector.hh" #include "BLI_exception_safety_test_utils.hh" diff --git a/source/blender/gpu/metal/mtl_index_buffer.hh b/source/blender/gpu/metal/mtl_index_buffer.hh index fde26b16927..702aa7f27d6 100644 --- a/source/blender/gpu/metal/mtl_index_buffer.hh +++ b/source/blender/gpu/metal/mtl_index_buffer.hh @@ -1,3 +1,4 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup gpu diff --git a/source/blender/gpu/metal/mtl_index_buffer.mm b/source/blender/gpu/metal/mtl_index_buffer.mm index 99795d7bbd9..2195ab7538d 100644 --- a/source/blender/gpu/metal/mtl_index_buffer.mm +++ b/source/blender/gpu/metal/mtl_index_buffer.mm @@ -1,7 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ /** \file * \ingroup gpu */ + #include "mtl_index_buffer.hh" #include "mtl_context.hh" #include "mtl_debug.hh" -- cgit v1.2.3 From 43b1624eee17f8e329450d5ac49791e69b1985a2 Mon Sep 17 00:00:00 2001 From: Nate Rupsis Date: Fri, 9 Sep 2022 15:55:51 +1000 Subject: Fix T96787: Edit mode normalize fails to respect locked groups Add BKE_object_defgroup_flip_map_unlocked which excludes locked groups from the flip-map. Reviewed By: zanqdo, campbellbarton Ref D15317 --- source/blender/blenkernel/BKE_deform.h | 9 +++++++++ source/blender/blenkernel/intern/deform.c | 28 ++++++++++++++++++++++---- source/blender/editors/object/object_vgroup.cc | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index f58a5502788..08f7e7f3c96 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -53,6 +53,15 @@ struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, cons * \note caller must free. */ int *BKE_object_defgroup_flip_map(const struct Object *ob, int *flip_map_len, bool use_default); + +/** + * Returns flip map for only unlocked defgroups. + * \note caller must free. + */ +int *BKE_object_defgroup_flip_map_unlocked(const struct Object *ob, + int *flip_map_len, + bool use_default); + /** * \note caller must free. */ diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index f928079f3ea..d784dfb020d 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -572,7 +572,10 @@ void BKE_object_defgroup_active_index_set(Object *ob, const int new_index) *index = new_index; } -int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default) +static int *object_defgroup_unlocked_flip_map_ex(const Object *ob, + int *flip_map_len, + const bool use_default, + const bool use_only_unlocked) { const ListBase *defbase = BKE_object_defgroup_list(ob); int defbase_tot = *flip_map_len = BLI_listbase_count(defbase); @@ -583,9 +586,10 @@ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const boo bDeformGroup *dg; char name_flip[sizeof(dg->name)]; - int i, flip_num, *map = MEM_mallocN(defbase_tot * sizeof(int), __func__); + int i, flip_num; + int *map = MEM_mallocN(defbase_tot * sizeof(int), __func__); - for (i = 0; i < defbase_tot; i++) { + for (int i = 0; i < defbase_tot; i++) { map[i] = -1; } @@ -597,11 +601,15 @@ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const boo map[i] = i; } + if (use_only_unlocked && (dg->flag & DG_LOCK_WEIGHT)) { + continue; + } + BLI_string_flip_side_name(name_flip, dg->name, false, sizeof(name_flip)); if (!STREQ(name_flip, dg->name)) { flip_num = BKE_object_defgroup_name_index(ob, name_flip); - if (flip_num >= 0) { + if (flip_num != -1) { map[i] = flip_num; map[flip_num] = i; /* save an extra lookup */ } @@ -611,6 +619,18 @@ int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const boo return map; } +int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default) +{ + return object_defgroup_unlocked_flip_map_ex(ob, flip_map_len, use_default, false); +} + +int *BKE_object_defgroup_flip_map_unlocked(const Object *ob, + int *flip_map_len, + const bool use_default) +{ + return object_defgroup_unlocked_flip_map_ex(ob, flip_map_len, use_default, true); +} + int *BKE_object_defgroup_flip_map_single(const Object *ob, int *flip_map_len, const bool use_default, diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index d2cb7ad4b43..c9f96166e31 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -506,7 +506,7 @@ static void mesh_defvert_mirror_update_internal(Object *ob, if (def_nr == -1) { /* All vgroups, add groups where needed. */ int flip_map_len; - int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); + int *flip_map = BKE_object_defgroup_flip_map_unlocked(ob, &flip_map_len, true); BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true); MEM_freeN(flip_map); } -- cgit v1.2.3 From 87a45db522e822cac922641da0eff8a42b186223 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 16:02:37 +1000 Subject: Edit mode normalize fails to respect locked groups Add BKE_object_defgroup_flip_map_unlocked which excludes locked groups from the flip-map. Reviewed By: zanqdo, campbellbarton Maniphest Tasks: T96787 Ref D15317 --- source/blender/blenkernel/intern/deform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index d784dfb020d..faba56bb4c7 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -589,7 +589,7 @@ static int *object_defgroup_unlocked_flip_map_ex(const Object *ob, int i, flip_num; int *map = MEM_mallocN(defbase_tot * sizeof(int), __func__); - for (int i = 0; i < defbase_tot; i++) { + for (i = 0; i < defbase_tot; i++) { map[i] = -1; } -- cgit v1.2.3 From 1e6a0038604f131b73f4d682e6cbe6a21ec26f7e Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 16:20:32 +1000 Subject: Cleanup: move return arguments last, use `r_` prefix Also use '_num' suffix instead of '_tot'. --- source/blender/blenkernel/BKE_deform.h | 55 +++++---- source/blender/blenkernel/intern/deform.c | 160 +++++++++++++------------ source/blender/blenkernel/intern/mesh_mirror.c | 2 +- source/blender/editors/object/object_vgroup.cc | 8 +- 4 files changed, 113 insertions(+), 112 deletions(-) diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 08f7e7f3c96..677a1053826 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -52,23 +52,22 @@ struct bDeformGroup *BKE_object_defgroup_find_name(const struct Object *ob, cons /** * \note caller must free. */ -int *BKE_object_defgroup_flip_map(const struct Object *ob, int *flip_map_len, bool use_default); +int *BKE_object_defgroup_flip_map(const struct Object *ob, bool use_default, int *r_flip_map_num); /** * Returns flip map for only unlocked defgroups. * \note caller must free. */ int *BKE_object_defgroup_flip_map_unlocked(const struct Object *ob, - int *flip_map_len, - bool use_default); - + bool use_default, + int *r_flip_map_num); /** * \note caller must free. */ int *BKE_object_defgroup_flip_map_single(const struct Object *ob, - int *flip_map_len, bool use_default, - int defgroup); + int defgroup, + int *r_flip_map_num); int BKE_object_defgroup_flip_index(const struct Object *ob, int index, bool use_default); int BKE_object_defgroup_name_index(const struct Object *ob, const char *name); void BKE_object_defgroup_unique_name(struct bDeformGroup *dg, struct Object *ob); @@ -121,7 +120,7 @@ float BKE_defvert_array_find_weight_safe(const struct MDeformVert *dvert, int in * \return The total weight in all groups marked in the selection mask. */ float BKE_defvert_total_selected_weight(const struct MDeformVert *dv, - int defbase_tot, + int defbase_num, const bool *defbase_sel); /** @@ -133,9 +132,9 @@ float BKE_defvert_total_selected_weight(const struct MDeformVert *dv, * commutative with the collective weight function. */ float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv, - int defbase_tot, + int defbase_num, const bool *defbase_sel, - int defbase_tot_sel, + int defbase_sel_num, bool is_normalized); /* This much unlocked weight is considered equivalent to none. */ @@ -156,7 +155,7 @@ float BKE_defvert_calc_lock_relative_weight(float weight, */ float BKE_defvert_lock_relative_weight(float weight, const struct MDeformVert *dv, - int defbase_tot, + int defbase_num, const bool *defbase_locked, const bool *defbase_unlocked); @@ -169,7 +168,7 @@ void BKE_defvert_copy(struct MDeformVert *dvert_dst, const struct MDeformVert *d void BKE_defvert_copy_subset(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool *vgroup_subset, - int vgroup_tot); + int vgroup_num); /** * Overwrite weights filtered by vgroup_subset and with mirroring specified by the flip map * - do nothing if neither are set. @@ -178,9 +177,9 @@ void BKE_defvert_copy_subset(struct MDeformVert *dvert_dst, void BKE_defvert_mirror_subset(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const bool *vgroup_subset, - int vgroup_tot, + int vgroup_num, const int *flip_map, - int flip_map_len); + int flip_map_num); /** * Copy an index from one #MDeformVert to another. * - do nothing if neither are set. @@ -203,43 +202,43 @@ void BKE_defvert_sync(struct MDeformVert *dvert_dst, void BKE_defvert_sync_mapped(struct MDeformVert *dvert_dst, const struct MDeformVert *dvert_src, const int *flip_map, - int flip_map_len, + int flip_map_num, bool use_ensure); /** * be sure all flip_map values are valid */ void BKE_defvert_remap(struct MDeformVert *dvert, const int *map, int map_len); -void BKE_defvert_flip(struct MDeformVert *dvert, const int *flip_map, int flip_map_len); -void BKE_defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, int flip_map_len); +void BKE_defvert_flip(struct MDeformVert *dvert, const int *flip_map, int flip_map_num); +void BKE_defvert_flip_merged(struct MDeformVert *dvert, const int *flip_map, int flip_map_num); void BKE_defvert_normalize(struct MDeformVert *dvert); /** * Same as #BKE_defvert_normalize but takes a bool array. */ void BKE_defvert_normalize_subset(struct MDeformVert *dvert, const bool *vgroup_subset, - int vgroup_tot); + int vgroup_num); /** * Same as BKE_defvert_normalize() if the locked vgroup is not a member of the subset */ void BKE_defvert_normalize_lock_single(struct MDeformVert *dvert, const bool *vgroup_subset, - int vgroup_tot, + int vgroup_num, uint def_nr_lock); /** * Same as BKE_defvert_normalize() if no locked vgroup is a member of the subset */ void BKE_defvert_normalize_lock_map(struct MDeformVert *dvert, const bool *vgroup_subset, - int vgroup_tot, + int vgroup_num, const bool *lock_flags, - int defbase_tot); + int defbase_num); /* Utilities to 'extract' a given vgroup into a simple float array, * for verts, but also edges/polys/loops. */ void BKE_defvert_extract_vgroup_to_vertweights(const struct MDeformVert *dvert, int defgroup, - int num_verts, + int verts_num, bool invert_vgroup, float *r_weights); /** @@ -248,25 +247,25 @@ void BKE_defvert_extract_vgroup_to_vertweights(const struct MDeformVert *dvert, */ void BKE_defvert_extract_vgroup_to_edgeweights(const struct MDeformVert *dvert, int defgroup, - int num_verts, + int verts_num, const struct MEdge *edges, - int num_edges, + int edges_num, bool invert_vgroup, float *r_weights); void BKE_defvert_extract_vgroup_to_loopweights(const struct MDeformVert *dvert, int defgroup, - int num_verts, + int verts_num, const struct MLoop *loops, - int num_loops, + int loops_num, bool invert_vgroup, float *r_weights); void BKE_defvert_extract_vgroup_to_polyweights(const struct MDeformVert *dvert, int defgroup, - int num_verts, + int verts_num, const struct MLoop *loops, - int num_loops, + int loops_num, const struct MPoly *polys, - int num_polys, + int polys_num, bool invert_vgroup, float *r_weights); diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index faba56bb4c7..7940d65b1bb 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -94,10 +94,10 @@ bDeformGroup *BKE_defgroup_duplicate(const bDeformGroup *ingroup) void BKE_defvert_copy_subset(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool *vgroup_subset, - const int vgroup_tot) + const int vgroup_num) { int defgroup; - for (defgroup = 0; defgroup < vgroup_tot; defgroup++) { + for (defgroup = 0; defgroup < vgroup_num; defgroup++) { if (vgroup_subset[defgroup]) { BKE_defvert_copy_index(dvert_dst, defgroup, dvert_src, defgroup); } @@ -107,12 +107,12 @@ void BKE_defvert_copy_subset(MDeformVert *dvert_dst, void BKE_defvert_mirror_subset(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const bool *vgroup_subset, - const int vgroup_tot, + const int vgroup_num, const int *flip_map, - const int flip_map_len) + const int flip_map_num) { int defgroup; - for (defgroup = 0; defgroup < vgroup_tot && defgroup < flip_map_len; defgroup++) { + for (defgroup = 0; defgroup < vgroup_num && defgroup < flip_map_num; defgroup++) { if (vgroup_subset[defgroup] && (dvert_dst != dvert_src || flip_map[defgroup] != defgroup)) { BKE_defvert_copy_index(dvert_dst, flip_map[defgroup], dvert_src, defgroup); } @@ -189,13 +189,13 @@ void BKE_defvert_sync(MDeformVert *dvert_dst, const MDeformVert *dvert_src, cons void BKE_defvert_sync_mapped(MDeformVert *dvert_dst, const MDeformVert *dvert_src, const int *flip_map, - const int flip_map_len, + const int flip_map_num, const bool use_ensure) { if (dvert_src->totweight && dvert_dst->totweight) { MDeformWeight *dw_src = dvert_src->dw; for (int i = 0; i < dvert_src->totweight; i++, dw_src++) { - if (dw_src->def_nr < flip_map_len) { + if (dw_src->def_nr < flip_map_num) { MDeformWeight *dw_dst; if (use_ensure) { dw_dst = BKE_defvert_ensure_index(dvert_dst, flip_map[dw_src->def_nr]); @@ -226,14 +226,14 @@ void BKE_defvert_remap(MDeformVert *dvert, const int *map, const int map_len) void BKE_defvert_normalize_subset(MDeformVert *dvert, const bool *vgroup_subset, - const int vgroup_tot) + const int vgroup_num) { if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { MDeformWeight *dw = dvert->dw; - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { dw->weight = 1.0f; } } @@ -241,7 +241,7 @@ void BKE_defvert_normalize_subset(MDeformVert *dvert, MDeformWeight *dw = dvert->dw; float tot_weight = 0.0f; for (int i = dvert->totweight; i != 0; i--, dw++) { - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { tot_weight += dw->weight; } } @@ -250,7 +250,7 @@ void BKE_defvert_normalize_subset(MDeformVert *dvert, float scalar = 1.0f / tot_weight; dw = dvert->dw; for (int i = dvert->totweight; i != 0; i--, dw++) { - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { dw->weight *= scalar; /* in case of division errors with very low weights */ @@ -292,7 +292,7 @@ void BKE_defvert_normalize(MDeformVert *dvert) void BKE_defvert_normalize_lock_single(MDeformVert *dvert, const bool *vgroup_subset, - const int vgroup_tot, + const int vgroup_num, const uint def_nr_lock) { if (dvert->totweight == 0) { @@ -300,7 +300,7 @@ void BKE_defvert_normalize_lock_single(MDeformVert *dvert, } else if (dvert->totweight == 1) { MDeformWeight *dw = dvert->dw; - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { if (def_nr_lock != dw->def_nr) { dw->weight = 1.0f; } @@ -314,7 +314,7 @@ void BKE_defvert_normalize_lock_single(MDeformVert *dvert, float lock_iweight = 1.0f; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { if (dw->def_nr != def_nr_lock) { tot_weight += dw->weight; } @@ -331,7 +331,7 @@ void BKE_defvert_normalize_lock_single(MDeformVert *dvert, float scalar = (1.0f / tot_weight) * lock_iweight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { if (dw != dw_lock) { dw->weight *= scalar; @@ -346,17 +346,17 @@ void BKE_defvert_normalize_lock_single(MDeformVert *dvert, void BKE_defvert_normalize_lock_map(MDeformVert *dvert, const bool *vgroup_subset, - const int vgroup_tot, + const int vgroup_num, const bool *lock_flags, - const int defbase_tot) + const int defbase_num) { if (dvert->totweight == 0) { /* nothing */ } else if (dvert->totweight == 1) { MDeformWeight *dw = dvert->dw; - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == false)) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_num) && (lock_flags[dw->def_nr] == false)) { dw->weight = 1.0f; } } @@ -368,8 +368,8 @@ void BKE_defvert_normalize_lock_map(MDeformVert *dvert, float lock_iweight = 0.0f; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == false)) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_num) && (lock_flags[dw->def_nr] == false)) { tot_weight += dw->weight; } else { @@ -386,8 +386,8 @@ void BKE_defvert_normalize_lock_map(MDeformVert *dvert, float scalar = (1.0f / tot_weight) * lock_iweight; for (i = dvert->totweight, dw = dvert->dw; i != 0; i--, dw++) { - if ((dw->def_nr < vgroup_tot) && vgroup_subset[dw->def_nr]) { - if ((dw->def_nr < defbase_tot) && (lock_flags[dw->def_nr] == false)) { + if ((dw->def_nr < vgroup_num) && vgroup_subset[dw->def_nr]) { + if ((dw->def_nr < defbase_num) && (lock_flags[dw->def_nr] == false)) { dw->weight *= scalar; /* in case of division errors with very low weights */ @@ -399,13 +399,13 @@ void BKE_defvert_normalize_lock_map(MDeformVert *dvert, } } -void BKE_defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_len) +void BKE_defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_map_num) { MDeformWeight *dw; int i; for (dw = dvert->dw, i = 0; i < dvert->totweight; dw++, i++) { - if (dw->def_nr < flip_map_len) { + if (dw->def_nr < flip_map_num) { if (flip_map[dw->def_nr] >= 0) { dw->def_nr = flip_map[dw->def_nr]; } @@ -413,7 +413,7 @@ void BKE_defvert_flip(MDeformVert *dvert, const int *flip_map, const int flip_ma } } -void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip_map_len) +void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int flip_map_num) { MDeformWeight *dw, *dw_cpy; float weight; @@ -421,7 +421,7 @@ void BKE_defvert_flip_merged(MDeformVert *dvert, const int *flip_map, const int /* copy weights */ for (dw = dvert->dw, i = 0; i < totweight; dw++, i++) { - if (dw->def_nr < flip_map_len) { + if (dw->def_nr < flip_map_num) { if (flip_map[dw->def_nr] >= 0) { /* error checkers complain of this but we'll never get NULL return */ dw_cpy = BKE_defvert_ensure_index(dvert, flip_map[dw->def_nr]); @@ -573,23 +573,24 @@ void BKE_object_defgroup_active_index_set(Object *ob, const int new_index) } static int *object_defgroup_unlocked_flip_map_ex(const Object *ob, - int *flip_map_len, const bool use_default, - const bool use_only_unlocked) + const bool use_only_unlocked, + int *r_flip_map_num) { const ListBase *defbase = BKE_object_defgroup_list(ob); - int defbase_tot = *flip_map_len = BLI_listbase_count(defbase); + const int defbase_num = BLI_listbase_count(defbase); + *r_flip_map_num = defbase_num; - if (defbase_tot == 0) { + if (defbase_num == 0) { return NULL; } bDeformGroup *dg; char name_flip[sizeof(dg->name)]; int i, flip_num; - int *map = MEM_mallocN(defbase_tot * sizeof(int), __func__); + int *map = MEM_mallocN(defbase_num * sizeof(int), __func__); - for (i = 0; i < defbase_tot; i++) { + for (i = 0; i < defbase_num; i++) { map[i] = -1; } @@ -619,35 +620,36 @@ static int *object_defgroup_unlocked_flip_map_ex(const Object *ob, return map; } -int *BKE_object_defgroup_flip_map(const Object *ob, int *flip_map_len, const bool use_default) +int *BKE_object_defgroup_flip_map(const Object *ob, const bool use_default, int *r_flip_map_num) { - return object_defgroup_unlocked_flip_map_ex(ob, flip_map_len, use_default, false); + return object_defgroup_unlocked_flip_map_ex(ob, use_default, false, r_flip_map_num); } int *BKE_object_defgroup_flip_map_unlocked(const Object *ob, - int *flip_map_len, - const bool use_default) + const bool use_default, + int *r_flip_map_num) { - return object_defgroup_unlocked_flip_map_ex(ob, flip_map_len, use_default, true); + return object_defgroup_unlocked_flip_map_ex(ob, use_default, true, r_flip_map_num); } int *BKE_object_defgroup_flip_map_single(const Object *ob, - int *flip_map_len, const bool use_default, - int defgroup) + const int defgroup, + int *r_flip_map_num) { const ListBase *defbase = BKE_object_defgroup_list(ob); - int defbase_tot = *flip_map_len = BLI_listbase_count(defbase); + const int defbase_num = BLI_listbase_count(defbase); + *r_flip_map_num = defbase_num; - if (defbase_tot == 0) { + if (defbase_num == 0) { return NULL; } bDeformGroup *dg; char name_flip[sizeof(dg->name)]; - int i, flip_num, *map = MEM_mallocN(defbase_tot * sizeof(int), __func__); + int i, flip_num, *map = MEM_mallocN(defbase_num * sizeof(int), __func__); - for (i = 0; i < defbase_tot; i++) { + for (i = 0; i < defbase_num; i++) { map[i] = use_default ? i : -1; } @@ -796,7 +798,7 @@ MDeformWeight *BKE_defvert_ensure_index(MDeformVert *dvert, const int defgroup) return dw_new; } -void BKE_defvert_add_index_notest(MDeformVert *dvert, int defgroup, const float weight) +void BKE_defvert_add_index_notest(MDeformVert *dvert, const int defgroup, const float weight) { /* TODO: merge with #BKE_defvert_ensure_index! */ @@ -890,7 +892,7 @@ bool BKE_defvert_is_weight_zero(const struct MDeformVert *dvert, const int defgr } float BKE_defvert_total_selected_weight(const struct MDeformVert *dv, - int defbase_tot, + int defbase_num, const bool *defbase_sel) { float total = 0.0f; @@ -901,7 +903,7 @@ float BKE_defvert_total_selected_weight(const struct MDeformVert *dv, } for (int i = dv->totweight; i != 0; i--, dw++) { - if (dw->def_nr < defbase_tot) { + if (dw->def_nr < defbase_num) { if (defbase_sel[dw->def_nr]) { total += dw->weight; } @@ -912,17 +914,17 @@ float BKE_defvert_total_selected_weight(const struct MDeformVert *dv, } float BKE_defvert_multipaint_collective_weight(const struct MDeformVert *dv, - int defbase_tot, + const int defbase_num, const bool *defbase_sel, - int defbase_tot_sel, - bool is_normalized) + const int defbase_sel_num, + const bool is_normalized) { - float total = BKE_defvert_total_selected_weight(dv, defbase_tot, defbase_sel); + float total = BKE_defvert_total_selected_weight(dv, defbase_num, defbase_sel); /* in multipaint, get the average if auto normalize is inactive * get the sum if it is active */ if (!is_normalized) { - total /= defbase_tot_sel; + total /= defbase_sel_num; } return total; @@ -956,19 +958,19 @@ float BKE_defvert_calc_lock_relative_weight(float weight, return weight / (1.0f - locked_weight); } -float BKE_defvert_lock_relative_weight(float weight, +float BKE_defvert_lock_relative_weight(const float weight, const struct MDeformVert *dv, - int defbase_tot, + const int defbase_num, const bool *defbase_locked, const bool *defbase_unlocked) { - float unlocked = BKE_defvert_total_selected_weight(dv, defbase_tot, defbase_unlocked); + float unlocked = BKE_defvert_total_selected_weight(dv, defbase_num, defbase_unlocked); if (unlocked > 0.0f) { return weight / unlocked; } - float locked = BKE_defvert_total_selected_weight(dv, defbase_tot, defbase_locked); + float locked = BKE_defvert_total_selected_weight(dv, defbase_num, defbase_locked); return BKE_defvert_calc_lock_relative_weight(weight, locked, unlocked); } @@ -1030,12 +1032,12 @@ void BKE_defvert_array_free(MDeformVert *dvert, int totvert) void BKE_defvert_extract_vgroup_to_vertweights(const MDeformVert *dvert, const int defgroup, - const int num_verts, + const int verts_num, const bool invert_vgroup, float *r_weights) { if (dvert && defgroup != -1) { - int i = num_verts; + int i = verts_num; while (i--) { const float w = BKE_defvert_find_weight(&dvert[i], defgroup); @@ -1043,24 +1045,24 @@ void BKE_defvert_extract_vgroup_to_vertweights(const MDeformVert *dvert, } } else { - copy_vn_fl(r_weights, num_verts, invert_vgroup ? 1.0f : 0.0f); + copy_vn_fl(r_weights, verts_num, invert_vgroup ? 1.0f : 0.0f); } } void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert, const int defgroup, - const int num_verts, + const int verts_num, const MEdge *edges, - const int num_edges, + const int edges_num, const bool invert_vgroup, float *r_weights) { if (dvert && defgroup != -1) { - int i = num_edges; - float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__); + int i = edges_num; + float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)verts_num, __func__); BKE_defvert_extract_vgroup_to_vertweights( - dvert, defgroup, num_verts, invert_vgroup, tmp_weights); + dvert, defgroup, verts_num, invert_vgroup, tmp_weights); while (i--) { const MEdge *me = &edges[i]; @@ -1071,24 +1073,24 @@ void BKE_defvert_extract_vgroup_to_edgeweights(const MDeformVert *dvert, MEM_freeN(tmp_weights); } else { - copy_vn_fl(r_weights, num_edges, 0.0f); + copy_vn_fl(r_weights, edges_num, 0.0f); } } void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, const int defgroup, - const int num_verts, + const int verts_num, const MLoop *loops, - const int num_loops, + const int loops_num, const bool invert_vgroup, float *r_weights) { if (dvert && defgroup != -1) { - int i = num_loops; - float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__); + int i = loops_num; + float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)verts_num, __func__); BKE_defvert_extract_vgroup_to_vertweights( - dvert, defgroup, num_verts, invert_vgroup, tmp_weights); + dvert, defgroup, verts_num, invert_vgroup, tmp_weights); while (i--) { const MLoop *ml = &loops[i]; @@ -1099,26 +1101,26 @@ void BKE_defvert_extract_vgroup_to_loopweights(const MDeformVert *dvert, MEM_freeN(tmp_weights); } else { - copy_vn_fl(r_weights, num_loops, 0.0f); + copy_vn_fl(r_weights, loops_num, 0.0f); } } void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert, const int defgroup, - const int num_verts, + const int verts_num, const MLoop *loops, - const int UNUSED(num_loops), + const int UNUSED(loops_num), const MPoly *polys, - const int num_polys, + const int polys_num, const bool invert_vgroup, float *r_weights) { if (dvert && defgroup != -1) { - int i = num_polys; - float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)num_verts, __func__); + int i = polys_num; + float *tmp_weights = MEM_mallocN(sizeof(*tmp_weights) * (size_t)verts_num, __func__); BKE_defvert_extract_vgroup_to_vertweights( - dvert, defgroup, num_verts, invert_vgroup, tmp_weights); + dvert, defgroup, verts_num, invert_vgroup, tmp_weights); while (i--) { const MPoly *mp = &polys[i]; @@ -1135,7 +1137,7 @@ void BKE_defvert_extract_vgroup_to_polyweights(const MDeformVert *dvert, MEM_freeN(tmp_weights); } else { - copy_vn_fl(r_weights, num_polys, 0.0f); + copy_vn_fl(r_weights, polys_num, 0.0f); } } @@ -1227,7 +1229,7 @@ static bool data_transfer_layersmapping_vgroups_multisrc_to_dst(ListBase *r_map, const ListBase *src_list = BKE_object_defgroup_list(ob_src); ListBase *dst_defbase = BKE_object_defgroup_list_mutable(ob_dst); - int tot_dst = BLI_listbase_count(dst_defbase); + const int tot_dst = BLI_listbase_count(dst_defbase); const size_t elem_size = sizeof(*((MDeformVert *)NULL)); diff --git a/source/blender/blenkernel/intern/mesh_mirror.c b/source/blender/blenkernel/intern/mesh_mirror.c index a2804db609b..261bc3d150b 100644 --- a/source/blender/blenkernel/intern/mesh_mirror.c +++ b/source/blender/blenkernel/intern/mesh_mirror.c @@ -450,7 +450,7 @@ Mesh *BKE_mesh_mirror_apply_mirror_on_axis_for_modifier(MirrorModifierData *mmd, MDeformVert *dvert = BKE_mesh_deform_verts_for_write(result) + maxVerts; int *flip_map = NULL, flip_map_len = 0; - flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, false); + flip_map = BKE_object_defgroup_flip_map(ob, false, &flip_map_len); if (flip_map) { for (i = 0; i < maxVerts; dvert++, i++) { diff --git a/source/blender/editors/object/object_vgroup.cc b/source/blender/editors/object/object_vgroup.cc index c9f96166e31..1d1263494c7 100644 --- a/source/blender/editors/object/object_vgroup.cc +++ b/source/blender/editors/object/object_vgroup.cc @@ -277,7 +277,7 @@ void ED_vgroup_parray_mirror_sync(Object *ob, } int flip_map_len; - const int *flip_map = BKE_object_defgroup_flip_map(ob, &flip_map_len, true); + const int *flip_map = BKE_object_defgroup_flip_map(ob, true, &flip_map_len); for (int i_src = 0; i_src < dvert_tot; i_src++) { if (dvert_array[i_src] != nullptr) { @@ -506,7 +506,7 @@ static void mesh_defvert_mirror_update_internal(Object *ob, if (def_nr == -1) { /* All vgroups, add groups where needed. */ int flip_map_len; - int *flip_map = BKE_object_defgroup_flip_map_unlocked(ob, &flip_map_len, true); + int *flip_map = BKE_object_defgroup_flip_map_unlocked(ob, true, &flip_map_len); BKE_defvert_sync_mapped(dvert_dst, dvert_src, flip_map, flip_map_len, true); MEM_freeN(flip_map); } @@ -2392,8 +2392,8 @@ void ED_vgroup_mirror(Object *ob, } if (flip_vgroups) { - flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, &flip_map_len, false) : - BKE_object_defgroup_flip_map_single(ob, &flip_map_len, false, def_nr); + flip_map = all_vgroups ? BKE_object_defgroup_flip_map(ob, false, &flip_map_len) : + BKE_object_defgroup_flip_map_single(ob, false, def_nr, &flip_map_len); BLI_assert(flip_map != nullptr); -- cgit v1.2.3 From 3baca3171978f99498d0aeba6fedd9f02961ca07 Mon Sep 17 00:00:00 2001 From: Loren Osborn Date: Fri, 9 Sep 2022 16:49:42 +1000 Subject: Fix error extracting arguments from project_source_info Output of make encounters path names that are single-quoted. This causes the path to be misinterpreted and fail validation. Resolves error in "make check_cppcheck" Ref D15801 (partially applied) --- build_files/cmake/project_source_info.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build_files/cmake/project_source_info.py b/build_files/cmake/project_source_info.py index a544f5733f0..f29d068044c 100644 --- a/build_files/cmake/project_source_info.py +++ b/build_files/cmake/project_source_info.py @@ -30,6 +30,8 @@ from typing import ( cast, ) +import shlex + SOURCE_DIR = join(dirname(__file__), "..", "..") SOURCE_DIR = normpath(SOURCE_DIR) @@ -160,7 +162,7 @@ def build_info( for c in compilers: args = args.replace(c, fake_compiler) - args = args.split() + args = shlex.split(args) # end # remove compiler -- cgit v1.2.3 From 58945b07f1171d5f29018e3561870d99efc3597a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 17:40:19 +1000 Subject: Cleanup: remove paranoid NULL checks --- source/blender/blenlib/BLI_path_util.h | 3 ++- source/blender/blenlib/intern/path_util.c | 17 +++-------------- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index 06dd9ab0db9..a2caaa0851b 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -44,7 +44,8 @@ const char *BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; * \param relabase: Optional prefix to substitute for "//" on front of `dir`. * \param string: Area to return result. */ -void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file); +void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) + ATTR_NONNULL(2, 3, 4); /** * Ensures that the parent directory of `name` exists. * diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 623dd572b11..73396fb34b1 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1206,19 +1206,8 @@ bool BLI_make_existing_file(const char *name) void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) { - int sl; - - if (string) { - /* ensure this is always set even if dir/file are NULL */ - string[0] = '\0'; - - if (ELEM(NULL, dir, file)) { - return; /* We don't want any NULLs */ - } - } - else { - return; /* string is NULL, probably shouldn't happen but return anyway */ - } + /* Ensure this is always set & the following `strcat` works as expected. */ + string[0] = '\0'; /* Resolve relative references */ if (relabase && dir[0] == '/' && dir[1] == '/') { @@ -1266,7 +1255,7 @@ void BLI_make_file_string(const char *relabase, char *string, const char *dir, c /* Make sure string ends in one (and only one) slash */ /* first trim all slashes from the end of the string */ - sl = strlen(string); + int sl = strlen(string); while ((sl > 0) && ELEM(string[sl - 1], '/', '\\')) { string[sl - 1] = '\0'; sl--; -- cgit v1.2.3 From dc937c5aee4532485c1927c278fe099f2f471f7e Mon Sep 17 00:00:00 2001 From: Dalai Felinto Date: Fri, 9 Sep 2022 11:50:21 +0200 Subject: Fix Auto-offset for nodes: Revert "Cleanup: Return early" This "cleanup" commit broke Auto-offset for nodes. This reverts commit e3ef6a6660032ca18af53dd24cd19bf36e56a85c. --- .../editors/space_node/node_relationships.cc | 45 +++++++++++----------- source/blender/editors/space_node/node_select.cc | 40 +++++++++---------- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/source/blender/editors/space_node/node_relationships.cc b/source/blender/editors/space_node/node_relationships.cc index 40f5d20d06d..7dbaa8ccd6d 100644 --- a/source/blender/editors/space_node/node_relationships.cc +++ b/source/blender/editors/space_node/node_relationships.cc @@ -1727,35 +1727,34 @@ static int node_attach_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent SpaceNode &snode = *CTX_wm_space_node(C); bNodeTree &ntree = *snode.edittree; bNode *frame = node_find_frame_to_attach(region, ntree, event->mval); - if (frame == nullptr) { - return OPERATOR_CANCELLED; - } - LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { - if (node->flag & NODE_SELECT) { - if (node->parent == nullptr) { - /* disallow moving a parent into its child */ - if (nodeAttachNodeCheck(frame, node) == false) { - /* attach all unparented nodes */ - nodeAttachNode(node, frame); - } - } - else { - /* attach nodes which share parent with the frame */ - bNode *parent; - for (parent = frame->parent; parent; parent = parent->parent) { - if (parent == node->parent) { - break; - } - } - - if (parent) { + if (frame) { + LISTBASE_FOREACH_BACKWARD (bNode *, node, &ntree.nodes) { + if (node->flag & NODE_SELECT) { + if (node->parent == nullptr) { /* disallow moving a parent into its child */ if (nodeAttachNodeCheck(frame, node) == false) { - nodeDetachNode(node); + /* attach all unparented nodes */ nodeAttachNode(node, frame); } } + else { + /* attach nodes which share parent with the frame */ + bNode *parent; + for (parent = frame->parent; parent; parent = parent->parent) { + if (parent == node->parent) { + break; + } + } + + if (parent) { + /* disallow moving a parent into its child */ + if (nodeAttachNodeCheck(frame, node) == false) { + nodeDetachNode(node); + nodeAttachNode(node, frame); + } + } + } } } } diff --git a/source/blender/editors/space_node/node_select.cc b/source/blender/editors/space_node/node_select.cc index 82aaa2c3cc6..1f1ce9c0c2b 100644 --- a/source/blender/editors/space_node/node_select.cc +++ b/source/blender/editors/space_node/node_select.cc @@ -14,7 +14,6 @@ #include "BLI_lasso_2d.h" #include "BLI_listbase.h" #include "BLI_rect.h" -#include "BLI_set.hh" #include "BLI_string.h" #include "BLI_string_search.h" #include "BLI_string_utf8.h" @@ -645,29 +644,28 @@ static bool node_mouse_select(bContext *C, } } - if (!(changed || found)) { - return false; - } + /* update node order */ + if (changed || found) { + bool active_texture_changed = false; + bool viewer_node_changed = false; + if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) { + viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; + ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed); + } + else if (node != nullptr && node->type == GEO_NODE_VIEWER) { + ED_spreadsheet_context_paths_set_geometry_node(&bmain, &snode, node); + } + ED_node_set_active_viewer_key(&snode); + node_sort(*snode.edittree); + if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) || + viewer_node_changed) { + DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE); + } - bool active_texture_changed = false; - bool viewer_node_changed = false; - if ((node != nullptr) && (node_was_selected == false || params->select_passthrough == false)) { - viewer_node_changed = (node->flag & NODE_DO_OUTPUT) == 0 && node->type == GEO_NODE_VIEWER; - ED_node_set_active(&bmain, &snode, snode.edittree, node, &active_texture_changed); - } - else if (node != nullptr && node->type == GEO_NODE_VIEWER) { - ED_spreadsheet_context_paths_set_geometry_node(&bmain, &snode, node); - } - ED_node_set_active_viewer_key(&snode); - node_sort(*snode.edittree); - if ((active_texture_changed && has_workbench_in_texture_color(wm, scene, ob)) || - viewer_node_changed) { - DEG_id_tag_update(&snode.edittree->id, ID_RECALC_COPY_ON_WRITE); + WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); } - WM_event_add_notifier(C, NC_NODE | NA_SELECTED, nullptr); - - return true; + return changed || found; } static int node_select_exec(bContext *C, wmOperator *op) -- cgit v1.2.3 From 0817966f14fed0bdc062d8c6bf5034f934b24f14 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Fri, 9 Sep 2022 12:24:51 +0200 Subject: Cleanup: Remove unused attribute in draw manager. There are no plans to use the object attribute anymore. --- source/blender/draw/intern/draw_manager.hh | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/draw/intern/draw_manager.hh b/source/blender/draw/intern/draw_manager.hh index aff56b0307b..fbd3d28d3f4 100644 --- a/source/blender/draw/intern/draw_manager.hh +++ b/source/blender/draw/intern/draw_manager.hh @@ -98,7 +98,6 @@ class Manager { /** Number of object attribute recorded. */ uint attribute_len_ = 0; - Object *object = nullptr; Object *object_active = nullptr; public: -- cgit v1.2.3 From fa0f18b37d1154dcb3c1d3fcc9075f68f79c8631 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 9 Sep 2022 12:36:51 +0200 Subject: Cleanup: readfile: use correct type --- source/blender/blenloader/intern/readfile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c5cf80fe635..506595fd6fe 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3066,8 +3066,8 @@ static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *all * This is kept disabled as the #malloc for the text always leaks memory. */ #if 0 { - const short *sp = fd->filesdna->structs[bhead->SDNAnr]; - allocname = fd->filesdna->types[sp[0]]; + SDNA_Struct *sp = fd->filesdna->structs[bhead->SDNAnr]; + allocname = fd->filesdna->types[sp->type]; size_t allocname_size = strlen(allocname) + 1; char *allocname_buf = malloc(allocname_size); memcpy(allocname_buf, allocname, allocname_size); -- cgit v1.2.3 From 77a4bb02cc99bfd581c6bb9e35ca3fe53389915e Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 9 Sep 2022 13:03:53 +0200 Subject: Fix T100697: Curve nodes change colors at identity settings Shader and compositor curve nodes change their inputs even if they are at identity settings. That is because shader and compositor curve nodes evaluate their curve map texture samplers at the normalized input directly, disregarding the fact that the samplers are evaluated using linear interpolation. This causes the output to be slightly different that it should be. This patch remaps the evaluation parameters such that the texture sampler is evaluated at the center of the pixels. Differential Revision: https://developer.blender.org/D15811 Reviewed By: Clement Foucault --- .../shaders/common/gpu_shader_common_curves.glsl | 43 +++++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl b/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl index db8e114ec7a..e68c173c055 100644 --- a/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl +++ b/source/blender/gpu/shaders/common/gpu_shader_common_curves.glsl @@ -26,9 +26,29 @@ vec3 extrapolate_if_needed(vec3 parameters, vec3 values, vec3 start_slopes, vec3 return values + parameters * slopes; } -/* Curve maps are stored in sampler objects that are evaluated in the [0, 1] range, so normalize - * parameters accordingly. */ -#define NORMALIZE_PARAMETER(parameter, minimum, range) ((parameter - minimum) * range) +/* Curve maps are stored in texture samplers that are evaluated in the [0, 1] range, so normalize + * the parameters accordingly. Additionally, ensure that the parameters evaluate the sampler at the + * center of the pixels, because samplers are evaluated using linear interpolation. */ +float normalize_parameter(float parameter, float minimum, float range_divider) +{ + float normalized_parameter = (parameter - minimum) * range_divider; + + /* Curve maps have a fixed width of 257. We offset by the equivalent of half a pixel and scale + * down such that the normalized parameter 1.0 corresponds to the center of the last pixel. */ + float sampler_offset = 0.5 / 257.0; + float sampler_scale = 1.0 - (1.0 / 257.0); + return normalized_parameter * sampler_scale + sampler_offset; +} + +/* Same as normalize_parameter but vectorized. */ +vec3 normalize_parameters(vec3 parameters, vec3 minimums, vec3 range_dividers) +{ + vec3 normalized_parameters = (parameters - minimums) * range_dividers; + + float sampler_offset = 0.5 / 257.0; + float sampler_scale = 1.0 - (1.0 / 257.0); + return normalized_parameters * sampler_scale + sampler_offset; +} void curves_combined_rgb(float factor, vec4 color, @@ -46,7 +66,7 @@ void curves_combined_rgb(float factor, /* First, evaluate alpha curve map at all channels. The alpha curve is the Combined curve in the * UI. */ - vec3 parameters = NORMALIZE_PARAMETER(balanced.rgb, range_minimums.aaa, range_dividers.aaa); + vec3 parameters = normalize_parameters(balanced.rgb, range_minimums.aaa, range_dividers.aaa); result.r = texture(curve_map, vec2(parameters.x, layer)).a; result.g = texture(curve_map, vec2(parameters.y, layer)).a; result.b = texture(curve_map, vec2(parameters.z, layer)).a; @@ -55,13 +75,14 @@ void curves_combined_rgb(float factor, result.rgb = extrapolate_if_needed(parameters, result.rgb, start_slopes.aaa, end_slopes.aaa); /* Then, evaluate each channel on its curve map. */ - parameters = NORMALIZE_PARAMETER(result.rgb, range_minimums.rgb, range_dividers.rgb); + parameters = normalize_parameters(result.rgb, range_minimums.rgb, range_dividers.rgb); result.r = texture(curve_map, vec2(parameters.r, layer)).r; result.g = texture(curve_map, vec2(parameters.g, layer)).g; result.b = texture(curve_map, vec2(parameters.b, layer)).b; /* Then, extrapolate again if needed. */ result.rgb = extrapolate_if_needed(parameters, result.rgb, start_slopes.rgb, end_slopes.rgb); + result.a = color.a; result = mix(color, result, factor); @@ -83,13 +104,14 @@ void curves_combined_only(float factor, /* Evaluate alpha curve map at all channels. The alpha curve is the Combined curve in the * UI. */ - vec3 parameters = NORMALIZE_PARAMETER(balanced.rgb, range_minimum, range_divider); + vec3 parameters = normalize_parameters(balanced.rgb, vec3(range_minimum), vec3(range_divider)); result.r = texture(curve_map, vec2(parameters.x, layer)).a; result.g = texture(curve_map, vec2(parameters.y, layer)).a; result.b = texture(curve_map, vec2(parameters.z, layer)).a; /* Then, extrapolate if needed. */ result.rgb = extrapolate_if_needed(parameters, result.rgb, vec3(start_slope), vec3(end_slope)); + result.a = color.a; result = mix(color, result, factor); @@ -147,8 +169,8 @@ void curves_film_like(float factor, /* Evaluate alpha curve map at the maximum and minimum channels. The alpha curve is the Combined * curve in the UI. */ - float min_parameter = NORMALIZE_PARAMETER(minimum, range_minimum, range_divider); - float max_parameter = NORMALIZE_PARAMETER(maximum, range_minimum, range_divider); + float min_parameter = normalize_parameter(minimum, range_minimum, range_divider); + float max_parameter = normalize_parameter(maximum, range_minimum, range_divider); float new_min = texture(curve_map, vec2(min_parameter, layer)).a; float new_max = texture(curve_map, vec2(max_parameter, layer)).a; @@ -165,6 +187,7 @@ void curves_film_like(float factor, vec3 median_or_min = mix(vec3(new_median), vec3(new_min), channel_is_min); bvec3 channel_is_max = equal(balanced.rgb, vec3(maximum)); result.rgb = mix(median_or_min, vec3(new_max), channel_is_max); + result.a = color.a; result = mix(color, result, clamp(factor, 0.0, 1.0)); @@ -180,7 +203,7 @@ void curves_vector(vec3 vector, out vec3 result) { /* Evaluate each component on its curve map. */ - vec3 parameters = NORMALIZE_PARAMETER(vector, range_minimums, range_dividers); + vec3 parameters = normalize_parameters(vector, range_minimums, range_dividers); result.x = texture(curve_map, vec2(parameters.x, layer)).x; result.y = texture(curve_map, vec2(parameters.y, layer)).y; result.z = texture(curve_map, vec2(parameters.z, layer)).z; @@ -214,7 +237,7 @@ void curves_float(float value, out float result) { /* Evaluate the normalized value on the first curve map. */ - float parameter = NORMALIZE_PARAMETER(value, range_minimum, range_divider); + float parameter = normalize_parameter(value, range_minimum, range_divider); result = texture(curve_map, vec2(parameter, layer)).x; /* Then, extrapolate if needed. */ -- cgit v1.2.3 From ac66a819c14265ee3e0f48e4cb54b6c10b7fb064 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 9 Sep 2022 13:15:01 +0200 Subject: Realtime Compositor: Implement pixelate node This patch implements the pixelate node for the realtime compositor. Differential Revision: https://developer.blender.org/D15662 Reviewed By: Clement Foucault --- source/blender/blenlib/BLI_float3x3.hh | 16 ++++++++++++ source/blender/blenlib/BLI_math_matrix.h | 2 ++ source/blender/blenlib/intern/math_matrix.c | 6 +++++ source/blender/blenlib/tests/BLI_float3x3_test.cc | 16 ++++++++++++ .../composite/nodes/node_composite_pixelate.cc | 29 ++++++++++++++++++++++ 5 files changed, 69 insertions(+) diff --git a/source/blender/blenlib/BLI_float3x3.hh b/source/blender/blenlib/BLI_float3x3.hh index 6a9e7dd04f0..178973c155d 100644 --- a/source/blender/blenlib/BLI_float3x3.hh +++ b/source/blender/blenlib/BLI_float3x3.hh @@ -63,6 +63,15 @@ struct float3x3 { return result; } + static float3x3 from_scale(const float2 scale) + { + float3x3 result = zero(); + result.values[0][0] = scale.x; + result.values[1][1] = scale.y; + result.values[2][2] = 1.0f; + return result; + } + static float3x3 from_translation_rotation_scale(const float2 translation, float rotation, const float2 scale) @@ -190,6 +199,13 @@ struct float3x3 { return result; } + float2 scale_2d() const + { + float2 scale; + mat3_to_size_2d(scale, values); + return scale; + } + friend bool operator==(const float3x3 &a, const float3x3 &b) { return equals_m3m3(a.values, b.values); diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index 467e6db4805..19943614881 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -410,6 +410,8 @@ float mat4_to_xy_scale(const float mat[4][4]); void size_to_mat3(float R[3][3], const float size[3]); void size_to_mat4(float R[4][4], const float size[3]); +/** Return 2D size assuming the given matrix is a 2D affine matrix. */ +void mat3_to_size_2d(float size[2], const float M[3][3]); void mat3_to_size(float size[3], const float M[3][3]); void mat4_to_size(float size[3], const float M[4][4]); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index e96b12033a9..221ae84e74d 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -2127,6 +2127,12 @@ void size_to_mat4(float R[4][4], const float size[3]) R[3][3] = 1.0f; } +void mat3_to_size_2d(float size[2], const float M[3][3]) +{ + size[0] = len_v2(M[0]); + size[1] = len_v2(M[1]); +} + void mat3_to_size(float size[3], const float M[3][3]) { size[0] = len_v3(M[0]); diff --git a/source/blender/blenlib/tests/BLI_float3x3_test.cc b/source/blender/blenlib/tests/BLI_float3x3_test.cc index d22993ee69e..cd823b6e368 100644 --- a/source/blender/blenlib/tests/BLI_float3x3_test.cc +++ b/source/blender/blenlib/tests/BLI_float3x3_test.cc @@ -34,6 +34,15 @@ TEST(float3x3, Rotation) EXPECT_FLOAT_EQ(result[1], 1.0f); } +TEST(float3x3, Scale) +{ + float2 point(1.0f, 2.0f); + float3x3 transformation = float3x3::from_scale(float2(2.0f, 3.0f)); + float2 result = transformation * point; + EXPECT_FLOAT_EQ(result[0], 2.0f); + EXPECT_FLOAT_EQ(result[1], 6.0f); +} + TEST(float3x3, TranslationRotationScale) { float2 point(1.0f, 2.0f); @@ -116,4 +125,11 @@ TEST(float3x3, Origin) EXPECT_FLOAT_EQ(result[1], 3.0f); } +TEST(float3x3, GetScale2D) +{ + float2 scale(2.0f, 3.0f); + float3x3 transformation = float3x3::from_scale(scale); + EXPECT_EQ(scale, transformation.scale_2d()); +} + } // namespace blender::tests diff --git a/source/blender/nodes/composite/nodes/node_composite_pixelate.cc b/source/blender/nodes/composite/nodes/node_composite_pixelate.cc index 4567464a547..c4e42f8247d 100644 --- a/source/blender/nodes/composite/nodes/node_composite_pixelate.cc +++ b/source/blender/nodes/composite/nodes/node_composite_pixelate.cc @@ -5,6 +5,9 @@ * \ingroup cmpnodes */ +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + #include "COM_node_operation.hh" #include "node_composite_util.hh" @@ -27,8 +30,34 @@ class PixelateOperation : public NodeOperation { void execute() override { + /* It might seems strange that the input is passed through without any processing, but note + * that the actual processing happens inside the domain realization input processor of the + * input. Indeed, the pixelate node merely realizes its input on a smaller-sized domain that + * matches its apparent size, that is, its size after the domain transformation. The pixelate + * node has no effect if the input is scaled-up. See the compute_domain method for more + * information. */ get_input("Color").pass_through(get_result("Color")); } + + /* Compute a smaller-sized domain that matches the apparent size of the input while having a unit + * scale transformation, see the execute method for more information. */ + Domain compute_domain() override + { + Domain domain = get_input("Color").domain(); + + /* Get the scaling component of the domain transformation, but make sure it doesn't exceed 1, + * because pixelation should only happen if the input is scaled down. */ + const float2 scale = math::min(float2(1.0f), domain.transformation.scale_2d()); + + /* Multiply the size of the domain by its scale to match its apparent size, but make sure it is + * at least 1 pixel in both axis. */ + domain.size = math::max(int2(float2(domain.size) * scale), int2(1)); + + /* Reset the scale of the transformation by transforming it with the inverse of the scale. */ + domain.transformation *= float3x3::from_scale(math::safe_divide(float2(1.0f), scale)); + + return domain; + } }; static NodeOperation *get_compositor_operation(Context &context, DNode node) -- cgit v1.2.3 From f15fecf0f701758b7cc4d9bf2d50153aed2cc8c8 Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 9 Sep 2022 13:16:13 +0200 Subject: Readfile: avoid confusion when debugging a memory leak --- source/blender/blenloader/intern/readfile.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 506595fd6fe..bf2017b80f4 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -3065,7 +3065,11 @@ static BHead *read_data_into_datamap(FileData *fd, BHead *bhead, const char *all * With the code below we get the struct-name to help tracking down the leak. * This is kept disabled as the #malloc for the text always leaks memory. */ #if 0 - { + if (bhead->SDNAnr == 0) { + /* The data type here is unclear because #writedata sets SDNAnr to 0. */ + allocname = "likely raw data"; + } + else { SDNA_Struct *sp = fd->filesdna->structs[bhead->SDNAnr]; allocname = fd->filesdna->types[sp->type]; size_t allocname_size = strlen(allocname) + 1; -- cgit v1.2.3 From 1339fec22a1aef25a719885977c4da3aab0e93fb Mon Sep 17 00:00:00 2001 From: Jacques Lucke Date: Fri, 9 Sep 2022 13:35:21 +0200 Subject: Nodes: fix memory leak --- source/blender/blenkernel/intern/node.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/source/blender/blenkernel/intern/node.cc b/source/blender/blenkernel/intern/node.cc index fadcceae393..2ae0b456b0d 100644 --- a/source/blender/blenkernel/intern/node.cc +++ b/source/blender/blenkernel/intern/node.cc @@ -1931,6 +1931,9 @@ static void node_socket_free(bNodeSocket *sock, const bool do_id_user) } MEM_freeN(sock->default_value); } + if (sock->default_attribute_name) { + MEM_freeN(sock->default_attribute_name); + } MEM_delete(sock->runtime); } @@ -3015,6 +3018,9 @@ static void node_socket_interface_free(bNodeTree *UNUSED(ntree), } MEM_freeN(sock->default_value); } + if (sock->default_attribute_name) { + MEM_freeN(sock->default_attribute_name); + } MEM_delete(sock->runtime); } -- cgit v1.2.3 From 04ae0fe46ba1f08ef141a051187bea3763afda8d Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 9 Sep 2022 13:57:04 +0200 Subject: Realtime Compositor: Implement blur node This patch implements the blur node for the realtime compositor. The patch is still missing the Variable Size option because it depends on the Erode/Dilate node, which is yet to be implemented. Furthermore, there are a number of optimizations that can be implemented, the most important of which is the IIR implementation of the Fast Gaussian filter, as well as the use of hardware filtering and thread local memory. The latter of which was attempted but was not robust enough, so it will be submitted as separate patch. Differential Revision: https://developer.blender.org/D15663 Reviewed By: Clement Foucault --- source/blender/gpu/CMakeLists.txt | 5 + .../compositor/compositor_symmetric_blur.glsl | 77 ++++ .../compositor_symmetric_separable_blur.glsl | 53 +++ .../infos/compositor_symmetric_blur_info.hh | 13 + .../compositor_symmetric_separable_blur_info.hh | 14 + .../library/gpu_shader_compositor_blur_common.glsl | 32 ++ .../nodes/composite/nodes/node_composite_blur.cc | 401 ++++++++++++++++++++- source/blender/render/intern/initrender.cc | 3 +- 8 files changed, 596 insertions(+), 2 deletions(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl create mode 100644 source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh create mode 100644 source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 47d4feb7ec9..cb5bb4331f9 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -345,8 +345,11 @@ set(GLSL_SRC shaders/compositor/compositor_screen_lens_distortion.glsl shaders/compositor/compositor_set_alpha.glsl shaders/compositor/compositor_split_viewer.glsl + shaders/compositor/compositor_symmetric_blur.glsl + shaders/compositor/compositor_symmetric_separable_blur.glsl shaders/compositor/library/gpu_shader_compositor_alpha_over.glsl + shaders/compositor/library/gpu_shader_compositor_blur_common.glsl shaders/compositor/library/gpu_shader_compositor_bright_contrast.glsl shaders/compositor/library/gpu_shader_compositor_channel_matte.glsl shaders/compositor/library/gpu_shader_compositor_chroma_matte.glsl @@ -620,6 +623,8 @@ set(SRC_SHADER_CREATE_INFOS shaders/compositor/infos/compositor_screen_lens_distortion_info.hh shaders/compositor/infos/compositor_set_alpha_info.hh shaders/compositor/infos/compositor_split_viewer_info.hh + shaders/compositor/infos/compositor_symmetric_blur_info.hh + shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh ) set(SRC_SHADER_CREATE_INFOS_MTL diff --git a/source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl new file mode 100644 index 00000000000..df08991a35c --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_symmetric_blur.glsl @@ -0,0 +1,77 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_blur_common.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +vec4 load_input(ivec2 texel) +{ + vec4 color; + if (extend_bounds) { + /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So + * we load the input with an offset by the radius amount and fallback to a transparent color if + * it is out of bounds. Notice that we subtract 1 because the weights texture have an extra + * center weight, see the SymmetricBlurWeights for more information. */ + ivec2 blur_size = texture_size(weights_tx) - 1; + color = texture_load(input_tx, texel - blur_size, vec4(0.0)); + } + else { + color = texture_load(input_tx, texel); + } + + if (gamma_correct) { + color = gamma_correct_blur_input(color); + } + + return color; +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 accumulated_color = vec4(0.0); + + /* First, compute the contribution of the center pixel. */ + vec4 center_color = load_input(texel); + accumulated_color += center_color * texture_load(weights_tx, ivec2(0)).x; + + ivec2 weights_size = texture_size(weights_tx); + + /* Then, compute the contributions of the pixels along the x axis of the filter, noting that the + * weights texture only stores the weights for the positive half, but since the filter is + * symmetric, the same weight is used for the negative half and we add both of their + * contributions. */ + for (int x = 1; x < weights_size.x; x++) { + float weight = texture_load(weights_tx, ivec2(x, 0)).x; + accumulated_color += load_input(texel + ivec2(x, 0)) * weight; + accumulated_color += load_input(texel + ivec2(-x, 0)) * weight; + } + + /* Then, compute the contributions of the pixels along the y axis of the filter, noting that the + * weights texture only stores the weights for the positive half, but since the filter is + * symmetric, the same weight is used for the negative half and we add both of their + * contributions. */ + for (int y = 1; y < weights_size.y; y++) { + float weight = texture_load(weights_tx, ivec2(0, y)).x; + accumulated_color += load_input(texel + ivec2(0, y)) * weight; + accumulated_color += load_input(texel + ivec2(0, -y)) * weight; + } + + /* Finally, compute the contributions of the pixels in the four quadrants of the filter, noting + * that the weights texture only stores the weights for the upper right quadrant, but since the + * filter is symmetric, the same weight is used for the rest of the quadrants and we add all four + * of their contributions. */ + for (int y = 1; y < weights_size.y; y++) { + for (int x = 1; x < weights_size.x; x++) { + float weight = texture_load(weights_tx, ivec2(x, y)).x; + accumulated_color += load_input(texel + ivec2(x, y)) * weight; + accumulated_color += load_input(texel + ivec2(-x, y)) * weight; + accumulated_color += load_input(texel + ivec2(x, -y)) * weight; + accumulated_color += load_input(texel + ivec2(-x, -y)) * weight; + } + } + + if (gamma_correct) { + accumulated_color = gamma_uncorrect_blur_output(accumulated_color); + } + + imageStore(output_img, texel, accumulated_color); +} diff --git a/source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl new file mode 100644 index 00000000000..ab0c7baa787 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_symmetric_separable_blur.glsl @@ -0,0 +1,53 @@ +#pragma BLENDER_REQUIRE(gpu_shader_compositor_blur_common.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +vec4 load_input(ivec2 texel) +{ + vec4 color; + if (extend_bounds) { + /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So + * we load the input with an offset by the radius amount and fallback to a transparent color if + * it is out of bounds. Notice that we subtract 1 because the weights texture have an extra + * center weight, see the SymmetricSeparableBlurWeights for more information. */ + int blur_size = texture_size(weights_tx) - 1; + color = texture_load(input_tx, texel - ivec2(blur_size, 0), vec4(0.0)); + } + else { + color = texture_load(input_tx, texel); + } + + if (gamma_correct_input) { + color = gamma_correct_blur_input(color); + } + + return color; +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + vec4 accumulated_color = vec4(0.0); + + /* First, compute the contribution of the center pixel. */ + vec4 center_color = load_input(texel); + accumulated_color += center_color * texture_load(weights_tx, 0).x; + + /* Then, compute the contributions of the pixel to the right and left, noting that the + * weights texture only stores the weights for the positive half, but since the filter is + * symmetric, the same weight is used for the negative half and we add both of their + * contributions. */ + for (int i = 1; i < texture_size(weights_tx); i++) { + float weight = texture_load(weights_tx, i).x; + accumulated_color += load_input(texel + ivec2(i, 0)) * weight; + accumulated_color += load_input(texel + ivec2(-i, 0)) * weight; + } + + if (gamma_uncorrect_output) { + accumulated_color = gamma_uncorrect_blur_output(accumulated_color); + } + + /* Write the color using the transposed texel. See the execute_separable_blur_horizontal_pass + * method for more information on the rational behind this. */ + imageStore(output_img, texel.yx, accumulated_color); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh new file mode 100644 index 00000000000..8ba2b4e04ef --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_blur_info.hh @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_symmetric_blur) + .local_group_size(16, 16) + .push_constant(Type::BOOL, "extend_bounds") + .push_constant(Type::BOOL, "gamma_correct") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "weights_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_symmetric_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh new file mode 100644 index 00000000000..57247dba4b8 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_symmetric_separable_blur_info.hh @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_symmetric_separable_blur) + .local_group_size(16, 16) + .push_constant(Type::BOOL, "extend_bounds") + .push_constant(Type::BOOL, "gamma_correct_input") + .push_constant(Type::BOOL, "gamma_uncorrect_output") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_1D, "weights_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_symmetric_separable_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl new file mode 100644 index 00000000000..e404c03bbb0 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/library/gpu_shader_compositor_blur_common.glsl @@ -0,0 +1,32 @@ +/* Preprocess the input of the blur filter by squaring it in its alpha straight form, assuming the + * given color is alpha premultiplied. */ +vec4 gamma_correct_blur_input(vec4 color) +{ + /* Unpremultiply alpha. */ + color.rgb /= color.a > 0.0 ? color.a : 1.0; + + /* Square color channel if it is positive, otherwise zero it. */ + color.rgb *= mix(color.rgb, vec3(0.0), lessThan(color.rgb, vec3(0.0))); + + /* Premultiply alpha to undo previous alpha unpremultiplication. */ + color.rgb *= color.a > 0.0 ? color.a : 1.0; + + return color; +} + +/* Postprocess the output of the blur filter by taking its square root it in its alpha straight + * form, assuming the given color is alpha premultiplied. This essential undoes the processing done + * by the gamma_correct_blur_input function. */ +vec4 gamma_uncorrect_blur_output(vec4 color) +{ + /* Unpremultiply alpha. */ + color.rgb /= color.a > 0.0 ? color.a : 1.0; + + /* Take the square root of the color channel if it is positive, otherwise zero it. */ + color.rgb = mix(sqrt(color.rgb), vec3(0.0), lessThan(color.rgb, vec3(0.0))); + + /* Premultiply alpha to undo previous alpha unpremultiplication. */ + color.rgb *= color.a > 0.0 ? color.a : 1.0; + + return color; +} diff --git a/source/blender/nodes/composite/nodes/node_composite_blur.cc b/source/blender/nodes/composite/nodes/node_composite_blur.cc index cb1d93fe10b..630f18361e3 100644 --- a/source/blender/nodes/composite/nodes/node_composite_blur.cc +++ b/source/blender/nodes/composite/nodes/node_composite_blur.cc @@ -5,12 +5,27 @@ * \ingroup cmpnodes */ +#include + +#include "BLI_array.hh" +#include "BLI_assert.h" +#include "BLI_index_range.hh" +#include "BLI_math_base.hh" +#include "BLI_math_vec_types.hh" +#include "BLI_math_vector.hh" + #include "RNA_access.h" #include "UI_interface.h" #include "UI_resources.h" +#include "RE_pipeline.h" + +#include "GPU_state.h" +#include "GPU_texture.h" + #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" @@ -18,6 +33,8 @@ namespace blender::nodes::node_composite_blur_cc { +NODE_STORAGE_FUNCS(NodeBlurData) + static void cmp_node_blur_declare(NodeDeclarationBuilder &b) { b.add_input(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); @@ -75,13 +92,395 @@ static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), Point using namespace blender::realtime_compositor; +/* A helper class that computes and caches a 1D GPU texture containing the weights of the separable + * filter of the given type and radius. The filter is assumed to be symmetric, because the filter + * functions are all even functions. Consequently, only the positive half of the filter is computed + * and the shader takes that into consideration. */ +class SymmetricSeparableBlurWeights { + private: + float radius_ = 1.0f; + int type_ = R_FILTER_GAUSS; + GPUTexture *texture_ = nullptr; + + public: + ~SymmetricSeparableBlurWeights() + { + if (texture_) { + GPU_texture_free(texture_); + } + } + + /* Check if a texture containing the weights was already computed for the given filter type and + * radius. If such texture exists, do nothing, otherwise, free the already computed texture and + * recompute it with the given filter type and radius. */ + void update(float radius, int type) + { + if (texture_ && type == type_ && radius == radius_) { + return; + } + + if (texture_) { + GPU_texture_free(texture_); + } + + /* The size of filter is double the radius plus 1, but since the filter is symmetric, we only + * compute half of it and no doubling happens. We add 1 to make sure the filter size is always + * odd and there is a center weight. */ + const int size = math::ceil(radius) + 1; + Array weights(size); + + float sum = 0.0f; + + /* First, compute the center weight. */ + const float center_weight = RE_filter_value(type, 0.0f); + weights[0] = center_weight; + sum += center_weight; + + /* Second, compute the other weights in the positive direction, making sure to add double the + * weight to the sum of weights because the filter is symmetric and we only loop over half of + * it. Skip the center weight already computed by dropping the front index. */ + const float scale = radius > 0.0f ? 1.0f / radius : 0.0f; + for (const int i : weights.index_range().drop_front(1)) { + const float weight = RE_filter_value(type, i * scale); + weights[i] = weight; + sum += weight * 2.0f; + } + + /* Finally, normalize the weights. */ + for (const int i : weights.index_range()) { + weights[i] /= sum; + } + + texture_ = GPU_texture_create_1d("Weights", size, 1, GPU_R16F, weights.data()); + + type_ = type; + radius_ = radius; + } + + void bind_as_texture(GPUShader *shader, const char *texture_name) + { + const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + GPU_texture_bind(texture_, texture_image_unit); + } + + void unbind_as_texture() + { + GPU_texture_unbind(texture_); + } +}; + +/* A helper class that computes and caches a 2D GPU texture containing the weights of the filter of + * the given type and radius. The filter is assumed to be symmetric, because the filter functions + * are evaluated on the normalized distance to the center. Consequently, only the upper right + * quadrant are computed and the shader takes that into consideration. */ +class SymmetricBlurWeights { + private: + int type_ = R_FILTER_GAUSS; + float2 radius_ = float2(1.0f); + GPUTexture *texture_ = nullptr; + + public: + ~SymmetricBlurWeights() + { + if (texture_) { + GPU_texture_free(texture_); + } + } + + /* Check if a texture containing the weights was already computed for the given filter type and + * radius. If such texture exists, do nothing, otherwise, free the already computed texture and + * recompute it with the given filter type and radius. */ + void update(float2 radius, int type) + { + if (texture_ && type == type_ && radius == radius_) { + return; + } + + if (texture_) { + GPU_texture_free(texture_); + } + + /* The full size of filter is double the radius plus 1, but since the filter is symmetric, we + * only compute a single quadrant of it and so no doubling happens. We add 1 to make sure the + * filter size is always odd and there is a center weight. */ + const float2 scale = math::safe_divide(float2(1.0f), radius); + const int2 size = int2(math::ceil(radius)) + int2(1); + Array weights(size.x * size.y); + + float sum = 0.0f; + + /* First, compute the center weight. */ + const float center_weight = RE_filter_value(type, 0.0f); + weights[0] = center_weight; + sum += center_weight; + + /* Then, compute the weights along the positive x axis, making sure to add double the weight to + * the sum of weights because the filter is symmetric and we only loop over the positive half + * of the x axis. Skip the center weight already computed by dropping the front index. */ + for (const int x : IndexRange(size.x).drop_front(1)) { + const float weight = RE_filter_value(type, x * scale.x); + weights[x] = weight; + sum += weight * 2.0f; + } + + /* Then, compute the weights along the positive y axis, making sure to add double the weight to + * the sum of weights because the filter is symmetric and we only loop over the positive half + * of the y axis. Skip the center weight already computed by dropping the front index. */ + for (const int y : IndexRange(size.y).drop_front(1)) { + const float weight = RE_filter_value(type, y * scale.y); + weights[size.x * y] = weight; + sum += weight * 2.0f; + } + + /* Then, compute the other weights in the upper right quadrant, making sure to add quadruple + * the weight to the sum of weights because the filter is symmetric and we only loop over one + * quadrant of it. Skip the weights along the y and x axis already computed by dropping the + * front index. */ + for (const int y : IndexRange(size.y).drop_front(1)) { + for (const int x : IndexRange(size.x).drop_front(1)) { + const float weight = RE_filter_value(type, math::length(float2(x, y) * scale)); + weights[size.x * y + x] = weight; + sum += weight * 4.0f; + } + } + + /* Finally, normalize the weights. */ + for (const int y : IndexRange(size.y)) { + for (const int x : IndexRange(size.x)) { + weights[size.x * y + x] /= sum; + } + } + + texture_ = GPU_texture_create_2d("Weights", size.x, size.y, 1, GPU_R16F, weights.data()); + + type_ = type; + radius_ = radius; + } + + void bind_as_texture(GPUShader *shader, const char *texture_name) + { + const int texture_image_unit = GPU_shader_get_texture_binding(shader, texture_name); + GPU_texture_bind(texture_, texture_image_unit); + } + + void unbind_as_texture() + { + GPU_texture_unbind(texture_); + } +}; + class BlurOperation : public NodeOperation { + private: + /* Cached symmetric blur weights. */ + SymmetricBlurWeights blur_weights_; + /* Cached symmetric blur weights for the separable horizontal pass. */ + SymmetricSeparableBlurWeights blur_horizontal_weights_; + /* Cached symmetric blur weights for the separable vertical pass. */ + SymmetricSeparableBlurWeights blur_vertical_weights_; + public: using NodeOperation::NodeOperation; void execute() override { - get_input("Image").pass_through(get_result("Image")); + if (is_identity()) { + get_input("Image").pass_through(get_result("Image")); + return; + } + + if (use_separable_filter()) { + GPUTexture *horizontal_pass_result = execute_separable_blur_horizontal_pass(); + execute_separable_blur_vertical_pass(horizontal_pass_result); + } + else { + execute_blur(); + } + } + + void execute_blur() + { + GPUShader *shader = shader_manager().get("compositor_symmetric_blur"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1b(shader, "extend_bounds", get_extend_bounds()); + GPU_shader_uniform_1b(shader, "gamma_correct", node_storage(bnode()).gamma); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + blur_weights_.update(compute_blur_radius(), node_storage(bnode()).filtertype); + blur_weights_.bind_as_texture(shader, "weights_tx"); + + Domain domain = compute_domain(); + if (get_extend_bounds()) { + /* Add a radius amount of pixels in both sides of the image, hence the multiply by 2. */ + domain.size += int2(math::ceil(compute_blur_radius())) * 2; + } + + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + blur_weights_.unbind_as_texture(); + } + + GPUTexture *execute_separable_blur_horizontal_pass() + { + GPUShader *shader = shader_manager().get("compositor_symmetric_separable_blur"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1b(shader, "extend_bounds", get_extend_bounds()); + GPU_shader_uniform_1b(shader, "gamma_correct_input", node_storage(bnode()).gamma); + GPU_shader_uniform_1b(shader, "gamma_uncorrect_output", false); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + blur_horizontal_weights_.update(compute_blur_radius().x, node_storage(bnode()).filtertype); + blur_horizontal_weights_.bind_as_texture(shader, "weights_tx"); + + Domain domain = compute_domain(); + if (get_extend_bounds()) { + domain.size.x += static_cast(math::ceil(compute_blur_radius().x)) * 2; + } + + /* We allocate an output image of a transposed size, that is, with a height equivalent to the + * width of the input and vice versa. This is done as a performance optimization. The shader + * will blur the image horizontally and write it to the intermediate output transposed. Then + * the vertical pass will execute the same horizontal blur shader, but since its input is + * transposed, it will effectively do a vertical blur and write to the output transposed, + * effectively undoing the transposition in the horizontal pass. This is done to improve + * spatial cache locality in the shader and to avoid having two separate shaders for each blur + * pass. */ + const int2 transposed_domain = int2(domain.size.y, domain.size.x); + + GPUTexture *horizontal_pass_result = texture_pool().acquire_color(transposed_domain); + const int image_unit = GPU_shader_get_texture_binding(shader, "output_img"); + GPU_texture_image_bind(horizontal_pass_result, image_unit); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + input_image.unbind_as_texture(); + blur_horizontal_weights_.unbind_as_texture(); + GPU_texture_image_unbind(horizontal_pass_result); + + return horizontal_pass_result; + } + + void execute_separable_blur_vertical_pass(GPUTexture *horizontal_pass_result) + { + GPUShader *shader = shader_manager().get("compositor_symmetric_separable_blur"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1b(shader, "extend_bounds", get_extend_bounds()); + GPU_shader_uniform_1b(shader, "gamma_correct_input", false); + GPU_shader_uniform_1b(shader, "gamma_uncorrect_output", node_storage(bnode()).gamma); + + GPU_memory_barrier(GPU_BARRIER_TEXTURE_FETCH); + const int texture_image_unit = GPU_shader_get_texture_binding(shader, "input_tx"); + GPU_texture_bind(horizontal_pass_result, texture_image_unit); + + blur_vertical_weights_.update(compute_blur_radius().y, node_storage(bnode()).filtertype); + blur_vertical_weights_.bind_as_texture(shader, "weights_tx"); + + Domain domain = compute_domain(); + if (get_extend_bounds()) { + /* Add a radius amount of pixels in both sides of the image, hence the multiply by 2. */ + domain.size += int2(math::ceil(compute_blur_radius())) * 2; + } + + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + /* Notice that the domain is transposed, see the note on the horizontal pass method for more + * information on the reasoning behind this. */ + compute_dispatch_threads_at_least(shader, int2(domain.size.y, domain.size.x)); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + blur_vertical_weights_.unbind_as_texture(); + GPU_texture_unbind(horizontal_pass_result); + } + + float2 compute_blur_radius() + { + const float size = math::clamp(get_input("Size").get_float_value_default(1.0f), 0.0f, 1.0f); + + if (!node_storage(bnode()).relative) { + return float2(node_storage(bnode()).sizex, node_storage(bnode()).sizey) * size; + } + + int2 image_size = get_input("Image").domain().size; + switch (node_storage(bnode()).aspect) { + case CMP_NODE_BLUR_ASPECT_Y: + image_size.y = image_size.x; + break; + case CMP_NODE_BLUR_ASPECT_X: + image_size.x = image_size.y; + break; + default: + BLI_assert(node_storage(bnode()).aspect == CMP_NODE_BLUR_ASPECT_NONE); + break; + } + + return float2(image_size) * get_size_factor() * size; + } + + /* Returns true if the operation does nothing and the input can be passed through. */ + bool is_identity() + { + const Result &input = get_input("Image"); + /* Single value inputs can't be blurred and are returned as is. */ + if (input.is_single_value()) { + return true; + } + + /* Zero blur radius. The operation does nothing and the input can be passed through. */ + if (compute_blur_radius() == float2(0.0)) { + return true; + } + + return false; + } + + /* The blur node can operate with different filter types, evaluated on the normalized distance to + * the center of the filter. Some of those filters are separable and can be computed as such. If + * the bokeh member is disabled in the node, then the filter is always computed as separable even + * if it is not in fact separable, in which case, the used filter is a cheaper approximation to + * the actual filter. If the bokeh member is enabled, then the filter is computed as separable if + * it is in fact separable and as a normal 2D filter otherwise. */ + bool use_separable_filter() + { + if (!node_storage(bnode()).bokeh) { + return true; + } + + /* Both Box and Gaussian filters are separable. The rest is not. */ + switch (node_storage(bnode()).filtertype) { + case R_FILTER_BOX: + case R_FILTER_GAUSS: + case R_FILTER_FAST_GAUSS: + return true; + default: + return false; + } + } + + float2 get_size_factor() + { + return float2(node_storage(bnode()).percentx, node_storage(bnode()).percenty) / 100.0f; + } + + bool get_extend_bounds() + { + return bnode().custom1 & CMP_NODEFLAG_BLUR_EXTEND_BOUNDS; } }; diff --git a/source/blender/render/intern/initrender.cc b/source/blender/render/intern/initrender.cc index cc05aa8621e..1ea93cbf6c8 100644 --- a/source/blender/render/intern/initrender.cc +++ b/source/blender/render/intern/initrender.cc @@ -124,7 +124,8 @@ float RE_filter_value(int type, float x) } return 1.0f - x; - case R_FILTER_GAUSS: { + case R_FILTER_GAUSS: + case R_FILTER_FAST_GAUSS: { const float two_gaussfac2 = 2.0f * gaussfac * gaussfac; x *= 3.0f * gaussfac; return 1.0f / sqrtf((float)M_PI * two_gaussfac2) * expf(-x * x / two_gaussfac2); -- cgit v1.2.3 From 860c3dce1b7ff201eccf17ef39114be65df45a07 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 9 Sep 2022 13:44:55 +0200 Subject: Outliner: Don't show asset context menu when no IDs are selected The asset context menu operators only make sense when at least one ID is selected in the Outliner. So don't show them unless that's the case. This also means the menu items don't show up anymore for things like RNA properties, or the overridden properties in the Library Overrides Properties view. Also see 7eda9d8dda59. --- release/scripts/startup/bl_ui/space_outliner.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index ec0ad401f5a..4354f4fbf77 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -326,6 +326,15 @@ class OUTLINER_MT_object(Menu): class OUTLINER_MT_asset(Menu): bl_label = "Assets" + @classmethod + def poll(cls, context): + if hasattr(context, "id"): + return True + if len(context.selected_ids) > 0: + return True + + return False + def draw(self, _context): layout = self.layout -- cgit v1.2.3 From e254d8867d666846fa8455ac8415763127eb48b6 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Fri, 9 Sep 2022 13:52:51 +0200 Subject: Outliner: Hide library overrdies context menu when no IDs are selected The library overrides context menu operators only make sense when at least one ID is selected in the Outliner. So don't show them unless that's the case. This also means the menu items don't show up anymore for things like RNA properties, or the overridden properties in the Library Overrides Properties view. Also see 7eda9d8dda59 and the previous commit. --- release/scripts/startup/bl_ui/space_outliner.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/release/scripts/startup/bl_ui/space_outliner.py b/release/scripts/startup/bl_ui/space_outliner.py index 4354f4fbf77..5c488748db8 100644 --- a/release/scripts/startup/bl_ui/space_outliner.py +++ b/release/scripts/startup/bl_ui/space_outliner.py @@ -323,17 +323,20 @@ class OUTLINER_MT_object(Menu): OUTLINER_MT_context_menu.draw_common_operators(layout) +def has_selected_ids_in_context(context): + if hasattr(context, "id"): + return True + if len(context.selected_ids) > 0: + return True + + return False + class OUTLINER_MT_asset(Menu): bl_label = "Assets" @classmethod def poll(cls, context): - if hasattr(context, "id"): - return True - if len(context.selected_ids) > 0: - return True - - return False + return has_selected_ids_in_context(context) def draw(self, _context): layout = self.layout @@ -346,6 +349,10 @@ class OUTLINER_MT_asset(Menu): class OUTLINER_MT_liboverride(Menu): bl_label = "Library Override" + @classmethod + def poll(cls, context): + return has_selected_ids_in_context(context) + def draw(self, _context): layout = self.layout -- cgit v1.2.3 From 0fd39da3a96adfe30e5260f72ecc8c6d8b68b98f Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 9 Sep 2022 14:10:38 +0200 Subject: Realtime Compositor: Implement scale node This patch implements the Scale node for the realtime compositor. Differential Revision: https://developer.blender.org/D15758 Reviewed By: Clement Foucault --- source/blender/blenkernel/BKE_node.h | 9 -- source/blender/compositor/nodes/COM_ScaleNode.cc | 13 +- source/blender/makesdna/DNA_node_types.h | 15 +++ source/blender/makesrna/intern/rna_nodetree.c | 14 +- .../nodes/composite/nodes/node_composite_scale.cc | 149 ++++++++++++++++++++- 5 files changed, 172 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h index 46303a4e19c..55bf24f943e 100644 --- a/source/blender/blenkernel/BKE_node.h +++ b/source/blender/blenkernel/BKE_node.h @@ -1337,15 +1337,6 @@ void BKE_nodetree_remove_layer_n(struct bNodeTree *ntree, struct Scene *scene, i #define CMP_CHAN_RGB 1 #define CMP_CHAN_A 2 -/* scale node type, in custom1 */ -#define CMP_SCALE_RELATIVE 0 -#define CMP_SCALE_ABSOLUTE 1 -#define CMP_SCALE_SCENEPERCENT 2 -#define CMP_SCALE_RENDERPERCENT 3 -/* custom2 */ -#define CMP_SCALE_RENDERSIZE_FRAME_ASPECT (1 << 0) -#define CMP_SCALE_RENDERSIZE_FRAME_CROP (1 << 1) - /* track position node, in custom1 */ #define CMP_TRACKPOS_ABSOLUTE 0 #define CMP_TRACKPOS_RELATIVE_START 1 diff --git a/source/blender/compositor/nodes/COM_ScaleNode.cc b/source/blender/compositor/nodes/COM_ScaleNode.cc index 4813e49cd11..1d613a030d7 100644 --- a/source/blender/compositor/nodes/COM_ScaleNode.cc +++ b/source/blender/compositor/nodes/COM_ScaleNode.cc @@ -25,7 +25,7 @@ void ScaleNode::convert_to_operations(NodeConverter &converter, NodeOutput *output_socket = this->get_output_socket(0); switch (bnode->custom1) { - case CMP_SCALE_RELATIVE: { + case CMP_NODE_SCALE_RELATIVE: { ScaleRelativeOperation *operation = new ScaleRelativeOperation(); converter.add_operation(operation); @@ -39,7 +39,7 @@ void ScaleNode::convert_to_operations(NodeConverter &converter, break; } - case CMP_SCALE_SCENEPERCENT: { + case CMP_NODE_SCALE_RENDER_PERCENT: { SetValueOperation *scale_factor_operation = new SetValueOperation(); scale_factor_operation->set_value(context.get_render_percentage_as_factor()); converter.add_operation(scale_factor_operation); @@ -59,13 +59,14 @@ void ScaleNode::convert_to_operations(NodeConverter &converter, break; } - case CMP_SCALE_RENDERPERCENT: { + case CMP_NODE_SCALE_RENDER_SIZE: { const RenderData *rd = context.get_render_data(); const float render_size_factor = context.get_render_percentage_as_factor(); ScaleFixedSizeOperation *operation = new ScaleFixedSizeOperation(); /* framing options */ - operation->set_is_aspect((bnode->custom2 & CMP_SCALE_RENDERSIZE_FRAME_ASPECT) != 0); - operation->set_is_crop((bnode->custom2 & CMP_SCALE_RENDERSIZE_FRAME_CROP) != 0); + operation->set_is_aspect( + ELEM(bnode->custom2, CMP_NODE_SCALE_RENDER_SIZE_FIT, CMP_NODE_SCALE_RENDER_SIZE_CROP)); + operation->set_is_crop(bnode->custom2 == CMP_NODE_SCALE_RENDER_SIZE_CROP); operation->set_offset(bnode->custom3, bnode->custom4); operation->set_new_width(rd->xsch * render_size_factor); operation->set_new_height(rd->ysch * render_size_factor); @@ -79,7 +80,7 @@ void ScaleNode::convert_to_operations(NodeConverter &converter, break; } - case CMP_SCALE_ABSOLUTE: { + case CMP_NODE_SCALE_ABSOLUTE: { /* TODO: what is the use of this one.... perhaps some issues when the ui was updated... */ ScaleAbsoluteOperation *operation = new ScaleAbsoluteOperation(); converter.add_operation(operation); diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 28bbd3a3e4e..b19210968d9 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -2029,6 +2029,21 @@ typedef enum CMPNodeFlipMode { CMP_NODE_FLIP_X_Y = 2, } CMPNodeFlipMode; +/* Scale Node. Stored in custom1. */ +typedef enum CMPNodeScaleMethod { + CMP_NODE_SCALE_RELATIVE = 0, + CMP_NODE_SCALE_ABSOLUTE = 1, + CMP_NODE_SCALE_RENDER_PERCENT = 2, + CMP_NODE_SCALE_RENDER_SIZE = 3, +} CMPNodeScaleMethod; + +/* Scale Node. Stored in custom2. */ +typedef enum CMPNodeScaleRenderSizeMethod { + CMP_NODE_SCALE_RENDER_SIZE_STRETCH = 0, + CMP_NODE_SCALE_RENDER_SIZE_FIT = 1, + CMP_NODE_SCALE_RENDER_SIZE_CROP = 2, +} CMPNodeScaleRenderSizeMethod; + /* Filter Node. Stored in custom1. */ typedef enum CMPNodeFilterMethod { CMP_NODE_FILTER_SOFT = 0, diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index 0be1dd3117c..caeee35a80a 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -7190,18 +7190,18 @@ static void def_cmp_scale(StructRNA *srna) PropertyRNA *prop; static const EnumPropertyItem space_items[] = { - {CMP_SCALE_RELATIVE, "RELATIVE", 0, "Relative", ""}, - {CMP_SCALE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", ""}, - {CMP_SCALE_SCENEPERCENT, "SCENE_SIZE", 0, "Scene Size", ""}, - {CMP_SCALE_RENDERPERCENT, "RENDER_SIZE", 0, "Render Size", ""}, + {CMP_NODE_SCALE_RELATIVE, "RELATIVE", 0, "Relative", ""}, + {CMP_NODE_SCALE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", ""}, + {CMP_NODE_SCALE_RENDER_PERCENT, "SCENE_SIZE", 0, "Scene Size", ""}, + {CMP_NODE_SCALE_RENDER_SIZE, "RENDER_SIZE", 0, "Render Size", ""}, {0, NULL, 0, NULL, NULL}, }; /* matching bgpic_camera_frame_items[] */ static const EnumPropertyItem space_frame_items[] = { - {0, "STRETCH", 0, "Stretch", ""}, - {CMP_SCALE_RENDERSIZE_FRAME_ASPECT, "FIT", 0, "Fit", ""}, - {CMP_SCALE_RENDERSIZE_FRAME_ASPECT | CMP_SCALE_RENDERSIZE_FRAME_CROP, "CROP", 0, "Crop", ""}, + {CMP_NODE_SCALE_RENDER_SIZE_STRETCH, "STRETCH", 0, "Stretch", ""}, + {CMP_NODE_SCALE_RENDER_SIZE_FIT, "FIT", 0, "Fit", ""}, + {CMP_NODE_SCALE_RENDER_SIZE_CROP, "CROP", 0, "Crop", ""}, {0, NULL, 0, NULL, NULL}, }; diff --git a/source/blender/nodes/composite/nodes/node_composite_scale.cc b/source/blender/nodes/composite/nodes/node_composite_scale.cc index 8b43ae8c9ca..eb2d7162c69 100644 --- a/source/blender/nodes/composite/nodes/node_composite_scale.cc +++ b/source/blender/nodes/composite/nodes/node_composite_scale.cc @@ -5,6 +5,11 @@ * \ingroup cmpnodes */ +#include "BLI_assert.h" +#include "BLI_float3x3.hh" +#include "BLI_math_base.hh" +#include "BLI_math_vec_types.hh" + #include "RNA_access.h" #include "UI_interface.h" @@ -20,16 +25,26 @@ namespace blender::nodes::node_composite_scale_cc { static void cmp_node_scale_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Image")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input(N_("X")).default_value(1.0f).min(0.0001f).max(CMP_SCALE_MAX); - b.add_input(N_("Y")).default_value(1.0f).min(0.0001f).max(CMP_SCALE_MAX); + b.add_input(N_("Image")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_domain_priority(0); + b.add_input(N_("X")) + .default_value(1.0f) + .min(0.0001f) + .max(CMP_SCALE_MAX) + .compositor_expects_single_value(); + b.add_input(N_("Y")) + .default_value(1.0f) + .min(0.0001f) + .max(CMP_SCALE_MAX) + .compositor_expects_single_value(); b.add_output(N_("Image")); } static void node_composite_update_scale(bNodeTree *ntree, bNode *node) { bNodeSocket *sock; - bool use_xy_scale = ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_ABSOLUTE); + bool use_xy_scale = ELEM(node->custom1, CMP_NODE_SCALE_RELATIVE, CMP_NODE_SCALE_ABSOLUTE); /* Only show X/Y scale factor inputs for modes using them! */ for (sock = (bNodeSocket *)node->inputs.first; sock; sock = sock->next) { @@ -43,7 +58,7 @@ static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), Poin { uiItemR(layout, ptr, "space", UI_ITEM_R_SPLIT_EMPTY_NAME, "", ICON_NONE); - if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) { + if (RNA_enum_get(ptr, "space") == CMP_NODE_SCALE_RENDER_SIZE) { uiLayout *row; uiItemR(layout, ptr, @@ -65,7 +80,129 @@ class ScaleOperation : public NodeOperation { void execute() override { - get_input("Image").pass_through(get_result("Image")); + Result &input = get_input("Image"); + Result &result = get_result("Image"); + input.pass_through(result); + + const float3x3 transformation = float3x3::from_translation_rotation_scale( + get_translation(), 0.0f, get_scale()); + + result.transform(transformation); + result.get_realization_options().interpolation = Interpolation::Bilinear; + } + + float2 get_scale() + { + switch (get_scale_method()) { + case CMP_NODE_SCALE_RELATIVE: + return get_scale_relative(); + case CMP_NODE_SCALE_ABSOLUTE: + return get_scale_absolute(); + case CMP_NODE_SCALE_RENDER_PERCENT: + return get_scale_render_percent(); + case CMP_NODE_SCALE_RENDER_SIZE: + return get_scale_render_size(); + default: + BLI_assert_unreachable(); + return float2(1.0f); + } + } + + /* Scale by the input factors. */ + float2 get_scale_relative() + { + return float2(get_input("X").get_float_value_default(1.0f), + get_input("Y").get_float_value_default(1.0f)); + } + + /* Scale such that the new size matches the input absolute size. */ + float2 get_scale_absolute() + { + const float2 input_size = float2(get_input("Image").domain().size); + const float2 absolute_size = float2(get_input("X").get_float_value_default(1.0f), + get_input("Y").get_float_value_default(1.0f)); + return absolute_size / input_size; + } + + /* Scale by the render resolution percentage. */ + float2 get_scale_render_percent() + { + return float2(context().get_scene()->r.size / 100.0f); + } + + float2 get_scale_render_size() + { + switch (get_scale_render_size_method()) { + case CMP_NODE_SCALE_RENDER_SIZE_STRETCH: + return get_scale_render_size_stretch(); + case CMP_NODE_SCALE_RENDER_SIZE_FIT: + return get_scale_render_size_fit(); + case CMP_NODE_SCALE_RENDER_SIZE_CROP: + return get_scale_render_size_crop(); + default: + BLI_assert_unreachable(); + return float2(1.0f); + } + } + + /* Scale such that the new size matches the render size. Since the input is freely scaled, it is + * potentially stretched, hence the name. */ + float2 get_scale_render_size_stretch() + { + const float2 input_size = float2(get_input("Image").domain().size); + const float2 render_size = float2(context().get_output_size()); + return render_size / input_size; + } + + /* Scale such that the dimension with the smaller scaling factor matches that of the render size + * while maintaining the input's aspect ratio. Since the other dimension is guaranteed not to + * exceed the render size region due to its larger scaling factor, the image is said to be fit + * inside that region, hence the name. */ + float2 get_scale_render_size_fit() + { + const float2 input_size = float2(get_input("Image").domain().size); + const float2 render_size = float2(context().get_output_size()); + const float2 scale = render_size / input_size; + return float2(math::min(scale.x, scale.y)); + } + + /* Scale such that the dimension with the larger scaling factor matches that of the render size + * while maintaining the input's aspect ratio. Since the other dimension is guaranteed to exceed + * the render size region due to its lower scaling factor, the image will be cropped inside that + * region, hence the name. */ + float2 get_scale_render_size_crop() + { + const float2 input_size = float2(get_input("Image").domain().size); + const float2 render_size = float2(context().get_output_size()); + const float2 scale = render_size / input_size; + return float2(math::max(scale.x, scale.y)); + } + + float2 get_translation() + { + /* Only the render size option supports offset translation. */ + if (get_scale_method() != CMP_NODE_SCALE_RENDER_SIZE) { + return float2(0.0f); + } + + /* Translate by the offset factor relative to the new size. */ + const float2 input_size = float2(get_input("Image").domain().size); + return get_offset() * input_size * get_scale(); + } + + CMPNodeScaleMethod get_scale_method() + { + return (CMPNodeScaleMethod)bnode().custom1; + } + + CMPNodeScaleRenderSizeMethod get_scale_render_size_method() + { + return (CMPNodeScaleRenderSizeMethod)bnode().custom2; + } + + float2 get_offset() + { + return float2(bnode().custom3, bnode().custom4); } }; -- cgit v1.2.3 From 03f33a6f237fba668d5caf900d9bdec73e366fef Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 9 Sep 2022 14:22:03 +0200 Subject: Realtime Compositor: Allow inputs to skip realization This patch adds support for the skip realization option of the input descriptor. Inputs that request skip realization will not be realized on the operation domain of the operation and will not contribute to its computation, and consequently, they can't be a domain input. An example is the bokeh input of the Bokeh Blur node, which is actually a resource that is decoupled from the rest of the inputs and should not affect or be affected by their domain. Differential Revision: https://developer.blender.org/D15767 Reviewed By: Clement Foucault --- .../realtime_compositor/intern/compile_state.cc | 5 +++++ .../compositor/realtime_compositor/intern/operation.cc | 5 +++++ .../compositor/realtime_compositor/intern/utilities.cc | 1 + source/blender/nodes/NOD_node_declaration.hh | 18 ++++++++++++++++++ 4 files changed, 29 insertions(+) diff --git a/source/blender/compositor/realtime_compositor/intern/compile_state.cc b/source/blender/compositor/realtime_compositor/intern/compile_state.cc index 97c1e47e86e..5fa2fc9d544 100644 --- a/source/blender/compositor/realtime_compositor/intern/compile_state.cc +++ b/source/blender/compositor/realtime_compositor/intern/compile_state.cc @@ -149,6 +149,11 @@ Domain CompileState::compute_shader_node_domain(DNode node) continue; } + /* An input that skips realization can't be a domain input. */ + if (input_descriptor.skip_realization) { + continue; + } + /* Notice that the lower the domain priority value is, the higher the priority is, hence the * less than comparison. */ if (input_descriptor.domain_priority < current_domain_priority) { diff --git a/source/blender/compositor/realtime_compositor/intern/operation.cc b/source/blender/compositor/realtime_compositor/intern/operation.cc index fb02807d729..832196cc5ef 100644 --- a/source/blender/compositor/realtime_compositor/intern/operation.cc +++ b/source/blender/compositor/realtime_compositor/intern/operation.cc @@ -66,6 +66,11 @@ Domain Operation::compute_domain() continue; } + /* An input that skips realization can't be a domain input. */ + if (descriptor.skip_realization) { + continue; + } + /* Notice that the lower the domain priority value is, the higher the priority is, hence the * less than comparison. */ if (descriptor.domain_priority < current_domain_priority) { diff --git a/source/blender/compositor/realtime_compositor/intern/utilities.cc b/source/blender/compositor/realtime_compositor/intern/utilities.cc index 2e1baec98a8..1a5823b8441 100644 --- a/source/blender/compositor/realtime_compositor/intern/utilities.cc +++ b/source/blender/compositor/realtime_compositor/intern/utilities.cc @@ -116,6 +116,7 @@ InputDescriptor input_descriptor_from_input_socket(const bNodeSocket *socket) } const SocketDeclarationPtr &socket_declaration = node_declaration->inputs()[socket->index()]; input_descriptor.domain_priority = socket_declaration->compositor_domain_priority(); + input_descriptor.skip_realization = socket_declaration->compositor_skip_realization(); input_descriptor.expects_single_value = socket_declaration->compositor_expects_single_value(); return input_descriptor; } diff --git a/source/blender/nodes/NOD_node_declaration.hh b/source/blender/nodes/NOD_node_declaration.hh index d8b8c354230..42755b2e8dd 100644 --- a/source/blender/nodes/NOD_node_declaration.hh +++ b/source/blender/nodes/NOD_node_declaration.hh @@ -92,6 +92,10 @@ class SocketDeclaration { * realtime_compositor::InputDescriptor for more information. */ int compositor_domain_priority_ = 0; + /** This input shouldn't be realized on the operation domain of the node. See + * realtime_compositor::InputDescriptor for more information. */ + bool compositor_skip_realization_ = false; + /** This input expects a single value and can't operate on non-single values. See * realtime_compositor::InputDescriptor for more information. */ bool compositor_expects_single_value_ = false; @@ -133,6 +137,7 @@ class SocketDeclaration { const OutputFieldDependency &output_field_dependency() const; int compositor_domain_priority() const; + bool compositor_skip_realization() const; bool compositor_expects_single_value() const; protected: @@ -257,6 +262,14 @@ class SocketDeclarationBuilder : public BaseSocketDeclarationBuilder { return *(Self *)this; } + /** This input shouldn't be realized on the operation domain of the node. See + * realtime_compositor::InputDescriptor for more information. */ + Self &compositor_skip_realization(bool value = true) + { + decl_->compositor_skip_realization_ = value; + return *(Self *)this; + } + /** This input expects a single value and can't operate on non-single values. See * realtime_compositor::InputDescriptor for more information. */ Self &compositor_expects_single_value(bool value = true) @@ -460,6 +473,11 @@ inline int SocketDeclaration::compositor_domain_priority() const return compositor_domain_priority_; } +inline bool SocketDeclaration::compositor_skip_realization() const +{ + return compositor_skip_realization_; +} + inline bool SocketDeclaration::compositor_expects_single_value() const { return compositor_expects_single_value_; -- cgit v1.2.3 From f4e5a8654487ef8b66cf5fb2ca3f4d66cb207618 Mon Sep 17 00:00:00 2001 From: Omar Emara Date: Fri, 9 Sep 2022 14:32:58 +0200 Subject: Realtime Compositor: Implement bokeh blur node This patch implements the bokeh blur node for the realtime compositor. The patch is still missing the Variable Size option because it depends on the Levels node, which is yet to be implemented. In particular, it requires the computation of global texture properties like the maximum color. Differential Revision: https://developer.blender.org/D15768 Reviewed By: Clement Foucault --- source/blender/gpu/CMakeLists.txt | 2 + .../gpu/shaders/compositor/compositor_blur.glsl | 55 +++++++++++ .../compositor/infos/compositor_blur_info.hh | 14 +++ .../composite/nodes/node_composite_bokehblur.cc | 103 ++++++++++++++++++++- 4 files changed, 169 insertions(+), 5 deletions(-) create mode 100644 source/blender/gpu/shaders/compositor/compositor_blur.glsl create mode 100644 source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index cb5bb4331f9..8b38c22ae28 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -326,6 +326,7 @@ set(GLSL_SRC shaders/compositor/compositor_alpha_crop.glsl shaders/compositor/compositor_bilateral_blur.glsl + shaders/compositor/compositor_blur.glsl shaders/compositor/compositor_bokeh_image.glsl shaders/compositor/compositor_box_mask.glsl shaders/compositor/compositor_convert.glsl @@ -604,6 +605,7 @@ set(SRC_SHADER_CREATE_INFOS shaders/compositor/infos/compositor_alpha_crop_info.hh shaders/compositor/infos/compositor_bilateral_blur_info.hh + shaders/compositor/infos/compositor_blur_info.hh shaders/compositor/infos/compositor_bokeh_image_info.hh shaders/compositor/infos/compositor_box_mask_info.hh shaders/compositor/infos/compositor_convert_info.hh diff --git a/source/blender/gpu/shaders/compositor/compositor_blur.glsl b/source/blender/gpu/shaders/compositor/compositor_blur.glsl new file mode 100644 index 00000000000..4f981c84f59 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/compositor_blur.glsl @@ -0,0 +1,55 @@ +#pragma BLENDER_REQUIRE(gpu_shader_common_math_utils.glsl) +#pragma BLENDER_REQUIRE(gpu_shader_compositor_texture_utilities.glsl) + +vec4 load_input(ivec2 texel) +{ + vec4 color; + if (extend_bounds) { + /* If bounds are extended, then we treat the input as padded by a radius amount of pixels. So + * we load the input with an offset by the radius amount and fallback to a transparent color if + * it is out of bounds. */ + color = texture_load(input_tx, texel - radius, vec4(0.0)); + } + else { + color = texture_load(input_tx, texel); + } + + return color; +} + +/* Given the texel in the range [-radius, radius] in both axis, load the appropriate weight from + * the weights texture, where the texel (0, 0) is considered the center of weights texture. */ +vec4 load_weight(ivec2 texel) +{ + /* Add the radius to transform the texel into the range [0, radius * 2], then divide by the upper + * bound plus one to transform the texel into the normalized range [0, 1] needed to sample the + * weights sampler. Finally, also add 0.5 to sample at the center of the pixels. */ + return texture(weights_tx, (texel + vec2(radius + 0.5)) / (radius * 2 + 1)); +} + +void main() +{ + ivec2 texel = ivec2(gl_GlobalInvocationID.xy); + + /* The mask input is treated as a boolean. If it is zero, then no blurring happens for this + * pixel. Otherwise, the pixel is blurred normally and the mask value is irrelevant. */ + float mask = texture_load(mask_tx, texel).x; + if (mask == 0.0) { + imageStore(output_img, texel, texture_load(input_tx, texel)); + return; + } + + /* Go over the window of the given radius and accumulate the colors multiplied by their + * respective weights as well as the weights themselves. */ + vec4 accumulated_color = vec4(0.0); + vec4 accumulated_weight = vec4(0.0); + for (int y = -radius; y <= radius; y++) { + for (int x = -radius; x <= radius; x++) { + vec4 weight = load_weight(ivec2(x, y)); + accumulated_color += load_input(texel + ivec2(x, y)) * weight; + accumulated_weight += weight; + } + } + + imageStore(output_img, texel, safe_divide(accumulated_color, accumulated_weight)); +} diff --git a/source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh b/source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh new file mode 100644 index 00000000000..36b772aa486 --- /dev/null +++ b/source/blender/gpu/shaders/compositor/infos/compositor_blur_info.hh @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "gpu_shader_create_info.hh" + +GPU_SHADER_CREATE_INFO(compositor_blur) + .local_group_size(16, 16) + .push_constant(Type::INT, "radius") + .push_constant(Type::BOOL, "extend_bounds") + .sampler(0, ImageType::FLOAT_2D, "input_tx") + .sampler(1, ImageType::FLOAT_2D, "weights_tx") + .sampler(2, ImageType::FLOAT_2D, "mask_tx") + .image(0, GPU_RGBA16F, Qualifier::WRITE, ImageType::FLOAT_2D, "output_img") + .compute_source("compositor_blur.glsl") + .do_static_compilation(true); diff --git a/source/blender/nodes/composite/nodes/node_composite_bokehblur.cc b/source/blender/nodes/composite/nodes/node_composite_bokehblur.cc index 538f00af12d..182169405de 100644 --- a/source/blender/nodes/composite/nodes/node_composite_bokehblur.cc +++ b/source/blender/nodes/composite/nodes/node_composite_bokehblur.cc @@ -5,10 +5,16 @@ * \ingroup cmpnodes */ +#include "BLI_math_base.hh" +#include "BLI_math_vec_types.hh" + #include "UI_interface.h" #include "UI_resources.h" +#include "GPU_texture.h" + #include "COM_node_operation.hh" +#include "COM_utilities.hh" #include "node_composite_util.hh" @@ -18,10 +24,22 @@ namespace blender::nodes::node_composite_bokehblur_cc { static void cmp_node_bokehblur_declare(NodeDeclarationBuilder &b) { - b.add_input(N_("Image")).default_value({0.8f, 0.8f, 0.8f, 1.0f}); - b.add_input(N_("Bokeh")).default_value({1.0f, 1.0f, 1.0f, 1.0f}); - b.add_input(N_("Size")).default_value(1.0f).min(0.0f).max(10.0f); - b.add_input(N_("Bounding box")).default_value(1.0f).min(0.0f).max(1.0f); + b.add_input(N_("Image")) + .default_value({0.8f, 0.8f, 0.8f, 1.0f}) + .compositor_domain_priority(0); + b.add_input(N_("Bokeh")) + .default_value({1.0f, 1.0f, 1.0f, 1.0f}) + .compositor_skip_realization(); + b.add_input(N_("Size")) + .default_value(1.0f) + .min(0.0f) + .max(10.0f) + .compositor_domain_priority(1); + b.add_input(N_("Bounding box")) + .default_value(1.0f) + .min(0.0f) + .max(1.0f) + .compositor_domain_priority(2); b.add_output(N_("Image")); } @@ -47,7 +65,82 @@ class BokehBlurOperation : public NodeOperation { void execute() override { - get_input("Image").pass_through(get_result("Image")); + if (is_identity()) { + get_input("Image").pass_through(get_result("Image")); + return; + } + + GPUShader *shader = shader_manager().get("compositor_blur"); + GPU_shader_bind(shader); + + GPU_shader_uniform_1i(shader, "radius", compute_blur_radius()); + GPU_shader_uniform_1b(shader, "extend_bounds", get_extend_bounds()); + + const Result &input_image = get_input("Image"); + input_image.bind_as_texture(shader, "input_tx"); + + const Result &input_weights = get_input("Bokeh"); + input_weights.bind_as_texture(shader, "weights_tx"); + + const Result &input_mask = get_input("Bounding box"); + input_mask.bind_as_texture(shader, "mask_tx"); + + Domain domain = compute_domain(); + if (get_extend_bounds()) { + /* Add a radius amount of pixels in both sides of the image, hence the multiply by 2. */ + domain.size += int2(compute_blur_radius() * 2); + } + + Result &output_image = get_result("Image"); + output_image.allocate_texture(domain); + output_image.bind_as_image(shader, "output_img"); + + compute_dispatch_threads_at_least(shader, domain.size); + + GPU_shader_unbind(); + output_image.unbind_as_image(); + input_image.unbind_as_texture(); + input_weights.unbind_as_texture(); + input_mask.unbind_as_texture(); + } + + int compute_blur_radius() + { + const int2 image_size = get_input("Image").domain().size; + const int max_size = math::max(image_size.x, image_size.y); + + /* The [0, 10] range of the size is arbitrary and is merely in place to avoid very long + * computations of the bokeh blur. */ + const float size = math::clamp(get_input("Size").get_float_value_default(1.0f), 0.0f, 10.0f); + + /* The 100 divisor is arbitrary and was chosen using visual judgement. */ + return size * (max_size / 100.0f); + } + + bool is_identity() + { + const Result &input = get_input("Image"); + if (input.is_single_value()) { + return true; + } + + if (compute_blur_radius() == 0) { + return true; + } + + /* This input is, in fact, a boolean mask. If it is zero, no blurring will take place. + * Otherwise, the blurring will take place ignoring the value of the input entirely. */ + const Result &bounding_box = get_input("Bounding box"); + if (bounding_box.is_single_value() && bounding_box.get_float_value() == 0.0) { + return true; + } + + return false; + } + + bool get_extend_bounds() + { + return bnode().custom1 & CMP_NODEFLAG_BLUR_EXTEND_BOUNDS; } }; -- cgit v1.2.3 From 8f8ae06b515c0fe479ba8b3cfb27c354c031e483 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 22:38:55 +1000 Subject: Fix use-after-free error when exiting on WIN32 The logging API was freed before calling wm_autosave_delete that called BKE_appdir_folder_id_create to get the auto-save location (when the temporary directory wasn't found). Detecting BLENDER_USER_AUTOSAVE would log details about the path, which would read data freed by CLG_exit. Resolve by calling CLG_exit last. --- source/blender/windowmanager/intern/wm_init_exit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/blender/windowmanager/intern/wm_init_exit.c b/source/blender/windowmanager/intern/wm_init_exit.c index 8163b39b3dd..283b87f1a2f 100644 --- a/source/blender/windowmanager/intern/wm_init_exit.c +++ b/source/blender/windowmanager/intern/wm_init_exit.c @@ -634,13 +634,15 @@ void WM_exit_ex(bContext *C, const bool do_python) BKE_sound_exit(); BKE_appdir_exit(); - CLG_exit(); BKE_blender_atexit(); wm_autosave_delete(); BKE_tempdir_session_purge(); + + /* Keep last (or near last) so logging can be used right up until everything is shut-down. */ + CLG_exit(); } void WM_exit(bContext *C) -- cgit v1.2.3 From 05f821b094b44ef588d4c678193f76ae2ee1797d Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 22:38:57 +1000 Subject: Cleanup: remove unnecessary use of BLI_make_file_string Use BLI_join_dirfile instead, also reduce right-shift. --- source/blender/editors/render/render_preview.cc | 46 ++++++++++--------------- source/blender/windowmanager/intern/wm_files.c | 26 +++++++------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/source/blender/editors/render/render_preview.cc b/source/blender/editors/render/render_preview.cc index 7d1ac079d08..aa05b2ff198 100644 --- a/source/blender/editors/render/render_preview.cc +++ b/source/blender/editors/render/render_preview.cc @@ -1304,41 +1304,33 @@ static void shader_preview_free(void *customdata) static ImBuf *icon_preview_imbuf_from_brush(Brush *brush) { - static const int flags = IB_rect | IB_multilayer | IB_metadata; + if (!brush->icon_imbuf && (brush->flag & BRUSH_CUSTOM_ICON) && brush->icon_filepath[0]) { + const int flags = IB_rect | IB_multilayer | IB_metadata; - char filepath[FILE_MAX]; - const char *folder; + /* First use the path directly to try and load the file. */ + char filepath[FILE_MAX]; - if (!(brush->icon_imbuf)) { - if (brush->flag & BRUSH_CUSTOM_ICON) { + BLI_strncpy(filepath, brush->icon_filepath, sizeof(brush->icon_filepath)); + BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&brush->id)); - if (brush->icon_filepath[0]) { - /* First use the path directly to try and load the file. */ + /* Use default color-spaces for brushes. */ + brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); - BLI_strncpy(filepath, brush->icon_filepath, sizeof(brush->icon_filepath)); - BLI_path_abs(filepath, ID_BLEND_PATH_FROM_GLOBAL(&brush->id)); + /* Otherwise lets try to find it in other directories. */ + if (!(brush->icon_imbuf)) { + const char *brushicons_dir = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); + /* Expected to be found, but don't crash if it's not. */ + if (brushicons_dir) { + BLI_join_dirfile(filepath, sizeof(filepath), brushicons_dir, brush->icon_filepath); - /* Use default color-spaces for brushes. */ + /* Use default color spaces. */ brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); - - /* otherwise lets try to find it in other directories */ - if (!(brush->icon_imbuf)) { - folder = BKE_appdir_folder_id(BLENDER_DATAFILES, "brushicons"); - - BLI_make_file_string( - BKE_main_blendfile_path_from_global(), filepath, folder, brush->icon_filepath); - - if (filepath[0]) { - /* Use default color spaces. */ - brush->icon_imbuf = IMB_loadiffname(filepath, flags, nullptr); - } - } - - if (brush->icon_imbuf) { - BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); - } } } + + if (brush->icon_imbuf) { + BKE_icon_changed(BKE_icon_id_ensure(&brush->id)); + } } if (!(brush->icon_imbuf)) { diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 13c1579d24b..38747bd706c 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1899,7 +1899,7 @@ static bool wm_file_write(bContext *C, /** \name Auto-Save API * \{ */ -static void wm_autosave_location(char *filepath) +static void wm_autosave_location(char filepath[FILE_MAX]) { const int pid = abs(getpid()); char path[1024]; @@ -1918,23 +1918,23 @@ static void wm_autosave_location(char *filepath) BLI_snprintf(path, sizeof(path), "%d_autosave.blend", pid); } + const char *tempdir_base = BKE_tempdir_base(); #ifdef WIN32 - /* XXX Need to investigate how to handle default location of '/tmp/' - * This is a relative directory on Windows, and it may be - * found. Example: - * Blender installed on D:\ drive, D:\ drive has D:\tmp\ - * Now, BLI_exists() will find '/tmp/' exists, but - * BLI_make_file_string will create string that has it most likely on C:\ - * through BLI_windows_get_default_root_dir(). - * If there is no C:\tmp autosave fails. */ - if (!BLI_exists(BKE_tempdir_base())) { + /* XXX Need to investigate how to handle default location of `/tmp/` + * This is a relative directory on Windows, and it may be found. Example: + * Blender installed on `D:\` drive, `D:\` drive has `D:\tmp\` Now, `BLI_exists()` + * will find `/tmp/` exists, but #BLI_make_file_string will create string + * that has it most likely on `C:\` through #BLI_windows_get_default_root_dir. + * If there is no `C:\tmp` autosave fails. */ + if (!BLI_exists(tempdir_base)) { const char *savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL); - BLI_make_file_string("/", filepath, savedir, path); - return; + if (savedir) { + tempdir_base = savedir; + } } #endif - BLI_join_dirfile(filepath, FILE_MAX, BKE_tempdir_base(), path); + BLI_join_dirfile(filepath, FILE_MAX, tempdir_base, path); } static void wm_autosave_write(Main *bmain, wmWindowManager *wm) -- cgit v1.2.3 From 6039d1573242fa5444c013351c000c6994ef8caf Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Fri, 9 Sep 2022 15:03:04 +0200 Subject: Fix Clang warning about braces around initialization --- intern/mikktspace/mikk_util.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/intern/mikktspace/mikk_util.hh b/intern/mikktspace/mikk_util.hh index 224ed647b30..857ca95910b 100644 --- a/intern/mikktspace/mikk_util.hh +++ b/intern/mikktspace/mikk_util.hh @@ -108,7 +108,7 @@ void radixsort(std::vector &data, std::vector &data2, KeyGetter getKey) static_assert(datasize % 2 == 0); static_assert(std::is_integral::value); - uint bins[datasize][257] = {0}; + uint bins[datasize][257] = {{0}}; /* Count number of elements per bin. */ for (const T &item : data) { -- cgit v1.2.3 From 436f1b4dbe3c111be12289cea4fa58b6aa148fc2 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 23:18:24 +1000 Subject: Correct error building on WIN32 Mistake in f7a4ede79f9512f39db8632ff112e08a93f3a9d4. --- source/blender/blenkernel/intern/appdir.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/source/blender/blenkernel/intern/appdir.c b/source/blender/blenkernel/intern/appdir.c index 295e85a5fc4..f4dec0aecd7 100644 --- a/source/blender/blenkernel/intern/appdir.c +++ b/source/blender/blenkernel/intern/appdir.c @@ -811,7 +811,7 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name) # endif # ifdef _WIN32 - if (!strict) { + { wchar_t *fullname_16 = MEM_mallocN(maxlen * sizeof(wchar_t), "ProgramPath"); if (GetModuleFileNameW(0, fullname_16, maxlen)) { conv_utf_16_to_8(fullname_16, fullname, maxlen); @@ -835,18 +835,14 @@ static void where_am_i(char *fullname, const size_t maxlen, const char *name) if (name[0] == '.') { BLI_path_abs_from_cwd(fullname, maxlen); # ifdef _WIN32 - if (!strict) { - BLI_path_program_extensions_add_win32(fullname, maxlen); - } + BLI_path_program_extensions_add_win32(fullname, maxlen); # endif } else if (BLI_path_slash_rfind(name)) { /* Full path. */ BLI_strncpy(fullname, name, maxlen); # ifdef _WIN32 - if (!strict) { - BLI_path_program_extensions_add_win32(fullname, maxlen); - } + BLI_path_program_extensions_add_win32(fullname, maxlen); # endif } else { -- cgit v1.2.3 From cef1b9c30f9ac96143d31f81d23db60dcf526f5a Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Fri, 9 Sep 2022 23:10:28 +1000 Subject: Cleanup: remove BLI_make_file_string This function did multiple things making it difficult to know what was intended by the caller: - Directory & file join. - Expand relative '//' prefix to an optional directory. - Expand drive letters on windows (guessing with fall-backs). - Switch slashes to native direction. This functionality wasn't needed as the full directory was always passed in, so guessing the drive letter wasn't needed. If functionality to add drive letters onto paths is needed in the future a function that only does this can be added. --- source/blender/blenlib/BLI_path_util.h | 11 ---- source/blender/blenlib/intern/path_util.c | 70 -------------------------- source/blender/render/intern/render_result.cc | 16 ++++-- source/blender/windowmanager/intern/wm_files.c | 3 +- 4 files changed, 13 insertions(+), 87 deletions(-) diff --git a/source/blender/blenlib/BLI_path_util.h b/source/blender/blenlib/BLI_path_util.h index a2caaa0851b..75002f52d94 100644 --- a/source/blender/blenlib/BLI_path_util.h +++ b/source/blender/blenlib/BLI_path_util.h @@ -35,17 +35,6 @@ void BLI_setenv_if_new(const char *env, const char *val) ATTR_NONNULL(1); */ const char *BLI_getenv(const char *env) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT; -/** - * Returns in `string` the concatenation of `dir` and `file` (also with `relabase` on the - * front if specified and `dir` begins with "//"). Normalizes all occurrences of path - * separators, including ensuring there is exactly one between the copies of `dir` and `file`, - * and between the copies of `relabase` and `dir`. - * - * \param relabase: Optional prefix to substitute for "//" on front of `dir`. - * \param string: Area to return result. - */ -void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) - ATTR_NONNULL(2, 3, 4); /** * Ensures that the parent directory of `name` exists. * diff --git a/source/blender/blenlib/intern/path_util.c b/source/blender/blenlib/intern/path_util.c index 73396fb34b1..1e95aa3b7b0 100644 --- a/source/blender/blenlib/intern/path_util.c +++ b/source/blender/blenlib/intern/path_util.c @@ -1204,76 +1204,6 @@ bool BLI_make_existing_file(const char *name) return BLI_dir_create_recursive(di); } -void BLI_make_file_string(const char *relabase, char *string, const char *dir, const char *file) -{ - /* Ensure this is always set & the following `strcat` works as expected. */ - string[0] = '\0'; - - /* Resolve relative references */ - if (relabase && dir[0] == '/' && dir[1] == '/') { - char *lslash; - - /* Get the file name, chop everything past the last slash (ie. the filename) */ - strcpy(string, relabase); - - lslash = (char *)BLI_path_slash_rfind(string); - if (lslash) { - *(lslash + 1) = 0; - } - - dir += 2; /* Skip over the relative reference */ - } -#ifdef WIN32 - else { - if (BLI_strnlen(dir, 3) >= 2 && dir[1] == ':') { - BLI_strncpy(string, dir, 3); - dir += 2; - } - else if (BLI_strnlen(dir, 3) >= 2 && BLI_path_is_unc(dir)) { - string[0] = 0; - } - else { /* no drive specified */ - /* first option: get the drive from the relabase if it has one */ - if (relabase && BLI_strnlen(relabase, 3) >= 2 && relabase[1] == ':') { - BLI_strncpy(string, relabase, 3); - string[2] = '\\'; - string[3] = '\0'; - } - else { /* we're out of luck here, guessing the first valid drive, usually c:\ */ - BLI_windows_get_default_root_dir(string); - } - - /* ignore leading slashes */ - while (ELEM(*dir, '/', '\\')) { - dir++; - } - } - } -#endif - - strcat(string, dir); - - /* Make sure string ends in one (and only one) slash */ - /* first trim all slashes from the end of the string */ - int sl = strlen(string); - while ((sl > 0) && ELEM(string[sl - 1], '/', '\\')) { - string[sl - 1] = '\0'; - sl--; - } - /* since we've now removed all slashes, put back one slash at the end. */ - strcat(string, "/"); - - while (ELEM(*file, '/', '\\')) { - /* Trim slashes from the front of file */ - file++; - } - - strcat(string, file); - - /* Push all slashes to the system preferred direction */ - BLI_path_slash_native(string); -} - static bool path_extension_check_ex(const char *str, const size_t str_len, const char *ext, diff --git a/source/blender/render/intern/render_result.cc b/source/blender/render/intern/render_result.cc index 86ee9ad779a..50eb7e9f2d2 100644 --- a/source/blender/render/intern/render_result.cc +++ b/source/blender/render/intern/render_result.cc @@ -929,7 +929,11 @@ int render_result_exr_file_read_path(RenderResult *rr, return 1; } -static void render_result_exr_file_cache_path(Scene *sce, const char *root, char *r_path) +#define FILE_CACHE_MAX (FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100) + +static void render_result_exr_file_cache_path(Scene *sce, + const char *root, + char r_path[FILE_CACHE_MAX]) { char filename_full[FILE_MAX + MAX_ID_NAME + 100], filename[FILE_MAXFILE], dirname[FILE_MAXDIR]; char path_digest[16] = {0}; @@ -959,13 +963,17 @@ static void render_result_exr_file_cache_path(Scene *sce, const char *root, char filename, sce->id.name + 2, path_hexdigest); - BLI_make_file_string(dirname, r_path, root, filename_full); + + BLI_join_dirfile(r_path, FILE_CACHE_MAX, root, filename_full); + if (BLI_path_is_rel(r_path)) { + BLI_path_abs(r_path, dirname); + } } void render_result_exr_file_cache_write(Render *re) { RenderResult *rr = re->result; - char str[FILE_MAXFILE + FILE_MAXFILE + MAX_ID_NAME + 100]; + char str[FILE_CACHE_MAX]; char *root = U.render_cachedir; render_result_passes_allocated_ensure(rr); @@ -979,7 +987,7 @@ void render_result_exr_file_cache_write(Render *re) bool render_result_exr_file_cache_read(Render *re) { /* File path to cache. */ - char filepath[FILE_MAXFILE + MAX_ID_NAME + MAX_ID_NAME + 100] = ""; + char filepath[FILE_CACHE_MAX] = ""; char *root = U.render_cachedir; render_result_exr_file_cache_path(re->scene, root, filepath); diff --git a/source/blender/windowmanager/intern/wm_files.c b/source/blender/windowmanager/intern/wm_files.c index 38747bd706c..186edfe68d6 100644 --- a/source/blender/windowmanager/intern/wm_files.c +++ b/source/blender/windowmanager/intern/wm_files.c @@ -1923,8 +1923,7 @@ static void wm_autosave_location(char filepath[FILE_MAX]) /* XXX Need to investigate how to handle default location of `/tmp/` * This is a relative directory on Windows, and it may be found. Example: * Blender installed on `D:\` drive, `D:\` drive has `D:\tmp\` Now, `BLI_exists()` - * will find `/tmp/` exists, but #BLI_make_file_string will create string - * that has it most likely on `C:\` through #BLI_windows_get_default_root_dir. + * will find `/tmp/` exists, but #BLI_windows_get_default_root_dir will expand this to `C:\`. * If there is no `C:\tmp` autosave fails. */ if (!BLI_exists(tempdir_base)) { const char *savedir = BKE_appdir_folder_id_create(BLENDER_USER_AUTOSAVE, NULL); -- cgit v1.2.3 From 12c235a1c515d41a18c497d6647253698579c01d Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 9 Sep 2022 08:13:37 -0500 Subject: Subdiv: Avoid quadratic runtime for loose edges Currently, when subdividing every single vertex on every loose edge, Blender iterates over all other edges to find neighbors. This has quadratic runtime and can be very slow. Instead, first create a map of edges connected to each vertex. With about 10000 edges, the performance goes from very slow to very smooth in my tests. Because of the nature of quadratic runtime, the improvement will depend massively on the number of elements. The only downside to this is that the map will still be built when there are only a couple loose edges, but that case is probably not so common. Differential Revision: https://developer.blender.org/D15923 --- source/blender/blenkernel/BKE_subdiv_mesh.h | 8 ++- source/blender/blenkernel/intern/subdiv_mesh.cc | 79 ++++++++++++++++------ .../draw/intern/draw_cache_impl_subdivision.cc | 33 +++++++-- 3 files changed, 92 insertions(+), 28 deletions(-) diff --git a/source/blender/blenkernel/BKE_subdiv_mesh.h b/source/blender/blenkernel/BKE_subdiv_mesh.h index b24db517143..49c45efafe0 100644 --- a/source/blender/blenkernel/BKE_subdiv_mesh.h +++ b/source/blender/blenkernel/BKE_subdiv_mesh.h @@ -14,7 +14,9 @@ extern "C" { #endif struct Mesh; +struct MeshElemMap; struct MEdge; +struct MVert; struct Subdiv; typedef struct SubdivToMeshSettings { @@ -37,8 +39,10 @@ struct Mesh *BKE_subdiv_to_mesh(struct Subdiv *subdiv, /* Interpolate a position along the `coarse_edge` at the relative `u` coordinate. If `is_simple` is * false, this will perform a B-Spline interpolation using the edge neighbors, otherwise a linear * interpolation will be done base on the edge vertices. */ -void BKE_subdiv_mesh_interpolate_position_on_edge(const struct Mesh *coarse_mesh, - const struct MEdge *coarse_edge, +void BKE_subdiv_mesh_interpolate_position_on_edge(const struct MVert *coarse_verts, + const struct MEdge *coarse_edges, + const struct MeshElemMap *vert_to_edge_map, + int coarse_edge_index, bool is_simple, float u, float pos_r[3]); diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index 5a2af36e83c..dc9fc3dee09 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -5,6 +5,8 @@ * \ingroup bke */ +#include + #include "atomic_ops.h" #include "DNA_key_types.h" @@ -18,6 +20,7 @@ #include "BKE_customdata.h" #include "BKE_key.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_subdiv.h" #include "BKE_subdiv_eval.h" #include "BKE_subdiv_foreach.h" @@ -25,6 +28,8 @@ #include "MEM_guardedalloc.h" +using blender::Span; + /* -------------------------------------------------------------------- */ /** \name Subdivision Context * \{ */ @@ -58,6 +63,11 @@ struct SubdivMeshContext { /* Per-subdivided vertex counter of averaged values. */ int *accumulated_counters; bool have_displacement; + + /* Lazily initialize a map from vertices to connected edges. */ + std::mutex vert_to_edge_map_mutex; + int *vert_to_edge_buffer; + MeshElemMap *vert_to_edge_map; }; static void subdiv_mesh_ctx_cache_uv_layers(SubdivMeshContext *ctx) @@ -106,6 +116,8 @@ static void subdiv_mesh_prepare_accumulator(SubdivMeshContext *ctx, int num_vert static void subdiv_mesh_context_free(SubdivMeshContext *ctx) { MEM_SAFE_FREE(ctx->accumulated_counters); + MEM_SAFE_FREE(ctx->vert_to_edge_buffer); + MEM_SAFE_FREE(ctx->vert_to_edge_map); } /** \} */ @@ -961,25 +973,30 @@ static void subdiv_mesh_vertex_loose(const SubdivForeachContext *foreach_context /* Get neighbor edges of the given one. * - neighbors[0] is an edge adjacent to edge->v1. * - neighbors[1] is an edge adjacent to edge->v2. */ -static void find_edge_neighbors(const Mesh *coarse_mesh, - const MEdge *edge, +static void find_edge_neighbors(const MEdge *coarse_edges, + const MeshElemMap *vert_to_edge_map, + const int edge_index, const MEdge *neighbors[2]) { - const blender::Span coarse_edges = coarse_mesh->edges(); + const MEdge *edge = &coarse_edges[edge_index]; neighbors[0] = nullptr; neighbors[1] = nullptr; int neighbor_counters[2] = {0, 0}; - for (int edge_index = 0; edge_index < coarse_mesh->totedge; edge_index++) { - const MEdge *current_edge = &coarse_edges[edge_index]; - if (current_edge == edge) { + for (const int i : Span(vert_to_edge_map[edge->v1].indices, vert_to_edge_map[edge->v1].count)) { + if (i == edge_index) { continue; } - if (ELEM(edge->v1, current_edge->v1, current_edge->v2)) { - neighbors[0] = current_edge; + if (ELEM(edge->v1, coarse_edges[i].v1, coarse_edges[i].v2)) { + neighbors[0] = &coarse_edges[i]; ++neighbor_counters[0]; } - if (ELEM(edge->v2, current_edge->v1, current_edge->v2)) { - neighbors[1] = current_edge; + } + for (const int i : Span(vert_to_edge_map[edge->v2].indices, vert_to_edge_map[edge->v2].count)) { + if (i == edge_index) { + continue; + } + if (ELEM(edge->v2, coarse_edges[i].v1, coarse_edges[i].v2)) { + neighbors[1] = &coarse_edges[i]; ++neighbor_counters[1]; } } @@ -994,12 +1011,11 @@ static void find_edge_neighbors(const Mesh *coarse_mesh, } } -static void points_for_loose_edges_interpolation_get(const Mesh *coarse_mesh, +static void points_for_loose_edges_interpolation_get(const MVert *coarse_mvert, const MEdge *coarse_edge, const MEdge *neighbors[2], float points_r[4][3]) { - const MVert *coarse_mvert = BKE_mesh_verts(coarse_mesh); /* Middle points corresponds to the edge. */ copy_v3_v3(points_r[1], coarse_mvert[coarse_edge->v1].co); copy_v3_v3(points_r[2], coarse_mvert[coarse_edge->v2].co); @@ -1031,24 +1047,26 @@ static void points_for_loose_edges_interpolation_get(const Mesh *coarse_mesh, } } -void BKE_subdiv_mesh_interpolate_position_on_edge(const Mesh *coarse_mesh, - const MEdge *coarse_edge, +void BKE_subdiv_mesh_interpolate_position_on_edge(const MVert *coarse_verts, + const MEdge *coarse_edges, + const MeshElemMap *vert_to_edge_map, + const int coarse_edge_index, const bool is_simple, const float u, float pos_r[3]) { + const MEdge *coarse_edge = &coarse_edges[coarse_edge_index]; if (is_simple) { - const MVert *coarse_mvert = BKE_mesh_verts(coarse_mesh); - const MVert *vert_1 = &coarse_mvert[coarse_edge->v1]; - const MVert *vert_2 = &coarse_mvert[coarse_edge->v2]; + const MVert *vert_1 = &coarse_verts[coarse_edge->v1]; + const MVert *vert_2 = &coarse_verts[coarse_edge->v2]; interp_v3_v3v3(pos_r, vert_1->co, vert_2->co, u); } else { /* Find neighbors of the coarse edge. */ const MEdge *neighbors[2]; - find_edge_neighbors(coarse_mesh, coarse_edge, neighbors); + find_edge_neighbors(coarse_edges, vert_to_edge_map, coarse_edge_index, neighbors); float points[4][3]; - points_for_loose_edges_interpolation_get(coarse_mesh, coarse_edge, neighbors, points); + points_for_loose_edges_interpolation_get(coarse_verts, coarse_edge, neighbors, points); float weights[4]; key_curve_position_weights(u, weights, KEY_BSPLINE); interp_v3_v3v3v3v3(pos_r, points[0], points[1], points[2], points[3], weights); @@ -1090,6 +1108,20 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach const Mesh *coarse_mesh = ctx->coarse_mesh; const MEdge *coarse_edge = &ctx->coarse_edges[coarse_edge_index]; const bool is_simple = ctx->subdiv->settings.is_simple; + + /* Lazily initialize a vertex to edge map to avoid quadratic runtime when subdividing loose + * edges. Do this here to avoid the cost in common cases when there are no loose edges at all. */ + if (ctx->vert_to_edge_map == NULL) { + std::lock_guard lock{ctx->vert_to_edge_map_mutex}; + if (ctx->vert_to_edge_map == NULL) { + BKE_mesh_vert_edge_map_create(&ctx->vert_to_edge_map, + &ctx->vert_to_edge_buffer, + ctx->coarse_edges, + coarse_mesh->totvert, + ctx->coarse_mesh->totedge); + } + } + /* Interpolate custom data when not an end point. * This data has already been copied from the original vertex by #subdiv_mesh_vertex_loose. */ if (!ELEM(u, 0.0, 1.0)) { @@ -1097,8 +1129,13 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach } /* Interpolate coordinate. */ MVert *subdiv_vertex = &ctx->subdiv_verts[subdiv_vertex_index]; - BKE_subdiv_mesh_interpolate_position_on_edge( - coarse_mesh, coarse_edge, is_simple, u, subdiv_vertex->co); + BKE_subdiv_mesh_interpolate_position_on_edge(ctx->coarse_verts, + ctx->coarse_edges, + ctx->vert_to_edge_map, + coarse_edge_index, + is_simple, + u, + subdiv_vertex->co); /* Reset flags and such. */ subdiv_vertex->flag = 0; /* TODO(sergey): This matches old behavior, but we can as well interpolate diff --git a/source/blender/draw/intern/draw_cache_impl_subdivision.cc b/source/blender/draw/intern/draw_cache_impl_subdivision.cc index 51fbc5a3027..ab935809f96 100644 --- a/source/blender/draw/intern/draw_cache_impl_subdivision.cc +++ b/source/blender/draw/intern/draw_cache_impl_subdivision.cc @@ -10,6 +10,7 @@ #include "BKE_attribute.hh" #include "BKE_editmesh.h" #include "BKE_mesh.h" +#include "BKE_mesh_mapping.h" #include "BKE_modifier.h" #include "BKE_object.h" #include "BKE_scene.h" @@ -2155,7 +2156,17 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac int subd_vert_offset = 0; /* Subdivide each loose coarse edge. */ + const Span coarse_verts = coarse_mesh->verts(); const Span coarse_edges = coarse_mesh->edges(); + + int *vert_to_edge_buffer; + MeshElemMap *vert_to_edge_map; + BKE_mesh_vert_edge_map_create(&vert_to_edge_map, + &vert_to_edge_buffer, + coarse_edges.data(), + coarse_mesh->totvert, + coarse_edges.size()); + for (int i = 0; i < coarse_loose_edge_len; i++) { const int coarse_edge_index = cache->loose_geom.edges[i]; const MEdge *coarse_edge = &coarse_edges[cache->loose_geom.edges[i]]; @@ -2169,8 +2180,13 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac DRWSubdivLooseVertex &subd_v1 = loose_subd_verts[subd_vert_offset]; subd_v1.coarse_vertex_index = (i == 0) ? coarse_edge->v1 : -1u; const float u1 = i * inv_resolution_1; - BKE_subdiv_mesh_interpolate_position_on_edge( - coarse_mesh, coarse_edge, is_simple, u1, subd_v1.co); + BKE_subdiv_mesh_interpolate_position_on_edge(coarse_verts.data(), + coarse_edges.data(), + vert_to_edge_map, + coarse_edge_index, + is_simple, + u1, + subd_v1.co); subd_edge.loose_subdiv_v1_index = subd_vert_offset++; @@ -2178,15 +2194,22 @@ void DRW_subdivide_loose_geom(DRWSubdivCache *subdiv_cache, MeshBufferCache *cac DRWSubdivLooseVertex &subd_v2 = loose_subd_verts[subd_vert_offset]; subd_v2.coarse_vertex_index = ((i + 1) == resolution - 1) ? coarse_edge->v2 : -1u; const float u2 = (i + 1) * inv_resolution_1; - BKE_subdiv_mesh_interpolate_position_on_edge( - coarse_mesh, coarse_edge, is_simple, u2, subd_v2.co); + BKE_subdiv_mesh_interpolate_position_on_edge(coarse_verts.data(), + coarse_edges.data(), + vert_to_edge_map, + coarse_edge_index, + is_simple, + u2, + subd_v2.co); subd_edge.loose_subdiv_v2_index = subd_vert_offset++; } } + MEM_freeN(vert_to_edge_buffer); + MEM_freeN(vert_to_edge_map); + /* Copy the remaining loose_verts. */ - const Span coarse_verts = coarse_mesh->verts(); for (int i = 0; i < coarse_loose_vert_len; i++) { const int coarse_vertex_index = cache->loose_geom.verts[i]; const MVert &coarse_vertex = coarse_verts[coarse_vertex_index]; -- cgit v1.2.3 From 21f2bacad977d3fd83d9e4730f2a14dc9932f043 Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 9 Sep 2022 08:24:31 -0500 Subject: Cleanup: Simplify BKE_mesh_nomain_to_mesh - Remove "take ownership" argument which was confusing and always true - The argument made ownership very confusing - Better to avoid boolean arguments that switch a function's purpose - Remove "mask" argument which was basically wrong and not used properly - "EVERYTHING" was used because developers are wary of removing data - Instead use `CD_MASK_MESH` for its purpose of original mesh data - Remove use of shallow copied temporary mesh, which is unnecessary now - Split shape key processing into separate functions and use C++ types - Copy fields explicitly rather than using memcpy for the whole struct - Use higher level functions and avoid redundant code - The whole idea is pretty simple and can be built from standard logic - Adjust `CustomData` logic to be consistent with "assign" expectations - Clear the layer data from the source, and moves the anonymous ID Differential Revision: https://developer.blender.org/D15857 --- source/blender/blenkernel/BKE_key.h | 3 + source/blender/blenkernel/BKE_mesh.h | 9 +- source/blender/blenkernel/intern/customdata.cc | 10 +- source/blender/blenkernel/intern/key.c | 10 + source/blender/blenkernel/intern/mesh.cc | 4 +- source/blender/blenkernel/intern/mesh_convert.cc | 282 ++++++--------------- .../blenkernel/intern/multires_unsubdivide.c | 2 +- .../blender/editors/mesh/editmesh_mask_extract.c | 6 +- source/blender/editors/object/object_add.cc | 2 +- source/blender/editors/object/object_modifier.cc | 2 +- source/blender/editors/object/object_remesh.cc | 4 +- source/blender/editors/sculpt_paint/paint_mask.c | 3 +- .../blender/io/alembic/intern/abc_reader_mesh.cc | 8 +- .../blender/io/alembic/intern/abc_reader_points.cc | 2 +- source/blender/io/usd/intern/usd_reader_mesh.cc | 6 +- .../io/wavefront_obj/importer/obj_import_mesh.cc | 6 +- source/blender/makesrna/intern/rna_mesh_api.c | 2 + 17 files changed, 123 insertions(+), 238 deletions(-) diff --git a/source/blender/blenkernel/BKE_key.h b/source/blender/blenkernel/BKE_key.h index 9f506ded8e9..45a72e8d7a3 100644 --- a/source/blender/blenkernel/BKE_key.h +++ b/source/blender/blenkernel/BKE_key.h @@ -95,6 +95,9 @@ struct KeyBlock *BKE_keyblock_from_key(struct Key *key, int index); * Get the appropriate #KeyBlock given a name to search for. */ struct KeyBlock *BKE_keyblock_find_name(struct Key *key, const char name[]); + +struct KeyBlock *BKE_keyblock_find_uid(struct Key *key, int uid); + /** * \brief copy shape-key attributes, but not key data or name/UID. */ diff --git a/source/blender/blenkernel/BKE_mesh.h b/source/blender/blenkernel/BKE_mesh.h index 1048ca39958..ef57c9a2e0e 100644 --- a/source/blender/blenkernel/BKE_mesh.h +++ b/source/blender/blenkernel/BKE_mesh.h @@ -292,13 +292,10 @@ struct Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, bool build_shapekey_layers); /** - * Copies a nomain-Mesh into an existing Mesh. + * Move data from a mesh outside of the main data-base into a mesh in the data-base. + * Takes ownership of the source mesh. */ -void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src, - struct Mesh *mesh_dst, - struct Object *ob, - const struct CustomData_MeshMasks *mask, - bool take_ownership); +void BKE_mesh_nomain_to_mesh(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct Object *ob); void BKE_mesh_nomain_to_meshkey(struct Mesh *mesh_src, struct Mesh *mesh_dst, struct KeyBlock *kb); /* vertex level transformations & checks (no derived mesh) */ diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index cfb8416b0b4..a3b9f012e45 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -2353,8 +2353,16 @@ bool CustomData_merge(const CustomData *source, changed = true; if (layer->anonymous_id != nullptr) { - BKE_anonymous_attribute_id_increment_weak(layer->anonymous_id); newlayer->anonymous_id = layer->anonymous_id; + if (alloctype == CD_ASSIGN) { + layer->anonymous_id = nullptr; + } + else { + BKE_anonymous_attribute_id_increment_weak(layer->anonymous_id); + } + } + if (alloctype == CD_ASSIGN) { + layer->data = nullptr; } } } diff --git a/source/blender/blenkernel/intern/key.c b/source/blender/blenkernel/intern/key.c index a4475869c2a..2ba81c54872 100644 --- a/source/blender/blenkernel/intern/key.c +++ b/source/blender/blenkernel/intern/key.c @@ -1938,6 +1938,16 @@ KeyBlock *BKE_keyblock_find_name(Key *key, const char name[]) return BLI_findstring(&key->block, name, offsetof(KeyBlock, name)); } +KeyBlock *BKE_keyblock_find_uid(Key *key, const int uid) +{ + LISTBASE_FOREACH (KeyBlock *, kb, &key->block) { + if (kb->uid == uid) { + return kb; + } + } + return NULL; +} + void BKE_keyblock_copy_settings(KeyBlock *kb_dst, const KeyBlock *kb_src) { kb_dst->pos = kb_src->pos; diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index 8254bb953d2..c82d9be008d 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -881,11 +881,12 @@ static void mesh_clear_geometry(Mesh *mesh) mesh->totpoly = 0; mesh->act_face = -1; mesh->totselect = 0; + + BLI_freelistN(&mesh->vertex_group_names); } void BKE_mesh_clear_geometry(Mesh *mesh) { - BKE_animdata_free(&mesh->id, false); BKE_mesh_runtime_clear_cache(mesh); mesh_clear_geometry(mesh); } @@ -975,6 +976,7 @@ void BKE_mesh_copy_parameters(Mesh *me_dst, const Mesh *me_src) copy_v3_v3(me_dst->size, me_src->size); me_dst->vertex_group_active_index = me_src->vertex_group_active_index; + me_dst->attributes_active_index = me_src->attributes_active_index; } void BKE_mesh_copy_parameters_for_eval(Mesh *me_dst, const Mesh *me_src) diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index a8ff90c128a..756529473f4 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -54,9 +54,11 @@ #include "DEG_depsgraph.h" #include "DEG_depsgraph_query.h" +using blender::float3; using blender::IndexRange; using blender::MutableSpan; using blender::Span; +using blender::StringRefNull; /* Define for cases when you want extra validation of mesh * after certain modifications. @@ -1081,7 +1083,7 @@ Mesh *BKE_mesh_new_from_object_to_bmain(Main *bmain, mesh_in_bmain->smoothresh = mesh->smoothresh; mesh->mat = nullptr; - BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(mesh, mesh_in_bmain, nullptr); /* Anonymous attributes shouldn't exist on original data. */ mesh_in_bmain->attributes_for_write().remove_anonymous(); @@ -1235,239 +1237,113 @@ Mesh *BKE_mesh_create_derived_for_modifier(struct Depsgraph *depsgraph, return result; } -/* This is a Mesh-based copy of the same function in DerivedMesh.cc */ -static void shapekey_layers_to_keyblocks(Mesh *mesh_src, Mesh *mesh_dst, int actshape_uid) +static KeyBlock *keyblock_ensure_from_uid(Key &key, const int uid, const StringRefNull name) { - KeyBlock *kb; - int i, j, tot; - - if (!mesh_dst->key) { - return; + if (KeyBlock *kb = BKE_keyblock_find_uid(&key, uid)) { + return kb; } + KeyBlock *kb = BKE_keyblock_add(&key, name.c_str()); + kb->uid = uid; + return kb; +} - tot = CustomData_number_of_layers(&mesh_src->vdata, CD_SHAPEKEY); - for (i = 0; i < tot; i++) { - CustomDataLayer *layer = - &mesh_src->vdata.layers[CustomData_get_layer_index_n(&mesh_src->vdata, CD_SHAPEKEY, i)]; - float(*kbcos)[3]; - - for (kb = (KeyBlock *)mesh_dst->key->block.first; kb; kb = kb->next) { - if (kb->uid == layer->uid) { - break; - } - } +static int find_object_active_key_uid(const Key &key, const Object &object) +{ + const int active_kb_index = object.shapenr - 1; + const KeyBlock *kb = (const KeyBlock *)BLI_findlink(&key.block, active_kb_index); + if (!kb) { + CLOG_ERROR(&LOG, "Could not find object's active shapekey %d", active_kb_index); + return -1; + } + return kb->uid; +} - if (!kb) { - kb = BKE_keyblock_add(mesh_dst->key, layer->name); - kb->uid = layer->uid; - } +static void move_shapekey_layers_to_keyblocks(Mesh &mesh, Key &key_dst, const int actshape_uid) +{ + using namespace blender::bke; + for (const int i : IndexRange(CustomData_number_of_layers(&mesh.vdata, CD_SHAPEKEY))) { + const int layer_index = CustomData_get_layer_index_n(&mesh.vdata, CD_SHAPEKEY, i); + CustomDataLayer &layer = mesh.vdata.layers[layer_index]; - if (kb->data) { - MEM_freeN(kb->data); - } + KeyBlock *kb = keyblock_ensure_from_uid(key_dst, layer.uid, layer.name); + MEM_SAFE_FREE(kb->data); - const float(*cos)[3] = (const float(*)[3])CustomData_get_layer_n( - &mesh_src->vdata, CD_SHAPEKEY, i); - kb->totelem = mesh_src->totvert; + kb->totelem = mesh.totvert; - kb->data = kbcos = (float(*)[3])MEM_malloc_arrayN(kb->totelem, sizeof(float[3]), __func__); if (kb->uid == actshape_uid) { - const Span verts = mesh_src->verts(); - for (j = 0; j < mesh_src->totvert; j++, kbcos++) { - copy_v3_v3(*kbcos, verts[j].co); - } + kb->data = MEM_malloc_arrayN(kb->totelem, sizeof(float3), __func__); + MutableSpan kb_coords(static_cast(kb->data), kb->totelem); + mesh.attributes().lookup("position").materialize(kb_coords); } else { - for (j = 0; j < kb->totelem; j++, cos++, kbcos++) { - copy_v3_v3(*kbcos, *cos); - } + kb->data = layer.data; + layer.data = nullptr; } } - for (kb = (KeyBlock *)mesh_dst->key->block.first; kb; kb = kb->next) { - if (kb->totelem != mesh_src->totvert) { - if (kb->data) { - MEM_freeN(kb->data); - } - - kb->totelem = mesh_src->totvert; - kb->data = MEM_calloc_arrayN(kb->totelem, sizeof(float[3]), __func__); - CLOG_ERROR(&LOG, "lost a shapekey layer: '%s'! (bmesh internal error)", kb->name); + LISTBASE_FOREACH (KeyBlock *, kb, &key_dst.block) { + if (kb->totelem != mesh.totvert) { + MEM_SAFE_FREE(kb->data); } + kb->totelem = mesh.totvert; + kb->data = MEM_cnew_array(kb->totelem, __func__); + CLOG_ERROR(&LOG, "Data for shape key '%s' on mesh missing from evaluated mesh ", kb->name); } } -void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, - Mesh *mesh_dst, - Object *ob, - const CustomData_MeshMasks *mask, - bool take_ownership) +void BKE_mesh_nomain_to_mesh(Mesh *mesh_src, Mesh *mesh_dst, Object *ob) { using namespace blender::bke; BLI_assert(mesh_src->id.tag & LIB_TAG_NO_MAIN); - - /* mesh_src might depend on mesh_dst, so we need to do everything with a local copy */ - /* TODO(Sybren): the above claim came from 2.7x derived-mesh code (DM_to_mesh); - * check whether it is still true with Mesh */ - Mesh tmp = blender::dna::shallow_copy(*mesh_dst); - int totvert, totedge /*, totface */ /* UNUSED */, totloop, totpoly; - bool did_shapekeys = false; - eCDAllocType alloctype = CD_DUPLICATE; - - if (take_ownership /* && dm->type == DM_TYPE_CDDM && dm->needsFree */) { - bool has_any_referenced_layers = CustomData_has_referenced(&mesh_src->vdata) || - CustomData_has_referenced(&mesh_src->edata) || - CustomData_has_referenced(&mesh_src->ldata) || - CustomData_has_referenced(&mesh_src->fdata) || - CustomData_has_referenced(&mesh_src->pdata); - if (!has_any_referenced_layers) { - alloctype = CD_ASSIGN; - } - } - CustomData_reset(&tmp.vdata); - CustomData_reset(&tmp.edata); - CustomData_reset(&tmp.fdata); - CustomData_reset(&tmp.ldata); - CustomData_reset(&tmp.pdata); - - totvert = tmp.totvert = mesh_src->totvert; - totedge = tmp.totedge = mesh_src->totedge; - totloop = tmp.totloop = mesh_src->totloop; - totpoly = tmp.totpoly = mesh_src->totpoly; - tmp.totface = 0; - - CustomData_copy(&mesh_src->vdata, &tmp.vdata, mask->vmask, alloctype, totvert); - CustomData_copy(&mesh_src->edata, &tmp.edata, mask->emask, alloctype, totedge); - CustomData_copy(&mesh_src->ldata, &tmp.ldata, mask->lmask, alloctype, totloop); - CustomData_copy(&mesh_src->pdata, &tmp.pdata, mask->pmask, alloctype, totpoly); - tmp.cd_flag = mesh_src->cd_flag; - tmp.runtime.deformed_only = mesh_src->runtime.deformed_only; - - /* Clear the normals completely, since the new vertex / polygon count might be different. */ - BKE_mesh_clear_derived_normals(&tmp); - - if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) { - KeyBlock *kb; - int uid; - - if (ob) { - kb = (KeyBlock *)BLI_findlink(&mesh_dst->key->block, ob->shapenr - 1); - if (kb) { - uid = kb->uid; - } - else { - CLOG_ERROR(&LOG, "could not find active shapekey %d!", ob->shapenr - 1); - - uid = INT_MAX; - } - } - else { - /* if no object, set to INT_MAX so we don't mess up any shapekey layers */ - uid = INT_MAX; - } - - shapekey_layers_to_keyblocks(mesh_src, mesh_dst, uid); - did_shapekeys = true; - } - - /* copy texture space */ if (ob) { - BKE_mesh_texspace_copy_from_object(&tmp, ob); + BLI_assert(mesh_dst == ob->data); } - /* not all DerivedMeshes store their verts/edges/faces in CustomData, so - * we set them here in case they are missing */ - /* TODO(Sybren): we could probably replace CD_ASSIGN with alloctype and - * always directly pass mesh_src->mxxx, instead of using a ternary operator. */ - if (!CustomData_has_layer(&tmp.vdata, CD_MVERT)) { - CustomData_add_layer(&tmp.vdata, - CD_MVERT, - CD_ASSIGN, - (alloctype == CD_ASSIGN) ? mesh_src->verts_for_write().data() : - MEM_dupallocN(mesh_src->verts().data()), - totvert); - } - if (!CustomData_has_layer(&tmp.edata, CD_MEDGE)) { - CustomData_add_layer(&tmp.edata, - CD_MEDGE, - CD_ASSIGN, - (alloctype == CD_ASSIGN) ? mesh_src->edges_for_write().data() : - MEM_dupallocN(mesh_src->edges().data()), - totedge); - } - if (!CustomData_has_layer(&tmp.pdata, CD_MPOLY)) { - CustomData_add_layer(&tmp.ldata, - CD_MLOOP, - CD_ASSIGN, - (alloctype == CD_ASSIGN) ? mesh_src->loops_for_write().data() : - MEM_dupallocN(mesh_src->loops().data()), - tmp.totloop); - CustomData_add_layer(&tmp.pdata, - CD_MPOLY, - CD_ASSIGN, - (alloctype == CD_ASSIGN) ? mesh_src->polys_for_write().data() : - MEM_dupallocN(mesh_src->polys().data()), - tmp.totpoly); - } - - /* object had got displacement layer, should copy this layer to save sculpted data */ - /* NOTE(nazgul): maybe some other layers should be copied? */ - if (CustomData_has_layer(&mesh_dst->ldata, CD_MDISPS)) { - if (totloop == mesh_dst->totloop) { - MDisps *mdisps = (MDisps *)CustomData_get_layer(&mesh_dst->ldata, CD_MDISPS); - CustomData_add_layer(&tmp.ldata, CD_MDISPS, alloctype, mdisps, totloop); - if (alloctype == CD_ASSIGN) { - /* Assign nullptr to prevent double-free. */ - CustomData_set_layer(&mesh_dst->ldata, CD_MDISPS, nullptr); - } - } - } + BKE_mesh_clear_geometry(mesh_dst); - CustomData_free(&mesh_dst->vdata, mesh_dst->totvert); - CustomData_free(&mesh_dst->edata, mesh_dst->totedge); - CustomData_free(&mesh_dst->fdata, mesh_dst->totface); - CustomData_free(&mesh_dst->ldata, mesh_dst->totloop); - CustomData_free(&mesh_dst->pdata, mesh_dst->totpoly); - - /* ok, this should now use new CD shapekey data, - * which should be fed through the modifier - * stack */ - if (tmp.totvert != mesh_dst->totvert && !did_shapekeys && mesh_dst->key) { - CLOG_ERROR(&LOG, "YEEK! this should be recoded! Shape key loss!: ID '%s'", tmp.id.name); - if (tmp.key && !(tmp.id.tag & LIB_TAG_NO_MAIN)) { - id_us_min(&tmp.key->id); - } - tmp.key = nullptr; - } - - /* Clear selection history */ - MEM_SAFE_FREE(tmp.mselect); - tmp.totselect = 0; - tmp.texflag &= ~ME_AUTOSPACE_EVALUATED; + /* Make sure referenced layers have a single user so assigning them to the mesh in main doesn't + * share them. "Referenced" layers are not expected to be shared between original meshes. */ + CustomData_duplicate_referenced_layers(&mesh_src->vdata, mesh_src->totvert); + CustomData_duplicate_referenced_layers(&mesh_src->edata, mesh_src->totedge); + CustomData_duplicate_referenced_layers(&mesh_src->pdata, mesh_src->totpoly); + CustomData_duplicate_referenced_layers(&mesh_src->ldata, mesh_src->totloop); - /* Clear any run-time data. - * Even though this mesh won't typically have run-time data, the Python API can for e.g. - * create loop-triangle cache here, which is confusing when left in the mesh, see: T81136. */ - BKE_mesh_runtime_clear_geometry(&tmp); + mesh_dst->totvert = mesh_src->totvert; + mesh_dst->totedge = mesh_src->totedge; + mesh_dst->totpoly = mesh_src->totpoly; + mesh_dst->totloop = mesh_src->totloop; - /* skip the listbase */ - MEMCPY_STRUCT_AFTER(mesh_dst, &tmp, id.prev); + /* Using #CD_MASK_MESH ensures that only data that should exist in Main meshes is moved. */ + const CustomData_MeshMasks mask = CD_MASK_MESH; + CustomData_copy(&mesh_src->vdata, &mesh_dst->vdata, mask.vmask, CD_ASSIGN, mesh_src->totvert); + CustomData_copy(&mesh_src->edata, &mesh_dst->edata, mask.emask, CD_ASSIGN, mesh_src->totedge); + CustomData_copy(&mesh_src->pdata, &mesh_dst->pdata, mask.pmask, CD_ASSIGN, mesh_src->totpoly); + CustomData_copy(&mesh_src->ldata, &mesh_dst->ldata, mask.lmask, CD_ASSIGN, mesh_src->totloop); BLI_freelistN(&mesh_dst->vertex_group_names); - BKE_defgroup_copy_list(&mesh_dst->vertex_group_names, &mesh_src->vertex_group_names); - mesh_dst->vertex_group_active_index = mesh_src->vertex_group_active_index; - - if (take_ownership) { - if (alloctype == CD_ASSIGN) { - CustomData_free_typemask(&mesh_src->vdata, mesh_src->totvert, ~mask->vmask); - CustomData_free_typemask(&mesh_src->edata, mesh_src->totedge, ~mask->emask); - CustomData_free_typemask(&mesh_src->ldata, mesh_src->totloop, ~mask->lmask); - CustomData_free_typemask(&mesh_src->pdata, mesh_src->totpoly, ~mask->pmask); + mesh_dst->vertex_group_names = mesh_src->vertex_group_names; + BLI_listbase_clear(&mesh_src->vertex_group_names); + + BKE_mesh_copy_parameters(mesh_dst, mesh_src); + mesh_dst->cd_flag = mesh_src->cd_flag; + + /* For original meshes, shape key data is stored in the #Key data-block, so it + * must be moved from the storage in #CustomData layers used for evaluation. */ + if (Key *key_dst = mesh_dst->key) { + if (CustomData_has_layer(&mesh_src->vdata, CD_SHAPEKEY)) { + /* If no object, set to -1 so we don't mess up any shapekey layers. */ + const int uid_active = ob ? find_object_active_key_uid(*key_dst, *ob) : -1; + move_shapekey_layers_to_keyblocks(*mesh_src, *key_dst, uid_active); + } + else if (mesh_src->totvert != mesh_dst->totvert) { + CLOG_ERROR(&LOG, "Mesh in Main '%s' lost shape keys", mesh_src->id.name); + if (mesh_src->key) { + id_us_min(&mesh_src->key->id); + } } - BKE_id_free(nullptr, mesh_src); } - BKE_mesh_assert_normals_dirty_or_calculated(mesh_dst); + BKE_id_free(nullptr, mesh_src); } void BKE_mesh_nomain_to_meshkey(Mesh *mesh_src, Mesh *mesh_dst, KeyBlock *kb) diff --git a/source/blender/blenkernel/intern/multires_unsubdivide.c b/source/blender/blenkernel/intern/multires_unsubdivide.c index 9a0f7aa2126..353fbec6933 100644 --- a/source/blender/blenkernel/intern/multires_unsubdivide.c +++ b/source/blender/blenkernel/intern/multires_unsubdivide.c @@ -1252,7 +1252,7 @@ int multiresModifier_rebuild_subdiv(struct Depsgraph *depsgraph, } /* Copy the new base mesh to the original mesh. */ - BKE_mesh_nomain_to_mesh(unsubdiv_context.base_mesh, object->data, object, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(unsubdiv_context.base_mesh, object->data, object); Mesh *base_mesh = object->data; multires_create_grids_in_unsubdivided_base_mesh(&unsubdiv_context, base_mesh); diff --git a/source/blender/editors/mesh/editmesh_mask_extract.c b/source/blender/editors/mesh/editmesh_mask_extract.c index 6a080e78086..a4d41400bae 100644 --- a/source/blender/editors/mesh/editmesh_mask_extract.c +++ b/source/blender/editors/mesh/editmesh_mask_extract.c @@ -204,7 +204,7 @@ static int geometry_extract_apply(bContext *C, local_view_bits = v3d->local_view_uuid; } Object *new_ob = ED_object_add_type(C, OB_MESH, NULL, ob->loc, ob->rot, false, local_view_bits); - BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob, &CD_MASK_EVERYTHING, true); + BKE_mesh_nomain_to_mesh(new_mesh, new_ob->data, new_ob); /* Remove the Face Sets as they need to be recreated when entering Sculpt Mode in the new object. * TODO(pablodobarro): In the future we can try to preserve them from the original mesh. */ @@ -548,7 +548,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) /* Remove the mask from the new object so it can be sculpted directly after slicing. */ CustomData_free_layers(&new_ob_mesh->vdata, CD_PAINT_MASK, new_ob_mesh->totvert); - BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_ob_mesh, new_ob->data, new_ob); BKE_mesh_copy_parameters_for_eval(new_ob->data, mesh); WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, new_ob); BKE_mesh_batch_cache_dirty_tag(new_ob->data, BKE_MESH_BATCH_DIRTY_ALL); @@ -557,7 +557,7 @@ static int paint_mask_slice_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_GEOM | ND_DATA, new_ob->data); } - BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, ob->data, ob); if (ob->mode == OB_MODE_SCULPT) { SculptSession *ss = ob->sculpt; diff --git a/source/blender/editors/object/object_add.cc b/source/blender/editors/object/object_add.cc index ddd54aa7953..c651affd96a 100644 --- a/source/blender/editors/object/object_add.cc +++ b/source/blender/editors/object/object_add.cc @@ -3151,7 +3151,7 @@ static int object_convert_exec(bContext *C, wmOperator *op) BKE_mesh_edges_set_draw_render(me_eval); BKE_object_material_from_eval_data(bmain, newob, &me_eval->id); Mesh *new_mesh = (Mesh *)newob->data; - BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(me_eval, new_mesh, newob); if (do_merge_customdata) { BKE_mesh_merge_customdata_for_apply_modifier(new_mesh); diff --git a/source/blender/editors/object/object_modifier.cc b/source/blender/editors/object/object_modifier.cc index 9bb82cc086c..2de33a3563a 100644 --- a/source/blender/editors/object/object_modifier.cc +++ b/source/blender/editors/object/object_modifier.cc @@ -763,7 +763,7 @@ static bool modifier_apply_obdata( Main *bmain = DEG_get_bmain(depsgraph); BKE_object_material_from_eval_data(bmain, ob, &mesh_applied->id); - BKE_mesh_nomain_to_mesh(mesh_applied, me, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(mesh_applied, me, ob); /* Anonymous attributes shouldn't be available on the applied geometry. */ me->attributes_for_write().remove_anonymous(); diff --git a/source/blender/editors/object/object_remesh.cc b/source/blender/editors/object/object_remesh.cc index 09489c50e9d..a6b51048209 100644 --- a/source/blender/editors/object/object_remesh.cc +++ b/source/blender/editors/object/object_remesh.cc @@ -179,7 +179,7 @@ static int voxel_remesh_exec(bContext *C, wmOperator *op) BKE_remesh_reproject_vertex_paint(new_mesh, mesh); } - BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob); if (smooth_normals) { BKE_mesh_smooth_flag_set(static_cast(ob->data), true); @@ -905,7 +905,7 @@ static void quadriflow_start_job(void *customdata, short *stop, short *do_update BKE_mesh_remesh_reproject_paint_mask(new_mesh, mesh); } - BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(new_mesh, mesh, ob); if (qj->smooth_normals) { BKE_mesh_smooth_flag_set(static_cast(ob->data), true); diff --git a/source/blender/editors/sculpt_paint/paint_mask.c b/source/blender/editors/sculpt_paint/paint_mask.c index 332a0830081..0ea45f83336 100644 --- a/source/blender/editors/sculpt_paint/paint_mask.c +++ b/source/blender/editors/sculpt_paint/paint_mask.c @@ -1315,8 +1315,7 @@ static void sculpt_gesture_apply_trim(SculptGestureContext *sgcontext) }), sculpt_mesh); BM_mesh_free(bm); - BKE_mesh_nomain_to_mesh( - result, sgcontext->vc.obact->data, sgcontext->vc.obact, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(result, sgcontext->vc.obact->data, sgcontext->vc.obact); } static void sculpt_gesture_trim_begin(bContext *C, SculptGestureContext *sgcontext) diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index 65d99e3f057..ebb1b5a29bd 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -619,11 +619,7 @@ void AbcMeshReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr); if (read_mesh != mesh) { - /* XXX FIXME: after 2.80; mesh->flag isn't copied by #BKE_mesh_nomain_to_mesh(). */ - /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ - uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); - mesh->flag |= autosmooth; + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object); } if (m_settings->validate_meshes) { @@ -1003,7 +999,7 @@ void AbcSubDReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSelec Mesh *read_mesh = this->read_mesh(mesh, sample_sel, MOD_MESHSEQ_READ_ALL, "", 0.0f, nullptr); if (read_mesh != mesh) { - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_EVERYTHING, true); + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object); } ISubDSchema::Sample sample; diff --git a/source/blender/io/alembic/intern/abc_reader_points.cc b/source/blender/io/alembic/intern/abc_reader_points.cc index ff189bc92dc..54ae71ad7a6 100644 --- a/source/blender/io/alembic/intern/abc_reader_points.cc +++ b/source/blender/io/alembic/intern/abc_reader_points.cc @@ -69,7 +69,7 @@ void AbcPointsReader::readObjectData(Main *bmain, const Alembic::Abc::ISampleSel Mesh *read_mesh = this->read_mesh(mesh, sample_sel, 0, "", 0.0f, nullptr); if (read_mesh != mesh) { - BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object, &CD_MASK_MESH, true); + BKE_mesh_nomain_to_mesh(read_mesh, mesh, m_object); } if (m_settings->validate_meshes) { diff --git a/source/blender/io/usd/intern/usd_reader_mesh.cc b/source/blender/io/usd/intern/usd_reader_mesh.cc index 0b96cd8ce90..7cb4c65f166 100644 --- a/source/blender/io/usd/intern/usd_reader_mesh.cc +++ b/source/blender/io/usd/intern/usd_reader_mesh.cc @@ -248,11 +248,7 @@ void USDMeshReader::read_object_data(Main *bmain, const double motionSampleTime) is_initial_load_ = false; if (read_mesh != mesh) { - /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */ - /* read_mesh can be freed by BKE_mesh_nomain_to_mesh(), so get the flag before that happens. */ - uint16_t autosmooth = (read_mesh->flag & ME_AUTOSMOOTH); - BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_, &CD_MASK_MESH, true); - mesh->flag |= autosmooth; + BKE_mesh_nomain_to_mesh(read_mesh, mesh, object_); } readFaceSetsSample(bmain, mesh, motionSampleTime); diff --git a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc index b1a2c7834f4..ef05534928a 100644 --- a/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc +++ b/source/blender/io/wavefront_obj/importer/obj_import_mesh.cc @@ -69,11 +69,7 @@ Object *MeshFromGeometry::create_mesh(Main *bmain, } transform_object(obj, import_params); - /* FIXME: after 2.80; `mesh->flag` isn't copied by #BKE_mesh_nomain_to_mesh() */ - const uint16_t autosmooth = (mesh->flag & ME_AUTOSMOOTH); - Mesh *dst = static_cast(obj->data); - BKE_mesh_nomain_to_mesh(mesh, dst, obj, &CD_MASK_EVERYTHING, true); - dst->flag |= autosmooth; + BKE_mesh_nomain_to_mesh(mesh, static_cast(obj->data), obj); /* NOTE: vertex groups have to be created after final mesh is assigned to the object. */ create_vertex_groups(obj); diff --git a/source/blender/makesrna/intern/rna_mesh_api.c b/source/blender/makesrna/intern/rna_mesh_api.c index 7551f9d7096..6b1df3fc4d4 100644 --- a/source/blender/makesrna/intern/rna_mesh_api.c +++ b/source/blender/makesrna/intern/rna_mesh_api.c @@ -22,6 +22,7 @@ # include "DNA_mesh_types.h" +# include "BKE_anim_data.h" # include "BKE_mesh.h" # include "BKE_mesh_mapping.h" # include "BKE_mesh_runtime.h" @@ -192,6 +193,7 @@ static void rna_Mesh_count_selected_items(Mesh *mesh, int r_count[3]) static void rna_Mesh_clear_geometry(Mesh *mesh) { BKE_mesh_clear_geometry(mesh); + BKE_animdata_free(&mesh->id, false); DEG_id_tag_update(&mesh->id, ID_RECALC_GEOMETRY_ALL_MODES); WM_main_add_notifier(NC_GEOM | ND_DATA, mesh); -- cgit v1.2.3 From 291c313f80b4cccc8fcce3035584caeaa654844f Mon Sep 17 00:00:00 2001 From: Hans Goudey Date: Fri, 9 Sep 2022 08:29:07 -0500 Subject: Mesh: Move bevel weight out of MVert and MEdge As described in T95966, the goal is to move to a "struct of arrays" approach rather than gathering an arbitrary set of data in hard-coded structs. This has performance benefits, but also code complexity benefits (this patch removes plenty of code, though the boilerplate for the new operators outweighs that here). To mirror the internal change, the options for storing mesh bevel weights are converted into operators that add or remove the layer, like for some other layers. The most complex change is to the solidify modifier, where bevel weights had special handling. Other than that, most changes are removing clearing of the weights, boilerplate for the add/remove operators, and removing the manual transfer of bevel weights in bmesh - mesh conversion. Eventually bevel weights can become a fully generic attribute, but for now this patch aims to avoid most functional changes. Bevel weights are still written and read from the mesh in the old way, so neither forward nor backward compatibility are affected. As described in T95965, writing in the old format will be done until 4.0. Differential Revision: https://developer.blender.org/D14077 --- .../scripts/startup/bl_ui/properties_data_mesh.py | 12 +- source/blender/blenkernel/BKE_customdata.h | 1 - .../blender/blenkernel/BKE_mesh_legacy_convert.h | 9 ++ source/blender/blenkernel/intern/customdata.cc | 20 +-- source/blender/blenkernel/intern/data_transfer.c | 67 +--------- .../blender/blenkernel/intern/mball_tessellate.c | 1 - source/blender/blenkernel/intern/mesh.cc | 2 + .../blenkernel/intern/mesh_boolean_convert.cc | 2 - source/blender/blenkernel/intern/mesh_convert.cc | 2 +- source/blender/blenkernel/intern/mesh_debug.cc | 6 - .../blenkernel/intern/mesh_legacy_convert.cc | 61 +++++++++ source/blender/blenkernel/intern/subdiv_mesh.cc | 4 - source/blender/blenkernel/intern/subsurf_ccg.c | 4 +- source/blender/bmesh/intern/bmesh_mesh_convert.cc | 63 --------- source/blender/editors/mesh/editmesh_path.c | 5 +- source/blender/editors/mesh/mesh_data.cc | 142 +++++++++++++++++++++ source/blender/editors/mesh/mesh_intern.h | 4 + source/blender/editors/mesh/mesh_ops.c | 4 + .../blender/editors/space_view3d/view3d_buttons.c | 8 +- .../transform/transform_convert_mesh_edge.c | 4 +- .../transform/transform_convert_mesh_vert_cdata.c | 4 +- .../geometry/intern/mesh_merge_by_distance.cc | 9 -- .../blender/io/alembic/intern/abc_reader_mesh.cc | 4 - source/blender/io/collada/MeshImporter.cpp | 1 - source/blender/makesdna/DNA_mesh_types.h | 2 + source/blender/makesdna/DNA_meshdata_types.h | 12 +- source/blender/makesrna/intern/rna_mesh.c | 57 ++++++--- source/blender/modifiers/intern/MOD_array.c | 2 +- source/blender/modifiers/intern/MOD_bevel.c | 4 + .../modifiers/intern/MOD_solidify_extrude.c | 56 ++++---- .../modifiers/intern/MOD_solidify_nonmanifold.c | 71 +++++++---- 31 files changed, 390 insertions(+), 253 deletions(-) diff --git a/release/scripts/startup/bl_ui/properties_data_mesh.py b/release/scripts/startup/bl_ui/properties_data_mesh.py index 686d455b6b4..d878eea0cb9 100644 --- a/release/scripts/startup/bl_ui/properties_data_mesh.py +++ b/release/scripts/startup/bl_ui/properties_data_mesh.py @@ -493,11 +493,19 @@ class DATA_PT_customdata(MeshButtonsPanel, Panel): else: col.operator("mesh.customdata_custom_splitnormals_add", icon='ADD') + if me.has_bevel_weight_edge: + col.operator("mesh.customdata_bevel_weight_edge_clear", icon='X') + else: + col.operator("mesh.customdata_bevel_weight_edge_add", icon='ADD') + + if me.has_bevel_weight_vertex: + col.operator("mesh.customdata_bevel_weight_vertex_clear", icon='X') + else: + col.operator("mesh.customdata_bevel_weight_vertex_add", icon='ADD') + col = layout.column(heading="Store") col.enabled = obj is not None and obj.mode != 'EDIT' - col.prop(me, "use_customdata_vertex_bevel", text="Vertex Bevel Weight") - col.prop(me, "use_customdata_edge_bevel", text="Edge Bevel Weight") col.prop(me, "use_customdata_vertex_crease", text="Vertex Crease") col.prop(me, "use_customdata_edge_crease", text="Edge Crease") diff --git a/source/blender/blenkernel/BKE_customdata.h b/source/blender/blenkernel/BKE_customdata.h index 44a4f4b5395..09d37682b3c 100644 --- a/source/blender/blenkernel/BKE_customdata.h +++ b/source/blender/blenkernel/BKE_customdata.h @@ -640,7 +640,6 @@ enum { CD_FAKE_CREASE = CD_FAKE | CD_CREASE, /* *sigh*. */ /* Multiple types of mesh elements... */ - CD_FAKE_BWEIGHT = CD_FAKE | CD_BWEIGHT, /* *sigh*. */ CD_FAKE_UV = CD_FAKE | CD_MLOOPUV, /* UV flag, because we handle both loop's UVs and poly's textures. */ diff --git a/source/blender/blenkernel/BKE_mesh_legacy_convert.h b/source/blender/blenkernel/BKE_mesh_legacy_convert.h index 11ee86c62a7..e67aec0b9ce 100644 --- a/source/blender/blenkernel/BKE_mesh_legacy_convert.h +++ b/source/blender/blenkernel/BKE_mesh_legacy_convert.h @@ -17,6 +17,15 @@ struct CustomData; struct Mesh; struct MFace; +/** + * Copy bevel weights from separate layers into vertices and edges. + */ +void BKE_mesh_legacy_bevel_weight_from_layers(struct Mesh *mesh); +/** + * Copy bevel weights from vertices and edges to separate layers. + */ +void BKE_mesh_legacy_bevel_weight_to_layers(struct Mesh *mesh); + /** * Convert the hidden element attributes to the old flag format for writing. */ diff --git a/source/blender/blenkernel/intern/customdata.cc b/source/blender/blenkernel/intern/customdata.cc index a3b9f012e45..24373053896 100644 --- a/source/blender/blenkernel/intern/customdata.cc +++ b/source/blender/blenkernel/intern/customdata.cc @@ -1867,7 +1867,7 @@ static const LayerTypeInfo LAYERTYPEINFO[CD_NUMTYPES] = { /* 28: CD_SHAPEKEY */ {sizeof(float[3]), "", 0, N_("ShapeKey"), nullptr, nullptr, layerInterp_shapekey}, /* 29: CD_BWEIGHT */ - {sizeof(float), "", 0, N_("BevelWeight"), nullptr, nullptr, layerInterp_bweight}, + {sizeof(MFloatProperty), "MFloatProperty", 1, nullptr, nullptr, nullptr, layerInterp_bweight}, /* 30: CD_CREASE */ /* NOTE: we do not interpolate crease data as it should be either inherited for subdivided * edges, or for vertex creases, only present on the original vertex. */ @@ -2108,23 +2108,23 @@ static const char *LAYERTYPENAMES[CD_NUMTYPES] = { }; const CustomData_MeshMasks CD_MASK_BAREMESH = { - /* vmask */ CD_MASK_MVERT | CD_MASK_BWEIGHT, - /* emask */ CD_MASK_MEDGE | CD_MASK_BWEIGHT, + /* vmask */ CD_MASK_MVERT, + /* emask */ CD_MASK_MEDGE, /* fmask */ 0, /* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP, /* lmask */ CD_MASK_MLOOP, }; const CustomData_MeshMasks CD_MASK_BAREMESH_ORIGINDEX = { - /* vmask */ CD_MASK_MVERT | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX, - /* emask */ CD_MASK_MEDGE | CD_MASK_BWEIGHT | CD_MASK_ORIGINDEX, + /* vmask */ CD_MASK_MVERT | CD_MASK_ORIGINDEX, + /* emask */ CD_MASK_MEDGE | CD_MASK_ORIGINDEX, /* fmask */ 0, /* pmask */ CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_ORIGINDEX, /* lmask */ CD_MASK_MLOOP, }; const CustomData_MeshMasks CD_MASK_MESH = { /* vmask */ (CD_MASK_MVERT | CD_MASK_MDEFORMVERT | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK | - CD_MASK_PROP_ALL | CD_MASK_CREASE), - /* emask */ (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), + CD_MASK_PROP_ALL | CD_MASK_CREASE | CD_MASK_BWEIGHT), + /* emask */ (CD_MASK_MEDGE | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL | CD_MASK_BWEIGHT), /* fmask */ 0, /* pmask */ (CD_MASK_MPOLY | CD_MASK_FACEMAP | CD_MASK_FREESTYLE_FACE | CD_MASK_PROP_ALL | @@ -2136,8 +2136,8 @@ const CustomData_MeshMasks CD_MASK_MESH = { const CustomData_MeshMasks CD_MASK_DERIVEDMESH = { /* vmask */ (CD_MASK_ORIGINDEX | CD_MASK_MDEFORMVERT | CD_MASK_SHAPEKEY | CD_MASK_MVERT_SKIN | CD_MASK_PAINT_MASK | CD_MASK_ORCO | CD_MASK_CLOTH_ORCO | CD_MASK_PROP_ALL | - CD_MASK_CREASE), - /* emask */ (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_PROP_ALL), + CD_MASK_CREASE | CD_MASK_BWEIGHT), + /* emask */ (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_EDGE | CD_MASK_BWEIGHT | CD_MASK_PROP_ALL), /* fmask */ (CD_MASK_ORIGINDEX | CD_MASK_ORIGSPACE | CD_MASK_PREVIEW_MCOL | CD_MASK_TANGENT), /* pmask */ (CD_MASK_ORIGINDEX | CD_MASK_FREESTYLE_FACE | CD_MASK_FACEMAP | CD_MASK_PROP_ALL | @@ -5175,7 +5175,7 @@ void CustomData_data_transfer(const MeshPairRemap *me_remap, else { const LayerTypeInfo *type_info = layerType_getInfo(data_type); - /* NOTE: we can use 'fake' CDLayers, like e.g. for crease, bweight, etc. :/. */ + /* NOTE: we can use 'fake' CDLayers for crease :/. */ data_size = (size_t)type_info->size; data_step = laymap->elem_size ? laymap->elem_size : data_size; data_offset = laymap->data_offset; diff --git a/source/blender/blenkernel/intern/data_transfer.c b/source/blender/blenkernel/intern/data_transfer.c index 6fbdade08f8..6c7715c625e 100644 --- a/source/blender/blenkernel/intern/data_transfer.c +++ b/source/blender/blenkernel/intern/data_transfer.c @@ -192,7 +192,7 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type) case DT_TYPE_SKIN: return CD_MVERT_SKIN; case DT_TYPE_BWEIGHT_VERT: - return CD_FAKE_BWEIGHT; + return CD_BWEIGHT; case DT_TYPE_SHARP_EDGE: return CD_FAKE_SHARP; @@ -201,7 +201,7 @@ int BKE_object_data_transfer_dttype_to_cdtype(const int dtdata_type) case DT_TYPE_CREASE: return CD_FAKE_CREASE; case DT_TYPE_BWEIGHT_EDGE: - return CD_FAKE_BWEIGHT; + return CD_BWEIGHT; case DT_TYPE_FREESTYLE_EDGE: return CD_FREESTYLE_EDGE; @@ -928,38 +928,6 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, } return true; } - if (cddata_type == CD_FAKE_BWEIGHT) { - const size_t elem_size = sizeof(*((MVert *)NULL)); - const size_t data_size = sizeof(((MVert *)NULL)->bweight); - const size_t data_offset = offsetof(MVert, bweight); - const uint64_t data_flag = 0; - - if (!(me_src->cd_flag & ME_CDFLAG_VERT_BWEIGHT)) { - if (use_delete) { - me_dst->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT; - } - return true; - } - me_dst->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; - if (r_map) { - data_transfer_layersmapping_add_item(r_map, - cddata_type, - mix_mode, - mix_factor, - mix_weights, - BKE_mesh_verts(me_src), - BKE_mesh_verts_for_write(me_dst), - me_src->totvert, - me_dst->totvert, - elem_size, - data_size, - data_offset, - data_flag, - data_transfer_interp_char, - interp_data); - } - return true; - } if (cddata_type == CD_FAKE_MDEFORMVERT) { bool ret; @@ -1045,38 +1013,7 @@ static bool data_transfer_layersmapping_generate(ListBase *r_map, } return true; } - if (cddata_type == CD_FAKE_BWEIGHT) { - const size_t elem_size = sizeof(*((MEdge *)NULL)); - const size_t data_size = sizeof(((MEdge *)NULL)->bweight); - const size_t data_offset = offsetof(MEdge, bweight); - const uint64_t data_flag = 0; - if (!(me_src->cd_flag & ME_CDFLAG_EDGE_BWEIGHT)) { - if (use_delete) { - me_dst->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT; - } - return true; - } - me_dst->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - if (r_map) { - data_transfer_layersmapping_add_item(r_map, - cddata_type, - mix_mode, - mix_factor, - mix_weights, - BKE_mesh_edges(me_src), - BKE_mesh_edges_for_write(me_dst), - me_src->totedge, - me_dst->totedge, - elem_size, - data_size, - data_offset, - data_flag, - data_transfer_interp_char, - interp_data); - } - return true; - } if (r_map && ELEM(cddata_type, CD_FAKE_SHARP, CD_FAKE_SEAM)) { const size_t elem_size = sizeof(*((MEdge *)NULL)); const size_t data_size = sizeof(((MEdge *)NULL)->flag); diff --git a/source/blender/blenkernel/intern/mball_tessellate.c b/source/blender/blenkernel/intern/mball_tessellate.c index 3917c020759..49963c333ec 100644 --- a/source/blender/blenkernel/intern/mball_tessellate.c +++ b/source/blender/blenkernel/intern/mball_tessellate.c @@ -1447,7 +1447,6 @@ Mesh *BKE_mball_polygonize(Depsgraph *depsgraph, Scene *scene, Object *ob) MVert *mvert = CustomData_add_layer(&mesh->vdata, CD_MVERT, CD_CONSTRUCT, NULL, mesh->totvert); for (int i = 0; i < mesh->totvert; i++) { copy_v3_v3(mvert[i].co, process.co[i]); - mvert->bweight = 0; mvert->flag = 0; } MEM_freeN(process.co); diff --git a/source/blender/blenkernel/intern/mesh.cc b/source/blender/blenkernel/intern/mesh.cc index c82d9be008d..a5b50824542 100644 --- a/source/blender/blenkernel/intern/mesh.cc +++ b/source/blender/blenkernel/intern/mesh.cc @@ -251,6 +251,7 @@ static void mesh_blend_write(BlendWriter *writer, ID *id, const void *id_address if (!BLO_write_is_undo(writer)) { BKE_mesh_legacy_convert_hide_layers_to_flags(mesh); BKE_mesh_legacy_convert_material_indices_to_mpoly(mesh); + BKE_mesh_legacy_bevel_weight_from_layers(mesh); /* When converting to the old mesh format, don't save redundant attributes. */ names_to_skip.add_multiple_new({".hide_vert", ".hide_edge", ".hide_poly"}); @@ -348,6 +349,7 @@ static void mesh_blend_read_data(BlendDataReader *reader, ID *id) if (!BLO_read_data_is_undo(reader)) { BKE_mesh_legacy_convert_flags_to_hide_layers(mesh); BKE_mesh_legacy_convert_mpoly_to_material_indices(mesh); + BKE_mesh_legacy_bevel_weight_to_layers(mesh); } /* We don't expect to load normals from files, since they are derived data. */ diff --git a/source/blender/blenkernel/intern/mesh_boolean_convert.cc b/source/blender/blenkernel/intern/mesh_boolean_convert.cc index 4b08e0b2ed5..7a04e45fe00 100644 --- a/source/blender/blenkernel/intern/mesh_boolean_convert.cc +++ b/source/blender/blenkernel/intern/mesh_boolean_convert.cc @@ -381,7 +381,6 @@ static void copy_vert_attributes(Mesh *dest_mesh, int mv_index, int index_in_orig_me) { - mv->bweight = orig_mv->bweight; mv->flag = orig_mv->flag; /* For all layers in the orig mesh, copy the layer information. */ @@ -450,7 +449,6 @@ static void copy_edge_attributes(Mesh *dest_mesh, int medge_index, int index_in_orig_me) { - medge->bweight = orig_medge->bweight; medge->crease = orig_medge->crease; medge->flag = orig_medge->flag; CustomData *target_cd = &dest_mesh->edata; diff --git a/source/blender/blenkernel/intern/mesh_convert.cc b/source/blender/blenkernel/intern/mesh_convert.cc index 756529473f4..b7d8972aa7b 100644 --- a/source/blender/blenkernel/intern/mesh_convert.cc +++ b/source/blender/blenkernel/intern/mesh_convert.cc @@ -118,7 +118,7 @@ static void make_edges_mdata_extend(Mesh &mesh) BLI_edgehashIterator_getKey(ehi, &medge->v1, &medge->v2); BLI_edgehashIterator_setValue(ehi, POINTER_FROM_UINT(e_index)); - medge->crease = medge->bweight = 0; + medge->crease = 0; medge->flag = ME_EDGEDRAW | ME_EDGERENDER; } BLI_edgehashIterator_free(ehi); diff --git a/source/blender/blenkernel/intern/mesh_debug.cc b/source/blender/blenkernel/intern/mesh_debug.cc index 1826a77d6f4..8a9ce901923 100644 --- a/source/blender/blenkernel/intern/mesh_debug.cc +++ b/source/blender/blenkernel/intern/mesh_debug.cc @@ -30,12 +30,6 @@ static void mesh_debug_info_from_cd_flag(const Mesh *me, DynStr *dynstr) { BLI_dynstr_append(dynstr, "'cd_flag': {"); - if (me->cd_flag & ME_CDFLAG_VERT_BWEIGHT) { - BLI_dynstr_append(dynstr, "'VERT_BWEIGHT', "); - } - if (me->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { - BLI_dynstr_append(dynstr, "'EDGE_BWEIGHT', "); - } if (me->cd_flag & ME_CDFLAG_EDGE_CREASE) { BLI_dynstr_append(dynstr, "'EDGE_CREASE', "); } diff --git a/source/blender/blenkernel/intern/mesh_legacy_convert.cc b/source/blender/blenkernel/intern/mesh_legacy_convert.cc index 2f67e303095..10fc8ff3195 100644 --- a/source/blender/blenkernel/intern/mesh_legacy_convert.cc +++ b/source/blender/blenkernel/intern/mesh_legacy_convert.cc @@ -917,6 +917,67 @@ void BKE_mesh_add_mface_layers(CustomData *fdata, CustomData *ldata, int total) /** \} */ +/* -------------------------------------------------------------------- */ +/** \name Bevel Weight Conversion + * \{ */ + +void BKE_mesh_legacy_bevel_weight_from_layers(Mesh *mesh) +{ + using namespace blender; + MutableSpan verts = mesh->verts_for_write(); + if (const float *weights = static_cast( + CustomData_get_layer(&mesh->vdata, CD_BWEIGHT))) { + mesh->cd_flag |= ME_CDFLAG_VERT_BWEIGHT; + for (const int i : verts.index_range()) { + verts[i].bweight = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; + } + } + else { + mesh->cd_flag &= ~ME_CDFLAG_VERT_BWEIGHT; + for (const int i : verts.index_range()) { + verts[i].bweight = 0; + } + } + MutableSpan edges = mesh->edges_for_write(); + if (const float *weights = static_cast( + CustomData_get_layer(&mesh->edata, CD_BWEIGHT))) { + mesh->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + for (const int i : edges.index_range()) { + edges[i].bweight = std::clamp(weights[i], 0.0f, 1.0f) * 255.0f; + } + } + else { + mesh->cd_flag &= ~ME_CDFLAG_EDGE_BWEIGHT; + for (const int i : edges.index_range()) { + edges[i].bweight = 0; + } + } +} + +void BKE_mesh_legacy_bevel_weight_to_layers(Mesh *mesh) +{ + using namespace blender; + const Span verts = mesh->verts(); + if (mesh->cd_flag & ME_CDFLAG_VERT_BWEIGHT) { + float *weights = static_cast( + CustomData_add_layer(&mesh->vdata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, verts.size())); + for (const int i : verts.index_range()) { + weights[i] = verts[i].bweight / 255.0f; + } + } + + const Span edges = mesh->edges(); + if (mesh->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { + float *weights = static_cast( + CustomData_add_layer(&mesh->edata, CD_BWEIGHT, CD_CONSTRUCT, nullptr, edges.size())); + for (const int i : edges.index_range()) { + weights[i] = edges[i].bweight / 255.0f; + } + } +} + +/** \} */ + /* -------------------------------------------------------------------- */ /** \name Hide Attribute and Legacy Flag Conversion * \{ */ diff --git a/source/blender/blenkernel/intern/subdiv_mesh.cc b/source/blender/blenkernel/intern/subdiv_mesh.cc index dc9fc3dee09..44bdd6e6d06 100644 --- a/source/blender/blenkernel/intern/subdiv_mesh.cc +++ b/source/blender/blenkernel/intern/subdiv_mesh.cc @@ -791,7 +791,6 @@ static void subdiv_copy_edge_data(SubdivMeshContext *ctx, const int subdiv_edge_index = subdiv_edge - ctx->subdiv_edges; if (coarse_edge == nullptr) { subdiv_edge->crease = 0; - subdiv_edge->bweight = 0; subdiv_edge->flag = 0; if (!ctx->settings->use_optimal_display) { subdiv_edge->flag |= ME_EDGERENDER; @@ -1138,9 +1137,6 @@ static void subdiv_mesh_vertex_of_loose_edge(const SubdivForeachContext *foreach subdiv_vertex->co); /* Reset flags and such. */ subdiv_vertex->flag = 0; - /* TODO(sergey): This matches old behavior, but we can as well interpolate - * it. Maybe even using vertex varying attributes. */ - subdiv_vertex->bweight = 0.0f; } /** \} */ diff --git a/source/blender/blenkernel/intern/subsurf_ccg.c b/source/blender/blenkernel/intern/subsurf_ccg.c index 88c260be9ba..0e5f9f30243 100644 --- a/source/blender/blenkernel/intern/subsurf_ccg.c +++ b/source/blender/blenkernel/intern/subsurf_ccg.c @@ -879,7 +879,7 @@ static void ccgDM_getFinalVertNo(DerivedMesh *dm, int vertNum, float r_no[3]) BLI_INLINE void ccgDM_to_MVert(MVert *mv, const CCGKey *key, CCGElem *elem) { copy_v3_v3(mv->co, CCG_elem_co(key, elem)); - mv->flag = mv->bweight = 0; + mv->flag = 0; } static void ccgDM_copyFinalVertArray(DerivedMesh *dm, MVert *mvert) @@ -949,7 +949,7 @@ BLI_INLINE void ccgDM_to_MEdge(MEdge *med, const int v1, const int v2, const sho { med->v1 = v1; med->v2 = v2; - med->crease = med->bweight = 0; + med->crease = 0; med->flag = flag; } diff --git a/source/blender/bmesh/intern/bmesh_mesh_convert.cc b/source/blender/bmesh/intern/bmesh_mesh_convert.cc index ccd82865178..94440916603 100644 --- a/source/blender/bmesh/intern/bmesh_mesh_convert.cc +++ b/source/blender/bmesh/intern/bmesh_mesh_convert.cc @@ -126,17 +126,6 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag) BLI_assert(bm->edata.totlayer == 0 || bm->edata.pool != nullptr); BLI_assert(bm->pdata.totlayer == 0 || bm->pdata.pool != nullptr); - if (cd_flag & ME_CDFLAG_VERT_BWEIGHT) { - if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { - BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); - } - } - else { - if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { - BM_data_layer_free(bm, &bm->vdata, CD_BWEIGHT); - } - } - if (cd_flag & ME_CDFLAG_VERT_CREASE) { if (!CustomData_has_layer(&bm->vdata, CD_CREASE)) { BM_data_layer_add(bm, &bm->vdata, CD_CREASE); @@ -148,17 +137,6 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag) } } - if (cd_flag & ME_CDFLAG_EDGE_BWEIGHT) { - if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); - } - } - else { - if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - BM_data_layer_free(bm, &bm->edata, CD_BWEIGHT); - } - } - if (cd_flag & ME_CDFLAG_EDGE_CREASE) { if (!CustomData_has_layer(&bm->edata, CD_CREASE)) { BM_data_layer_add(bm, &bm->edata, CD_CREASE); @@ -174,15 +152,9 @@ void BM_mesh_cd_flag_apply(BMesh *bm, const char cd_flag) char BM_mesh_cd_flag_from_bmesh(BMesh *bm) { char cd_flag = 0; - if (CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { - cd_flag |= ME_CDFLAG_VERT_BWEIGHT; - } if (CustomData_has_layer(&bm->vdata, CD_CREASE)) { cd_flag |= ME_CDFLAG_VERT_CREASE; } - if (CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { - cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - } if (CustomData_has_layer(&bm->edata, CD_CREASE)) { cd_flag |= ME_CDFLAG_EDGE_CREASE; } @@ -342,12 +314,6 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Only copy these values over if the source mesh is flagged to be using them. * Even if `bm` has these layers, they may have been added from another mesh, when `!is_new`. */ - const int cd_vert_bweight_offset = (me->cd_flag & ME_CDFLAG_VERT_BWEIGHT) ? - CustomData_get_offset(&bm->vdata, CD_BWEIGHT) : - -1; - const int cd_edge_bweight_offset = (me->cd_flag & ME_CDFLAG_EDGE_BWEIGHT) ? - CustomData_get_offset(&bm->edata, CD_BWEIGHT) : - -1; const int cd_edge_crease_offset = (me->cd_flag & ME_CDFLAG_EDGE_CREASE) ? CustomData_get_offset(&bm->edata, CD_CREASE) : -1; @@ -391,10 +357,6 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Copy Custom Data */ CustomData_to_bmesh_block(&me->vdata, &bm->vdata, i, &v->head.data, true); - if (cd_vert_bweight_offset != -1) { - BM_ELEM_CD_SET_FLOAT(v, cd_vert_bweight_offset, (float)mvert[i].bweight / 255.0f); - } - /* Set shape key original index. */ if (cd_shape_keyindex_offset != -1) { BM_ELEM_CD_SET_INT(v, cd_shape_keyindex_offset, i); @@ -433,9 +395,6 @@ void BM_mesh_bm_from_me(BMesh *bm, const Mesh *me, const struct BMeshFromMeshPar /* Copy Custom Data */ CustomData_to_bmesh_block(&me->edata, &bm->edata, i, &e->head.data, true); - if (cd_edge_bweight_offset != -1) { - BM_ELEM_CD_SET_FLOAT(e, cd_edge_bweight_offset, (float)medge[i].bweight / 255.0f); - } if (cd_edge_crease_offset != -1) { BM_ELEM_CD_SET_FLOAT(e, cd_edge_crease_offset, (float)medge[i].crease / 255.0f); } @@ -990,8 +949,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh BMIter iter; int i, j; - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); const int cd_shape_keyindex_offset = CustomData_get_offset(&bm->vdata, CD_SHAPE_KEYINDEX); @@ -1073,10 +1030,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh /* Copy over custom-data. */ CustomData_from_bmesh_block(&bm->vdata, &me->vdata, v->head.data, i); - if (cd_vert_bweight_offset != -1) { - mvert[i].bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(v, cd_vert_bweight_offset); - } - i++; BM_CHECK_ELEMENT(v); @@ -1103,9 +1056,6 @@ void BM_mesh_bm_to_me(Main *bmain, BMesh *bm, Mesh *me, const struct BMeshToMesh if (cd_edge_crease_offset != -1) { medge[i].crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_crease_offset); } - if (cd_edge_bweight_offset != -1) { - medge[i].bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(e, cd_edge_bweight_offset); - } i++; BM_CHECK_ELEMENT(e); @@ -1312,8 +1262,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * MLoop *mloop = loops.data(); unsigned int i, j; - const int cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); - const int cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); const int cd_edge_crease_offset = CustomData_get_offset(&bm->edata, CD_CREASE); bool need_hide_vert = false; @@ -1339,14 +1287,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * need_hide_vert = true; } - if (cd_vert_bweight_offset != -1) { - mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); - } - - if (cd_vert_bweight_offset != -1) { - mv->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eve, cd_vert_bweight_offset); - } - CustomData_from_bmesh_block(&bm->vdata, &me->vdata, eve->head.data, i); } bm->elem_index_dirty &= ~BM_VERT; @@ -1375,9 +1315,6 @@ void BM_mesh_bm_to_me_for_eval(BMesh *bm, Mesh *me, const CustomData_MeshMasks * if (cd_edge_crease_offset != -1) { med->crease = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_crease_offset); } - if (cd_edge_bweight_offset != -1) { - med->bweight = BM_ELEM_CD_GET_FLOAT_AS_UCHAR(eed, cd_edge_bweight_offset); - } CustomData_from_bmesh_block(&bm->edata, &me->edata, eed->head.data, i); } diff --git a/source/blender/editors/mesh/editmesh_path.c b/source/blender/editors/mesh/editmesh_path.c index 6f2f43b844e..1db915940a0 100644 --- a/source/blender/editors/mesh/editmesh_path.c +++ b/source/blender/editors/mesh/editmesh_path.c @@ -21,6 +21,7 @@ #include "BLI_math.h" #include "BKE_context.h" +#include "BKE_customdata.h" #include "BKE_editmesh.h" #include "BKE_layer.h" #include "BKE_report.h" @@ -348,7 +349,9 @@ static void edgetag_ensure_cd_flag(Mesh *me, const char edge_mode) BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_CREASE); break; case EDGE_MODE_TAG_BEVEL: - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); + } break; #ifdef WITH_FREESTYLE case EDGE_MODE_TAG_FREESTYLE: diff --git a/source/blender/editors/mesh/mesh_data.cc b/source/blender/editors/mesh/mesh_data.cc index 4ee518b5662..e362501d86c 100644 --- a/source/blender/editors/mesh/mesh_data.cc +++ b/source/blender/editors/mesh/mesh_data.cc @@ -626,6 +626,28 @@ static int mesh_customdata_clear_exec__internal(bContext *C, char htype, int typ return OPERATOR_CANCELLED; } +static int mesh_customdata_add_exec__internal(bContext *C, char htype, int type) +{ + Mesh *mesh = ED_mesh_context(C); + + int tot; + CustomData *data = mesh_customdata_get_type(mesh, htype, &tot); + + BLI_assert(CustomData_layertype_is_singleton(type) == true); + + if (mesh->edit_mesh) { + BM_data_layer_add(mesh->edit_mesh->bm, data, type); + } + else { + CustomData_add_layer(data, type, CD_SET_DEFAULT, NULL, tot); + } + + DEG_id_tag_update(&mesh->id, 0); + WM_event_add_notifier(C, NC_GEOM | ND_DATA, mesh); + + return CustomData_has_layer(data, type) ? OPERATOR_FINISHED : OPERATOR_CANCELLED; +} + /* Clear Mask */ static bool mesh_customdata_mask_clear_poll(bContext *C) { @@ -848,6 +870,126 @@ void MESH_OT_customdata_custom_splitnormals_clear(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; } +/* Vertex bevel weight. */ + +static int mesh_customdata_bevel_weight_vertex_state(bContext *C) +{ + const Object *object = ED_object_context(C); + + if (object && object->type == OB_MESH) { + const Mesh *mesh = static_cast(object->data); + if (!ID_IS_LINKED(mesh)) { + const CustomData *data = GET_CD_DATA(mesh, vdata); + return CustomData_has_layer(data, CD_BWEIGHT); + } + } + return -1; +} + +static bool mesh_customdata_bevel_weight_vertex_add_poll(bContext *C) +{ + return mesh_customdata_bevel_weight_vertex_state(C) == 0; +} + +static int mesh_customdata_bevel_weight_vertex_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_add_exec__internal(C, BM_VERT, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_vertex_add(wmOperatorType *ot) +{ + ot->name = "Add Vertex Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_vertex_add"; + ot->description = "Add a vertex bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_vertex_add_exec; + ot->poll = mesh_customdata_bevel_weight_vertex_add_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static bool mesh_customdata_bevel_weight_vertex_clear_poll(bContext *C) +{ + return (mesh_customdata_bevel_weight_vertex_state(C) == 1); +} + +static int mesh_customdata_bevel_weight_vertex_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_VERT, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_vertex_clear(wmOperatorType *ot) +{ + ot->name = "Clear Vertex Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_vertex_clear"; + ot->description = "Clear the vertex bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_vertex_clear_exec; + ot->poll = mesh_customdata_bevel_weight_vertex_clear_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +/* Edge bevel weight. */ + +static int mesh_customdata_bevel_weight_edge_state(bContext *C) +{ + const Object *ob = ED_object_context(C); + + if (ob && ob->type == OB_MESH) { + const Mesh *mesh = static_cast(ob->data); + if (!ID_IS_LINKED(mesh)) { + const CustomData *data = GET_CD_DATA(mesh, edata); + return CustomData_has_layer(data, CD_BWEIGHT); + } + } + return -1; +} + +static bool mesh_customdata_bevel_weight_edge_add_poll(bContext *C) +{ + return mesh_customdata_bevel_weight_edge_state(C) == 0; +} + +static int mesh_customdata_bevel_weight_edge_add_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_add_exec__internal(C, BM_EDGE, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_edge_add(wmOperatorType *ot) +{ + ot->name = "Add Edge Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_edge_add"; + ot->description = "Add an edge bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_edge_add_exec; + ot->poll = mesh_customdata_bevel_weight_edge_add_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + +static bool mesh_customdata_bevel_weight_edge_clear_poll(bContext *C) +{ + return mesh_customdata_bevel_weight_edge_state(C) == 1; +} + +static int mesh_customdata_bevel_weight_edge_clear_exec(bContext *C, wmOperator *UNUSED(op)) +{ + return mesh_customdata_clear_exec__internal(C, BM_EDGE, CD_BWEIGHT); +} + +void MESH_OT_customdata_bevel_weight_edge_clear(wmOperatorType *ot) +{ + ot->name = "Clear Edge Bevel Weight"; + ot->idname = "MESH_OT_customdata_bevel_weight_edge_clear"; + ot->description = "Clear the edge bevel weight layer"; + + ot->exec = mesh_customdata_bevel_weight_edge_clear_exec; + ot->poll = mesh_customdata_bevel_weight_edge_clear_poll; + + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; +} + /************************** Add Geometry Layers *************************/ void ED_mesh_update(Mesh *mesh, bContext *C, bool calc_edges, bool calc_edges_loose) diff --git a/source/blender/editors/mesh/mesh_intern.h b/source/blender/editors/mesh/mesh_intern.h index 7c8dbffeb31..14b8cf55493 100644 --- a/source/blender/editors/mesh/mesh_intern.h +++ b/source/blender/editors/mesh/mesh_intern.h @@ -313,6 +313,10 @@ void MESH_OT_customdata_skin_add(struct wmOperatorType *ot); void MESH_OT_customdata_skin_clear(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_add(struct wmOperatorType *ot); void MESH_OT_customdata_custom_splitnormals_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_vertex_add(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_vertex_clear(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_edge_add(struct wmOperatorType *ot); +void MESH_OT_customdata_bevel_weight_edge_clear(struct wmOperatorType *ot); #ifdef __cplusplus } diff --git a/source/blender/editors/mesh/mesh_ops.c b/source/blender/editors/mesh/mesh_ops.c index b9e78740e3c..01c92a59fc9 100644 --- a/source/blender/editors/mesh/mesh_ops.c +++ b/source/blender/editors/mesh/mesh_ops.c @@ -139,6 +139,10 @@ void ED_operatortypes_mesh(void) WM_operatortype_append(MESH_OT_customdata_skin_clear); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_add); WM_operatortype_append(MESH_OT_customdata_custom_splitnormals_clear); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_vertex_add); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_vertex_clear); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_edge_add); + WM_operatortype_append(MESH_OT_customdata_bevel_weight_edge_clear); WM_operatortype_append(MESH_OT_edgering_select); WM_operatortype_append(MESH_OT_loopcut); diff --git a/source/blender/editors/space_view3d/view3d_buttons.c b/source/blender/editors/space_view3d/view3d_buttons.c index 5a5747bdf84..fe7e3a797c9 100644 --- a/source/blender/editors/space_view3d/view3d_buttons.c +++ b/source/blender/editors/space_view3d/view3d_buttons.c @@ -995,7 +995,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (apply_vcos || median->bv_weight || median->v_crease || median->skin[0] || median->skin[1]) { if (median->bv_weight) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); + if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); + } cd_vert_bweight_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); BLI_assert(cd_vert_bweight_offset != -1); @@ -1061,7 +1063,9 @@ static void v3d_editvertex_buts(uiLayout *layout, View3D *v3d, Object *ob, float if (median->be_weight || median->e_crease) { if (median->be_weight) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->edata, CD_BWEIGHT); + } cd_edge_bweight_offset = CustomData_get_offset(&bm->edata, CD_BWEIGHT); BLI_assert(cd_edge_bweight_offset != -1); diff --git a/source/blender/editors/transform/transform_convert_mesh_edge.c b/source/blender/editors/transform/transform_convert_mesh_edge.c index becf3c7ce5a..b1627e62f8c 100644 --- a/source/blender/editors/transform/transform_convert_mesh_edge.c +++ b/source/blender/editors/transform/transform_convert_mesh_edge.c @@ -67,7 +67,9 @@ static void createTransEdge(bContext *UNUSED(C), TransInfo *t) /* create data we need */ if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(em->bm, BKE_mesh_from_object(tc->obedit), ME_CDFLAG_EDGE_BWEIGHT); + if (!CustomData_has_layer(&em->bm->edata, CD_BWEIGHT)) { + BM_data_layer_add(em->bm, &em->bm->edata, CD_BWEIGHT); + } cd_edge_float_offset = CustomData_get_offset(&em->bm->edata, CD_BWEIGHT); } else { /* if (t->mode == TFM_EDGE_CREASE) { */ diff --git a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c index f05688f3325..39705f87a0d 100644 --- a/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c +++ b/source/blender/editors/transform/transform_convert_mesh_vert_cdata.c @@ -84,7 +84,9 @@ static void createTransMeshVertCData(bContext *UNUSED(C), TransInfo *t) int cd_offset = -1; if (t->mode == TFM_BWEIGHT) { - BM_mesh_cd_flag_ensure(bm, me, ME_CDFLAG_VERT_BWEIGHT); + if (!CustomData_has_layer(&bm->vdata, CD_BWEIGHT)) { + BM_data_layer_add(bm, &bm->vdata, CD_BWEIGHT); + } cd_offset = CustomData_get_offset(&bm->vdata, CD_BWEIGHT); } else { diff --git a/source/blender/geometry/intern/mesh_merge_by_distance.cc b/source/blender/geometry/intern/mesh_merge_by_distance.cc index 831241aa274..17318c277aa 100644 --- a/source/blender/geometry/intern/mesh_merge_by_distance.cc +++ b/source/blender/geometry/intern/mesh_merge_by_distance.cc @@ -1233,7 +1233,6 @@ static void customdata_weld( float no[3] = {0.0f, 0.0f, 0.0f}; #endif int crease = 0; - int bweight = 0; short flag = 0; /* interpolates a layer at a time */ @@ -1267,7 +1266,6 @@ static void customdata_weld( no[1] += mv_src_no[1]; no[2] += mv_src_no[2]; #endif - bweight += mv_src->bweight; flag |= mv_src->flag; } } @@ -1275,7 +1273,6 @@ static void customdata_weld( for (j = 0; j < count; j++) { MEdge *me_src = &((MEdge *)src_data)[src_indices[j]]; crease += me_src->crease; - bweight += me_src->bweight; flag |= me_src->flag; } } @@ -1312,8 +1309,6 @@ static void customdata_weld( if (type == CD_MVERT) { MVert *mv = &((MVert *)layer_dst->data)[dest_index]; mul_v3_fl(co, fac); - bweight *= fac; - CLAMP_MAX(bweight, 255); copy_v3_v3(mv->co, co); #ifdef USE_WELD_NORMALS @@ -1325,17 +1320,13 @@ static void customdata_weld( #endif mv->flag = (char)flag; - mv->bweight = (char)bweight; } else if (type == CD_MEDGE) { MEdge *me = &((MEdge *)layer_dst->data)[dest_index]; crease *= fac; - bweight *= fac; CLAMP_MAX(crease, 255); - CLAMP_MAX(bweight, 255); me->crease = (char)crease; - me->bweight = (char)bweight; me->flag = flag; } else if (CustomData_layer_has_interp(dest, dest_i)) { diff --git a/source/blender/io/alembic/intern/abc_reader_mesh.cc b/source/blender/io/alembic/intern/abc_reader_mesh.cc index ebb1b5a29bd..c07aaa37988 100644 --- a/source/blender/io/alembic/intern/abc_reader_mesh.cc +++ b/source/blender/io/alembic/intern/abc_reader_mesh.cc @@ -135,8 +135,6 @@ static void read_mverts_interp(MVert *mverts, interp_v3_v3v3(tmp, floor_pos.getValue(), ceil_pos.getValue(), static_cast(weight)); copy_zup_from_yup(mvert.co, tmp); - - mvert.bweight = 0; } } @@ -163,8 +161,6 @@ void read_mverts(Mesh &mesh, const P3fArraySamplePtr positions, const N3fArraySa Imath::V3f pos_in = (*positions)[i]; copy_zup_from_yup(mvert.co, pos_in.getValue()); - - mvert.bweight = 0; } if (normals) { float(*vert_normals)[3] = BKE_mesh_vertex_normals_for_write(&mesh); diff --git a/source/blender/io/collada/MeshImporter.cpp b/source/blender/io/collada/MeshImporter.cpp index e7a4f7b6b51..b22346d0281 100644 --- a/source/blender/io/collada/MeshImporter.cpp +++ b/source/blender/io/collada/MeshImporter.cpp @@ -587,7 +587,6 @@ void MeshImporter::read_lines(COLLADAFW::Mesh *mesh, Mesh *me) unsigned int *indices = mp->getPositionIndices().getData(); for (int j = 0; j < edge_count; j++, med++) { - med->bweight = 0; med->crease = 0; med->flag |= ME_LOOSEEDGE; med->v1 = indices[2 * j]; diff --git a/source/blender/makesdna/DNA_mesh_types.h b/source/blender/makesdna/DNA_mesh_types.h index 00a9e36612c..d335b36950c 100644 --- a/source/blender/makesdna/DNA_mesh_types.h +++ b/source/blender/makesdna/DNA_mesh_types.h @@ -440,8 +440,10 @@ enum { /** #Mesh.cd_flag */ enum { +#ifdef DNA_DEPRECATED_ALLOW ME_CDFLAG_VERT_BWEIGHT = 1 << 0, ME_CDFLAG_EDGE_BWEIGHT = 1 << 1, +#endif ME_CDFLAG_EDGE_CREASE = 1 << 2, ME_CDFLAG_VERT_CREASE = 1 << 3, }; diff --git a/source/blender/makesdna/DNA_meshdata_types.h b/source/blender/makesdna/DNA_meshdata_types.h index e0333f3ef03..e621343b818 100644 --- a/source/blender/makesdna/DNA_meshdata_types.h +++ b/source/blender/makesdna/DNA_meshdata_types.h @@ -25,7 +25,11 @@ extern "C" { */ typedef struct MVert { float co[3]; - char flag, bweight; + char flag; + /** + * Deprecated bevel weight storage, now located in #CD_BWEIGHT, except for file read and write. + */ + char bweight DNA_DEPRECATED; char _pad[2]; } MVert; @@ -47,7 +51,11 @@ enum { typedef struct MEdge { /** Un-ordered vertex indices (cannot match). */ unsigned int v1, v2; - char crease, bweight; + char crease; + /** + * Deprecated bevel weight storage, now located in #CD_BWEIGHT, except for file read and write. + */ + char bweight DNA_DEPRECATED; short flag; } MEdge; diff --git a/source/blender/makesrna/intern/rna_mesh.c b/source/blender/makesrna/intern/rna_mesh.c index c36e53a49cd..28ceb0d1d9d 100644 --- a/source/blender/makesrna/intern/rna_mesh.c +++ b/source/blender/makesrna/intern/rna_mesh.c @@ -108,13 +108,11 @@ static CustomData *rna_mesh_vdata(const PointerRNA *ptr) Mesh *me = rna_mesh(ptr); return rna_mesh_vdata_helper(me); } -# if 0 static CustomData *rna_mesh_edata(PointerRNA *ptr) { Mesh *me = rna_mesh(ptr); return rna_mesh_edata_helper(me); } -# endif static CustomData *rna_mesh_pdata(const PointerRNA *ptr) { Mesh *me = rna_mesh(ptr); @@ -231,6 +229,16 @@ static bool rna_Mesh_has_custom_normals_get(PointerRNA *ptr) return BKE_mesh_has_custom_loop_normals(me); } +static bool rna_Mesh_has_edge_bevel_weight_get(PointerRNA *ptr) +{ + return CustomData_has_layer(rna_mesh_edata(ptr), CD_BWEIGHT); +} + +static bool rna_Mesh_has_vertex_bevel_weight_get(PointerRNA *ptr) +{ + return CustomData_has_layer(rna_mesh_vdata(ptr), CD_BWEIGHT); +} + /** \} */ /* -------------------------------------------------------------------- */ @@ -430,26 +438,36 @@ static void rna_MeshVertex_hide_set(PointerRNA *ptr, bool value) static float rna_MeshVertex_bevel_weight_get(PointerRNA *ptr) { - MVert *mvert = (MVert *)ptr->data; - return mvert->bweight / 255.0f; + const Mesh *mesh = rna_mesh(ptr); + const int index = rna_MeshVertex_index_get(ptr); + const float *values = (const float *)CustomData_get_layer(&mesh->vdata, CD_BWEIGHT); + return values == NULL ? 0.0f : values[index]; } static void rna_MeshVertex_bevel_weight_set(PointerRNA *ptr, float value) { - MVert *mvert = (MVert *)ptr->data; - mvert->bweight = round_fl_to_uchar_clamp(value * 255.0f); + Mesh *mesh = rna_mesh(ptr); + const int index = rna_MeshVertex_index_get(ptr); + float *values = (float *)CustomData_add_layer( + &mesh->vdata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, mesh->totvert); + values[index] = clamp_f(value, 0.0f, 1.0f); } static float rna_MEdge_bevel_weight_get(PointerRNA *ptr) { - MEdge *medge = (MEdge *)ptr->data; - return medge->bweight / 255.0f; + const Mesh *mesh = rna_mesh(ptr); + const int index = rna_MeshEdge_index_get(ptr); + const float *values = (const float *)CustomData_get_layer(&mesh->edata, CD_BWEIGHT); + return values == NULL ? 0.0f : values[index]; } static void rna_MEdge_bevel_weight_set(PointerRNA *ptr, float value) { - MEdge *medge = (MEdge *)ptr->data; - medge->bweight = round_fl_to_uchar_clamp(value * 255.0f); + Mesh *mesh = rna_mesh(ptr); + const int index = rna_MeshEdge_index_get(ptr); + float *values = (float *)CustomData_add_layer( + &mesh->edata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, mesh->totedge); + values[index] = clamp_f(value, 0.0f, 1.0f); } static float rna_MEdge_crease_get(PointerRNA *ptr) @@ -3854,6 +3872,18 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_boolean_funcs(prop, "rna_Mesh_has_custom_normals_get", NULL); RNA_define_verify_sdna(true); + prop = RNA_def_property(srna, "has_bevel_weight_edge", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, "Has Edge Bevel Weight", "True if the mesh has an edge bevel weight layer"); + RNA_def_property_boolean_funcs(prop, "rna_Mesh_has_edge_bevel_weight_get", NULL); + + prop = RNA_def_property(srna, "has_bevel_weight_vertex", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_EDITABLE); + RNA_def_property_ui_text( + prop, "Has Vertex Bevel Weight", "True if the mesh has an vertex bevel weight layer"); + RNA_def_property_boolean_funcs(prop, "rna_Mesh_has_vertex_bevel_weight_get", NULL); + prop = RNA_def_property(srna, "texco_mesh", PROP_POINTER, PROP_NONE); RNA_def_property_pointer_sdna(prop, NULL, "texcomesh"); RNA_def_property_flag(prop, PROP_EDITABLE); @@ -3907,13 +3937,6 @@ static void rna_def_mesh(BlenderRNA *brna) RNA_def_property_update(prop, NC_SPACE | ND_SPACE_VIEW3D, "rna_Mesh_update_vertmask"); /* customdata flags */ - prop = RNA_def_property(srna, "use_customdata_vertex_bevel", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_VERT_BWEIGHT); - RNA_def_property_ui_text(prop, "Store Vertex Bevel Weight", ""); - - prop = RNA_def_property(srna, "use_customdata_edge_bevel", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_EDGE_BWEIGHT); - RNA_def_property_ui_text(prop, "Store Edge Bevel Weight", ""); prop = RNA_def_property(srna, "use_customdata_vertex_crease", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "cd_flag", ME_CDFLAG_VERT_CREASE); diff --git a/source/blender/modifiers/intern/MOD_array.c b/source/blender/modifiers/intern/MOD_array.c index 5ac6bfea879..7feff30968f 100644 --- a/source/blender/modifiers/intern/MOD_array.c +++ b/source/blender/modifiers/intern/MOD_array.c @@ -294,7 +294,7 @@ static void mesh_merge_transform(Mesh *result, for (i = 0; i < cap_nverts; i++, mv++) { mul_m4_v3(cap_offset, mv->co); /* Reset MVert flags for caps */ - mv->flag = mv->bweight = 0; + mv->flag = 0; } /* We have to correct normals too, if we do not tag them as dirty later! */ diff --git a/source/blender/modifiers/intern/MOD_bevel.c b/source/blender/modifiers/intern/MOD_bevel.c index ee9a2856ab0..668843188ab 100644 --- a/source/blender/modifiers/intern/MOD_bevel.c +++ b/source/blender/modifiers/intern/MOD_bevel.c @@ -74,6 +74,10 @@ static void requiredDataMask(Object *UNUSED(ob), if (bmd->defgrp_name[0] != '\0') { r_cddata_masks->vmask |= CD_MASK_MDEFORMVERT; } + if (bmd->lim_flags & MOD_BEVEL_WEIGHT) { + r_cddata_masks->vmask |= CD_MASK_BWEIGHT; + r_cddata_masks->emask |= CD_MASK_BWEIGHT; + } } /* diff --git a/source/blender/modifiers/intern/MOD_solidify_extrude.c b/source/blender/modifiers/intern/MOD_solidify_extrude.c index 343aa3920d9..1456254c31f 100644 --- a/source/blender/modifiers/intern/MOD_solidify_extrude.c +++ b/source/blender/modifiers/intern/MOD_solidify_extrude.c @@ -340,11 +340,6 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex MPoly *mpoly = BKE_mesh_polys_for_write(result); MLoop *mloop = BKE_mesh_loops_for_write(result); - if (do_bevel_convex) { - /* Make sure bweight is enabled. */ - result->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; - } - if (do_shell) { CustomData_copy_data(&mesh->vdata, &result->vdata, 0, 0, (int)verts_num); CustomData_copy_data(&mesh->vdata, &result->vdata, 0, (int)verts_num, (int)verts_num); @@ -392,6 +387,12 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex CustomData_copy_data(&mesh->pdata, &result->pdata, 0, 0, (int)polys_num); } + float *result_edge_bweight = NULL; + if (do_bevel_convex) { + result_edge_bweight = CustomData_add_layer( + &result->edata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, result->totedge); + } + /* initializes: (i_end, do_shell_align, mv). */ #define INIT_VERT_ARRAY_OFFSETS(test) \ if (((ofs_new >= ofs_orig) == do_flip) == test) { \ @@ -671,20 +672,18 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex for (uint i = 0; i < edges_num; i++) { if (edge_users[i] == INVALID_PAIR) { float angle = edge_angs[i]; - medge[i].bweight = (char)clamp_i( - (int)medge[i].bweight + (int)((angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : - clamp_f(bevel_convex, -1.0f, 0.0f)) * - 255), - 0, - 255); + result_edge_bweight[i] = clamp_f(result_edge_bweight[i] + + (angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)), + 0.0f, + 1.0f); if (do_shell) { - medge[i + edges_num].bweight = (char)clamp_i( - (int)medge[i + edges_num].bweight + - (int)((angle > M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : - clamp_f(bevel_convex, -1.0f, 0.0f)) * - 255), + result_edge_bweight[i + edges_num] = clamp_f( + result_edge_bweight[i + edges_num] + (angle > M_PI ? + clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)), 0, - 255); + 1.0f); } } } @@ -900,20 +899,17 @@ Mesh *MOD_solidify_extrude_modifyMesh(ModifierData *md, const ModifierEvalContex for (i = 0; i < edges_num; i++) { if (edge_users[i] == INVALID_PAIR) { float angle = edge_angs[i]; - medge[i].bweight = (char)clamp_i( - (int)medge[i].bweight + (int)((angle < M_PI ? clamp_f(bevel_convex, 0, 1) : - clamp_f(bevel_convex, -1, 0)) * - 255), - 0, - 255); + result_edge_bweight[i] = clamp_f(result_edge_bweight[i] + + (angle < M_PI ? clamp_f(bevel_convex, 0.0f, 1.0f) : + clamp_f(bevel_convex, -1.0f, 0.0f)), + 0.0f, + 1.0f); if (do_shell) { - medge[i + edges_num].bweight = (char)clamp_i( - (int)medge[i + edges_num].bweight + - (int)((angle > M_PI ? clamp_f(bevel_convex, 0, 1) : - clamp_f(bevel_convex, -1, 0)) * - 255), - 0, - 255); + result_edge_bweight[i + edges_num] = clamp_f( + result_edge_bweight[i + edges_num] + + (angle > M_PI ? clamp_f(bevel_convex, 0, 1) : clamp_f(bevel_convex, -1, 0)), + 0.0f, + 1.0f); } } } diff --git a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c index e73df0d1c12..d3aff5c58c5 100644 --- a/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c +++ b/source/blender/modifiers/intern/MOD_solidify_nonmanifold.c @@ -189,6 +189,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, const MPoly *orig_mpoly = BKE_mesh_polys(mesh); const MLoop *orig_mloop = BKE_mesh_loops(mesh); + /* These might be null. */ + const float *orig_vert_bweight = CustomData_get_layer(&mesh->vdata, CD_BWEIGHT); + const float *orig_edge_bweight = CustomData_get_layer(&mesh->edata, CD_BWEIGHT); + uint new_verts_num = 0; uint new_edges_num = 0; uint new_loops_num = 0; @@ -1965,9 +1969,10 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, int *origindex_edge = CustomData_get_layer(&result->edata, CD_ORIGINDEX); int *origindex_poly = CustomData_get_layer(&result->pdata, CD_ORIGINDEX); - if (bevel_convex != 0.0f || (result->cd_flag & ME_CDFLAG_VERT_BWEIGHT) != 0) { - /* make sure bweight is enabled */ - result->cd_flag |= ME_CDFLAG_EDGE_BWEIGHT; + float *result_edge_bweight = CustomData_get_layer(&result->edata, CD_BWEIGHT); + if (bevel_convex != 0.0f || orig_vert_bweight != NULL) { + result_edge_bweight = CustomData_add_layer( + &result->edata, CD_BWEIGHT, CD_SET_DEFAULT, NULL, result->totedge); } /* Checks that result has dvert data. */ @@ -2038,17 +2043,18 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, medge[insert].v2 = v2; medge[insert].flag = orig_medge[(*l)->old_edge].flag | ME_EDGEDRAW | ME_EDGERENDER; medge[insert].crease = orig_medge[(*l)->old_edge].crease; - medge[insert].bweight = orig_medge[(*l)->old_edge].bweight; + if (result_edge_bweight) { + result_edge_bweight[insert] = orig_edge_bweight[(*l)->old_edge]; + } if (bevel_convex != 0.0f && (*l)->faces[1] != NULL) { - medge[insert].bweight = (char)clamp_i( - (int)medge[insert].bweight + (int)(((*l)->angle > M_PI + FLT_EPSILON ? - clamp_f(bevel_convex, 0.0f, 1.0f) : - ((*l)->angle < M_PI - FLT_EPSILON ? - clamp_f(bevel_convex, -1.0f, 0.0f) : - 0)) * - 255), - 0, - 255); + result_edge_bweight[insert] = clamp_f( + result_edge_bweight[insert] + + ((*l)->angle > M_PI + FLT_EPSILON ? + clamp_f(bevel_convex, 0.0f, 1.0f) : + ((*l)->angle < M_PI - FLT_EPSILON ? clamp_f(bevel_convex, -1.0f, 0.0f) : + 0)), + 0.0f, + 1.0f); } (*l)->new_edge = insert; } @@ -2113,13 +2119,14 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, EdgeGroup *last_g = NULL; EdgeGroup *first_g = NULL; char mv_crease = vertex_crease ? (char)(vertex_crease[i] * 255.0f) : 0; + float mv_bweight = orig_vert_bweight ? orig_vert_bweight[i] : 0.0f; /* Data calculation cache. */ char max_crease; char last_max_crease = 0; char first_max_crease = 0; - char max_bweight; - char last_max_bweight = 0; - char first_max_bweight = 0; + float max_bweight; + float last_max_bweight = 0.0f; + float first_max_bweight = 0.0f; short flag; short last_flag = 0; short first_flag = 0; @@ -2142,20 +2149,24 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, max_crease = ed->crease; } if (g->edges[k]->new_edge != MOD_SOLIDIFY_EMPTY_TAG) { - char bweight = medge[g->edges[k]->new_edge].bweight; - if (bweight > max_bweight) { - max_bweight = bweight; + if (result_edge_bweight) { + float bweight = result_edge_bweight[g->edges[k]->new_edge]; + if (bweight > max_bweight) { + max_bweight = bweight; + } } } flag |= ed->flag; } } - const char bweight_open_edge = min_cc( - orig_medge[g->edges[0]->old_edge].bweight, - orig_medge[g->edges[g->edges_len - 1]->old_edge].bweight); + const float bweight_open_edge = + orig_edge_bweight ? + min_ff(orig_edge_bweight[g->edges[0]->old_edge], + orig_edge_bweight[g->edges[g->edges_len - 1]->old_edge]) : + 0.0f; if (bweight_open_edge > 0) { - max_bweight = min_cc(bweight_open_edge, max_bweight); + max_bweight = min_ff(bweight_open_edge, max_bweight); } else { if (bevel_convex < 0.0f) { @@ -2183,8 +2194,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, medge[edge_index].flag = ME_EDGEDRAW | ME_EDGERENDER | ((last_flag | flag) & (ME_SEAM | ME_SHARP)); medge[edge_index].crease = max_cc(mv_crease, min_cc(last_max_crease, max_crease)); - medge[edge_index++].bweight = max_cc(mv->bweight, - min_cc(last_max_bweight, max_bweight)); + if (result_edge_bweight) { + result_edge_bweight[edge_index] = max_ff(mv_bweight, + min_ff(last_max_bweight, max_bweight)); + } + edge_index++; } last_g = g; last_max_crease = max_crease; @@ -2212,8 +2226,11 @@ Mesh *MOD_solidify_nonmanifold_modifyMesh(ModifierData *md, ((last_flag | first_flag) & (ME_SEAM | ME_SHARP)); medge[edge_index].crease = max_cc(mv_crease, min_cc(last_max_crease, first_max_crease)); - medge[edge_index++].bweight = max_cc(mv->bweight, - min_cc(last_max_bweight, first_max_bweight)); + if (result_edge_bweight) { + result_edge_bweight[edge_index] = max_ff( + mv_bweight, min_ff(last_max_bweight, first_max_bweight)); + } + edge_index++; /* Loop data. */ int *loops = MEM_malloc_arrayN(j, sizeof(*loops), "loops in solidify"); -- cgit v1.2.3 From ef7c9e793ec5331ac694eec9336565bd2254c406 Mon Sep 17 00:00:00 2001 From: Patrick Mours Date: Fri, 9 Sep 2022 11:55:35 +0200 Subject: Cycles: Remove separate OSL attribute map and instead always use SVM attribute map The SVM attribute map is always generated and uses a simple linear search to lookup by an opaque ID, so can reuse that for OSL as well and simply use the attribute name hash as ID instead of generating a unique value separately. This works for both object and geometry attributes since the SVM attribute map already stores both. Simplifies code somewhat and reduces memory usage slightly. This patch was split from D15902. Differential Revision: https://developer.blender.org/D15918 --- intern/cycles/kernel/geom/attribute.h | 32 +++--- intern/cycles/kernel/geom/primitive.h | 10 +- intern/cycles/kernel/geom/subd_triangle.h | 8 +- intern/cycles/kernel/geom/volume.h | 2 +- intern/cycles/kernel/osl/globals.h | 8 -- intern/cycles/kernel/osl/services.cpp | 160 +++++++++--------------------- intern/cycles/kernel/osl/shader.cpp | 38 ------- intern/cycles/kernel/osl/shader.h | 6 -- intern/cycles/kernel/types.h | 11 +- intern/cycles/scene/geometry.cpp | 152 ++++++++++------------------ intern/cycles/scene/geometry.h | 4 +- intern/cycles/scene/osl.cpp | 12 +++ intern/cycles/scene/osl.h | 3 + intern/cycles/scene/shader.cpp | 8 +- intern/cycles/scene/shader.h | 6 +- 15 files changed, 155 insertions(+), 305 deletions(-) diff --git a/intern/cycles/kernel/geom/attribute.h b/intern/cycles/kernel/geom/attribute.h index 31a9e39d528..3a0ee1b09d1 100644 --- a/intern/cycles/kernel/geom/attribute.h +++ b/intern/cycles/kernel/geom/attribute.h @@ -16,14 +16,14 @@ CCL_NAMESPACE_BEGIN /* Patch index for triangle, -1 if not subdivision triangle */ -ccl_device_inline uint subd_triangle_patch(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device_inline uint subd_triangle_patch(KernelGlobals kg, int prim) { - return (sd->prim != PRIM_NONE) ? kernel_data_fetch(tri_patch, sd->prim) : ~0; + return (prim != PRIM_NONE) ? kernel_data_fetch(tri_patch, prim) : ~0; } -ccl_device_inline uint attribute_primitive_type(KernelGlobals kg, ccl_private const ShaderData *sd) +ccl_device_inline uint attribute_primitive_type(KernelGlobals kg, int prim, int type) { - if ((sd->type & PRIMITIVE_TRIANGLE) && subd_triangle_patch(kg, sd) != ~0) { + if ((type & PRIMITIVE_TRIANGLE) && subd_triangle_patch(kg, prim) != ~0) { return ATTR_PRIM_SUBD; } else { @@ -45,17 +45,16 @@ ccl_device_inline uint object_attribute_map_offset(KernelGlobals kg, int object) return kernel_data_fetch(objects, object).attribute_map_offset; } -ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, - ccl_private const ShaderData *sd, - uint id) +ccl_device_inline AttributeDescriptor +find_attribute(KernelGlobals kg, int object, int prim, int type, uint64_t id) { - if (sd->object == OBJECT_NONE) { + if (object == OBJECT_NONE) { return attribute_not_found(); } /* for SVM, find attribute by unique id */ - uint attr_offset = object_attribute_map_offset(kg, sd->object); - attr_offset += attribute_primitive_type(kg, sd); + uint attr_offset = object_attribute_map_offset(kg, object); + attr_offset += attribute_primitive_type(kg, prim, type); AttributeMap attr_map = kernel_data_fetch(attributes_map, attr_offset); while (attr_map.id != id) { @@ -77,7 +76,7 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, AttributeDescriptor desc; desc.element = (AttributeElement)attr_map.element; - if (sd->prim == PRIM_NONE && desc.element != ATTR_ELEMENT_MESH && + if (prim == PRIM_NONE && desc.element != ATTR_ELEMENT_MESH && desc.element != ATTR_ELEMENT_VOXEL && desc.element != ATTR_ELEMENT_OBJECT) { return attribute_not_found(); } @@ -91,11 +90,16 @@ ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, return desc; } +ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals kg, + ccl_private const ShaderData *sd, + uint64_t id) +{ + return find_attribute(kg, sd->object, sd->prim, sd->type, id); +} + /* Transform matrix attribute on meshes */ -ccl_device Transform primitive_attribute_matrix(KernelGlobals kg, - ccl_private const ShaderData *sd, - const AttributeDescriptor desc) +ccl_device Transform primitive_attribute_matrix(KernelGlobals kg, const AttributeDescriptor desc) { Transform tfm; diff --git a/intern/cycles/kernel/geom/primitive.h b/intern/cycles/kernel/geom/primitive.h index 0f1a3fc11bc..04b04ff5985 100644 --- a/intern/cycles/kernel/geom/primitive.h +++ b/intern/cycles/kernel/geom/primitive.h @@ -25,7 +25,7 @@ ccl_device_forceinline float primitive_surface_attribute_float(KernelGlobals kg, ccl_private float *dy) { if (sd->type & PRIMITIVE_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) + if (subd_triangle_patch(kg, sd->prim) == ~0) return triangle_attribute_float(kg, sd, desc, dx, dy); else return subd_triangle_attribute_float(kg, sd, desc, dx, dy); @@ -56,7 +56,7 @@ ccl_device_forceinline float2 primitive_surface_attribute_float2(KernelGlobals k ccl_private float2 *dy) { if (sd->type & PRIMITIVE_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) + if (subd_triangle_patch(kg, sd->prim) == ~0) return triangle_attribute_float2(kg, sd, desc, dx, dy); else return subd_triangle_attribute_float2(kg, sd, desc, dx, dy); @@ -87,7 +87,7 @@ ccl_device_forceinline float3 primitive_surface_attribute_float3(KernelGlobals k ccl_private float3 *dy) { if (sd->type & PRIMITIVE_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) + if (subd_triangle_patch(kg, sd->prim) == ~0) return triangle_attribute_float3(kg, sd, desc, dx, dy); else return subd_triangle_attribute_float3(kg, sd, desc, dx, dy); @@ -118,7 +118,7 @@ ccl_device_forceinline float4 primitive_surface_attribute_float4(KernelGlobals k ccl_private float4 *dy) { if (sd->type & PRIMITIVE_TRIANGLE) { - if (subd_triangle_patch(kg, sd) == ~0) + if (subd_triangle_patch(kg, sd->prim) == ~0) return triangle_attribute_float4(kg, sd, desc, dx, dy); else return subd_triangle_attribute_float4(kg, sd, desc, dx, dy); @@ -320,7 +320,7 @@ ccl_device_forceinline float4 primitive_motion_vector(KernelGlobals kg, #endif if (sd->type & PRIMITIVE_TRIANGLE) { /* Triangle */ - if (subd_triangle_patch(kg, sd) == ~0) { + if (subd_triangle_patch(kg, sd->prim) == ~0) { motion_pre = triangle_attribute_float3(kg, sd, desc, NULL, NULL); desc.offset += numverts; motion_post = triangle_attribute_float3(kg, sd, desc, NULL, NULL); diff --git a/intern/cycles/kernel/geom/subd_triangle.h b/intern/cycles/kernel/geom/subd_triangle.h index c6f883461bd..784ba377318 100644 --- a/intern/cycles/kernel/geom/subd_triangle.h +++ b/intern/cycles/kernel/geom/subd_triangle.h @@ -87,7 +87,7 @@ ccl_device_noinline float subd_triangle_attribute_float(KernelGlobals kg, ccl_private float *dx, ccl_private float *dy) { - int patch = subd_triangle_patch(kg, sd); + int patch = subd_triangle_patch(kg, sd->prim); #ifdef __PATCH_EVAL__ if (desc.flags & ATTR_SUBDIVIDED) { @@ -226,7 +226,7 @@ ccl_device_noinline float2 subd_triangle_attribute_float2(KernelGlobals kg, ccl_private float2 *dx, ccl_private float2 *dy) { - int patch = subd_triangle_patch(kg, sd); + int patch = subd_triangle_patch(kg, sd->prim); #ifdef __PATCH_EVAL__ if (desc.flags & ATTR_SUBDIVIDED) { @@ -368,7 +368,7 @@ ccl_device_noinline float3 subd_triangle_attribute_float3(KernelGlobals kg, ccl_private float3 *dx, ccl_private float3 *dy) { - int patch = subd_triangle_patch(kg, sd); + int patch = subd_triangle_patch(kg, sd->prim); #ifdef __PATCH_EVAL__ if (desc.flags & ATTR_SUBDIVIDED) { @@ -509,7 +509,7 @@ ccl_device_noinline float4 subd_triangle_attribute_float4(KernelGlobals kg, ccl_private float4 *dx, ccl_private float4 *dy) { - int patch = subd_triangle_patch(kg, sd); + int patch = subd_triangle_patch(kg, sd->prim); #ifdef __PATCH_EVAL__ if (desc.flags & ATTR_SUBDIVIDED) { diff --git a/intern/cycles/kernel/geom/volume.h b/intern/cycles/kernel/geom/volume.h index 3510a905def..885a420c97f 100644 --- a/intern/cycles/kernel/geom/volume.h +++ b/intern/cycles/kernel/geom/volume.h @@ -29,7 +29,7 @@ ccl_device_inline float3 volume_normalized_position(KernelGlobals kg, object_inverse_position_transform(kg, sd, &P); if (desc.offset != ATTR_STD_NOT_FOUND) { - Transform tfm = primitive_attribute_matrix(kg, sd, desc); + Transform tfm = primitive_attribute_matrix(kg, desc); P = transform_point(&tfm, P); } diff --git a/intern/cycles/kernel/osl/globals.h b/intern/cycles/kernel/osl/globals.h index 172091c55f5..496965a50ec 100644 --- a/intern/cycles/kernel/osl/globals.h +++ b/intern/cycles/kernel/osl/globals.h @@ -56,16 +56,8 @@ struct OSLGlobals { OSL::ShaderGroupRef background_state; /* attributes */ - struct Attribute { - TypeDesc type; - AttributeDescriptor desc; - ParamValue value; - }; - - typedef unordered_map AttributeMap; typedef unordered_map ObjectNameMap; - vector attribute_map; ObjectNameMap object_name_map; vector object_names; }; diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp index faa027f4e1e..eef661c203e 100644 --- a/intern/cycles/kernel/osl/services.cpp +++ b/intern/cycles/kernel/osl/services.cpp @@ -740,76 +740,75 @@ static bool set_attribute_matrix(const Transform &tfm, TypeDesc type, void *val) return false; } -static bool get_primitive_attribute(const KernelGlobalsCPU *kg, - const ShaderData *sd, - const OSLGlobals::Attribute &attr, - const TypeDesc &type, - bool derivatives, - void *val) +static bool get_object_attribute(const KernelGlobalsCPU *kg, + ShaderData *sd, + const AttributeDescriptor &desc, + const TypeDesc &type, + bool derivatives, + void *val) { - if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { + if (desc.type == NODE_ATTR_FLOAT3) { float3 fval[3]; - if (primitive_is_volume_attribute(sd, attr.desc)) { - fval[0] = primitive_volume_attribute_float3(kg, sd, attr.desc); +#ifdef __VOLUME__ + if (primitive_is_volume_attribute(sd, desc)) { + fval[0] = primitive_volume_attribute_float3(kg, sd, desc); } - else { + else +#endif + { memset(fval, 0, sizeof(fval)); fval[0] = primitive_surface_attribute_float3( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + kg, sd, desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); } return set_attribute_float3(fval, type, derivatives, val); } - else if (attr.type == TypeFloat2) { - if (primitive_is_volume_attribute(sd, attr.desc)) { + else if (desc.type == NODE_ATTR_FLOAT2) { +#ifdef __VOLUME__ + if (primitive_is_volume_attribute(sd, desc)) { assert(!"Float2 attribute not support for volumes"); return false; } - else { + else +#endif + { float2 fval[3]; fval[0] = primitive_surface_attribute_float2( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + kg, sd, desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); return set_attribute_float2(fval, type, derivatives, val); } } - else if (attr.type == TypeDesc::TypeFloat) { + else if (desc.type == NODE_ATTR_FLOAT) { float fval[3]; - if (primitive_is_volume_attribute(sd, attr.desc)) { +#ifdef __VOLUME__ + if (primitive_is_volume_attribute(sd, desc)) { memset(fval, 0, sizeof(fval)); - fval[0] = primitive_volume_attribute_float(kg, sd, attr.desc); + fval[0] = primitive_volume_attribute_float(kg, sd, desc); } - else { + else +#endif + { fval[0] = primitive_surface_attribute_float( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + kg, sd, desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); } return set_attribute_float(fval, type, derivatives, val); } - else if (attr.type == TypeDesc::TypeFloat4 || attr.type == TypeRGBA) { + else if (desc.type == NODE_ATTR_FLOAT4 || desc.type == NODE_ATTR_RGBA) { float4 fval[3]; - if (primitive_is_volume_attribute(sd, attr.desc)) { +#ifdef __VOLUME__ + if (primitive_is_volume_attribute(sd, desc)) { memset(fval, 0, sizeof(fval)); - fval[0] = primitive_volume_attribute_float4(kg, sd, attr.desc); + fval[0] = primitive_volume_attribute_float4(kg, sd, desc); } - else { + else +#endif + { fval[0] = primitive_surface_attribute_float4( - kg, sd, attr.desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); + kg, sd, desc, (derivatives) ? &fval[1] : NULL, (derivatives) ? &fval[2] : NULL); } return set_attribute_float4(fval, type, derivatives, val); } - else { - return false; - } -} - -static bool get_mesh_attribute(const KernelGlobalsCPU *kg, - const ShaderData *sd, - const OSLGlobals::Attribute &attr, - const TypeDesc &type, - bool derivatives, - void *val) -{ - if (attr.type == TypeDesc::TypeMatrix) { - Transform tfm = primitive_attribute_matrix(kg, sd, attr.desc); + else if (desc.type == NODE_ATTR_MATRIX) { + Transform tfm = primitive_attribute_matrix(kg, desc); return set_attribute_matrix(tfm, type, val); } else { @@ -817,44 +816,6 @@ static bool get_mesh_attribute(const KernelGlobalsCPU *kg, } } -static bool get_object_attribute(const OSLGlobals::Attribute &attr, - TypeDesc type, - bool derivatives, - void *val) -{ - if (attr.type == TypeDesc::TypePoint || attr.type == TypeDesc::TypeVector || - attr.type == TypeDesc::TypeNormal || attr.type == TypeDesc::TypeColor) { - const float *data = (const float *)attr.value.data(); - return set_attribute_float3(make_float3(data[0], data[1], data[2]), type, derivatives, val); - } - else if (attr.type == TypeFloat2) { - const float *data = (const float *)attr.value.data(); - return set_attribute_float2(make_float2(data[0], data[1]), type, derivatives, val); - } - else if (attr.type == TypeDesc::TypeFloat) { - const float *data = (const float *)attr.value.data(); - return set_attribute_float(data[0], type, derivatives, val); - } - else if (attr.type == TypeRGBA || attr.type == TypeDesc::TypeFloat4) { - const float *data = (const float *)attr.value.data(); - return set_attribute_float4( - make_float4(data[0], data[1], data[2], data[3]), type, derivatives, val); - } - else if (attr.type == type) { - size_t datasize = attr.value.datasize(); - - memcpy(val, attr.value.data(), datasize); - if (derivatives) { - memset((char *)val + datasize, 0, datasize * 2); - } - - return true; - } - else { - return false; - } -} - bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg, ShaderData *sd, ustring name, @@ -979,6 +940,7 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg float f = ((sd->shader & SHADER_SMOOTH_NORMAL) != 0); return set_attribute_float(f, type, derivatives, val); } +#ifdef __HAIR__ /* Hair Attributes */ else if (name == u_is_curve) { float f = (sd->type & PRIMITIVE_CURVE) != 0; @@ -996,6 +958,8 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg float f = curve_random(kg, sd); return set_attribute_float(f, type, derivatives, val); } +#endif +#ifdef __POINTCLOUD__ /* point attributes */ else if (name == u_is_point) { float f = (sd->type & PRIMITIVE_POINT) != 0; @@ -1013,6 +977,7 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg float f = point_random(kg, sd); return set_attribute_float(f, type, derivatives, val); } +#endif else if (name == u_normal_map_normal) { if (sd->type & PRIMITIVE_TRIANGLE) { float3 f = triangle_smooth_normal_unnormalized(kg, sd, sd->Ng, sd->prim, sd->u, sd->v); @@ -1023,7 +988,7 @@ bool OSLRenderServices::get_object_standard_attribute(const KernelGlobalsCPU *kg } } else { - return false; + return get_background_attribute(kg, sd, name, type, derivatives, val); } } @@ -1131,7 +1096,6 @@ bool OSLRenderServices::get_attribute( ShaderData *sd, bool derivatives, ustring object_name, TypeDesc type, ustring name, void *val) { const KernelGlobalsCPU *kg = sd->osl_globals; - int prim_type = 0; int object; /* lookup of attribute on another object */ @@ -1145,44 +1109,18 @@ bool OSLRenderServices::get_attribute( } else { object = sd->object; - prim_type = attribute_primitive_type(kg, sd); - - if (object == OBJECT_NONE) - return get_background_attribute(kg, sd, name, type, derivatives, val); } /* find attribute on object */ - object = object * ATTR_PRIM_TYPES + prim_type; - OSLGlobals::AttributeMap &attribute_map = kg->osl->attribute_map[object]; - OSLGlobals::AttributeMap::iterator it = attribute_map.find(name); - - if (it != attribute_map.end()) { - const OSLGlobals::Attribute &attr = it->second; - - if (attr.desc.element != ATTR_ELEMENT_OBJECT) { - /* triangle and vertex attributes */ - if (get_primitive_attribute(kg, sd, attr, type, derivatives, val)) - return true; - else - return get_mesh_attribute(kg, sd, attr, type, derivatives, val); - } - else { - /* object attribute */ - return get_object_attribute(attr, type, derivatives, val); - } + const AttributeDescriptor desc = find_attribute( + kg, object, sd->prim, object == sd->object ? sd->type : PRIMITIVE_NONE, name.hash()); + if (desc.offset != ATTR_STD_NOT_FOUND) { + return get_object_attribute(kg, sd, desc, type, derivatives, val); } else { /* not found in attribute, check standard object info */ - bool is_std_object_attribute = get_object_standard_attribute( - kg, sd, name, type, derivatives, val); - - if (is_std_object_attribute) - return true; - - return get_background_attribute(kg, sd, name, type, derivatives, val); + return get_object_standard_attribute(kg, sd, name, type, derivatives, val); } - - return false; } bool OSLRenderServices::get_userdata( diff --git a/intern/cycles/kernel/osl/shader.cpp b/intern/cycles/kernel/osl/shader.cpp index 5862b6a8a2b..3355f5c869a 100644 --- a/intern/cycles/kernel/osl/shader.cpp +++ b/intern/cycles/kernel/osl/shader.cpp @@ -21,8 +21,6 @@ #include "kernel/util/differential.h" // clang-format on -#include "scene/attribute.h" - CCL_NAMESPACE_BEGIN /* Threads */ @@ -386,40 +384,4 @@ void OSLShader::eval_displacement(const KernelGlobalsCPU *kg, const void *state, sd->P = TO_FLOAT3(globals->P); } -/* Attributes */ - -int OSLShader::find_attribute(const KernelGlobalsCPU *kg, - const ShaderData *sd, - uint id, - AttributeDescriptor *desc) -{ - /* for OSL, a hash map is used to lookup the attribute by name. */ - int object = sd->object * ATTR_PRIM_TYPES; - - OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object]; - ustring stdname(std::string("geom:") + - std::string(Attribute::standard_name((AttributeStandard)id))); - OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname); - - if (it != attr_map.end()) { - const OSLGlobals::Attribute &osl_attr = it->second; - *desc = osl_attr.desc; - - if (sd->prim == PRIM_NONE && (AttributeElement)osl_attr.desc.element != ATTR_ELEMENT_MESH) { - desc->offset = ATTR_STD_NOT_FOUND; - return ATTR_STD_NOT_FOUND; - } - - /* return result */ - if (osl_attr.desc.element == ATTR_ELEMENT_NONE) { - desc->offset = ATTR_STD_NOT_FOUND; - } - return desc->offset; - } - else { - desc->offset = ATTR_STD_NOT_FOUND; - return (int)ATTR_STD_NOT_FOUND; - } -} - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/shader.h b/intern/cycles/kernel/osl/shader.h index f0ab49dd6a8..56c87d7c8ac 100644 --- a/intern/cycles/kernel/osl/shader.h +++ b/intern/cycles/kernel/osl/shader.h @@ -54,12 +54,6 @@ class OSLShader { ShaderData *sd, uint32_t path_flag); static void eval_displacement(const KernelGlobalsCPU *kg, const void *state, ShaderData *sd); - - /* attributes */ - static int find_attribute(const KernelGlobalsCPU *kg, - const ShaderData *sd, - uint id, - AttributeDescriptor *desc); }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/types.h b/intern/cycles/kernel/types.h index 873d594f1f8..bd3791594e0 100644 --- a/intern/cycles/kernel/types.h +++ b/intern/cycles/kernel/types.h @@ -655,12 +655,11 @@ typedef struct AttributeDescriptor { /* For looking up attributes on objects and geometry. */ typedef struct AttributeMap { - uint id; /* Global unique identifier. */ - uint element; /* AttributeElement. */ - int offset; /* Offset into __attributes global arrays. */ - uint8_t type; /* NodeAttributeType. */ - uint8_t flags; /* AttributeFlag. */ - uint8_t pad[2]; + uint64_t id; /* Global unique identifier. */ + int offset; /* Offset into __attributes global arrays. */ + uint16_t element; /* AttributeElement. */ + uint8_t type; /* NodeAttributeType. */ + uint8_t flags; /* AttributeFlag. */ } AttributeMap; /* Closure data */ diff --git a/intern/cycles/scene/geometry.cpp b/intern/cycles/scene/geometry.cpp index ae8dcaa43b6..d1a3df851c1 100644 --- a/intern/cycles/scene/geometry.cpp +++ b/intern/cycles/scene/geometry.cpp @@ -302,111 +302,32 @@ GeometryManager::~GeometryManager() { } -void GeometryManager::update_osl_attributes(Device *device, - Scene *scene, - vector &geom_attributes) +void GeometryManager::update_osl_globals(Device *device, Scene *scene) { #ifdef WITH_OSL - /* for OSL, a hash map is used to lookup the attribute by name. */ OSLGlobals *og = (OSLGlobals *)device->get_cpu_osl_memory(); og->object_name_map.clear(); - og->attribute_map.clear(); og->object_names.clear(); - og->attribute_map.resize(scene->objects.size() * ATTR_PRIM_TYPES); - for (size_t i = 0; i < scene->objects.size(); i++) { /* set object name to object index map */ Object *object = scene->objects[i]; og->object_name_map[object->name] = i; og->object_names.push_back(object->name); - - /* set object attributes */ - foreach (ParamValue &attr, object->attributes) { - OSLGlobals::Attribute osl_attr; - - osl_attr.type = attr.type(); - osl_attr.desc.element = ATTR_ELEMENT_OBJECT; - osl_attr.value = attr; - osl_attr.desc.offset = 0; - osl_attr.desc.flags = 0; - - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][attr.name()] = osl_attr; - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][attr.name()] = osl_attr; - } - - /* find geometry attributes */ - size_t j = object->geometry->index; - assert(j < scene->geometry.size() && scene->geometry[j] == object->geometry); - - AttributeRequestSet &attributes = geom_attributes[j]; - - /* set mesh attributes */ - foreach (AttributeRequest &req, attributes.requests) { - OSLGlobals::Attribute osl_attr; - - if (req.desc.element != ATTR_ELEMENT_NONE) { - osl_attr.desc = req.desc; - - if (req.type == TypeDesc::TypeFloat) - osl_attr.type = TypeDesc::TypeFloat; - else if (req.type == TypeDesc::TypeMatrix) - osl_attr.type = TypeDesc::TypeMatrix; - else if (req.type == TypeFloat2) - osl_attr.type = TypeFloat2; - else if (req.type == TypeRGBA) - osl_attr.type = TypeRGBA; - else - osl_attr.type = TypeDesc::TypeColor; - - if (req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by geom: name convention */ - ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][stdname] = osl_attr; - } - else if (req.name != ustring()) { - /* add lookup by geometry attribute name */ - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_GEOMETRY][req.name] = osl_attr; - } - } - - if (req.subd_desc.element != ATTR_ELEMENT_NONE) { - osl_attr.desc = req.subd_desc; - - if (req.subd_type == TypeDesc::TypeFloat) - osl_attr.type = TypeDesc::TypeFloat; - else if (req.subd_type == TypeDesc::TypeMatrix) - osl_attr.type = TypeDesc::TypeMatrix; - else if (req.subd_type == TypeFloat2) - osl_attr.type = TypeFloat2; - else if (req.subd_type == TypeRGBA) - osl_attr.type = TypeRGBA; - else - osl_attr.type = TypeDesc::TypeColor; - - if (req.std != ATTR_STD_NONE) { - /* if standard attribute, add lookup by geom: name convention */ - ustring stdname(string("geom:") + string(Attribute::standard_name(req.std))); - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][stdname] = osl_attr; - } - else if (req.name != ustring()) { - /* add lookup by geometry attribute name */ - og->attribute_map[i * ATTR_PRIM_TYPES + ATTR_PRIM_SUBD][req.name] = osl_attr; - } - } - } } #else (void)device; (void)scene; - (void)geom_attributes; #endif } /* Generate a normal attribute map entry from an attribute descriptor. */ -static void emit_attribute_map_entry( - AttributeMap *attr_map, int index, uint id, TypeDesc type, const AttributeDescriptor &desc) +static void emit_attribute_map_entry(AttributeMap *attr_map, + size_t index, + uint64_t id, + TypeDesc type, + const AttributeDescriptor &desc) { attr_map[index].id = id; attr_map[index].element = desc.element; @@ -431,7 +352,7 @@ static void emit_attribute_map_entry( /* Generate an attribute map end marker, optionally including a link to another map. * Links are used to connect object attribute maps to mesh attribute maps. */ static void emit_attribute_map_terminator(AttributeMap *attr_map, - int index, + size_t index, bool chain, uint chain_link) { @@ -446,15 +367,8 @@ static void emit_attribute_map_terminator(AttributeMap *attr_map, /* Generate all necessary attribute map entries from the attribute request. */ static void emit_attribute_mapping( - AttributeMap *attr_map, int index, Scene *scene, AttributeRequest &req, Geometry *geom) + AttributeMap *attr_map, size_t index, uint64_t id, AttributeRequest &req, Geometry *geom) { - uint id; - - if (req.std == ATTR_STD_NONE) - id = scene->shader_manager->get_attribute_id(req.name); - else - id = scene->shader_manager->get_attribute_id(req.std); - emit_attribute_map_entry(attr_map, index, id, req.type, req.desc); if (geom->is_mesh()) { @@ -475,12 +389,26 @@ void GeometryManager::update_svm_attributes(Device *, * attribute, based on a unique shader attribute id. */ /* compute array stride */ - int attr_map_size = 0; + size_t attr_map_size = 0; for (size_t i = 0; i < scene->geometry.size(); i++) { Geometry *geom = scene->geometry[i]; geom->attr_map_offset = attr_map_size; - attr_map_size += (geom_attributes[i].size() + 1) * ATTR_PRIM_TYPES; + +#ifdef WITH_OSL + size_t attr_count = 0; + foreach (AttributeRequest &req, geom_attributes[i].requests) { + if (req.std != ATTR_STD_NONE && + scene->shader_manager->get_attribute_id(req.std) != (uint64_t)req.std) + attr_count += 2; + else + attr_count += 1; + } +#else + const size_t attr_count = geom_attributes[i].size(); +#endif + + attr_map_size += (attr_count + 1) * ATTR_PRIM_TYPES; } for (size_t i = 0; i < scene->objects.size(); i++) { @@ -512,11 +440,26 @@ void GeometryManager::update_svm_attributes(Device *, AttributeRequestSet &attributes = geom_attributes[i]; /* set geometry attributes */ - int index = geom->attr_map_offset; + size_t index = geom->attr_map_offset; foreach (AttributeRequest &req, attributes.requests) { - emit_attribute_mapping(attr_map, index, scene, req, geom); + uint64_t id; + if (req.std == ATTR_STD_NONE) + id = scene->shader_manager->get_attribute_id(req.name); + else + id = scene->shader_manager->get_attribute_id(req.std); + + emit_attribute_mapping(attr_map, index, id, req, geom); index += ATTR_PRIM_TYPES; + +#ifdef WITH_OSL + /* Some standard attributes are explicitly referenced via their standard ID, so add those + * again in case they were added under a different attribute ID. */ + if (req.std != ATTR_STD_NONE && id != (uint64_t)req.std) { + emit_attribute_mapping(attr_map, index, (uint64_t)req.std, req, geom); + index += ATTR_PRIM_TYPES; + } +#endif } emit_attribute_map_terminator(attr_map, index, false, 0); @@ -528,10 +471,16 @@ void GeometryManager::update_svm_attributes(Device *, /* set object attributes */ if (attributes.size() > 0) { - int index = object->attr_map_offset; + size_t index = object->attr_map_offset; foreach (AttributeRequest &req, attributes.requests) { - emit_attribute_mapping(attr_map, index, scene, req, object->geometry); + uint64_t id; + if (req.std == ATTR_STD_NONE) + id = scene->shader_manager->get_attribute_id(req.name); + else + id = scene->shader_manager->get_attribute_id(req.std); + + emit_attribute_mapping(attr_map, index, id, req, object->geometry); index += ATTR_PRIM_TYPES; } @@ -982,7 +931,7 @@ void GeometryManager::device_update_attributes(Device *device, /* create attribute lookup maps */ if (scene->shader_manager->use_osl()) - update_osl_attributes(device, scene, geom_attributes); + update_osl_globals(device, scene); update_svm_attributes(device, dscene, scene, geom_attributes, object_attributes); @@ -2188,7 +2137,6 @@ void GeometryManager::device_free(Device *device, DeviceScene *dscene, bool forc if (og) { og->object_name_map.clear(); - og->attribute_map.clear(); og->object_names.clear(); } #else diff --git a/intern/cycles/scene/geometry.h b/intern/cycles/scene/geometry.h index 6210a64509a..8a1bdc33a6f 100644 --- a/intern/cycles/scene/geometry.h +++ b/intern/cycles/scene/geometry.h @@ -219,9 +219,7 @@ class GeometryManager { void create_volume_mesh(const Scene *scene, Volume *volume, Progress &progress); /* Attributes */ - void update_osl_attributes(Device *device, - Scene *scene, - vector &geom_attributes); + void update_osl_globals(Device *device, Scene *scene); void update_svm_attributes(Device *device, DeviceScene *dscene, Scene *scene, diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp index f5ee0c0f1d3..7c8d9bcd3e2 100644 --- a/intern/cycles/scene/osl.cpp +++ b/intern/cycles/scene/osl.cpp @@ -78,6 +78,18 @@ void OSLShaderManager::reset(Scene * /*scene*/) shading_system_init(); } +uint64_t OSLShaderManager::get_attribute_id(ustring name) +{ + return name.hash(); +} + +uint64_t OSLShaderManager::get_attribute_id(AttributeStandard std) +{ + /* if standard attribute, use geom: name convention */ + ustring stdname(string("geom:") + string(Attribute::standard_name(std))); + return stdname.hash(); +} + void OSLShaderManager::device_update_specific(Device *device, DeviceScene *dscene, Scene *scene, diff --git a/intern/cycles/scene/osl.h b/intern/cycles/scene/osl.h index bf27069b1b1..76c6bd96ce1 100644 --- a/intern/cycles/scene/osl.h +++ b/intern/cycles/scene/osl.h @@ -66,6 +66,9 @@ class OSLShaderManager : public ShaderManager { return true; } + uint64_t get_attribute_id(ustring name) override; + uint64_t get_attribute_id(AttributeStandard std) override; + void device_update_specific(Device *device, DeviceScene *dscene, Scene *scene, diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index bd647ab55e7..96a8f40bbad 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -414,7 +414,7 @@ ShaderManager *ShaderManager::create(int shadingsystem) return manager; } -uint ShaderManager::get_attribute_id(ustring name) +uint64_t ShaderManager::get_attribute_id(ustring name) { thread_scoped_spin_lock lock(attribute_lock_); @@ -424,14 +424,14 @@ uint ShaderManager::get_attribute_id(ustring name) if (it != unique_attribute_id.end()) return it->second; - uint id = (uint)ATTR_STD_NUM + unique_attribute_id.size(); + uint64_t id = ATTR_STD_NUM + unique_attribute_id.size(); unique_attribute_id[name] = id; return id; } -uint ShaderManager::get_attribute_id(AttributeStandard std) +uint64_t ShaderManager::get_attribute_id(AttributeStandard std) { - return (uint)std; + return (uint64_t)std; } int ShaderManager::get_shader_id(Shader *shader, bool smooth) diff --git a/intern/cycles/scene/shader.h b/intern/cycles/scene/shader.h index 274bb9b4fa1..2670776aca4 100644 --- a/intern/cycles/scene/shader.h +++ b/intern/cycles/scene/shader.h @@ -192,8 +192,8 @@ class ShaderManager { void device_free_common(Device *device, DeviceScene *dscene, Scene *scene); /* get globally unique id for a type of attribute */ - uint get_attribute_id(ustring name); - uint get_attribute_id(AttributeStandard std); + virtual uint64_t get_attribute_id(ustring name); + virtual uint64_t get_attribute_id(AttributeStandard std); /* get shader id for mesh faces */ int get_shader_id(Shader *shader, bool smooth = false); @@ -223,7 +223,7 @@ class ShaderManager { uint32_t update_flags; - typedef unordered_map AttributeIDMap; + typedef unordered_map AttributeIDMap; AttributeIDMap unique_attribute_id; static thread_mutex lookup_table_mutex; -- cgit v1.2.3 From 8611c37f975737efe0d159822edfc21733268f51 Mon Sep 17 00:00:00 2001 From: Patrick Mours Date: Thu, 8 Sep 2022 19:31:44 +0200 Subject: Cycles: Generate OSL closures using macros and a template file This has the advantage of being able to use information about the existing OSL closures in various places without code duplication. In addition, the setup code for all closures was moved to standalone functions to avoid usage of virtual function calls in preparation for GPU support. This patch was split from D15902. Differential Revision: https://developer.blender.org/D15917 --- .clang-format | 4 +- intern/cycles/kernel/closure/alloc.h | 30 - intern/cycles/kernel/osl/CMakeLists.txt | 8 +- intern/cycles/kernel/osl/background.cpp | 77 -- intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp | 68 -- intern/cycles/kernel/osl/bsdf_phong_ramp.cpp | 69 -- intern/cycles/kernel/osl/bssrdf.cpp | 105 --- intern/cycles/kernel/osl/closures.cpp | 1001 +------------------- intern/cycles/kernel/osl/closures.h | 142 --- intern/cycles/kernel/osl/closures_setup.h | 1166 ++++++++++++++++++++++++ intern/cycles/kernel/osl/closures_template.h | 258 ++++++ intern/cycles/kernel/osl/emissive.cpp | 54 -- intern/cycles/kernel/osl/services.cpp | 13 +- intern/cycles/kernel/osl/services.h | 2 + intern/cycles/kernel/osl/shader.cpp | 108 ++- intern/cycles/kernel/osl/shader.h | 3 - intern/cycles/kernel/osl/types.h | 21 + intern/cycles/scene/osl.cpp | 2 +- 18 files changed, 1542 insertions(+), 1589 deletions(-) delete mode 100644 intern/cycles/kernel/osl/background.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp delete mode 100644 intern/cycles/kernel/osl/bsdf_phong_ramp.cpp delete mode 100644 intern/cycles/kernel/osl/bssrdf.cpp delete mode 100644 intern/cycles/kernel/osl/closures.h create mode 100644 intern/cycles/kernel/osl/closures_setup.h create mode 100644 intern/cycles/kernel/osl/closures_template.h delete mode 100644 intern/cycles/kernel/osl/emissive.cpp create mode 100644 intern/cycles/kernel/osl/types.h diff --git a/.clang-format b/.clang-format index 7e88e6d1cb1..72add4594a4 100644 --- a/.clang-format +++ b/.clang-format @@ -273,5 +273,5 @@ StatementMacros: - PyObject_VAR_HEAD - ccl_gpu_kernel_postfix -MacroBlockBegin: "^BSDF_CLOSURE_CLASS_BEGIN$" -MacroBlockEnd: "^BSDF_CLOSURE_CLASS_END$" +MacroBlockBegin: "^OSL_CLOSURE_STRUCT_BEGIN$" +MacroBlockEnd: "^OSL_CLOSURE_STRUCT_END$" diff --git a/intern/cycles/kernel/closure/alloc.h b/intern/cycles/kernel/closure/alloc.h index 9847898ee89..1cf06614f3b 100644 --- a/intern/cycles/kernel/closure/alloc.h +++ b/intern/cycles/kernel/closure/alloc.h @@ -59,39 +59,10 @@ ccl_device_inline ccl_private ShaderClosure *bsdf_alloc(ccl_private ShaderData * * we will not allocate new closure. */ if (sample_weight >= CLOSURE_WEIGHT_CUTOFF) { ccl_private ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight); - if (sc == NULL) { - return NULL; - } - - sc->sample_weight = sample_weight; - - return sc; - } - - return NULL; -} - -#ifdef __OSL__ -ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, - int size, - Spectrum weight, - void *data) -{ - kernel_assert(isfinite_safe(weight)); - - const float sample_weight = fabsf(average(weight)); - - /* Use comparison this way to help dealing with non-finite weight: if the average is not finite - * we will not allocate new closure. */ - if (sample_weight >= CLOSURE_WEIGHT_CUTOFF) { - ShaderClosure *sc = closure_alloc(sd, size, CLOSURE_NONE_ID, weight); if (!sc) { return NULL; } - memcpy((void *)sc, data, size); - - sc->weight = weight; sc->sample_weight = sample_weight; return sc; @@ -99,6 +70,5 @@ ccl_device_inline ShaderClosure *bsdf_alloc_osl(ShaderData *sd, return NULL; } -#endif CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/CMakeLists.txt b/intern/cycles/kernel/osl/CMakeLists.txt index 7570490be7c..b27bcb066fd 100644 --- a/intern/cycles/kernel/osl/CMakeLists.txt +++ b/intern/cycles/kernel/osl/CMakeLists.txt @@ -10,18 +10,14 @@ set(INC_SYS ) set(SRC - background.cpp - bsdf_diffuse_ramp.cpp - bsdf_phong_ramp.cpp - emissive.cpp - bssrdf.cpp closures.cpp services.cpp shader.cpp ) set(HEADER_SRC - closures.h + closures_setup.h + closures_template.h globals.h services.h shader.h diff --git a/intern/cycles/kernel/osl/background.cpp b/intern/cycles/kernel/osl/background.cpp deleted file mode 100644 index 4b5a2686117..00000000000 --- a/intern/cycles/kernel/osl/background.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Adapted from Open Shading Language - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011-2022 Blender Foundation. */ - -#include - -#include - -#include "kernel/osl/closures.h" - -// clang-format off -#include "kernel/device/cpu/compat.h" -#include "kernel/device/cpu/globals.h" - -#include "kernel/closure/alloc.h" -#include "kernel/closure/emissive.h" - -#include "kernel/util/color.h" -// clang-format on - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -/// Generic background closure -/// -/// We only have a background closure for the shaders -/// to return a color in background shaders. No methods, -/// only the weight is taking into account -/// -class GenericBackgroundClosure : public CClosurePrimitive { - public: - void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) - { - background_setup(sd, rgb_to_spectrum(weight)); - } -}; - -/// Holdout closure -/// -/// This will be used by the shader to mark the -/// amount of holdout for the current shading -/// point. No parameters, only the weight will be -/// used -/// -class HoldoutClosure : CClosurePrimitive { - public: - void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) - { - closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, rgb_to_spectrum(weight)); - sd->flag |= SD_HOLDOUT; - } -}; - -ClosureParam *closure_background_params() -{ - static ClosureParam params[] = { - CLOSURE_STRING_KEYPARAM(GenericBackgroundClosure, label, "label"), - CLOSURE_FINISH_PARAM(GenericBackgroundClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_background_prepare, GenericBackgroundClosure) - -ClosureParam *closure_holdout_params() -{ - static ClosureParam params[] = {CLOSURE_FINISH_PARAM(HoldoutClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp deleted file mode 100644 index 667207ec6bf..00000000000 --- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Adapted from Open Shading Language - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011-2022 Blender Foundation. */ - -#include - -#include - -#include "kernel/device/cpu/compat.h" -#include "kernel/osl/closures.h" - -// clang-format off -#include "kernel/device/cpu/compat.h" -#include "kernel/device/cpu/globals.h" - -#include "kernel/types.h" -#include "kernel/closure/alloc.h" -#include "kernel/closure/bsdf_diffuse_ramp.h" -#include "kernel/closure/bsdf_util.h" - -#include "kernel/util/color.h" -// clang-format on - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class DiffuseRampClosure : public CBSDFClosure { - public: - DiffuseRampBsdf params; - Color3 colors[8]; - - void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - DiffuseRampBsdf *bsdf = (DiffuseRampBsdf *)bsdf_alloc_osl( - sd, sizeof(DiffuseRampBsdf), rgb_to_spectrum(weight), ¶ms); - - if (bsdf) { - bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); - - if (bsdf->colors) { - for (int i = 0; i < 8; i++) - bsdf->colors[i] = TO_FLOAT3(colors[i]); - - sd->flag |= bsdf_diffuse_ramp_setup(bsdf); - } - } - } -}; - -ClosureParam *closure_bsdf_diffuse_ramp_params() -{ - static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, params.N), - CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8), - CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"), - CLOSURE_FINISH_PARAM(DiffuseRampClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_bsdf_diffuse_ramp_prepare, DiffuseRampClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp deleted file mode 100644 index 6f54a96e542..00000000000 --- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Adapted from Open Shading Language - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011-2022 Blender Foundation. */ - -#include - -#include - -#include "kernel/device/cpu/compat.h" -#include "kernel/osl/closures.h" - -// clang-format off -#include "kernel/device/cpu/compat.h" -#include "kernel/device/cpu/globals.h" - -#include "kernel/types.h" -#include "kernel/closure/alloc.h" -#include "kernel/closure/bsdf_phong_ramp.h" -#include "kernel/closure/bsdf_util.h" - -#include "kernel/util/color.h" -// clang-format on - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -class PhongRampClosure : public CBSDFClosure { - public: - PhongRampBsdf params; - Color3 colors[8]; - - void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - PhongRampBsdf *bsdf = (PhongRampBsdf *)bsdf_alloc_osl( - sd, sizeof(PhongRampBsdf), rgb_to_spectrum(weight), ¶ms); - - if (bsdf) { - bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); - - if (bsdf->colors) { - for (int i = 0; i < 8; i++) - bsdf->colors[i] = TO_FLOAT3(colors[i]); - - sd->flag |= bsdf_phong_ramp_setup(bsdf); - } - } - } -}; - -ClosureParam *closure_bsdf_phong_ramp_params() -{ - static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PhongRampClosure, params.N), - CLOSURE_FLOAT_PARAM(PhongRampClosure, params.exponent), - CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8), - CLOSURE_STRING_KEYPARAM(PhongRampClosure, label, "label"), - CLOSURE_FINISH_PARAM(PhongRampClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_bsdf_phong_ramp_prepare, PhongRampClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/bssrdf.cpp b/intern/cycles/kernel/osl/bssrdf.cpp deleted file mode 100644 index 3054946ba5a..00000000000 --- a/intern/cycles/kernel/osl/bssrdf.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Adapted from Open Shading Language - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011-2022 Blender Foundation. */ - -#include - -#include "kernel/device/cpu/compat.h" -#include "kernel/osl/closures.h" - -// clang-format off -#include "kernel/device/cpu/compat.h" -#include "kernel/device/cpu/globals.h" - -#include "kernel/types.h" - -#include "kernel/closure/alloc.h" -#include "kernel/closure/bsdf_util.h" -#include "kernel/closure/bsdf_diffuse.h" -#include "kernel/closure/bsdf_principled_diffuse.h" -#include "kernel/closure/bssrdf.h" - -#include "kernel/util/color.h" -// clang-format on - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -static ustring u_burley("burley"); -static ustring u_random_walk_fixed_radius("random_walk_fixed_radius"); -static ustring u_random_walk("random_walk"); - -class CBSSRDFClosure : public CClosurePrimitive { - public: - Bssrdf params; - float ior; - ustring method; - - CBSSRDFClosure() - { - params.roughness = FLT_MAX; - params.anisotropy = 1.0f; - ior = 1.4f; - } - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - if (method == u_burley) { - alloc(sd, path_flag, weight, CLOSURE_BSSRDF_BURLEY_ID); - } - else if (method == u_random_walk_fixed_radius) { - alloc(sd, path_flag, weight, CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID); - } - else if (method == u_random_walk) { - alloc(sd, path_flag, weight, CLOSURE_BSSRDF_RANDOM_WALK_ID); - } - } - - void alloc(ShaderData *sd, uint32_t path_flag, float3 weight, ClosureType type) - { - Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(weight)); - - if (bssrdf) { - /* disable in case of diffuse ancestor, can't see it well then and - * adds considerably noise due to probabilities of continuing path - * getting lower and lower */ - if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) { - params.radius = zero_spectrum(); - } - - /* create one closure per color channel */ - bssrdf->radius = params.radius; - bssrdf->albedo = params.albedo; - bssrdf->N = params.N; - bssrdf->roughness = params.roughness; - bssrdf->anisotropy = clamp(params.anisotropy, 0.0f, 0.9f); - sd->flag |= bssrdf_setup(sd, bssrdf, (ClosureType)type, clamp(ior, 1.01f, 3.8f)); - } - } -}; - -ClosureParam *closure_bssrdf_params() -{ - static ClosureParam params[] = { - CLOSURE_STRING_PARAM(CBSSRDFClosure, method), - CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.N), - CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.radius), - CLOSURE_FLOAT3_PARAM(CBSSRDFClosure, params.albedo), - CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.roughness, "roughness"), - CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, ior, "ior"), - CLOSURE_FLOAT_KEYPARAM(CBSSRDFClosure, params.anisotropy, "anisotropy"), - CLOSURE_STRING_KEYPARAM(CBSSRDFClosure, label, "label"), - CLOSURE_FINISH_PARAM(CBSSRDFClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_bssrdf_prepare, CBSSRDFClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/closures.cpp b/intern/cycles/kernel/osl/closures.cpp index 8766fb73dbb..604d672063b 100644 --- a/intern/cycles/kernel/osl/closures.cpp +++ b/intern/cycles/kernel/osl/closures.cpp @@ -9,999 +9,48 @@ #include #include -#include "kernel/osl/closures.h" -#include "kernel/osl/shader.h" +#include "kernel/types.h" + +#include "kernel/osl/globals.h" +#include "kernel/osl/services.h" #include "util/math.h" #include "util/param.h" -// clang-format off #include "kernel/device/cpu/compat.h" #include "kernel/device/cpu/globals.h" -#include "kernel/types.h" - -#include "kernel/closure/alloc.h" -#include "kernel/closure/bsdf_util.h" -#include "kernel/closure/bsdf_ashikhmin_velvet.h" -#include "kernel/closure/bsdf_diffuse.h" -#include "kernel/closure/bsdf_microfacet.h" -#include "kernel/closure/bsdf_microfacet_multi.h" -#include "kernel/closure/bsdf_oren_nayar.h" -#include "kernel/closure/bsdf_reflection.h" -#include "kernel/closure/bsdf_refraction.h" -#include "kernel/closure/bsdf_transparent.h" -#include "kernel/closure/bsdf_ashikhmin_shirley.h" -#include "kernel/closure/bsdf_toon.h" -#include "kernel/closure/bsdf_hair.h" -#include "kernel/closure/bsdf_hair_principled.h" -#include "kernel/closure/bsdf_principled_diffuse.h" -#include "kernel/closure/bsdf_principled_sheen.h" -#include "kernel/closure/volume.h" - -#include "kernel/util/color.h" -// clang-format on +#include "kernel/osl/types.h" +#include "kernel/osl/closures_setup.h" CCL_NAMESPACE_BEGIN -using namespace OSL; - -/* BSDF class definitions */ - -BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, DiffuseBsdf, LABEL_DIFFUSE) - BSDF_CLOSURE_FLOAT3_PARAM(DiffuseClosure, params.N) -BSDF_CLOSURE_CLASS_END(Diffuse, diffuse) - -BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, DiffuseBsdf, LABEL_DIFFUSE) - BSDF_CLOSURE_FLOAT3_PARAM(TranslucentClosure, params.N) -BSDF_CLOSURE_CLASS_END(Translucent, translucent) - -BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, OrenNayarBsdf, LABEL_DIFFUSE) - BSDF_CLOSURE_FLOAT3_PARAM(OrenNayarClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(OrenNayarClosure, params.roughness) -BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar) - -BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, MicrofacetBsdf, LABEL_SINGULAR) - BSDF_CLOSURE_FLOAT3_PARAM(ReflectionClosure, params.N) -BSDF_CLOSURE_CLASS_END(Reflection, reflection) - -BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, MicrofacetBsdf, LABEL_SINGULAR) - BSDF_CLOSURE_FLOAT3_PARAM(RefractionClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(RefractionClosure, params.ior) -BSDF_CLOSURE_CLASS_END(Refraction, refraction) - -BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, VelvetBsdf, LABEL_DIFFUSE) - BSDF_CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, params.sigma) -BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet) - -BSDF_CLOSURE_CLASS_BEGIN(AshikhminShirley, - ashikhmin_shirley, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_REFLECT) - BSDF_CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.N) - BSDF_CLOSURE_FLOAT3_PARAM(AshikhminShirleyClosure, params.T) - BSDF_CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_x) - BSDF_CLOSURE_FLOAT_PARAM(AshikhminShirleyClosure, params.alpha_y) -BSDF_CLOSURE_CLASS_END(AshikhminShirley, ashikhmin_shirley) - -BSDF_CLOSURE_CLASS_BEGIN(DiffuseToon, diffuse_toon, ToonBsdf, LABEL_DIFFUSE) - BSDF_CLOSURE_FLOAT3_PARAM(DiffuseToonClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.size) - BSDF_CLOSURE_FLOAT_PARAM(DiffuseToonClosure, params.smooth) -BSDF_CLOSURE_CLASS_END(DiffuseToon, diffuse_toon) - -BSDF_CLOSURE_CLASS_BEGIN(GlossyToon, glossy_toon, ToonBsdf, LABEL_GLOSSY) - BSDF_CLOSURE_FLOAT3_PARAM(GlossyToonClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.size) - BSDF_CLOSURE_FLOAT_PARAM(GlossyToonClosure, params.smooth) -BSDF_CLOSURE_CLASS_END(GlossyToon, glossy_toon) - -BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXIsotropic, - microfacet_ggx_isotropic, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_REFLECT) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetGGXIsotropicClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetGGXIsotropicClosure, params.alpha_x) -BSDF_CLOSURE_CLASS_END(MicrofacetGGXIsotropic, microfacet_ggx_isotropic) - -BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, - microfacet_ggx, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_REFLECT) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.N) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, params.T) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_x) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, params.alpha_y) -BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx) - -BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannIsotropic, - microfacet_beckmann_isotropic, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_REFLECT) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannIsotropicClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetBeckmannIsotropicClosure, params.alpha_x) -BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannIsotropic, microfacet_beckmann_isotropic) - -BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, - microfacet_beckmann, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_REFLECT) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.N) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, params.T) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_x) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, params.alpha_y) -BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann) - -BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, - microfacet_ggx_refraction, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_TRANSMIT) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.alpha_x) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, params.ior) -BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction) - -BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, - microfacet_beckmann_refraction, - MicrofacetBsdf, - LABEL_GLOSSY | LABEL_TRANSMIT) - BSDF_CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.alpha_x) - BSDF_CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, params.ior) -BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) - -BSDF_CLOSURE_CLASS_BEGIN(HairReflection, hair_reflection, HairBsdf, LABEL_GLOSSY) - BSDF_CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness1) - BSDF_CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.roughness2) - BSDF_CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T) - BSDF_CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset) -BSDF_CLOSURE_CLASS_END(HairReflection, hair_reflection) - -BSDF_CLOSURE_CLASS_BEGIN(HairTransmission, hair_transmission, HairBsdf, LABEL_GLOSSY) - BSDF_CLOSURE_FLOAT3_PARAM(HairTransmissionClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness1) - BSDF_CLOSURE_FLOAT_PARAM(HairTransmissionClosure, params.roughness2) - BSDF_CLOSURE_FLOAT3_PARAM(HairReflectionClosure, params.T) - BSDF_CLOSURE_FLOAT_PARAM(HairReflectionClosure, params.offset) -BSDF_CLOSURE_CLASS_END(HairTransmission, hair_transmission) - -BSDF_CLOSURE_CLASS_BEGIN(PrincipledDiffuse, - principled_diffuse, - PrincipledDiffuseBsdf, - LABEL_DIFFUSE) - BSDF_CLOSURE_FLOAT3_PARAM(PrincipledDiffuseClosure, params.N) - BSDF_CLOSURE_FLOAT_PARAM(PrincipledDiffuseClosure, params.roughness) -BSDF_CLOSURE_CLASS_END(PrincipledDiffuse, principled_diffuse) - -class PrincipledSheenClosure : public CBSDFClosure { - public: - PrincipledSheenBsdf params; - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - if (!skip(sd, path_flag, LABEL_DIFFUSE)) { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - PrincipledSheenBsdf *bsdf = (PrincipledSheenBsdf *)bsdf_alloc_osl( - sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight), ¶ms); - sd->flag |= (bsdf) ? bsdf_principled_sheen_setup(sd, bsdf) : 0; - } - } -}; - -static ClosureParam *bsdf_principled_sheen_params() -{ - static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PrincipledSheenClosure, params.N), - CLOSURE_STRING_KEYPARAM(PrincipledSheenClosure, label, "label"), - CLOSURE_FINISH_PARAM(PrincipledSheenClosure)}; - return params; -} - -CCLOSURE_PREPARE_STATIC(closure_bsdf_principled_sheen_prepare, PrincipledSheenClosure) - -/* PRINCIPLED HAIR BSDF */ -class PrincipledHairClosure : public CBSDFClosure { - public: - PrincipledHairBSDF params; - - PrincipledHairBSDF *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) - { - PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)bsdf_alloc_osl( - sd, sizeof(PrincipledHairBSDF), rgb_to_spectrum(weight), ¶ms); - if (!bsdf) { - return NULL; - } - - PrincipledHairExtra *extra = (PrincipledHairExtra *)closure_alloc_extra( - sd, sizeof(PrincipledHairExtra)); - if (!extra) { - return NULL; - } - - bsdf->extra = extra; - return bsdf; - } - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - if (!skip(sd, path_flag, LABEL_GLOSSY)) { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - PrincipledHairBSDF *bsdf = (PrincipledHairBSDF *)alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - sd->flag |= (bsdf) ? bsdf_principled_hair_setup(sd, bsdf) : 0; - } - } -}; - -static ClosureParam *closure_bsdf_principled_hair_params() -{ - static ClosureParam params[] = {CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.N), - CLOSURE_FLOAT3_PARAM(PrincipledHairClosure, params.sigma), - CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.v), - CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.s), - CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.m0_roughness), - CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.alpha), - CLOSURE_FLOAT_PARAM(PrincipledHairClosure, params.eta), - CLOSURE_STRING_KEYPARAM(PrincipledHairClosure, label, "label"), - CLOSURE_FINISH_PARAM(PrincipledHairClosure)}; - - return params; -} - -CCLOSURE_PREPARE(closure_bsdf_principled_hair_prepare, PrincipledHairClosure) - -/* DISNEY PRINCIPLED CLEARCOAT */ -class PrincipledClearcoatClosure : public CBSDFClosure { - public: - MicrofacetBsdf params; - float clearcoat, clearcoat_roughness; - - MicrofacetBsdf *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) - { - MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); - if (!bsdf) { - return NULL; - } - - MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); - if (!extra) { - return NULL; - } - - bsdf->T = zero_float3(); - bsdf->extra = extra; - bsdf->ior = 1.5f; - bsdf->alpha_x = clearcoat_roughness; - bsdf->alpha_y = clearcoat_roughness; - bsdf->extra->color = zero_spectrum(); - bsdf->extra->cspec0 = make_spectrum(0.04f); - bsdf->extra->clearcoat = clearcoat; - return bsdf; - } - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd); - } -}; - -ClosureParam *closure_bsdf_principled_clearcoat_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(PrincipledClearcoatClosure, params.N), - CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat), - CLOSURE_FLOAT_PARAM(PrincipledClearcoatClosure, clearcoat_roughness), - CLOSURE_STRING_KEYPARAM(PrincipledClearcoatClosure, label, "label"), - CLOSURE_FINISH_PARAM(PrincipledClearcoatClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_principled_clearcoat_prepare, PrincipledClearcoatClosure) - /* Registration */ -static void register_closure(OSL::ShadingSystem *ss, - const char *name, - int id, - OSL::ClosureParam *params, - OSL::PrepareClosureFunc prepare) -{ - /* optimization: it's possible to not use a prepare function at all and - * only initialize the actual class when accessing the closure component - * data, but then we need to map the id to the class somehow */ -#if OSL_LIBRARY_VERSION_CODE >= 10900 - ss->register_closure(name, id, params, prepare, NULL); -#else - ss->register_closure(name, id, params, prepare, NULL, 16); -#endif -} - -void OSLShader::register_closures(OSLShadingSystem *ss_) -{ - OSL::ShadingSystem *ss = (OSL::ShadingSystem *)ss_; - int id = 0; - - register_closure(ss, "diffuse", id++, bsdf_diffuse_params(), bsdf_diffuse_prepare); - register_closure(ss, "oren_nayar", id++, bsdf_oren_nayar_params(), bsdf_oren_nayar_prepare); - register_closure(ss, "translucent", id++, bsdf_translucent_params(), bsdf_translucent_prepare); - register_closure(ss, "reflection", id++, bsdf_reflection_params(), bsdf_reflection_prepare); - register_closure(ss, "refraction", id++, bsdf_refraction_params(), bsdf_refraction_prepare); - register_closure(ss, - "transparent", - id++, - closure_bsdf_transparent_params(), - closure_bsdf_transparent_prepare); - - register_closure( - ss, "microfacet", id++, closure_bsdf_microfacet_params(), closure_bsdf_microfacet_prepare); - register_closure(ss, - "microfacet_ggx", - id++, - bsdf_microfacet_ggx_isotropic_params(), - bsdf_microfacet_ggx_isotropic_prepare); - register_closure( - ss, "microfacet_ggx_aniso", id++, bsdf_microfacet_ggx_params(), bsdf_microfacet_ggx_prepare); - register_closure(ss, - "microfacet_ggx_refraction", - id++, - bsdf_microfacet_ggx_refraction_params(), - bsdf_microfacet_ggx_refraction_prepare); - register_closure(ss, - "microfacet_multi_ggx", - id++, - closure_bsdf_microfacet_multi_ggx_params(), - closure_bsdf_microfacet_multi_ggx_prepare); - register_closure(ss, - "microfacet_multi_ggx_glass", - id++, - closure_bsdf_microfacet_multi_ggx_glass_params(), - closure_bsdf_microfacet_multi_ggx_glass_prepare); - register_closure(ss, - "microfacet_multi_ggx_aniso", - id++, - closure_bsdf_microfacet_multi_ggx_aniso_params(), - closure_bsdf_microfacet_multi_ggx_aniso_prepare); - register_closure(ss, - "microfacet_ggx_fresnel", - id++, - closure_bsdf_microfacet_ggx_fresnel_params(), - closure_bsdf_microfacet_ggx_fresnel_prepare); - register_closure(ss, - "microfacet_ggx_aniso_fresnel", - id++, - closure_bsdf_microfacet_ggx_aniso_fresnel_params(), - closure_bsdf_microfacet_ggx_aniso_fresnel_prepare); - register_closure(ss, - "microfacet_multi_ggx_fresnel", - id++, - closure_bsdf_microfacet_multi_ggx_fresnel_params(), - closure_bsdf_microfacet_multi_ggx_fresnel_prepare); - register_closure(ss, - "microfacet_multi_ggx_glass_fresnel", - id++, - closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(), - closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare); - register_closure(ss, - "microfacet_multi_ggx_aniso_fresnel", - id++, - closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(), - closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare); - register_closure(ss, - "microfacet_beckmann", - id++, - bsdf_microfacet_beckmann_isotropic_params(), - bsdf_microfacet_beckmann_isotropic_prepare); - register_closure(ss, - "microfacet_beckmann_aniso", - id++, - bsdf_microfacet_beckmann_params(), - bsdf_microfacet_beckmann_prepare); - register_closure(ss, - "microfacet_beckmann_refraction", - id++, - bsdf_microfacet_beckmann_refraction_params(), - bsdf_microfacet_beckmann_refraction_prepare); - register_closure(ss, - "ashikhmin_shirley", - id++, - bsdf_ashikhmin_shirley_params(), - bsdf_ashikhmin_shirley_prepare); - register_closure( - ss, "ashikhmin_velvet", id++, bsdf_ashikhmin_velvet_params(), bsdf_ashikhmin_velvet_prepare); - register_closure( - ss, "diffuse_toon", id++, bsdf_diffuse_toon_params(), bsdf_diffuse_toon_prepare); - register_closure(ss, "glossy_toon", id++, bsdf_glossy_toon_params(), bsdf_glossy_toon_prepare); - register_closure(ss, - "principled_diffuse", - id++, - bsdf_principled_diffuse_params(), - bsdf_principled_diffuse_prepare); - register_closure(ss, - "principled_sheen", - id++, - bsdf_principled_sheen_params(), - closure_bsdf_principled_sheen_prepare); - register_closure(ss, - "principled_clearcoat", - id++, - closure_bsdf_principled_clearcoat_params(), - closure_bsdf_principled_clearcoat_prepare); - - register_closure(ss, "emission", id++, closure_emission_params(), closure_emission_prepare); - register_closure( - ss, "background", id++, closure_background_params(), closure_background_prepare); - register_closure(ss, "holdout", id++, closure_holdout_params(), closure_holdout_prepare); - register_closure(ss, - "diffuse_ramp", - id++, - closure_bsdf_diffuse_ramp_params(), - closure_bsdf_diffuse_ramp_prepare); - register_closure( - ss, "phong_ramp", id++, closure_bsdf_phong_ramp_params(), closure_bsdf_phong_ramp_prepare); - register_closure(ss, "bssrdf", id++, closure_bssrdf_params(), closure_bssrdf_prepare); - - register_closure( - ss, "hair_reflection", id++, bsdf_hair_reflection_params(), bsdf_hair_reflection_prepare); - register_closure(ss, - "hair_transmission", - id++, - bsdf_hair_transmission_params(), - bsdf_hair_transmission_prepare); - - register_closure(ss, - "principled_hair", - id++, - closure_bsdf_principled_hair_params(), - closure_bsdf_principled_hair_prepare); - - register_closure(ss, - "henyey_greenstein", - id++, - closure_henyey_greenstein_params(), - closure_henyey_greenstein_prepare); - register_closure( - ss, "absorption", id++, closure_absorption_params(), closure_absorption_prepare); -} - -/* BSDF Closure */ - -bool CBSDFClosure::skip(const ShaderData *sd, uint32_t path_flag, int scattering) -{ - /* caustic options */ - if ((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) { - const KernelGlobalsCPU *kg = sd->osl_globals; - - if ((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) || - (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) { - return true; - } - } - - return false; -} - -/* Standard Microfacet Closure */ - -class MicrofacetClosure : public CBSDFClosure { - public: - MicrofacetBsdf params; - ustring distribution; - int refract; - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - static ustring u_ggx("ggx"); - static ustring u_default("default"); - - const int label = (refract) ? LABEL_TRANSMIT : LABEL_REFLECT; - if (skip(sd, path_flag, LABEL_GLOSSY | label)) { - return; - } - - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); - - if (!bsdf) { - return; - } - - /* GGX */ - if (distribution == u_ggx || distribution == u_default) { - if (!refract) { - if (params.alpha_x == params.alpha_y) { - /* Isotropic */ - sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf); - } - else { - /* Anisotropic */ - sd->flag |= bsdf_microfacet_ggx_setup(bsdf); - } - } - else { - sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf); - } - } - /* Beckmann */ - else { - if (!refract) { - if (params.alpha_x == params.alpha_y) { - /* Isotropic */ - sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf); - } - else { - /* Anisotropic */ - sd->flag |= bsdf_microfacet_beckmann_setup(bsdf); - } - } - else { - sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf); - } - } - } -}; - -ClosureParam *closure_bsdf_microfacet_params() -{ - static ClosureParam params[] = {CLOSURE_STRING_PARAM(MicrofacetClosure, distribution), - CLOSURE_FLOAT3_PARAM(MicrofacetClosure, params.N), - CLOSURE_FLOAT3_PARAM(MicrofacetClosure, params.T), - CLOSURE_FLOAT_PARAM(MicrofacetClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetClosure, params.alpha_y), - CLOSURE_FLOAT_PARAM(MicrofacetClosure, params.ior), - CLOSURE_INT_PARAM(MicrofacetClosure, refract), - CLOSURE_STRING_KEYPARAM(MicrofacetClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetClosure)}; - - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_prepare, MicrofacetClosure) - -/* GGX closures with Fresnel */ - -class MicrofacetFresnelClosure : public CBSDFClosure { - public: - MicrofacetBsdf params; - float3 color; - float3 cspec0; - - MicrofacetBsdf *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) - { - /* Technically, the MultiGGX Glass closure may also transmit. However, - * since this is set statically and only used for caustic flags, this - * is probably as good as it gets. */ - if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { - return NULL; - } - - MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); - if (!bsdf) { - return NULL; - } - - MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); - if (!extra) { - return NULL; - } - - bsdf->extra = extra; - bsdf->extra->color = rgb_to_spectrum(color); - bsdf->extra->cspec0 = rgb_to_spectrum(cspec0); - bsdf->extra->clearcoat = 0.0f; - return bsdf; - } -}; - -class MicrofacetGGXFresnelClosure : public MicrofacetFresnelClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - bsdf->T = zero_float3(); - bsdf->alpha_y = bsdf->alpha_x; - sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd); - } -}; - -ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N), - CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior), - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color), - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0), - CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_fresnel_prepare, MicrofacetGGXFresnelClosure); - -class MicrofacetGGXAnisoFresnelClosure : public MicrofacetFresnelClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd); - } -}; - -ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.N), - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, params.T), - CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.alpha_y), - CLOSURE_FLOAT_PARAM(MicrofacetGGXFresnelClosure, params.ior), - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, color), - CLOSURE_FLOAT3_PARAM(MicrofacetGGXFresnelClosure, cspec0), - CLOSURE_STRING_KEYPARAM(MicrofacetGGXFresnelClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetGGXFresnelClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_ggx_aniso_fresnel_prepare, - MicrofacetGGXAnisoFresnelClosure); - -/* Multiscattering GGX closures */ - -class MicrofacetMultiClosure : public CBSDFClosure { - public: - MicrofacetBsdf params; - float3 color; - - MicrofacetBsdf *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) - { - /* Technically, the MultiGGX closure may also transmit. However, - * since this is set statically and only used for caustic flags, this - * is probably as good as it gets. */ - if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { - return NULL; - } - - MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); - if (!bsdf) { - return NULL; - } - - MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); - if (!extra) { - return NULL; - } - - bsdf->extra = extra; - bsdf->extra->color = rgb_to_spectrum(color); - bsdf->extra->cspec0 = zero_spectrum(); - bsdf->extra->clearcoat = 0.0f; - return bsdf; - } -}; - -class MicrofacetMultiGGXClosure : public MicrofacetMultiClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - bsdf->ior = 0.0f; - bsdf->T = zero_float3(); - bsdf->alpha_y = bsdf->alpha_x; - sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf); - } -}; - -ClosureParam *closure_bsdf_microfacet_multi_ggx_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color), - CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_prepare, MicrofacetMultiGGXClosure); - -class MicrofacetMultiGGXAnisoClosure : public MicrofacetMultiClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - bsdf->ior = 0.0f; - sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf); - } -}; - -ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.T), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_y), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color), - CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_prepare, MicrofacetMultiGGXAnisoClosure); - -class MicrofacetMultiGGXGlassClosure : public MicrofacetMultiClosure { - public: - MicrofacetMultiGGXGlassClosure() : MicrofacetMultiClosure() - { - } - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - bsdf->T = zero_float3(); - bsdf->alpha_y = bsdf->alpha_x; - sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf); - } -}; - -ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, params.N), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXClosure, params.ior), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXClosure, color), - CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetMultiGGXClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_prepare, MicrofacetMultiGGXGlassClosure); - -/* Multiscattering GGX closures with Fresnel */ - -class MicrofacetMultiFresnelClosure : public CBSDFClosure { - public: - MicrofacetBsdf params; - float3 color; - float3 cspec0; - - MicrofacetBsdf *alloc(ShaderData *sd, uint32_t path_flag, float3 weight) - { - /* Technically, the MultiGGX closure may also transmit. However, - * since this is set statically and only used for caustic flags, this - * is probably as good as it gets. */ - if (skip(sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { - return NULL; - } - - MicrofacetBsdf *bsdf = (MicrofacetBsdf *)bsdf_alloc_osl( - sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight), ¶ms); - if (!bsdf) { - return NULL; - } - - MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); - if (!extra) { - return NULL; - } - - bsdf->extra = extra; - bsdf->extra->color = rgb_to_spectrum(color); - bsdf->extra->cspec0 = rgb_to_spectrum(cspec0); - bsdf->extra->clearcoat = 0.0f; - return bsdf; - } -}; - -class MicrofacetMultiGGXFresnelClosure : public MicrofacetMultiFresnelClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - bsdf->T = zero_float3(); - bsdf->alpha_y = bsdf->alpha_x; - sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd); +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + static OSL::ClosureParam *osl_closure_##lower##_params() \ + { \ + static OSL::ClosureParam params[] = { +#define OSL_CLOSURE_STRUCT_END(Upper, lower) \ + CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), CLOSURE_FINISH_PARAM(Upper##Closure) \ + } \ + ; \ + return params; \ } -}; - -ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0), - CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_fresnel_prepare, - MicrofacetMultiGGXFresnelClosure); +#define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) \ + CLOSURE_##TYPE##_KEYPARAM(Upper##Closure, name, key), +#define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) \ + CLOSURE_##TYPE##_ARRAY_PARAM(Upper##Closure, name, size), -class MicrofacetMultiGGXAnisoFresnelClosure : public MicrofacetMultiFresnelClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); +#include "closures_template.h" - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd); - } -}; - -ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params() +void OSLRenderServices::register_closures(OSL::ShadingSystem *ss) { - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.T), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_y), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0), - CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)}; - return params; -} -CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare, - MicrofacetMultiGGXAnisoFresnelClosure); - -class MicrofacetMultiGGXGlassFresnelClosure : public MicrofacetMultiFresnelClosure { - public: - MicrofacetMultiGGXGlassFresnelClosure() : MicrofacetMultiFresnelClosure() - { - } +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + ss->register_closure( \ + #lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr); - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); - - MicrofacetBsdf *bsdf = alloc(sd, path_flag, weight); - if (!bsdf) { - return; - } - - bsdf->T = zero_float3(); - bsdf->alpha_y = bsdf->alpha_x; - sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd); - } -}; - -ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, params.N), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.alpha_x), - CLOSURE_FLOAT_PARAM(MicrofacetMultiGGXFresnelClosure, params.ior), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, color), - CLOSURE_FLOAT3_PARAM(MicrofacetMultiGGXFresnelClosure, cspec0), - CLOSURE_STRING_KEYPARAM(MicrofacetMultiGGXFresnelClosure, label, "label"), - CLOSURE_FINISH_PARAM(MicrofacetMultiGGXFresnelClosure)}; - return params; +#include "closures_template.h" } -CCLOSURE_PREPARE(closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare, - MicrofacetMultiGGXGlassFresnelClosure); - -/* Transparent */ - -class TransparentClosure : public CBSDFClosure { - public: - ShaderClosure params; - float3 unused; - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - bsdf_transparent_setup(sd, rgb_to_spectrum(weight), path_flag); - } -}; - -ClosureParam *closure_bsdf_transparent_params() -{ - static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(TransparentClosure, label, "label"), - CLOSURE_FINISH_PARAM(TransparentClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_bsdf_transparent_prepare, TransparentClosure) - -/* Volume */ - -class VolumeAbsorptionClosure : public CBSDFClosure { - public: - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - volume_extinction_setup(sd, rgb_to_spectrum(weight)); - } -}; - -ClosureParam *closure_absorption_params() -{ - static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(VolumeAbsorptionClosure, label, "label"), - CLOSURE_FINISH_PARAM(VolumeAbsorptionClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_absorption_prepare, VolumeAbsorptionClosure) - -class VolumeHenyeyGreensteinClosure : public CBSDFClosure { - public: - HenyeyGreensteinVolume params; - - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) - { - volume_extinction_setup(sd, rgb_to_spectrum(weight)); - - HenyeyGreensteinVolume *volume = (HenyeyGreensteinVolume *)bsdf_alloc_osl( - sd, sizeof(HenyeyGreensteinVolume), rgb_to_spectrum(weight), ¶ms); - if (!volume) { - return; - } - - sd->flag |= volume_henyey_greenstein_setup(volume); - } -}; - -ClosureParam *closure_henyey_greenstein_params() -{ - static ClosureParam params[] = { - CLOSURE_FLOAT_PARAM(VolumeHenyeyGreensteinClosure, params.g), - CLOSURE_STRING_KEYPARAM(VolumeHenyeyGreensteinClosure, label, "label"), - CLOSURE_FINISH_PARAM(VolumeHenyeyGreensteinClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_henyey_greenstein_prepare, VolumeHenyeyGreensteinClosure) CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/closures.h b/intern/cycles/kernel/osl/closures.h deleted file mode 100644 index 97666be7a1e..00000000000 --- a/intern/cycles/kernel/osl/closures.h +++ /dev/null @@ -1,142 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Adapted from Open Shading Language - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011-2022 Blender Foundation. */ - -#ifndef __OSL_CLOSURES_H__ -#define __OSL_CLOSURES_H__ - -#include "kernel/types.h" -#include "util/types.h" - -#include -#include -#include - -CCL_NAMESPACE_BEGIN - -OSL::ClosureParam *closure_emission_params(); -OSL::ClosureParam *closure_background_params(); -OSL::ClosureParam *closure_holdout_params(); -OSL::ClosureParam *closure_bsdf_diffuse_ramp_params(); -OSL::ClosureParam *closure_bsdf_phong_ramp_params(); -OSL::ClosureParam *closure_bsdf_transparent_params(); -OSL::ClosureParam *closure_bssrdf_params(); -OSL::ClosureParam *closure_absorption_params(); -OSL::ClosureParam *closure_henyey_greenstein_params(); -OSL::ClosureParam *closure_bsdf_microfacet_params(); -OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_params(); -OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_params(); -OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_params(); -OSL::ClosureParam *closure_bsdf_microfacet_ggx_fresnel_params(); -OSL::ClosureParam *closure_bsdf_microfacet_ggx_aniso_fresnel_params(); -OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_fresnel_params(); -OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_glass_fresnel_params(); -OSL::ClosureParam *closure_bsdf_microfacet_multi_ggx_aniso_fresnel_params(); -OSL::ClosureParam *closure_bsdf_principled_clearcoat_params(); - -void closure_emission_prepare(OSL::RendererServices *, int id, void *data); -void closure_background_prepare(OSL::RendererServices *, int id, void *data); -void closure_holdout_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_diffuse_ramp_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_phong_ramp_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_transparent_prepare(OSL::RendererServices *, int id, void *data); -void closure_bssrdf_prepare(OSL::RendererServices *, int id, void *data); -void closure_absorption_prepare(OSL::RendererServices *, int id, void *data); -void closure_henyey_greenstein_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_microfacet_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_microfacet_multi_ggx_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_microfacet_multi_ggx_glass_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_microfacet_multi_ggx_aniso_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_microfacet_ggx_fresnel_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_microfacet_ggx_aniso_fresnel_prepare(OSL::RendererServices *, - int id, - void *data); -void closure_bsdf_microfacet_multi_ggx_fresnel_prepare(OSL::RendererServices *, - int id, - void *data); -void closure_bsdf_microfacet_multi_ggx_glass_fresnel_prepare(OSL::RendererServices *, - int id, - void *data); -void closure_bsdf_microfacet_multi_ggx_aniso_fresnel_prepare(OSL::RendererServices *, - int id, - void *data); -void closure_bsdf_principled_clearcoat_prepare(OSL::RendererServices *, int id, void *data); -void closure_bsdf_principled_hair_prepare(OSL::RendererServices *, int id, void *data); - -#define CCLOSURE_PREPARE(name, classname) \ - void name(RendererServices *, int id, void *data) \ - { \ - memset(data, 0, sizeof(classname)); \ - new (data) classname(); \ - } - -#define CCLOSURE_PREPARE_STATIC(name, classname) static CCLOSURE_PREPARE(name, classname) - -#define CLOSURE_FLOAT3_PARAM(st, fld) \ - { \ - TypeDesc::TypeVector, (int)reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) \ - } - -#define BSDF_CLOSURE_FLOAT_PARAM(st, fld) CLOSURE_FLOAT_PARAM(st, fld), -#define BSDF_CLOSURE_FLOAT3_PARAM(st, fld) CLOSURE_FLOAT3_PARAM(st, fld), - -#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z) -#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z) -#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) - -/* Closure */ - -class CClosurePrimitive { - public: - virtual void setup(ShaderData *sd, uint32_t path_flag, float3 weight) = 0; - - OSL::ustring label; -}; - -/* BSDF */ - -class CBSDFClosure : public CClosurePrimitive { - public: - bool skip(const ShaderData *sd, uint32_t path_flag, int scattering); -}; - -#define BSDF_CLOSURE_CLASS_BEGIN(Upper, lower, structname, TYPE) \ -\ - class Upper##Closure : public CBSDFClosure { \ - public: \ - structname params; \ - float3 unused; \ -\ - void setup(ShaderData *sd, uint32_t path_flag, float3 weight) \ - { \ - if (!skip(sd, path_flag, TYPE)) { \ - params.N = ensure_valid_reflection(sd->Ng, sd->I, params.N); \ - structname *bsdf = (structname *)bsdf_alloc_osl( \ - sd, sizeof(structname), rgb_to_spectrum(weight), ¶ms); \ - sd->flag |= (bsdf) ? bsdf_##lower##_setup(bsdf) : 0; \ - } \ - } \ - }; \ -\ - static ClosureParam *bsdf_##lower##_params() \ - { \ - static ClosureParam params[] = { - -/* parameters */ - -#define BSDF_CLOSURE_CLASS_END(Upper, lower) \ - CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), CLOSURE_FINISH_PARAM(Upper##Closure) \ - } \ - ; \ - return params; \ - } \ -\ - CCLOSURE_PREPARE_STATIC(bsdf_##lower##_prepare, Upper##Closure) - -CCL_NAMESPACE_END - -#endif /* __OSL_CLOSURES_H__ */ diff --git a/intern/cycles/kernel/osl/closures_setup.h b/intern/cycles/kernel/osl/closures_setup.h new file mode 100644 index 00000000000..7972bba7d5c --- /dev/null +++ b/intern/cycles/kernel/osl/closures_setup.h @@ -0,0 +1,1166 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * + * Adapted from Open Shading Language + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011-2022 Blender Foundation. */ + +#pragma once + +// clang-format off +#include "kernel/closure/alloc.h" +#include "kernel/closure/bsdf_util.h" +#include "kernel/closure/bsdf_ashikhmin_velvet.h" +#include "kernel/closure/bsdf_diffuse.h" +#include "kernel/closure/bsdf_microfacet.h" +#include "kernel/closure/bsdf_microfacet_multi.h" +#include "kernel/closure/bsdf_oren_nayar.h" +#include "kernel/closure/bsdf_reflection.h" +#include "kernel/closure/bsdf_refraction.h" +#include "kernel/closure/bsdf_transparent.h" +#include "kernel/closure/bsdf_ashikhmin_shirley.h" +#include "kernel/closure/bsdf_toon.h" +#include "kernel/closure/bsdf_hair.h" +#include "kernel/closure/bsdf_hair_principled.h" +#include "kernel/closure/bsdf_principled_diffuse.h" +#include "kernel/closure/bsdf_principled_sheen.h" +#include "kernel/closure/volume.h" +#include "kernel/closure/bsdf_diffuse_ramp.h" +#include "kernel/closure/bsdf_phong_ramp.h" +#include "kernel/closure/bssrdf.h" +#include "kernel/closure/emissive.h" +// clang-format on + +CCL_NAMESPACE_BEGIN + +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + struct ccl_align(8) Upper##Closure \ + { \ + const char *label; +#define OSL_CLOSURE_STRUCT_END(Upper, lower) \ + } \ + ; \ + ccl_device void osl_closure_##lower##_setup(KernelGlobals kg, \ + ccl_private ShaderData *sd, \ + uint32_t path_flag, \ + float3 weight, \ + ccl_private Upper##Closure *closure); +#define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) type name; +#define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) type name[size]; + +#include "closures_template.h" + +ccl_device_forceinline bool osl_closure_skip(KernelGlobals kg, + ccl_private const ShaderData *sd, + uint32_t path_flag, + int scattering) +{ + /* caustic options */ + if ((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) { + if ((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) || + (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) { + return true; + } + } + + return false; +} + +/* Diffuse */ + +ccl_device void osl_closure_diffuse_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const DiffuseClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( + sd, sizeof(DiffuseBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + + sd->flag |= bsdf_diffuse_setup(bsdf); +} + +ccl_device void osl_closure_oren_nayar_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const OrenNayarClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private OrenNayarBsdf *bsdf = (ccl_private OrenNayarBsdf *)bsdf_alloc( + sd, sizeof(OrenNayarBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->roughness = closure->roughness; + + sd->flag |= bsdf_oren_nayar_setup(bsdf); +} + +ccl_device void osl_closure_translucent_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const TranslucentClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private DiffuseBsdf *bsdf = (ccl_private DiffuseBsdf *)bsdf_alloc( + sd, sizeof(DiffuseBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + + sd->flag |= bsdf_translucent_setup(bsdf); +} + +ccl_device void osl_closure_reflection_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const ReflectionClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_SINGULAR)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + + sd->flag |= bsdf_reflection_setup(bsdf); +} + +ccl_device void osl_closure_refraction_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const RefractionClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_SINGULAR)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->ior = closure->ior; + + sd->flag |= bsdf_refraction_setup(bsdf); +} + +ccl_device void osl_closure_transparent_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const TransparentClosure *closure) +{ + bsdf_transparent_setup(sd, rgb_to_spectrum(weight), path_flag); +} + +/* Standard microfacet closures */ + +ccl_device void osl_closure_microfacet_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetClosure *closure) +{ + const int label = (closure->refract) ? LABEL_TRANSMIT : LABEL_REFLECT; + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | label)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->ior = closure->ior; + bsdf->T = closure->T; + + static OSL::ustring u_ggx("ggx"); + static OSL::ustring u_default("default"); + + /* GGX */ + if (closure->distribution == u_ggx || closure->distribution == u_default) { + if (!closure->refract) { + if (closure->alpha_x == closure->alpha_y) { + /* Isotropic */ + sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf); + } + else { + /* Anisotropic */ + sd->flag |= bsdf_microfacet_ggx_setup(bsdf); + } + } + else { + sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf); + } + } + /* Beckmann */ + else { + if (!closure->refract) { + if (closure->alpha_x == closure->alpha_y) { + /* Isotropic */ + sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf); + } + else { + /* Anisotropic */ + sd->flag |= bsdf_microfacet_beckmann_setup(bsdf); + } + } + else { + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf); + } + } +} + +ccl_device void osl_closure_microfacet_ggx_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetGGXIsotropicClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + + sd->flag |= bsdf_microfacet_ggx_isotropic_setup(bsdf); +} + +ccl_device void osl_closure_microfacet_ggx_aniso_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetGGXClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->T = closure->T; + + sd->flag |= bsdf_microfacet_ggx_setup(bsdf); +} + +ccl_device void osl_closure_microfacet_ggx_refraction_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetGGXRefractionClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_TRANSMIT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->ior = closure->ior; + + sd->flag |= bsdf_microfacet_ggx_refraction_setup(bsdf); +} + +/* GGX closures with Fresnel */ + +ccl_device void osl_closure_microfacet_ggx_fresnel_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetGGXFresnelClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = bsdf->alpha_x; + bsdf->ior = closure->ior; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = zero_float3(); + + sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd); +} + +ccl_device void osl_closure_microfacet_ggx_aniso_fresnel_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetGGXAnisoFresnelClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->ior = closure->ior; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = closure->T; + + sd->flag |= bsdf_microfacet_ggx_fresnel_setup(bsdf, sd); +} + +/* Multiscattering GGX closures */ + +ccl_device void osl_closure_microfacet_multi_ggx_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetMultiGGXClosure *closure) +{ + /* Technically, the MultiGGX closure may also transmit. However, + * since this is set statically and only used for caustic flags, this + * is probably as good as it gets. */ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = bsdf->alpha_x; + bsdf->ior = 0.0f; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = zero_spectrum(); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = zero_float3(); + + sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf); +} + +ccl_device void osl_closure_microfacet_multi_ggx_glass_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetMultiGGXGlassClosure *closure) +{ + /* Technically, the MultiGGX closure may also transmit. However, + * since this is set statically and only used for caustic flags, this + * is probably as good as it gets. */ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = bsdf->alpha_x; + bsdf->ior = closure->ior; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = zero_spectrum(); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = zero_float3(); + + sd->flag |= bsdf_microfacet_multi_ggx_glass_setup(bsdf); +} + +ccl_device void osl_closure_microfacet_multi_ggx_aniso_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetMultiGGXAnisoClosure *closure) +{ + /* Technically, the MultiGGX closure may also transmit. However, + * since this is set statically and only used for caustic flags, this + * is probably as good as it gets. */ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->ior = 0.0f; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = zero_spectrum(); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = closure->T; + + sd->flag |= bsdf_microfacet_multi_ggx_setup(bsdf); +} + +/* Multiscattering GGX closures with Fresnel */ + +ccl_device void osl_closure_microfacet_multi_ggx_fresnel_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetMultiGGXFresnelClosure *closure) +{ + /* Technically, the MultiGGX closure may also transmit. However, + * since this is set statically and only used for caustic flags, this + * is probably as good as it gets. */ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = bsdf->alpha_x; + bsdf->ior = closure->ior; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = zero_float3(); + + sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd); +} + +ccl_device void osl_closure_microfacet_multi_ggx_glass_fresnel_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetMultiGGXGlassFresnelClosure *closure) +{ + /* Technically, the MultiGGX closure may also transmit. However, + * since this is set statically and only used for caustic flags, this + * is probably as good as it gets. */ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = bsdf->alpha_x; + bsdf->ior = closure->ior; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = zero_float3(); + + sd->flag |= bsdf_microfacet_multi_ggx_glass_fresnel_setup(bsdf, sd); +} + +ccl_device void osl_closure_microfacet_multi_ggx_aniso_fresnel_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetMultiGGXAnisoFresnelClosure *closure) +{ + /* Technically, the MultiGGX closure may also transmit. However, + * since this is set statically and only used for caustic flags, this + * is probably as good as it gets. */ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private MicrofacetExtra *extra = (ccl_private MicrofacetExtra *)closure_alloc_extra( + sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->ior = closure->ior; + + bsdf->extra = extra; + bsdf->extra->color = rgb_to_spectrum(closure->color); + bsdf->extra->cspec0 = rgb_to_spectrum(closure->cspec0); + bsdf->extra->clearcoat = 0.0f; + + bsdf->T = closure->T; + + sd->flag |= bsdf_microfacet_multi_ggx_fresnel_setup(bsdf, sd); +} + +/* Beckmann closures */ + +ccl_device void osl_closure_microfacet_beckmann_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetBeckmannIsotropicClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + + sd->flag |= bsdf_microfacet_beckmann_isotropic_setup(bsdf); +} + +ccl_device void osl_closure_microfacet_beckmann_aniso_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetBeckmannClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->T = closure->T; + + sd->flag |= bsdf_microfacet_beckmann_setup(bsdf); +} + +ccl_device void osl_closure_microfacet_beckmann_refraction_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const MicrofacetBeckmannRefractionClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_TRANSMIT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->ior = closure->ior; + + sd->flag |= bsdf_microfacet_beckmann_refraction_setup(bsdf); +} + +/* Ashikhmin closures */ + +ccl_device void osl_closure_ashikhmin_velvet_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const AshikhminVelvetClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private VelvetBsdf *bsdf = (ccl_private VelvetBsdf *)bsdf_alloc( + sd, sizeof(VelvetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->sigma = closure->sigma; + + sd->flag |= bsdf_ashikhmin_velvet_setup(bsdf); +} + +ccl_device void osl_closure_ashikhmin_shirley_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const AshikhminShirleyClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY | LABEL_REFLECT)) { + return; + } + + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->alpha_x; + bsdf->alpha_y = closure->alpha_y; + bsdf->T = closure->T; + + sd->flag |= bsdf_ashikhmin_shirley_setup(bsdf); +} + +ccl_device void osl_closure_diffuse_toon_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const DiffuseToonClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private ToonBsdf *bsdf = (ccl_private ToonBsdf *)bsdf_alloc( + sd, sizeof(ToonBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->size = closure->size; + bsdf->smooth = closure->smooth; + + sd->flag |= bsdf_diffuse_toon_setup(bsdf); +} + +ccl_device void osl_closure_glossy_toon_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const GlossyToonClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) { + return; + } + + ccl_private ToonBsdf *bsdf = (ccl_private ToonBsdf *)bsdf_alloc( + sd, sizeof(ToonBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->size = closure->size; + bsdf->smooth = closure->smooth; + + sd->flag |= bsdf_glossy_toon_setup(bsdf); +} + +/* Disney principled closures */ + +ccl_device void osl_closure_principled_diffuse_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const PrincipledDiffuseClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private PrincipledDiffuseBsdf *bsdf = (ccl_private PrincipledDiffuseBsdf *)bsdf_alloc( + sd, sizeof(PrincipledDiffuseBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->roughness = closure->roughness; + + sd->flag |= bsdf_principled_diffuse_setup(bsdf); +} + +ccl_device void osl_closure_principled_sheen_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const PrincipledSheenClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_DIFFUSE)) { + return; + } + + ccl_private PrincipledSheenBsdf *bsdf = (ccl_private PrincipledSheenBsdf *)bsdf_alloc( + sd, sizeof(PrincipledSheenBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->avg_value = 0.0f; + + sd->flag |= bsdf_principled_sheen_setup(sd, bsdf); +} + +ccl_device void osl_closure_principled_clearcoat_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const PrincipledClearcoatClosure *closure) +{ + ccl_private MicrofacetBsdf *bsdf = (ccl_private MicrofacetBsdf *)bsdf_alloc( + sd, sizeof(MicrofacetBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + MicrofacetExtra *extra = (MicrofacetExtra *)closure_alloc_extra(sd, sizeof(MicrofacetExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->alpha_x = closure->clearcoat_roughness; + bsdf->alpha_y = closure->clearcoat_roughness; + bsdf->ior = 1.5f; + + bsdf->extra = extra; + bsdf->extra->color = zero_spectrum(); + bsdf->extra->cspec0 = make_spectrum(0.04f); + bsdf->extra->clearcoat = closure->clearcoat; + + bsdf->T = zero_float3(); + + sd->flag |= bsdf_microfacet_ggx_clearcoat_setup(bsdf, sd); +} + +/* Variable cone emissive closure + * + * This primitive emits in a cone having a configurable penumbra area where the light decays to 0 + * reaching the outer_angle limit. It can also behave as a lambertian emitter if the provided + * angles are PI/2, which is the default + */ +ccl_device void osl_closure_emission_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t /* path_flag */, + float3 weight, + ccl_private const GenericEmissiveClosure *closure) +{ + emission_setup(sd, rgb_to_spectrum(weight)); +} + +/* Generic background closure + * + * We only have a background closure for the shaders to return a color in background shaders. No + * methods, only the weight is taking into account + */ +ccl_device void osl_closure_background_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t /* path_flag */, + float3 weight, + ccl_private const GenericBackgroundClosure *closure) +{ + background_setup(sd, rgb_to_spectrum(weight)); +} + +/* Holdout closure + * + * This will be used by the shader to mark the amount of holdout for the current shading point. No + * parameters, only the weight will be used + */ +ccl_device void osl_closure_holdout_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t /* path_flag */, + float3 weight, + ccl_private const HoldoutClosure *closure) +{ + closure_alloc(sd, sizeof(ShaderClosure), CLOSURE_HOLDOUT_ID, rgb_to_spectrum(weight)); + sd->flag |= SD_HOLDOUT; +} + +ccl_device void osl_closure_diffuse_ramp_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t /* path_flag */, + float3 weight, + ccl_private const DiffuseRampClosure *closure) +{ + ccl_private DiffuseRampBsdf *bsdf = (ccl_private DiffuseRampBsdf *)bsdf_alloc( + sd, sizeof(DiffuseRampBsdf), rgb_to_spectrum(weight)); + + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + + bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); + if (!bsdf->colors) { + return; + } + + for (int i = 0; i < 8; i++) + bsdf->colors[i] = closure->colors[i]; + + sd->flag |= bsdf_diffuse_ramp_setup(bsdf); +} + +ccl_device void osl_closure_phong_ramp_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t /* path_flag */, + float3 weight, + ccl_private const PhongRampClosure *closure) +{ + ccl_private PhongRampBsdf *bsdf = (ccl_private PhongRampBsdf *)bsdf_alloc( + sd, sizeof(PhongRampBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->exponent = closure->exponent; + + bsdf->colors = (float3 *)closure_alloc_extra(sd, sizeof(float3) * 8); + if (!bsdf->colors) { + return; + } + + for (int i = 0; i < 8; i++) + bsdf->colors[i] = closure->colors[i]; + + sd->flag |= bsdf_phong_ramp_setup(bsdf); +} + +ccl_device void osl_closure_bssrdf_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const BSSRDFClosure *closure) +{ + static ustring u_burley("burley"); + static ustring u_random_walk_fixed_radius("random_walk_fixed_radius"); + static ustring u_random_walk("random_walk"); + + ClosureType type; + if (closure->method == u_burley) { + type = CLOSURE_BSSRDF_BURLEY_ID; + } + else if (closure->method == u_random_walk_fixed_radius) { + type = CLOSURE_BSSRDF_RANDOM_WALK_FIXED_RADIUS_ID; + } + else if (closure->method == u_random_walk) { + type = CLOSURE_BSSRDF_RANDOM_WALK_ID; + } + else { + return; + } + + ccl_private Bssrdf *bssrdf = bssrdf_alloc(sd, rgb_to_spectrum(weight)); + if (!bssrdf) { + return; + } + + /* disable in case of diffuse ancestor, can't see it well then and + * adds considerably noise due to probabilities of continuing path + * getting lower and lower */ + if (path_flag & PATH_RAY_DIFFUSE_ANCESTOR) { + bssrdf->radius = zero_spectrum(); + } + else { + bssrdf->radius = closure->radius; + } + + /* create one closure per color channel */ + bssrdf->albedo = closure->albedo; + bssrdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bssrdf->roughness = closure->roughness; + bssrdf->anisotropy = clamp(closure->anisotropy, 0.0f, 0.9f); + + sd->flag |= bssrdf_setup(sd, bssrdf, type, clamp(closure->ior, 1.01f, 3.8f)); +} + +/* Hair */ + +ccl_device void osl_closure_hair_reflection_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const HairReflectionClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) { + return; + } + + ccl_private HairBsdf *bsdf = (ccl_private HairBsdf *)bsdf_alloc( + sd, sizeof(HairBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->T = closure->T; + bsdf->roughness1 = closure->roughness1; + bsdf->roughness2 = closure->roughness2; + bsdf->offset = closure->offset; + + sd->flag |= bsdf_hair_reflection_setup(bsdf); +} + +ccl_device void osl_closure_hair_transmission_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const HairTransmissionClosure *closure) +{ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) { + return; + } + + ccl_private HairBsdf *bsdf = (ccl_private HairBsdf *)bsdf_alloc( + sd, sizeof(HairBsdf), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->T = closure->T; + bsdf->roughness1 = closure->roughness1; + bsdf->roughness2 = closure->roughness2; + bsdf->offset = closure->offset; + + sd->flag |= bsdf_hair_transmission_setup(bsdf); +} + +ccl_device void osl_closure_principled_hair_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const PrincipledHairClosure *closure) +{ +#ifdef __HAIR__ + if (osl_closure_skip(kg, sd, path_flag, LABEL_GLOSSY)) { + return; + } + + ccl_private PrincipledHairBSDF *bsdf = (ccl_private PrincipledHairBSDF *)bsdf_alloc( + sd, sizeof(PrincipledHairBSDF), rgb_to_spectrum(weight)); + if (!bsdf) { + return; + } + + ccl_private PrincipledHairExtra *extra = (ccl_private PrincipledHairExtra *)closure_alloc_extra( + sd, sizeof(PrincipledHairExtra)); + if (!extra) { + return; + } + + bsdf->N = ensure_valid_reflection(sd->Ng, sd->I, closure->N); + bsdf->sigma = closure->sigma; + bsdf->v = closure->v; + bsdf->s = closure->s; + bsdf->alpha = closure->alpha; + bsdf->eta = closure->eta; + bsdf->m0_roughness = closure->m0_roughness; + + bsdf->extra = extra; + + sd->flag |= bsdf_principled_hair_setup(sd, bsdf); +#endif +} + +/* Volume */ + +ccl_device void osl_closure_absorption_setup(KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const VolumeAbsorptionClosure *closure) +{ + volume_extinction_setup(sd, rgb_to_spectrum(weight)); +} + +ccl_device void osl_closure_henyey_greenstein_setup( + KernelGlobals kg, + ccl_private ShaderData *sd, + uint32_t path_flag, + float3 weight, + ccl_private const VolumeHenyeyGreensteinClosure *closure) +{ + volume_extinction_setup(sd, rgb_to_spectrum(weight)); + + ccl_private HenyeyGreensteinVolume *volume = (ccl_private HenyeyGreensteinVolume *)bsdf_alloc( + sd, sizeof(HenyeyGreensteinVolume), rgb_to_spectrum(weight)); + if (!volume) { + return; + } + + volume->g = closure->g; + + sd->flag |= volume_henyey_greenstein_setup(volume); +} + +CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/closures_template.h b/intern/cycles/kernel/osl/closures_template.h new file mode 100644 index 00000000000..c808b275966 --- /dev/null +++ b/intern/cycles/kernel/osl/closures_template.h @@ -0,0 +1,258 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#ifndef OSL_CLOSURE_STRUCT_BEGIN +# define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) +#endif +#ifndef OSL_CLOSURE_STRUCT_END +# define OSL_CLOSURE_STRUCT_END(Upper, lower) +#endif +#ifndef OSL_CLOSURE_STRUCT_MEMBER +# define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) +#endif +#ifndef OSL_CLOSURE_STRUCT_ARRAY_MEMBER +# define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) +#endif + +OSL_CLOSURE_STRUCT_BEGIN(Diffuse, diffuse) + OSL_CLOSURE_STRUCT_MEMBER(Diffuse, VECTOR, packed_float3, N, NULL) +OSL_CLOSURE_STRUCT_END(Diffuse, diffuse) + +OSL_CLOSURE_STRUCT_BEGIN(OrenNayar, oren_nayar) + OSL_CLOSURE_STRUCT_MEMBER(OrenNayar, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(OrenNayar, FLOAT, float, roughness, NULL) +OSL_CLOSURE_STRUCT_END(OrenNayar, oren_nayar) + +OSL_CLOSURE_STRUCT_BEGIN(Translucent, translucent) + OSL_CLOSURE_STRUCT_MEMBER(Translucent, VECTOR, packed_float3, N, NULL) +OSL_CLOSURE_STRUCT_END(Translucent, translucent) + +OSL_CLOSURE_STRUCT_BEGIN(Reflection, reflection) + OSL_CLOSURE_STRUCT_MEMBER(Reflection, VECTOR, packed_float3, N, NULL) +OSL_CLOSURE_STRUCT_END(Reflection, reflection) + +OSL_CLOSURE_STRUCT_BEGIN(Refraction, refraction) + OSL_CLOSURE_STRUCT_MEMBER(Refraction, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Refraction, FLOAT, float, ior, NULL) +OSL_CLOSURE_STRUCT_END(Refraction, refraction) + +OSL_CLOSURE_STRUCT_BEGIN(Transparent, transparent) +OSL_CLOSURE_STRUCT_END(Transparent, transparent) + +OSL_CLOSURE_STRUCT_BEGIN(Microfacet, microfacet) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, STRING, ustring, distribution, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, FLOAT, float, alpha_y, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(Microfacet, INT, int, refract, NULL) +OSL_CLOSURE_STRUCT_END(Microfacet, microfacet) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetGGXIsotropic, microfacet_ggx) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXIsotropic, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXIsotropic, FLOAT, float, alpha_x, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetGGXIsotropic, microfacet_ggx) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetGGX, microfacet_ggx_aniso) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGX, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGX, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGX, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGX, FLOAT, float, alpha_y, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetGGX, microfacet_ggx_aniso) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXRefraction, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXRefraction, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXRefraction, FLOAT, float, ior, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetGGXRefraction, microfacet_ggx_refraction) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGX, microfacet_multi_ggx) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGX, VECTOR, packed_float3, color, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGX, microfacet_multi_ggx) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXGlass, microfacet_multi_ggx_glass) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlass, VECTOR, packed_float3, color, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGXGlass, microfacet_multi_ggx_glass) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXAniso, microfacet_multi_ggx_aniso) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAniso, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAniso, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAniso, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAniso, FLOAT, float, alpha_y, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAniso, VECTOR, packed_float3, color, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGXAniso, microfacet_multi_ggx_aniso) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetGGXFresnel, microfacet_ggx_fresnel) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXFresnel, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXFresnel, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXFresnel, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXFresnel, VECTOR, packed_float3, color, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXFresnel, VECTOR, packed_float3, cspec0, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetGGXFresnel, microfacet_ggx_fresnel) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetGGXAnisoFresnel, microfacet_ggx_aniso_fresnel) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, FLOAT, float, alpha_y, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, VECTOR, packed_float3, color, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetGGXAnisoFresnel, VECTOR, packed_float3, cspec0, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetGGXAnisoFresnel, microfacet_ggx_aniso_fresnel) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXFresnel, microfacet_multi_ggx_fresnel) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXFresnel, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXFresnel, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXFresnel, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXFresnel, VECTOR, packed_float3, color, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXFresnel, VECTOR, packed_float3, cspec0, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGXFresnel, microfacet_multi_ggx_fresnel) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXGlassFresnel, microfacet_multi_ggx_glass_fresnel) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlassFresnel, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlassFresnel, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlassFresnel, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlassFresnel, VECTOR, packed_float3, color, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXGlassFresnel, VECTOR, packed_float3, cspec0, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGXGlassFresnel, microfacet_multi_ggx_glass_fresnel) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetMultiGGXAnisoFresnel, microfacet_multi_ggx_aniso_fresnel) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, FLOAT, float, alpha_y, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, FLOAT, float, ior, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, VECTOR, packed_float3, color, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetMultiGGXAnisoFresnel, VECTOR, packed_float3, cspec0, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetMultiGGXAnisoFresnel, microfacet_multi_ggx_aniso_fresnel) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetBeckmannIsotropic, microfacet_beckmann) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmannIsotropic, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmannIsotropic, FLOAT, float, alpha_x, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetBeckmannIsotropic, microfacet_beckmann) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetBeckmann, microfacet_beckmann_aniso) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmann, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmann, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmann, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmann, FLOAT, float, alpha_y, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetBeckmann, microfacet_beckmann_aniso) + +OSL_CLOSURE_STRUCT_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmannRefraction, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmannRefraction, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(MicrofacetBeckmannRefraction, FLOAT, float, ior, NULL) +OSL_CLOSURE_STRUCT_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) + +OSL_CLOSURE_STRUCT_BEGIN(AshikhminShirley, ashikhmin_shirley) + OSL_CLOSURE_STRUCT_MEMBER(AshikhminShirley, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(AshikhminShirley, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(AshikhminShirley, FLOAT, float, alpha_x, NULL) + OSL_CLOSURE_STRUCT_MEMBER(AshikhminShirley, FLOAT, float, alpha_y, NULL) +OSL_CLOSURE_STRUCT_END(AshikhminShirley, ashikhmin_shirley) + +OSL_CLOSURE_STRUCT_BEGIN(AshikhminVelvet, ashikhmin_velvet) + OSL_CLOSURE_STRUCT_MEMBER(AshikhminVelvet, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(AshikhminVelvet, FLOAT, float, sigma, NULL) +OSL_CLOSURE_STRUCT_END(AshikhminVelvet, ashikhmin_velvet) + +OSL_CLOSURE_STRUCT_BEGIN(DiffuseToon, diffuse_toon) + OSL_CLOSURE_STRUCT_MEMBER(DiffuseToon, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(DiffuseToon, FLOAT, float, size, NULL) + OSL_CLOSURE_STRUCT_MEMBER(DiffuseToon, FLOAT, float, smooth, NULL) +OSL_CLOSURE_STRUCT_END(DiffuseToon, diffuse_toon) + +OSL_CLOSURE_STRUCT_BEGIN(GlossyToon, glossy_toon) + OSL_CLOSURE_STRUCT_MEMBER(GlossyToon, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(GlossyToon, FLOAT, float, size, NULL) + OSL_CLOSURE_STRUCT_MEMBER(GlossyToon, FLOAT, float, smooth, NULL) +OSL_CLOSURE_STRUCT_END(GlossyToon, glossy_toon) + +OSL_CLOSURE_STRUCT_BEGIN(PrincipledDiffuse, principled_diffuse) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledDiffuse, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledDiffuse, FLOAT, float, roughness, NULL) +OSL_CLOSURE_STRUCT_END(PrincipledDiffuse, principled_diffuse) + +OSL_CLOSURE_STRUCT_BEGIN(PrincipledSheen, principled_sheen) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledSheen, VECTOR, packed_float3, N, NULL) +OSL_CLOSURE_STRUCT_END(PrincipledSheen, principled_sheen) + +OSL_CLOSURE_STRUCT_BEGIN(PrincipledClearcoat, principled_clearcoat) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledClearcoat, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledClearcoat, FLOAT, float, clearcoat, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledClearcoat, FLOAT, float, clearcoat_roughness, NULL) +OSL_CLOSURE_STRUCT_END(PrincipledClearcoat, principled_clearcoat) + +OSL_CLOSURE_STRUCT_BEGIN(GenericEmissive, emission) +OSL_CLOSURE_STRUCT_END(GenericEmissive, emission) + +OSL_CLOSURE_STRUCT_BEGIN(GenericBackground, background) +OSL_CLOSURE_STRUCT_END(GenericBackground, background) + +OSL_CLOSURE_STRUCT_BEGIN(Holdout, holdout) +OSL_CLOSURE_STRUCT_END(Holdout, holdout) + +OSL_CLOSURE_STRUCT_BEGIN(DiffuseRamp, diffuse_ramp) + OSL_CLOSURE_STRUCT_MEMBER(DiffuseRamp, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_ARRAY_MEMBER(DiffuseRamp, COLOR, packed_float3, colors, NULL, 8) +OSL_CLOSURE_STRUCT_END(DiffuseRamp, diffuse_ramp) + +OSL_CLOSURE_STRUCT_BEGIN(PhongRamp, phong_ramp) + OSL_CLOSURE_STRUCT_MEMBER(PhongRamp, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PhongRamp, FLOAT, float, exponent, NULL) + OSL_CLOSURE_STRUCT_ARRAY_MEMBER(PhongRamp, COLOR, packed_float3, colors, NULL, 8) +OSL_CLOSURE_STRUCT_END(PhongRamp, phong_ramp) + +OSL_CLOSURE_STRUCT_BEGIN(BSSRDF, bssrdf) + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, STRING, ustring, method, NULL) + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, VECTOR, packed_float3, radius, NULL) + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, VECTOR, packed_float3, albedo, NULL) + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, FLOAT, float, roughness, "roughness") + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, FLOAT, float, ior, "ior") + OSL_CLOSURE_STRUCT_MEMBER(BSSRDF, FLOAT, float, anisotropy, "anisotropy") +OSL_CLOSURE_STRUCT_END(BSSRDF, bssrdf) + +OSL_CLOSURE_STRUCT_BEGIN(HairReflection, hair_reflection) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, roughness1, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, roughness2, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, offset, NULL) +OSL_CLOSURE_STRUCT_END(HairReflection, hair_reflection) + +OSL_CLOSURE_STRUCT_BEGIN(HairTransmission, hair_transmission) + OSL_CLOSURE_STRUCT_MEMBER(HairTransmission, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairTransmission, FLOAT, float, roughness1, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairTransmission, FLOAT, float, roughness2, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, VECTOR, packed_float3, T, NULL) + OSL_CLOSURE_STRUCT_MEMBER(HairReflection, FLOAT, float, offset, NULL) +OSL_CLOSURE_STRUCT_END(HairTransmission, hair_transmission) + +OSL_CLOSURE_STRUCT_BEGIN(PrincipledHair, principled_hair) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, VECTOR, packed_float3, N, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, VECTOR, packed_float3, sigma, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, FLOAT, float, v, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, FLOAT, float, s, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, FLOAT, float, m0_roughness, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, FLOAT, float, alpha, NULL) + OSL_CLOSURE_STRUCT_MEMBER(PrincipledHair, FLOAT, float, eta, NULL) +OSL_CLOSURE_STRUCT_END(PrincipledHair, principled_hair) + +OSL_CLOSURE_STRUCT_BEGIN(VolumeAbsorption, absorption) +OSL_CLOSURE_STRUCT_END(VolumeAbsorption, absorption) + +OSL_CLOSURE_STRUCT_BEGIN(VolumeHenyeyGreenstein, henyey_greenstein) + OSL_CLOSURE_STRUCT_MEMBER(VolumeHenyeyGreenstein, FLOAT, float, g, NULL) +OSL_CLOSURE_STRUCT_END(VolumeHenyeyGreenstein, henyey_greenstein) + +#undef OSL_CLOSURE_STRUCT_BEGIN +#undef OSL_CLOSURE_STRUCT_END +#undef OSL_CLOSURE_STRUCT_MEMBER +#undef OSL_CLOSURE_STRUCT_ARRAY_MEMBER diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp deleted file mode 100644 index 8d1928d0126..00000000000 --- a/intern/cycles/kernel/osl/emissive.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause - * - * Adapted from Open Shading Language - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. - * - * Modifications Copyright 2011-2022 Blender Foundation. */ - -#include - -#include - -#include "kernel/osl/closures.h" - -// clang-format off -#include "kernel/device/cpu/compat.h" -#include "kernel/device/cpu/globals.h" - -#include "kernel/types.h" -#include "kernel/closure/alloc.h" -#include "kernel/closure/emissive.h" - -#include "kernel/util/color.h" -// clang-format on - -CCL_NAMESPACE_BEGIN - -using namespace OSL; - -/// Variable cone emissive closure -/// -/// This primitive emits in a cone having a configurable -/// penumbra area where the light decays to 0 reaching the -/// outer_angle limit. It can also behave as a lambertian emitter -/// if the provided angles are PI/2, which is the default -/// -class GenericEmissiveClosure : public CClosurePrimitive { - public: - void setup(ShaderData *sd, uint32_t /* path_flag */, float3 weight) - { - emission_setup(sd, rgb_to_spectrum(weight)); - } -}; - -ClosureParam *closure_emission_params() -{ - static ClosureParam params[] = {CLOSURE_STRING_KEYPARAM(GenericEmissiveClosure, label, "label"), - CLOSURE_FINISH_PARAM(GenericEmissiveClosure)}; - return params; -} - -CCLOSURE_PREPARE(closure_emission_prepare, GenericEmissiveClosure) - -CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/services.cpp b/intern/cycles/kernel/osl/services.cpp index eef661c203e..334f06861b2 100644 --- a/intern/cycles/kernel/osl/services.cpp +++ b/intern/cycles/kernel/osl/services.cpp @@ -18,7 +18,6 @@ #include "scene/pointcloud.h" #include "scene/scene.h" -#include "kernel/osl/closures.h" #include "kernel/osl/globals.h" #include "kernel/osl/services.h" #include "kernel/osl/shader.h" @@ -1605,8 +1604,8 @@ bool OSLRenderServices::trace(TraceOpt &options, /* setup ray */ Ray ray; - ray.P = TO_FLOAT3(P); - ray.D = TO_FLOAT3(R); + ray.P = make_float3(P.x, P.y, P.z); + ray.D = make_float3(R.x, R.y, R.z); ray.tmin = 0.0f; ray.tmax = (options.maxdist == 1.0e30f) ? FLT_MAX : options.maxdist - options.mindist; ray.time = sd->time; @@ -1629,12 +1628,12 @@ bool OSLRenderServices::trace(TraceOpt &options, /* ray differentials */ differential3 dP; - dP.dx = TO_FLOAT3(dPdx); - dP.dy = TO_FLOAT3(dPdy); + dP.dx = make_float3(dPdx.x, dPdx.y, dPdx.z); + dP.dy = make_float3(dPdy.x, dPdy.y, dPdy.z); ray.dP = differential_make_compact(dP); differential3 dD; - dD.dx = TO_FLOAT3(dRdx); - dD.dy = TO_FLOAT3(dRdy); + dD.dx = make_float3(dRdx.x, dRdx.y, dRdx.z); + dD.dy = make_float3(dRdy.x, dRdy.y, dRdy.z); ray.dD = differential_make_compact(dD); /* allocate trace data */ diff --git a/intern/cycles/kernel/osl/services.h b/intern/cycles/kernel/osl/services.h index edffd912bad..eb4e35f80a2 100644 --- a/intern/cycles/kernel/osl/services.h +++ b/intern/cycles/kernel/osl/services.h @@ -76,6 +76,8 @@ class OSLRenderServices : public OSL::RendererServices { OSLRenderServices(OSL::TextureSystem *texture_system); ~OSLRenderServices(); + static void register_closures(OSL::ShadingSystem *ss); + bool get_matrix(OSL::ShaderGlobals *sg, OSL::Matrix44 &result, OSL::TransformationPtr xform, diff --git a/intern/cycles/kernel/osl/shader.cpp b/intern/cycles/kernel/osl/shader.cpp index 3355f5c869a..83fdfab1217 100644 --- a/intern/cycles/kernel/osl/shader.cpp +++ b/intern/cycles/kernel/osl/shader.cpp @@ -13,14 +13,19 @@ #include "kernel/integrator/state.h" -#include "kernel/osl/closures.h" #include "kernel/osl/globals.h" #include "kernel/osl/services.h" #include "kernel/osl/shader.h" +#include "kernel/osl/types.h" +#include "kernel/osl/closures_setup.h" + #include "kernel/util/differential.h" // clang-format on +#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z) +#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) + CCL_NAMESPACE_BEGIN /* Threads */ @@ -133,7 +138,8 @@ static void shaderdata_to_shaderglobals(const KernelGlobalsCPU *kg, /* Surface */ -static void flatten_surface_closure_tree(ShaderData *sd, +static void flatten_surface_closure_tree(const KernelGlobalsCPU *kg, + ShaderData *sd, uint32_t path_flag, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) @@ -144,27 +150,30 @@ static void flatten_surface_closure_tree(ShaderData *sd, switch (closure->id) { case OSL::ClosureColor::MUL: { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; - flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight); + flatten_surface_closure_tree(kg, sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight); break; } case OSL::ClosureColor::ADD: { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; - flatten_surface_closure_tree(sd, path_flag, add->closureA, weight); - flatten_surface_closure_tree(sd, path_flag, add->closureB, weight); + flatten_surface_closure_tree(kg, sd, path_flag, add->closureA, weight); + flatten_surface_closure_tree(kg, sd, path_flag, add->closureB, weight); break; } - default: { - OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; - CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); - - if (prim) { -#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS - weight = weight * TO_FLOAT3(comp->w); -#endif - prim->setup(sd, path_flag, weight); - } +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + case OSL_CLOSURE_##Upper##_ID: { \ + const OSL::ClosureComponent *comp = \ + reinterpret_cast(closure); \ + weight *= TO_FLOAT3(comp->w); \ + osl_closure_##lower##_setup(kg, \ + sd, \ + path_flag, \ + weight, \ + reinterpret_cast(comp + 1)); \ + break; \ + } +#include "closures_template.h" + default: break; - } } } @@ -238,12 +247,13 @@ void OSLShader::eval_surface(const KernelGlobalsCPU *kg, /* flatten closure tree */ if (globals->Ci) - flatten_surface_closure_tree(sd, path_flag, globals->Ci); + flatten_surface_closure_tree(kg, sd, path_flag, globals->Ci); } /* Background */ -static void flatten_background_closure_tree(ShaderData *sd, +static void flatten_background_closure_tree(const KernelGlobalsCPU *kg, + ShaderData *sd, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { @@ -254,28 +264,27 @@ static void flatten_background_closure_tree(ShaderData *sd, switch (closure->id) { case OSL::ClosureColor::MUL: { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; - flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight)); + flatten_background_closure_tree(kg, sd, mul->closure, weight * TO_FLOAT3(mul->weight)); break; } case OSL::ClosureColor::ADD: { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; - flatten_background_closure_tree(sd, add->closureA, weight); - flatten_background_closure_tree(sd, add->closureB, weight); + flatten_background_closure_tree(kg, sd, add->closureA, weight); + flatten_background_closure_tree(kg, sd, add->closureB, weight); break; } - default: { - OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; - CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); - - if (prim) { -#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS - weight = weight * TO_FLOAT3(comp->w); -#endif - prim->setup(sd, 0, weight); - } +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + case OSL_CLOSURE_##Upper##_ID: { \ + const OSL::ClosureComponent *comp = reinterpret_cast(closure); \ + weight *= TO_FLOAT3(comp->w); \ + osl_closure_##lower##_setup( \ + kg, sd, 0, weight, reinterpret_cast(comp + 1)); \ + break; \ + } +#include "closures_template.h" + default: break; - } } } @@ -299,12 +308,13 @@ void OSLShader::eval_background(const KernelGlobalsCPU *kg, /* return background color immediately */ if (globals->Ci) - flatten_background_closure_tree(sd, globals->Ci); + flatten_background_closure_tree(kg, sd, globals->Ci); } /* Volume */ -static void flatten_volume_closure_tree(ShaderData *sd, +static void flatten_volume_closure_tree(const KernelGlobalsCPU *kg, + ShaderData *sd, const OSL::ClosureColor *closure, float3 weight = make_float3(1.0f, 1.0f, 1.0f)) { @@ -314,26 +324,26 @@ static void flatten_volume_closure_tree(ShaderData *sd, switch (closure->id) { case OSL::ClosureColor::MUL: { OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; - flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight); + flatten_volume_closure_tree(kg, sd, mul->closure, TO_FLOAT3(mul->weight) * weight); break; } case OSL::ClosureColor::ADD: { OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; - flatten_volume_closure_tree(sd, add->closureA, weight); - flatten_volume_closure_tree(sd, add->closureB, weight); + flatten_volume_closure_tree(kg, sd, add->closureA, weight); + flatten_volume_closure_tree(kg, sd, add->closureB, weight); break; } - default: { - OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure; - CClosurePrimitive *prim = (CClosurePrimitive *)comp->data(); - - if (prim) { -#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS - weight = weight * TO_FLOAT3(comp->w); -#endif - prim->setup(sd, 0, weight); - } - } +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + case OSL_CLOSURE_##Upper##_ID: { \ + const OSL::ClosureComponent *comp = reinterpret_cast(closure); \ + weight *= TO_FLOAT3(comp->w); \ + osl_closure_##lower##_setup( \ + kg, sd, 0, weight, reinterpret_cast(comp + 1)); \ + break; \ + } +#include "closures_template.h" + default: + break; } } @@ -358,7 +368,7 @@ void OSLShader::eval_volume(const KernelGlobalsCPU *kg, /* flatten closure tree */ if (globals->Ci) - flatten_volume_closure_tree(sd, globals->Ci); + flatten_volume_closure_tree(kg, sd, globals->Ci); } /* Displacement */ diff --git a/intern/cycles/kernel/osl/shader.h b/intern/cycles/kernel/osl/shader.h index 56c87d7c8ac..c89eecb7698 100644 --- a/intern/cycles/kernel/osl/shader.h +++ b/intern/cycles/kernel/osl/shader.h @@ -33,9 +33,6 @@ struct OSLShadingSystem; class OSLShader { public: - /* init */ - static void register_closures(OSLShadingSystem *ss); - /* per thread data */ static void thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals); static void thread_free(KernelGlobalsCPU *kg); diff --git a/intern/cycles/kernel/osl/types.h b/intern/cycles/kernel/osl/types.h new file mode 100644 index 00000000000..14feb16aad4 --- /dev/null +++ b/intern/cycles/kernel/osl/types.h @@ -0,0 +1,21 @@ +/* SPDX-License-Identifier: Apache-2.0 + * Copyright 2011-2022 Blender Foundation */ + +#pragma once + +CCL_NAMESPACE_BEGIN + +/* Closure */ + +enum ClosureTypeOSL { + OSL_CLOSURE_MUL_ID = -1, + OSL_CLOSURE_ADD_ID = -2, + + OSL_CLOSURE_NONE_ID = 0, + +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) OSL_CLOSURE_##Upper##_ID, +#include "closures_template.h" +}; + + +CCL_NAMESPACE_END diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp index 7c8d9bcd3e2..f0246b5b40e 100644 --- a/intern/cycles/scene/osl.cpp +++ b/intern/cycles/scene/osl.cpp @@ -298,7 +298,7 @@ void OSLShaderManager::shading_system_init() const int nraytypes = sizeof(raytypes) / sizeof(raytypes[0]); ss_shared->attribute("raytypes", TypeDesc(TypeDesc::STRING, nraytypes), raytypes); - OSLShader::register_closures((OSLShadingSystem *)ss_shared); + OSLRenderServices::register_closures(ss_shared); loaded_shaders.clear(); } -- cgit v1.2.3 From 1e1e9014cfc9f47d8496dd283a1cccae0ce29552 Mon Sep 17 00:00:00 2001 From: Bastien Montagne Date: Fri, 9 Sep 2022 17:59:24 +0200 Subject: install_deps: update OIIO/Boost/Python/NumPy versions. OIIO: 2.3.18.0 Boost: 1.80.0 Python:3.10.6 NumPy: 1.23.2 Ref T99618. --- build_files/build_environment/install_deps.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build_files/build_environment/install_deps.sh b/build_files/build_environment/install_deps.sh index 814834ccf34..60665d31521 100755 --- a/build_files/build_environment/install_deps.sh +++ b/build_files/build_environment/install_deps.sh @@ -385,7 +385,7 @@ CLANG_FORMAT_VERSION="10.0" CLANG_FORMAT_VERSION_MIN="6.0" CLANG_FORMAT_VERSION_MEX="14.0" -PYTHON_VERSION="3.10.2" +PYTHON_VERSION="3.10.6" PYTHON_VERSION_SHORT="3.10" PYTHON_VERSION_MIN="3.10" PYTHON_VERSION_MEX="3.12" @@ -425,7 +425,7 @@ PYTHON_ZSTANDARD_VERSION_MIN="0.15.2" PYTHON_ZSTANDARD_VERSION_MEX="0.20.0" PYTHON_ZSTANDARD_NAME="zstandard" -PYTHON_NUMPY_VERSION="1.22.0" +PYTHON_NUMPY_VERSION="1.23.2" PYTHON_NUMPY_VERSION_MIN="1.14" PYTHON_NUMPY_VERSION_MEX="2.0" PYTHON_NUMPY_NAME="numpy" @@ -453,8 +453,8 @@ PYTHON_MODULES_PIP=( ) -BOOST_VERSION="1.78.0" -BOOST_VERSION_SHORT="1.78" +BOOST_VERSION="1.80.0" +BOOST_VERSION_SHORT="1.80" BOOST_VERSION_MIN="1.49" BOOST_VERSION_MEX="2.0" BOOST_FORCE_BUILD=false @@ -496,7 +496,7 @@ OPENEXR_FORCE_REBUILD=false OPENEXR_SKIP=false _with_built_openexr=false -OIIO_VERSION="2.3.13.0" +OIIO_VERSION="2.3.18.0" OIIO_VERSION_SHORT="2.3" OIIO_VERSION_MIN="2.1.12" OIIO_VERSION_MEX="2.4.0" -- cgit v1.2.3